renfe-cli 5.0.0__tar.gz → 5.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,256 @@
1
+ # This file is autogenerated by maturin v1.3.2
2
+ # To update, run
3
+ #
4
+ # maturin generate-ci github
5
+ #
6
+ name: CICD
7
+
8
+ on:
9
+ push:
10
+ branches:
11
+ - main
12
+ tags:
13
+ - '*'
14
+ pull_request:
15
+ branches: [ main ]
16
+ workflow_dispatch:
17
+
18
+ permissions:
19
+ contents: read
20
+
21
+ env:
22
+ CARGO_TERM_COLOR: always
23
+
24
+ jobs:
25
+
26
+ test:
27
+ name: Tests
28
+ strategy:
29
+ matrix:
30
+ os: [ubuntu-latest, macos-latest, windows-latest]
31
+ runs-on: ${{ matrix.os }}
32
+ steps:
33
+ - uses: actions/checkout@v3
34
+ - uses: actions-rs/toolchain@v1
35
+ with:
36
+ profile: minimal
37
+ toolchain: stable
38
+ override: true
39
+ - uses: actions-rs/cargo@v1
40
+ with:
41
+ command: test
42
+
43
+ fmt:
44
+ name: Rustfmt
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v3
48
+ - uses: actions-rs/toolchain@v1
49
+ with:
50
+ profile: minimal
51
+ toolchain: stable
52
+ override: true
53
+ - run: rustup component add rustfmt
54
+ - uses: actions-rs/cargo@v1
55
+ with:
56
+ command: fmt
57
+ args: --all -- --check
58
+
59
+ clippy:
60
+ name: Build Clippy
61
+ runs-on: ubuntu-latest
62
+ strategy:
63
+ matrix:
64
+ rust:
65
+ - stable
66
+ - 1.72.0
67
+ steps:
68
+ - uses: actions/checkout@v3
69
+ - uses: actions-rs/toolchain@v1
70
+ with:
71
+ profile: minimal
72
+ toolchain: ${{ matrix.rust }}
73
+ override: true
74
+ - run: rustup component add clippy
75
+ - uses: actions-rs/cargo@v1
76
+ with:
77
+ command: clippy
78
+ args: -- -D warnings
79
+
80
+ linux:
81
+ runs-on: ${{ matrix.platform.runner }}
82
+ strategy:
83
+ matrix:
84
+ platform:
85
+ - runner: ubuntu-latest
86
+ target: x86_64
87
+ - runner: ubuntu-latest
88
+ target: x86
89
+ # skipping until ring update/fix compile issue: include/ring-core/asm_base.h:73:2: error: #error "ARM assembler must define __ARM_ARCH"
90
+ # - runner: ubuntu-latest
91
+ # target: aarch64
92
+ - runner: ubuntu-latest
93
+ target: armv7
94
+ - runner: ubuntu-latest
95
+ target: s390x
96
+ - runner: ubuntu-latest
97
+ target: ppc64le
98
+ steps:
99
+ - uses: actions/checkout@v4
100
+ - uses: actions/setup-python@v5
101
+ with:
102
+ python-version: 3.x
103
+ - name: Build wheels
104
+ uses: PyO3/maturin-action@v1
105
+ with:
106
+ target: ${{ matrix.platform.target }}
107
+ args: --release --out dist
108
+ sccache: 'true'
109
+ manylinux: auto
110
+ - name: Upload wheels
111
+ uses: actions/upload-artifact@v4
112
+ with:
113
+ name: wheels-linux-${{ matrix.platform.target }}
114
+ path: dist
115
+
116
+ musllinux:
117
+ runs-on: ${{ matrix.platform.runner }}
118
+ strategy:
119
+ matrix:
120
+ platform:
121
+ - runner: ubuntu-latest
122
+ target: x86_64
123
+ - runner: ubuntu-latest
124
+ target: x86
125
+ # skipping until ring update/fix compile issue: include/ring-core/asm_base.h:73:2: error: #error "ARM assembler must define __ARM_ARCH"
126
+ # - runner: ubuntu-latest
127
+ # target: aarch64
128
+ - runner: ubuntu-latest
129
+ target: armv7
130
+ steps:
131
+ - uses: actions/checkout@v4
132
+ - uses: actions/setup-python@v5
133
+ with:
134
+ python-version: 3.x
135
+ - name: Build wheels
136
+ uses: PyO3/maturin-action@v1
137
+ with:
138
+ target: ${{ matrix.platform.target }}
139
+ args: --release --out dist
140
+ sccache: 'true'
141
+ manylinux: musllinux_1_2
142
+ - name: Upload wheels
143
+ uses: actions/upload-artifact@v4
144
+ with:
145
+ name: wheels-musllinux-${{ matrix.platform.target }}
146
+ path: dist
147
+
148
+ windows:
149
+ runs-on: ${{ matrix.platform.runner }}
150
+ strategy:
151
+ matrix:
152
+ platform:
153
+ - runner: windows-latest
154
+ target: x64
155
+ - runner: windows-latest
156
+ target: x86
157
+ steps:
158
+ - uses: actions/checkout@v4
159
+ - uses: actions/setup-python@v5
160
+ with:
161
+ python-version: 3.x
162
+ architecture: ${{ matrix.platform.target }}
163
+ - name: Build wheels
164
+ uses: PyO3/maturin-action@v1
165
+ with:
166
+ target: ${{ matrix.platform.target }}
167
+ args: --release --out dist
168
+ sccache: 'true'
169
+ - name: Upload wheels
170
+ uses: actions/upload-artifact@v4
171
+ with:
172
+ name: wheels-windows-${{ matrix.platform.target }}
173
+ path: dist
174
+
175
+ macos:
176
+ runs-on: ${{ matrix.platform.runner }}
177
+ strategy:
178
+ matrix:
179
+ platform:
180
+ - runner: macos-12
181
+ target: x86_64
182
+ - runner: macos-14
183
+ target: aarch64
184
+ steps:
185
+ - uses: actions/checkout@v4
186
+ - uses: actions/setup-python@v5
187
+ with:
188
+ python-version: 3.x
189
+ - name: Build wheels
190
+ uses: PyO3/maturin-action@v1
191
+ with:
192
+ target: ${{ matrix.platform.target }}
193
+ args: --release --out dist
194
+ sccache: 'true'
195
+ - name: Upload wheels
196
+ uses: actions/upload-artifact@v4
197
+ with:
198
+ name: wheels-macos-${{ matrix.platform.target }}
199
+ path: dist
200
+
201
+ sdist:
202
+ runs-on: ubuntu-latest
203
+ steps:
204
+ - uses: actions/checkout@v4
205
+ - name: Build sdist
206
+ uses: PyO3/maturin-action@v1
207
+ with:
208
+ command: sdist
209
+ args: --out dist
210
+ - name: Upload sdist
211
+ uses: actions/upload-artifact@v4
212
+ with:
213
+ name: wheels-sdist
214
+ path: dist
215
+
216
+ release:
217
+ name: Release (PyPI)
218
+ runs-on: ubuntu-latest
219
+ if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
220
+ needs: [linux, musllinux, windows, macos, sdist]
221
+ permissions:
222
+ # Use to sign the release artifacts
223
+ id-token: write
224
+ # Used to upload release artifacts
225
+ contents: write
226
+ # Used to generate artifact attestation
227
+ attestations: write
228
+ steps:
229
+ - uses: actions/download-artifact@v4
230
+ - name: Generate artifact attestation
231
+ uses: actions/attest-build-provenance@v1
232
+ with:
233
+ subject-path: 'wheels-*/*'
234
+ - name: Publish to PyPI
235
+ if: "startsWith(github.ref, 'refs/tags/')"
236
+ uses: PyO3/maturin-action@v1
237
+ env:
238
+ MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
239
+ with:
240
+ command: upload
241
+ args: --non-interactive --skip-existing wheels-*/*
242
+
243
+ publish:
244
+ name: Publish (crates.io)
245
+ if: startsWith(github.ref, 'refs/tags/')
246
+ needs: [release]
247
+ runs-on: ubuntu-latest
248
+ steps:
249
+ - uses: actions/checkout@v3
250
+ - uses: actions-rs/toolchain@v1
251
+ with:
252
+ profile: minimal
253
+ toolchain: stable
254
+ override: true
255
+ - name: Publish
256
+ run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.2.0 (2024-10-03)
4
+
5
+ * Publish Rust crate binary via crates.io [#202](https://github.com/gerardcl/renfe-cli/issues/202)
6
+
7
+ ## v5.1.0 (2024-10-02)
8
+
9
+ * Enable Renfe Cercanías GTFS dataset [#200](https://github.com/gerardcl/renfe-cli/issues/200)
10
+
3
11
  ## v5.0.0 (2024-09-29)
4
12
 
5
13
  * Major refactor using GTFS data from Renfe online datasets. No more scrapping required
@@ -132,9 +132,9 @@ dependencies = [
132
132
 
133
133
  [[package]]
134
134
  name = "cc"
135
- version = "1.1.22"
135
+ version = "1.1.24"
136
136
  source = "registry+https://github.com/rust-lang/crates.io-index"
137
- checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
137
+ checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938"
138
138
  dependencies = [
139
139
  "jobserver",
140
140
  "libc",
@@ -462,9 +462,9 @@ dependencies = [
462
462
 
463
463
  [[package]]
464
464
  name = "httparse"
465
- version = "1.9.4"
465
+ version = "1.9.5"
466
466
  source = "registry+https://github.com/rust-lang/crates.io-index"
467
- checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
467
+ checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
468
468
 
469
469
  [[package]]
470
470
  name = "hyper"
@@ -689,9 +689,12 @@ dependencies = [
689
689
 
690
690
  [[package]]
691
691
  name = "once_cell"
692
- version = "1.19.0"
692
+ version = "1.20.1"
693
693
  source = "registry+https://github.com/rust-lang/crates.io-index"
694
- checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
694
+ checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1"
695
+ dependencies = [
696
+ "portable-atomic",
697
+ ]
695
698
 
696
699
  [[package]]
697
700
  name = "password-hash"
@@ -922,7 +925,7 @@ dependencies = [
922
925
 
923
926
  [[package]]
924
927
  name = "renfe-cli"
925
- version = "5.0.0"
928
+ version = "5.2.0"
926
929
  dependencies = [
927
930
  "chrono",
928
931
  "getopts",
@@ -933,9 +936,9 @@ dependencies = [
933
936
 
934
937
  [[package]]
935
938
  name = "reqwest"
936
- version = "0.12.7"
939
+ version = "0.12.8"
937
940
  source = "registry+https://github.com/rust-lang/crates.io-index"
938
- checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63"
941
+ checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b"
939
942
  dependencies = [
940
943
  "base64",
941
944
  "bytes",
@@ -1026,11 +1029,10 @@ dependencies = [
1026
1029
 
1027
1030
  [[package]]
1028
1031
  name = "rustls-pemfile"
1029
- version = "2.1.3"
1032
+ version = "2.2.0"
1030
1033
  source = "registry+https://github.com/rust-lang/crates.io-index"
1031
- checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
1034
+ checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
1032
1035
  dependencies = [
1033
- "base64",
1034
1036
  "rustls-pki-types",
1035
1037
  ]
1036
1038
 
@@ -1,7 +1,8 @@
1
1
  [package]
2
2
  name = "renfe-cli"
3
- version = "5.0.0"
3
+ version = "5.2.0"
4
4
  edition = "2021"
5
+ authors = ["Gerard C.L. <gerardcl@gmail.com>"]
5
6
  license = "BSD-3-Clause"
6
7
  description = "CLI for searching Renfe train timetables in the Spanish country"
7
8
  readme = "README.md"
@@ -13,7 +14,8 @@ categories = ["command-line-utilities"]
13
14
 
14
15
  [lib]
15
16
  name = "renfe_cli"
16
- crate-type = ["cdylib"]
17
+ # https://doc.rust-lang.org/reference/linkage.html
18
+ crate-type = ["cdylib", "lib"]
17
19
 
18
20
  [dependencies]
19
21
  pyo3 = { version = "0.22", features = ["abi3-py37"] }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: renfe-cli
3
- Version: 5.0.0
3
+ Version: 5.2.0
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -15,15 +15,15 @@ Classifier: Operating System :: POSIX
15
15
  Classifier: Operating System :: Microsoft :: Windows
16
16
  Classifier: Topic :: Utilities
17
17
  Classifier: Topic :: Terminals
18
- Classifier: Topic :: Text Processing :: Markup :: HTML
19
18
  License-File: LICENSE
20
19
  Summary: Get faster Renfe Spanish Trains timetables in your terminal.
21
20
  Keywords: timetables,schedules,trains,renfe,cli,rust,python,pyo3,maturin
22
21
  Home-Page: https://github.com/gerardcl/renfe-cli
22
+ Author: Gerard C.L. <gerardcl@gmail.com>
23
23
  Author-email: Gerard Castillo Lasheras <gerardcl@gmail.com>
24
24
  Maintainer-email: Gerard Castillo Lasheras <gerardcl@gmail.com>
25
25
  License: BSD-3-Clause
26
- Requires-Python: >=3.7
26
+ Requires-Python: >=3.8
27
27
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
28
28
  Project-URL: Homepage, https://github.com/gerardcl/renfe-cli
29
29
  Project-URL: Documentation, https://github.com/gerardcl/renfe-cli
@@ -35,28 +35,42 @@ Project-URL: Changelog, https://github.com/gerardcl/renfe-cli/blob/master/CHANGE
35
35
 
36
36
  # Renfe Timetables CLI
37
37
 
38
- Get faster Renfe trains timetables in your terminal, with Python3.7+ support.
38
+ Get faster Renfe trains timetables in your terminal, with Python3.8+ support.
39
39
  No longer need to open the browser! Just keep using your terminal 😀
40
40
 
41
+ It supports both [Horarios de alta velocidad, larga distancia y media distancia](https://data.renfe.com/dataset/horarios-de-alta-velocidad-larga-distancia-y-media-distancia) (default option, as in the web) and [Renfe Cercanías](https://data.renfe.com/dataset/horarios-cercanias) GTFS datasets.
42
+
41
43
  `renfe-cli` is written in [Rust](https://www.rust-lang.org/) (since v4.0.0) and published to [pypi.org](https://pypi.org/project/renfe-cli/) as a Python package (CLI and library).
42
44
 
45
+ It is provided as a Python package due to historical reasons, but was ported to Rust to showcase Rust's interoperability and performance improvements that can offer to the Python ecosystem. Nevertheless, one can optionally use the built [renfe-cli](https://crates.io/crates/renfe-cli) crate that is publised to crates.io.
46
+
43
47
  See the [changelog](https://github.com/gerardcl/renfe-cli/blob/master/CHANGELOG.md).
44
48
 
45
49
  **NOTE** since I am more often using Rodalies trains I have created [rodalies-cli](https://github.com/gerardcl/rodalies-cli). I hope you like it too!
46
50
 
47
- **DISCLAIMER**: Renfe's GTFS dataset might not be in sync with autonomic train schedules (e.g. Rodalies de la Generalitat de Catalunya), hence Renfe Cercanias train types (e.g.: REGIONAL or MD type) might not be accurate. For that, please use autonomic data/apps (.e.g: [rodalies-cli](https://github.com/gerardcl/rodalies-cli)).
51
+ **DISCLAIMER**: Renfe's GTFS dataset might not be in sync with autonomic train schedules systems (e.g. Rodalies de la Generalitat de Catalunya), hence Renfe Cercanias train types (e.g.: REGIONAL or MD type) might not be accurate, or when using the `cercanias` flag you won't find timetables for the stations belonging to autonomic systems. For that, please use autonomic data/apps (.e.g: [rodalies-cli](https://github.com/gerardcl/rodalies-cli)).
48
52
 
49
53
  ## Installation
50
54
 
55
+ ### Python package
56
+
51
57
  Install Python CLI package [renfe-cli](https://pypi.org/project/renfe-cli/)
52
58
 
53
59
  ```bash
54
60
  pip install renfe-cli --upgrade
55
61
  ```
56
62
 
63
+ ### Rust crate (optional)
64
+
65
+ Install the Rust crate [renfe-cli](https://crates.io/crates/renfe-cli)
66
+
67
+ ```bash
68
+ cargo install renfe-cli
69
+ ```
70
+
57
71
  ## Usage (CLI)
58
72
 
59
- The CLI uses the official and latest Renfe's GTFS dataset, from [Horarios de alta velocidad, larga distancia y media distancia](https://data.renfe.com/dataset/horarios-de-alta-velocidad-larga-distancia-y-media-distancia).
73
+ The CLI uses the official and latest Renfe's GTFS dataset, from [Horarios de alta velocidad, larga distancia y media distancia](https://data.renfe.com/dataset/horarios-de-alta-velocidad-larga-distancia-y-media-distancia), by default. Optionally, one can enable searching over [Renfe Cercanías GTFS dataset](https://data.renfe.com/dataset/horarios-cercanias) (expect longer load time in this case).
60
74
 
61
75
  ```bash
62
76
  $ renfe-cli -h
@@ -69,16 +83,17 @@ Options:
69
83
  -m, --month MONTH Set the Month (default: today's month)
70
84
  -y, --year YEAR Set the Year (default: today's year)
71
85
  -s, --sort Option to sort the timetable by Duration
86
+ -c, --cercanias Option to search over Renfe Cercanías
72
87
  -h, --help Print this help menu
73
88
  ```
74
89
 
75
90
  ### **Getting the timetable**
76
91
 
77
- Let's show an example of minimal inputs (origin and destination stations) with specific date:
92
+ Let's show an example of minimal inputs (origin and destination stations) with specific date and default GTFS dataset:
78
93
 
79
94
  ```bash
80
95
  $ renfe-cli -f girona -t "puerta de atocha" -d 30
81
- Loading GTFS data from Renfe web
96
+ Loading default GTFS data from Renfe web - Alta velocidad, Larga distancia y Media distancia
82
97
  Provided input 'girona' does a match with 'Estación de tren Girona'
83
98
  Provided input 'puerta de atocha' does a match with 'Estación de tren Madrid-Puerta de Atocha'
84
99
  Today is: 2024-9-29
@@ -103,6 +118,38 @@ Destination station: Estación de tren Madrid-Puerta de Atocha
103
118
  ===========================================================
104
119
  ```
105
120
 
121
+ Let's show an example using Renfe Cercanías GTFS dataset:
122
+
123
+ ```bash
124
+ $ renfe-cli -f chamartín -t "tres cantos" -c
125
+ Loading Cercanías GTFS data from Renfe web - long load time
126
+ Provided input 'chamartín' does a match with 'Station { name: "Estación de tren Madrid-Chamartín-Clara Campoamor", id: "17000" }'
127
+ Provided input 'tres cantos' does a match with 'Station { name: "Estación de tren Tres Cantos (apt)", id: "17004" }'
128
+ Today is: 2024-10-2
129
+ Searching timetable for date: 2024-10-2
130
+ Origin station: Estación de tren Madrid-Chamartín-Clara Campoamor
131
+ Destination station: Estación de tren Tres Cantos (apt)
132
+
133
+ =========================TIMETABLE=========================
134
+ Train | Departure | Arrival | Duration
135
+ -----------------------------------------------------------
136
+ C4b | 05:06 | 05:22 | 00:16
137
+ -----------------------------------------------------------
138
+ C4b | 05:38 | 05:55 | 00:17
139
+ -----------------------------------------------------------
140
+ C4b | 06:10 | 06:27 | 00:17
141
+ -----------------------------------------------------------
142
+ .........
143
+ .........
144
+ -----------------------------------------------------------
145
+ C4b | 21:56 | 22:13 | 00:17
146
+ -----------------------------------------------------------
147
+ C4b | 22:20 | 22:37 | 00:17
148
+ -----------------------------------------------------------
149
+ C4b | 23:16 | 23:33 | 00:17
150
+ ===========================================================
151
+ ```
152
+
106
153
  ## Usage (Library)
107
154
 
108
155
  `renfe-cli` can be imported as a python package into your project, offering utilities when willing to deal with the Renfe search web site.
@@ -115,7 +162,20 @@ Type "help", "copyright", "credits" or "license" for more information.
115
162
  >>> renfe = renfe_cli.
116
163
  renfe_cli.Renfe() renfe_cli.Schedule( renfe_cli.Station( renfe_cli.main() renfe_cli.renfe_cli
117
164
  >>> renfe = renfe_cli.Renfe()
118
- Loading GTFS data from Renfe web
165
+ Traceback (most recent call last):
166
+ File "<stdin>", line 1, in <module>
167
+ TypeError: Renfe.__new__() missing 1 required positional argument: 'cercanias'
168
+ >>> renfe = renfe_cli.Renfe(False)
169
+ Loading default GTFS data from Renfe web - Alta velocidad, Larga distancia y Media distancia
170
+ GTFS data:
171
+ Read in 2171 ms
172
+ Stops: 793
173
+ Routes: 644
174
+ Trips: 4150
175
+ Agencies: 1
176
+ Shapes: 0
177
+ Fare attributes: 0
178
+ Feed info: 0
119
179
  >>> renfe.filter_station("madrid")
120
180
  Traceback (most recent call last):
121
181
  File "<stdin>", line 1, in <module>
@@ -171,10 +231,10 @@ $ maturin develop
171
231
  🔗 Found pyo3 bindings with abi3 support for Python ≥ 3.7
172
232
  🐍 Not using a specific python interpreter
173
233
  📡 Using build options features from pyproject.toml
174
- Compiling renfe-cli v4.1.0 (/path/to/renfe-cli)
234
+ Compiling renfe-cli v5.1.0 (/path/to/renfe-cli)
175
235
  Finished dev [unoptimized + debuginfo] target(s) in 7.07s
176
- 📦 Built wheel for abi3 Python ≥ 3.7 to /tmp/.tmpDsjowL/renfe_cli-4.1.0-cp37-abi3-linux_x86_64.whl
177
- 🛠 Installed renfe-cli-4.1.0
236
+ 📦 Built wheel for abi3 Python ≥ 3.7 to /tmp/.tmpDsjowL/renfe_cli-5.1.0-cp37-abi3-linux_x86_64.whl
237
+ 🛠 Installed renfe-cli-5.1.0
178
238
  ```
179
239
 
180
240
  Maturin takes care of compiling the rust code, generating the bindings for python and installing the package for local use (as library or binary/CLI).
@@ -2,28 +2,42 @@
2
2
 
3
3
  # Renfe Timetables CLI
4
4
 
5
- Get faster Renfe trains timetables in your terminal, with Python3.7+ support.
5
+ Get faster Renfe trains timetables in your terminal, with Python3.8+ support.
6
6
  No longer need to open the browser! Just keep using your terminal 😀
7
7
 
8
+ It supports both [Horarios de alta velocidad, larga distancia y media distancia](https://data.renfe.com/dataset/horarios-de-alta-velocidad-larga-distancia-y-media-distancia) (default option, as in the web) and [Renfe Cercanías](https://data.renfe.com/dataset/horarios-cercanias) GTFS datasets.
9
+
8
10
  `renfe-cli` is written in [Rust](https://www.rust-lang.org/) (since v4.0.0) and published to [pypi.org](https://pypi.org/project/renfe-cli/) as a Python package (CLI and library).
9
11
 
12
+ It is provided as a Python package due to historical reasons, but was ported to Rust to showcase Rust's interoperability and performance improvements that can offer to the Python ecosystem. Nevertheless, one can optionally use the built [renfe-cli](https://crates.io/crates/renfe-cli) crate that is publised to crates.io.
13
+
10
14
  See the [changelog](https://github.com/gerardcl/renfe-cli/blob/master/CHANGELOG.md).
11
15
 
12
16
  **NOTE** since I am more often using Rodalies trains I have created [rodalies-cli](https://github.com/gerardcl/rodalies-cli). I hope you like it too!
13
17
 
14
- **DISCLAIMER**: Renfe's GTFS dataset might not be in sync with autonomic train schedules (e.g. Rodalies de la Generalitat de Catalunya), hence Renfe Cercanias train types (e.g.: REGIONAL or MD type) might not be accurate. For that, please use autonomic data/apps (.e.g: [rodalies-cli](https://github.com/gerardcl/rodalies-cli)).
18
+ **DISCLAIMER**: Renfe's GTFS dataset might not be in sync with autonomic train schedules systems (e.g. Rodalies de la Generalitat de Catalunya), hence Renfe Cercanias train types (e.g.: REGIONAL or MD type) might not be accurate, or when using the `cercanias` flag you won't find timetables for the stations belonging to autonomic systems. For that, please use autonomic data/apps (.e.g: [rodalies-cli](https://github.com/gerardcl/rodalies-cli)).
15
19
 
16
20
  ## Installation
17
21
 
22
+ ### Python package
23
+
18
24
  Install Python CLI package [renfe-cli](https://pypi.org/project/renfe-cli/)
19
25
 
20
26
  ```bash
21
27
  pip install renfe-cli --upgrade
22
28
  ```
23
29
 
30
+ ### Rust crate (optional)
31
+
32
+ Install the Rust crate [renfe-cli](https://crates.io/crates/renfe-cli)
33
+
34
+ ```bash
35
+ cargo install renfe-cli
36
+ ```
37
+
24
38
  ## Usage (CLI)
25
39
 
26
- The CLI uses the official and latest Renfe's GTFS dataset, from [Horarios de alta velocidad, larga distancia y media distancia](https://data.renfe.com/dataset/horarios-de-alta-velocidad-larga-distancia-y-media-distancia).
40
+ The CLI uses the official and latest Renfe's GTFS dataset, from [Horarios de alta velocidad, larga distancia y media distancia](https://data.renfe.com/dataset/horarios-de-alta-velocidad-larga-distancia-y-media-distancia), by default. Optionally, one can enable searching over [Renfe Cercanías GTFS dataset](https://data.renfe.com/dataset/horarios-cercanias) (expect longer load time in this case).
27
41
 
28
42
  ```bash
29
43
  $ renfe-cli -h
@@ -36,16 +50,17 @@ Options:
36
50
  -m, --month MONTH Set the Month (default: today's month)
37
51
  -y, --year YEAR Set the Year (default: today's year)
38
52
  -s, --sort Option to sort the timetable by Duration
53
+ -c, --cercanias Option to search over Renfe Cercanías
39
54
  -h, --help Print this help menu
40
55
  ```
41
56
 
42
57
  ### **Getting the timetable**
43
58
 
44
- Let's show an example of minimal inputs (origin and destination stations) with specific date:
59
+ Let's show an example of minimal inputs (origin and destination stations) with specific date and default GTFS dataset:
45
60
 
46
61
  ```bash
47
62
  $ renfe-cli -f girona -t "puerta de atocha" -d 30
48
- Loading GTFS data from Renfe web
63
+ Loading default GTFS data from Renfe web - Alta velocidad, Larga distancia y Media distancia
49
64
  Provided input 'girona' does a match with 'Estación de tren Girona'
50
65
  Provided input 'puerta de atocha' does a match with 'Estación de tren Madrid-Puerta de Atocha'
51
66
  Today is: 2024-9-29
@@ -70,6 +85,38 @@ Destination station: Estación de tren Madrid-Puerta de Atocha
70
85
  ===========================================================
71
86
  ```
72
87
 
88
+ Let's show an example using Renfe Cercanías GTFS dataset:
89
+
90
+ ```bash
91
+ $ renfe-cli -f chamartín -t "tres cantos" -c
92
+ Loading Cercanías GTFS data from Renfe web - long load time
93
+ Provided input 'chamartín' does a match with 'Station { name: "Estación de tren Madrid-Chamartín-Clara Campoamor", id: "17000" }'
94
+ Provided input 'tres cantos' does a match with 'Station { name: "Estación de tren Tres Cantos (apt)", id: "17004" }'
95
+ Today is: 2024-10-2
96
+ Searching timetable for date: 2024-10-2
97
+ Origin station: Estación de tren Madrid-Chamartín-Clara Campoamor
98
+ Destination station: Estación de tren Tres Cantos (apt)
99
+
100
+ =========================TIMETABLE=========================
101
+ Train | Departure | Arrival | Duration
102
+ -----------------------------------------------------------
103
+ C4b | 05:06 | 05:22 | 00:16
104
+ -----------------------------------------------------------
105
+ C4b | 05:38 | 05:55 | 00:17
106
+ -----------------------------------------------------------
107
+ C4b | 06:10 | 06:27 | 00:17
108
+ -----------------------------------------------------------
109
+ .........
110
+ .........
111
+ -----------------------------------------------------------
112
+ C4b | 21:56 | 22:13 | 00:17
113
+ -----------------------------------------------------------
114
+ C4b | 22:20 | 22:37 | 00:17
115
+ -----------------------------------------------------------
116
+ C4b | 23:16 | 23:33 | 00:17
117
+ ===========================================================
118
+ ```
119
+
73
120
  ## Usage (Library)
74
121
 
75
122
  `renfe-cli` can be imported as a python package into your project, offering utilities when willing to deal with the Renfe search web site.
@@ -82,7 +129,20 @@ Type "help", "copyright", "credits" or "license" for more information.
82
129
  >>> renfe = renfe_cli.
83
130
  renfe_cli.Renfe() renfe_cli.Schedule( renfe_cli.Station( renfe_cli.main() renfe_cli.renfe_cli
84
131
  >>> renfe = renfe_cli.Renfe()
85
- Loading GTFS data from Renfe web
132
+ Traceback (most recent call last):
133
+ File "<stdin>", line 1, in <module>
134
+ TypeError: Renfe.__new__() missing 1 required positional argument: 'cercanias'
135
+ >>> renfe = renfe_cli.Renfe(False)
136
+ Loading default GTFS data from Renfe web - Alta velocidad, Larga distancia y Media distancia
137
+ GTFS data:
138
+ Read in 2171 ms
139
+ Stops: 793
140
+ Routes: 644
141
+ Trips: 4150
142
+ Agencies: 1
143
+ Shapes: 0
144
+ Fare attributes: 0
145
+ Feed info: 0
86
146
  >>> renfe.filter_station("madrid")
87
147
  Traceback (most recent call last):
88
148
  File "<stdin>", line 1, in <module>
@@ -138,10 +198,10 @@ $ maturin develop
138
198
  🔗 Found pyo3 bindings with abi3 support for Python ≥ 3.7
139
199
  🐍 Not using a specific python interpreter
140
200
  📡 Using build options features from pyproject.toml
141
- Compiling renfe-cli v4.1.0 (/path/to/renfe-cli)
201
+ Compiling renfe-cli v5.1.0 (/path/to/renfe-cli)
142
202
  Finished dev [unoptimized + debuginfo] target(s) in 7.07s
143
- 📦 Built wheel for abi3 Python ≥ 3.7 to /tmp/.tmpDsjowL/renfe_cli-4.1.0-cp37-abi3-linux_x86_64.whl
144
- 🛠 Installed renfe-cli-4.1.0
203
+ 📦 Built wheel for abi3 Python ≥ 3.7 to /tmp/.tmpDsjowL/renfe_cli-5.1.0-cp37-abi3-linux_x86_64.whl
204
+ 🛠 Installed renfe-cli-5.1.0
145
205
  ```
146
206
 
147
207
  Maturin takes care of compiling the rust code, generating the bindings for python and installing the package for local use (as library or binary/CLI).
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "renfe-cli"
7
- requires-python = ">=3.7"
7
+ requires-python = ">=3.8"
8
8
  authors = [
9
9
  {name = "Gerard Castillo Lasheras", email = "gerardcl@gmail.com"},
10
10
  ]
@@ -30,7 +30,6 @@ classifiers = [
30
30
  "Operating System :: Microsoft :: Windows",
31
31
  "Topic :: Utilities",
32
32
  "Topic :: Terminals",
33
- "Topic :: Text Processing :: Markup :: HTML",
34
33
  ]
35
34
  dynamic = ["version"]
36
35
 
@@ -24,7 +24,7 @@ pub fn main() -> PyResult<()> {
24
24
  return Ok(());
25
25
  }
26
26
 
27
- let mut renfe = Renfe::new()?;
27
+ let mut renfe = Renfe::new(matches.opt_present("c"))?;
28
28
 
29
29
  let origin = renfe.filter_station(matches.opt_str("f").expect("Missing origin station"))?;
30
30
  let destination =
@@ -74,6 +74,7 @@ fn set_opts() -> Options {
74
74
  );
75
75
  opts.optopt("y", "year", "Set the Year (default: today's year)", "YEAR");
76
76
  opts.optflag("s", "sort", "Option to sort the timetable by Duration");
77
+ opts.optflag("c", "cercanias", "Option to search over Renfe Cercanías");
77
78
  opts.optflag("h", "help", "Print this help menu");
78
79
 
79
80
  opts
@@ -1,9 +1,10 @@
1
+ pub mod cli;
2
+ pub mod renfe;
3
+
1
4
  use pyo3::prelude::*;
2
5
 
3
- mod renfe;
4
- use renfe::{Renfe, Schedule, Station};
5
- mod cli;
6
6
  use cli::main;
7
+ use renfe::{Renfe, Schedule, Station};
7
8
 
8
9
  /// A Python module implemented in Rust. The name of this function must match
9
10
  /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
@@ -0,0 +1,10 @@
1
+ use renfe_cli::cli;
2
+
3
+ fn main() -> Result<(), pyo3::PyErr> {
4
+ // Initialize the Python interpreter required
5
+ pyo3::prepare_freethreaded_python();
6
+
7
+ cli::main()?;
8
+
9
+ Ok(())
10
+ }
@@ -1,8 +1,7 @@
1
- use std::io::Read;
2
-
3
1
  use chrono::{Datelike, NaiveDate, NaiveTime, TimeDelta, Timelike};
4
2
  use gtfs_structures::Gtfs;
5
3
  use pyo3::{exceptions::PyValueError, pyclass, pymethods, PyResult};
4
+ use std::io::Read;
6
5
 
7
6
  #[pyclass]
8
7
  pub struct Renfe {
@@ -32,11 +31,18 @@ pub struct Station {
32
31
  #[pymethods]
33
32
  impl Renfe {
34
33
  #[new]
35
- pub fn new() -> PyResult<Self> {
36
- println!("Loading GTFS data from Renfe web");
37
-
34
+ pub fn new(cercanias: bool) -> PyResult<Self> {
38
35
  let mut res = reqwest::blocking::get(
39
- "https://ssl.renfe.com/gtransit/Fichero_AV_LD/google_transit.zip",
36
+ match cercanias {
37
+ false => {
38
+ println!("Loading default GTFS data from Renfe web - Alta velocidad, Larga distancia y Media distancia");
39
+ "https://ssl.renfe.com/gtransit/Fichero_AV_LD/google_transit.zip"
40
+ },
41
+ true => {
42
+ println!("Loading Cercanías GTFS data from Renfe web - long load time");
43
+ "https://ssl.renfe.com/ftransit/Fichero_CER_FOMENTO/fomento_transit.zip"
44
+ },
45
+ },
40
46
  )
41
47
  .expect("Error downloading GTFS zip file");
42
48
  let mut body = Vec::new();
@@ -44,7 +50,8 @@ impl Renfe {
44
50
  let cursor = std::io::Cursor::new(body);
45
51
 
46
52
  let gtfs = Gtfs::from_reader(cursor).expect("Error parsing GTFS zip");
47
- // gtfs.print_stats();
53
+
54
+ gtfs.print_stats();
48
55
 
49
56
  Ok(Renfe {
50
57
  gtfs,
@@ -143,18 +150,22 @@ impl Renfe {
143
150
  let time_origin = origin.departure_time.unwrap();
144
151
  let time_destination = destination.arrival_time.unwrap();
145
152
  let departure_time = NaiveTime::from_hms_opt(
146
- time_origin / 3600,
153
+ (time_origin / 3600) % 24,
147
154
  time_origin % 3600 / 60,
148
155
  time_origin % 60,
149
156
  )
150
157
  .unwrap();
151
158
  let arrival_time = NaiveTime::from_hms_opt(
152
- time_destination / 3600,
159
+ (time_destination / 3600) % 24,
153
160
  time_destination % 3600 / 60,
154
161
  time_destination % 60,
155
162
  )
156
163
  .unwrap();
157
- let duration = arrival_time.signed_duration_since(departure_time);
164
+
165
+ let mut duration = arrival_time.signed_duration_since(departure_time);
166
+ if time_destination >= 86400 {
167
+ duration = duration.checked_add(&TimeDelta::seconds(86400)).unwrap();
168
+ }
158
169
 
159
170
  schedules.push(Schedule {
160
171
  train_type: gtfs
@@ -1,175 +0,0 @@
1
- # This file is autogenerated by maturin v1.3.2
2
- # To update, run
3
- #
4
- # maturin generate-ci github
5
- #
6
- name: CICD
7
-
8
- on:
9
- push:
10
- branches:
11
- - 'main'
12
- tags:
13
- - '*'
14
- pull_request:
15
- branches: [ main ]
16
- workflow_dispatch:
17
-
18
- permissions:
19
- contents: read
20
-
21
- jobs:
22
-
23
- test:
24
- name: Tests
25
- strategy:
26
- matrix:
27
- os: [ubuntu-latest, macos-latest, windows-latest]
28
- runs-on: ${{ matrix.os }}
29
- steps:
30
- - uses: actions/checkout@v3
31
- - uses: actions-rs/toolchain@v1
32
- with:
33
- profile: minimal
34
- toolchain: stable
35
- override: true
36
- - uses: actions-rs/cargo@v1
37
- with:
38
- command: test
39
-
40
- fmt:
41
- name: Rustfmt
42
- runs-on: ubuntu-latest
43
- steps:
44
- - uses: actions/checkout@v3
45
- - uses: actions-rs/toolchain@v1
46
- with:
47
- profile: minimal
48
- toolchain: stable
49
- override: true
50
- - run: rustup component add rustfmt
51
- - uses: actions-rs/cargo@v1
52
- with:
53
- command: fmt
54
- args: --all -- --check
55
-
56
- clippy:
57
- name: Build Clippy
58
- runs-on: ubuntu-latest
59
- strategy:
60
- matrix:
61
- rust:
62
- - stable
63
- - 1.72.0
64
- steps:
65
- - uses: actions/checkout@v3
66
- - uses: actions-rs/toolchain@v1
67
- with:
68
- profile: minimal
69
- toolchain: ${{ matrix.rust }}
70
- override: true
71
- - run: rustup component add clippy
72
- - uses: actions-rs/cargo@v1
73
- with:
74
- command: clippy
75
- args: -- -D warnings
76
-
77
- linux:
78
- runs-on: ubuntu-latest
79
- strategy:
80
- matrix:
81
- target: [x86_64, x86, armv7, s390x, ppc64le]
82
- steps:
83
- - uses: actions/checkout@v3
84
- - uses: actions/setup-python@v4
85
- with:
86
- python-version: '3.10'
87
- - name: Build wheels
88
- uses: PyO3/maturin-action@v1
89
- with:
90
- target: ${{ matrix.target }}
91
- args: --release --out dist --find-interpreter
92
- sccache: 'true'
93
- manylinux: auto
94
- - name: Upload wheels
95
- uses: actions/upload-artifact@v3
96
- with:
97
- name: wheels
98
- path: dist
99
-
100
- windows:
101
- runs-on: windows-latest
102
- strategy:
103
- matrix:
104
- target: [x64, x86]
105
- steps:
106
- - uses: actions/checkout@v3
107
- - uses: actions/setup-python@v4
108
- with:
109
- python-version: '3.10'
110
- architecture: ${{ matrix.target }}
111
- - name: Build wheels
112
- uses: PyO3/maturin-action@v1
113
- with:
114
- target: ${{ matrix.target }}
115
- args: --release --out dist --find-interpreter
116
- sccache: 'true'
117
- - name: Upload wheels
118
- uses: actions/upload-artifact@v3
119
- with:
120
- name: wheels
121
- path: dist
122
-
123
- macos:
124
- runs-on: macos-latest
125
- strategy:
126
- matrix:
127
- target: [x86_64, aarch64]
128
- steps:
129
- - uses: actions/checkout@v3
130
- - uses: actions/setup-python@v4
131
- with:
132
- python-version: '3.10'
133
- - name: Build wheels
134
- uses: PyO3/maturin-action@v1
135
- with:
136
- target: ${{ matrix.target }}
137
- args: --release --out dist --find-interpreter
138
- sccache: 'true'
139
- - name: Upload wheels
140
- uses: actions/upload-artifact@v3
141
- with:
142
- name: wheels
143
- path: dist
144
-
145
- sdist:
146
- runs-on: ubuntu-latest
147
- steps:
148
- - uses: actions/checkout@v3
149
- - name: Build sdist
150
- uses: PyO3/maturin-action@v1
151
- with:
152
- command: sdist
153
- args: --out dist
154
- - name: Upload sdist
155
- uses: actions/upload-artifact@v3
156
- with:
157
- name: wheels
158
- path: dist
159
-
160
- release:
161
- name: Release
162
- runs-on: ubuntu-latest
163
- if: "startsWith(github.ref, 'refs/tags/')"
164
- needs: [linux, windows, macos, sdist]
165
- steps:
166
- - uses: actions/download-artifact@v3
167
- with:
168
- name: wheels
169
- - name: Publish to PyPI
170
- uses: PyO3/maturin-action@v1
171
- env:
172
- MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
173
- with:
174
- command: upload
175
- args: --non-interactive --skip-existing *
File without changes
File without changes
File without changes