koleo-cli 0.2.137.15__tar.gz → 0.2.137.17__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.
Potentially problematic release.
This version of koleo-cli might be problematic. Click here for more details.
- koleo_cli-0.2.137.17/MANIFEST.in +1 -0
- {koleo_cli-0.2.137.15/koleo_cli.egg-info → koleo_cli-0.2.137.17}/PKG-INFO +17 -4
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo/cli.py +107 -49
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo/storage.py +10 -7
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo/types.py +1 -1
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo/utils.py +1 -1
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17/koleo_cli.egg-info}/PKG-INFO +17 -4
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo_cli.egg-info/SOURCES.txt +2 -0
- koleo_cli-0.2.137.17/koleo_cli.egg-info/requires.txt +2 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/pyproject.toml +1 -1
- koleo_cli-0.2.137.17/requirements.txt +2 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/setup.py +1 -1
- koleo_cli-0.2.137.15/koleo_cli.egg-info/requires.txt +0 -2
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/LICENSE +0 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/README.md +0 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo/__init__.py +0 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo/__main__.py +0 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo/api.py +0 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo_cli.egg-info/dependency_links.txt +0 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo_cli.egg-info/entry_points.txt +0 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/koleo_cli.egg-info/top_level.txt +0 -0
- {koleo_cli-0.2.137.15 → koleo_cli-0.2.137.17}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include requirements.txt
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: koleo-cli
|
|
3
|
-
Version: 0.2.137.
|
|
3
|
+
Version: 0.2.137.17
|
|
4
4
|
Summary: Koleo CLI
|
|
5
5
|
Home-page: https://github.com/lzgirlcat/koleo-cli
|
|
6
6
|
Author: Zoey !
|
|
@@ -14,8 +14,21 @@ Classifier: Operating System :: OS Independent
|
|
|
14
14
|
Requires-Python: >=3.12
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: rich
|
|
18
|
-
Requires-Dist: requests
|
|
17
|
+
Requires-Dist: rich~=13.7
|
|
18
|
+
Requires-Dist: requests~=2.32
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: keywords
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: maintainer-email
|
|
28
|
+
Dynamic: project-url
|
|
29
|
+
Dynamic: requires-dist
|
|
30
|
+
Dynamic: requires-python
|
|
31
|
+
Dynamic: summary
|
|
19
32
|
|
|
20
33
|
# Koleo CLI
|
|
21
34
|
[](https://pypi.org/project/koleo-cli)
|
|
@@ -6,7 +6,7 @@ from rich.console import Console
|
|
|
6
6
|
|
|
7
7
|
from .api import KoleoAPI
|
|
8
8
|
from .storage import DEFAULT_CONFIG_PATH, Storage
|
|
9
|
-
from .types import ExtendedBaseStationInfo,
|
|
9
|
+
from .types import ExtendedBaseStationInfo, TrainCalendar, TrainOnStationInfo, TrainStop
|
|
10
10
|
from .utils import RemainderString, arr_dep_to_dt, convert_platform_number, name_to_slug, parse_datetime
|
|
11
11
|
|
|
12
12
|
|
|
@@ -79,19 +79,19 @@ class CLI:
|
|
|
79
79
|
|
|
80
80
|
def full_departures(self, station: str, date: datetime):
|
|
81
81
|
st = self.get_station(station)
|
|
82
|
-
station_info = f"[bold blue][link=https://koleo.pl/dworzec-pkp/{st["name_slug"]}/{date.strftime("%Y-%m-%d")}]{st["name"]} at {date.strftime("%d-%m %H:%M")}[/bold blue] ID: {st["id"]}[/link]"
|
|
82
|
+
station_info = f"[bold blue][link=https://koleo.pl/dworzec-pkp/{st["name_slug"]}/odjazdy/{date.strftime("%Y-%m-%d")}]{st["name"]} at {date.strftime("%d-%m %H:%M")}[/bold blue] ID: {st["id"]}[/link]"
|
|
83
83
|
self.print(station_info)
|
|
84
84
|
self.get_departures(st["id"], date)
|
|
85
85
|
|
|
86
86
|
def full_arrivals(self, station: str, date: datetime):
|
|
87
87
|
st = self.get_station(station)
|
|
88
|
-
station_info = f"[bold blue][link=https://koleo.pl/dworzec-pkp/{st["name_slug"]}/{date.strftime("%Y-%m-%d")}]{st["name"]} at {date.strftime("%d-%m %H:%M")}[/bold blue] ID: {st["id"]}[/link]"
|
|
88
|
+
station_info = f"[bold blue][link=https://koleo.pl/dworzec-pkp/{st["name_slug"]}/przyjazdy/{date.strftime("%Y-%m-%d")}]{st["name"]} at {date.strftime("%d-%m %H:%M")}[/bold blue] ID: {st["id"]}[/link]"
|
|
89
89
|
self.print(station_info)
|
|
90
90
|
self.get_arrivals(st["id"], date)
|
|
91
91
|
|
|
92
92
|
def all_trains(self, station: str, date: datetime):
|
|
93
93
|
st = self.get_station(station)
|
|
94
|
-
station_info = f"[bold blue][link=https://koleo.pl/dworzec-pkp/{st["name_slug"]}/{date.strftime("%Y-%m-%d")}]{st["name"]} at {date.strftime("%d-%m %H:%M")}[/bold blue] ID: {st["id"]}[/link]"
|
|
94
|
+
station_info = f"[bold blue][link=https://koleo.pl/dworzec-pkp/{st["name_slug"]}/odjazdy/{date.strftime("%Y-%m-%d")}]{st["name"]} at {date.strftime("%d-%m %H:%M")}[/bold blue] ID: {st["id"]}[/link]"
|
|
95
95
|
self.print(station_info)
|
|
96
96
|
arr_cache_id = f"arr-{st['id']}-{date.strftime("%Y-%m-%d")}"
|
|
97
97
|
dep_cache_id = f"dep-{st['id']}-{date.strftime("%Y-%m-%d")}"
|
|
@@ -103,8 +103,10 @@ class CLI:
|
|
|
103
103
|
)
|
|
104
104
|
trains = sorted(
|
|
105
105
|
[(i, 1) for i in departures] + [(i, 2) for i in arrivals],
|
|
106
|
-
key=lambda train:
|
|
107
|
-
train[0]["departure"]
|
|
106
|
+
key=lambda train: (
|
|
107
|
+
datetime.fromisoformat(train[0]["departure"]) + timedelta(microseconds=1)
|
|
108
|
+
if train[1] == 1
|
|
109
|
+
else (datetime.fromisoformat(train[0]["arrival"]))
|
|
108
110
|
).timestamp(),
|
|
109
111
|
)
|
|
110
112
|
trains = [
|
|
@@ -169,32 +171,61 @@ class CLI:
|
|
|
169
171
|
train_calendars = self.get_train_calendars(brand, name)
|
|
170
172
|
brands = self.storage.get_cache("brands") or self.storage.set_cache("brands", self.client.get_brands())
|
|
171
173
|
for calendar in train_calendars:
|
|
172
|
-
|
|
174
|
+
brand_obj = next(iter(i for i in brands if i["id"] == calendar["trainBrand"]), {})
|
|
175
|
+
link = f"https://koleo.pl/pociag/{brand_obj["name"]}/{name.replace(" ", "-")}"
|
|
176
|
+
brand = brand_obj.get("logo_text", "")
|
|
173
177
|
parts = [
|
|
174
|
-
f"[red]{brand}[/red] [bold blue]{calendar['train_nr']}{" "+ v if (v:=calendar.get("train_name")) else ""}[/bold blue]:"
|
|
178
|
+
f"[red][link={link}]{brand}[/red] [bold blue]{calendar['train_nr']}{" "+ v if (v:=calendar.get("train_name")) else ""}[/bold blue]:[/link]"
|
|
175
179
|
]
|
|
176
|
-
for k, v in calendar["date_train_map"].items():
|
|
180
|
+
for k, v in sorted(calendar["date_train_map"].items(), key=lambda x: datetime.strptime(x[0], "%Y-%m-%d")):
|
|
177
181
|
parts.append(f" [bold green]{k}[/bold green]: [purple]{v}[/purple]")
|
|
178
182
|
self.print("\n".join(parts))
|
|
179
183
|
|
|
180
|
-
def train_info(
|
|
184
|
+
def train_info(
|
|
185
|
+
self, brand: str, name: str, date: datetime, closest: bool, show_stations: tuple[str, str] | None = None
|
|
186
|
+
):
|
|
181
187
|
train_calendars = self.get_train_calendars(brand, name)
|
|
188
|
+
if closest:
|
|
189
|
+
dates = sorted([datetime.strptime(i, "%Y-%m-%d") for i in train_calendars[0]["dates"]])
|
|
190
|
+
date = next(iter(i for i in dates if i > date)) or next(iter(i for i in reversed(dates) if i < date))
|
|
182
191
|
if not (train_id := train_calendars[0]["date_train_map"].get(date.strftime("%Y-%m-%d"))):
|
|
183
192
|
self.print(f"[bold red]This train doesn't run on the selected date: {date.strftime("%Y-%m-%d")}[/bold red]")
|
|
184
193
|
exit(2)
|
|
185
|
-
self.train_detail(train_id)
|
|
194
|
+
self.train_detail(train_id, date=date.strftime("%Y-%m-%d"), show_stations=show_stations)
|
|
186
195
|
|
|
187
|
-
def train_detail(self, train_id: int):
|
|
196
|
+
def train_detail(self, train_id: int, date: str | None = None, show_stations: tuple[str, str] | None = None):
|
|
188
197
|
train_details = self.client.get_train(train_id)
|
|
189
198
|
brands = self.storage.get_cache("brands") or self.storage.set_cache("brands", self.client.get_brands())
|
|
190
|
-
|
|
191
|
-
|
|
199
|
+
brand_obj = next(iter(i for i in brands if i["id"] == train_details["train"]["brand_id"]), {})
|
|
200
|
+
brand = brand_obj.get("logo_text", "")
|
|
192
201
|
parts = [f"[red]{brand}[/red] [bold blue]{train_details["train"]["train_full_name"]}[/bold blue]"]
|
|
202
|
+
|
|
203
|
+
link = (
|
|
204
|
+
f"https://koleo.pl/pociag/{brand_obj["name"]}/{train_details["train"]["train_full_name"].replace(" ", "-")}"
|
|
205
|
+
)
|
|
206
|
+
if date:
|
|
207
|
+
link += f"/{date}"
|
|
208
|
+
parts[0] = f"[link={link}]{parts[0]}[/link]"
|
|
209
|
+
|
|
193
210
|
if train_details["train"]["run_desc"]:
|
|
194
211
|
parts.append(f" {train_details["train"]["run_desc"]}")
|
|
195
212
|
|
|
196
|
-
|
|
197
|
-
|
|
213
|
+
if show_stations:
|
|
214
|
+
slugs = [self.get_station(i)["name_slug"] for i in show_stations]
|
|
215
|
+
first_stop, fs_index = next(
|
|
216
|
+
iter((i, n) for n, i in enumerate(train_details["stops"]) if i["station_slug"] == slugs[0]), {}
|
|
217
|
+
)
|
|
218
|
+
last_stop, ls_index = next(
|
|
219
|
+
iter((i, n + 1) for n, i in enumerate(train_details["stops"]) if i["station_slug"] == slugs[1]), {}
|
|
220
|
+
)
|
|
221
|
+
if fs_index >= ls_index:
|
|
222
|
+
self.print("[bold red]Station B has to be after station A (-s / --show_stations)[/bold red]")
|
|
223
|
+
exit(2)
|
|
224
|
+
else:
|
|
225
|
+
first_stop, last_stop = train_details["stops"][0], train_details["stops"][-1]
|
|
226
|
+
fs_index, ls_index = 0, len(train_details["stops"]) + 1
|
|
227
|
+
route_start = arr_dep_to_dt(first_stop["departure"])
|
|
228
|
+
route_end = arr_dep_to_dt(last_stop["arrival"])
|
|
198
229
|
|
|
199
230
|
if route_end.hour < route_start.hour or (
|
|
200
231
|
route_end.hour == route_start.hour and route_end.minute < route_end.minute
|
|
@@ -202,7 +233,7 @@ class CLI:
|
|
|
202
233
|
route_end += timedelta(days=1)
|
|
203
234
|
|
|
204
235
|
travel_time = route_end - route_start
|
|
205
|
-
speed =
|
|
236
|
+
speed = (last_stop["distance"] - first_stop["distance"]) / 1000 / travel_time.seconds * 3600
|
|
206
237
|
parts.append(
|
|
207
238
|
f"[white] {travel_time.seconds//3600}h{(travel_time.seconds % 3600)/60:.0f}m {speed:^4.1f}km/h [/white]"
|
|
208
239
|
)
|
|
@@ -221,17 +252,10 @@ class CLI:
|
|
|
221
252
|
start = keys[i]
|
|
222
253
|
parts.append(f" {start} - {keys[-1]}: [bold green]{vehicle_types[start]}[/bold green]")
|
|
223
254
|
self.print("\n".join(parts))
|
|
224
|
-
self.print(self.train_route_table(train_details))
|
|
255
|
+
self.print(self.train_route_table(train_details["stops"][fs_index:ls_index]))
|
|
225
256
|
|
|
226
257
|
def connections(
|
|
227
|
-
self,
|
|
228
|
-
start: str,
|
|
229
|
-
end: str,
|
|
230
|
-
date: datetime,
|
|
231
|
-
brands: list[str],
|
|
232
|
-
direct: bool,
|
|
233
|
-
purchasable: bool,
|
|
234
|
-
length: int = 1
|
|
258
|
+
self, start: str, end: str, date: datetime, brands: list[str], direct: bool, purchasable: bool, length: int = 1
|
|
235
259
|
):
|
|
236
260
|
start_station = self.get_station(start)
|
|
237
261
|
end_station = self.get_station(end)
|
|
@@ -241,7 +265,7 @@ class CLI:
|
|
|
241
265
|
connection_brands = {i["name"]: i["id"] for i in api_brands}
|
|
242
266
|
else:
|
|
243
267
|
connection_brands = {
|
|
244
|
-
i["name"]:i["id"]
|
|
268
|
+
i["name"]: i["id"]
|
|
245
269
|
for i in api_brands
|
|
246
270
|
if i["name"].lower().strip() in brands or i["logo_text"].lower().strip() in brands
|
|
247
271
|
}
|
|
@@ -252,21 +276,27 @@ class CLI:
|
|
|
252
276
|
fetch_date = date
|
|
253
277
|
while len(results) < length:
|
|
254
278
|
connections = self.client.get_connections(
|
|
255
|
-
start_station["name_slug"],
|
|
279
|
+
start_station["name_slug"],
|
|
280
|
+
end_station["name_slug"],
|
|
281
|
+
list(connection_brands.values()),
|
|
282
|
+
fetch_date,
|
|
283
|
+
direct,
|
|
284
|
+
purchasable,
|
|
256
285
|
)
|
|
257
286
|
if connections:
|
|
258
|
-
fetch_date = arr_dep_to_dt(connections[-1]["departure"]) + timedelta(seconds=(30*60)+1)
|
|
287
|
+
fetch_date = arr_dep_to_dt(connections[-1]["departure"]) + timedelta(seconds=(30 * 60) + 1) # wtf
|
|
259
288
|
results.extend(connections)
|
|
260
289
|
else:
|
|
261
290
|
break
|
|
262
291
|
link = (
|
|
263
292
|
f"https://koleo.pl/rozklad-pkp/{start_station["name_slug"]}/{end_station["name_slug"]}"
|
|
264
293
|
+ f"/{date.strftime("%d-%m-%Y_%H:%M")}"
|
|
265
|
-
+f"{"all" if not direct else "direct"}/{"-".join(connection_brands.keys()) if brands else "all"}"
|
|
294
|
+
+ f"/{"all" if not direct else "direct"}/{"-".join(connection_brands.keys()) if brands else "all"}"
|
|
266
295
|
)
|
|
267
296
|
parts = [
|
|
268
297
|
f"[bold blue][link={link}]{start_station["name"]} → {end_station["name"]} at {date.strftime("%H:%M %d-%m")}[/link][/bold blue]"
|
|
269
298
|
]
|
|
299
|
+
|
|
270
300
|
for i in results:
|
|
271
301
|
arr = arr_dep_to_dt(i["arrival"])
|
|
272
302
|
dep = arr_dep_to_dt(i["departure"])
|
|
@@ -277,19 +307,26 @@ class CLI:
|
|
|
277
307
|
)
|
|
278
308
|
if len(i["trains"]) == 1:
|
|
279
309
|
train = i["trains"][0]
|
|
280
|
-
|
|
281
|
-
|
|
310
|
+
brand = next(iter(i for i in api_brands if i["id"] == train["brand_id"]), {}).get("logo_text")
|
|
311
|
+
|
|
312
|
+
fs = next(iter(i for i in train["stops"] if i["station_id"] == train["start_station_id"]), {})
|
|
313
|
+
fs_station = (
|
|
282
314
|
start_station
|
|
283
|
-
if
|
|
284
|
-
else self.storage.get_cache(f"st-{
|
|
285
|
-
or self.storage.set_cache(
|
|
286
|
-
f"st-{stop['station_id']}", self.client.get_station_by_id(stop["station_id"])
|
|
287
|
-
)
|
|
315
|
+
if fs["station_id"] == start_station["id"]
|
|
316
|
+
else self.storage.get_cache(f"st-{fs['station_id']}")
|
|
317
|
+
or self.storage.set_cache(f"st-{fs['station_id']}", self.client.get_station_by_id(fs["station_id"]))
|
|
288
318
|
)
|
|
289
|
-
|
|
290
|
-
|
|
319
|
+
|
|
320
|
+
ls = next(iter(i for i in train["stops"] if i["station_id"] == train["end_station_id"]), {})
|
|
321
|
+
ls_station = (
|
|
322
|
+
start_station
|
|
323
|
+
if ls["station_id"] == start_station["id"]
|
|
324
|
+
else self.storage.get_cache(f"st-{ls['station_id']}")
|
|
325
|
+
or self.storage.set_cache(f"st-{ls['station_id']}", self.client.get_station_by_id(ls["station_id"]))
|
|
326
|
+
)
|
|
327
|
+
|
|
291
328
|
parts[-1] += (
|
|
292
|
-
f" [red]{brand}[/red] {train["train_full_name"]}[purple] {
|
|
329
|
+
f" [red]{brand}[/red] {train["train_full_name"]}[purple] {fs_station['name']} {self.format_position(fs["platform"], fs["track"])}[/purple] - [purple]{ls_station['name']} {self.format_position(ls["platform"], ls["track"])}[/purple]"
|
|
293
330
|
)
|
|
294
331
|
for constriction in i["constriction_info"]:
|
|
295
332
|
parts.append(f" [bold red]- {constriction}[/bold red]")
|
|
@@ -300,6 +337,8 @@ class CLI:
|
|
|
300
337
|
for train in i["trains"]:
|
|
301
338
|
brand = next(iter(i for i in api_brands if i["id"] == train["brand_id"]), {}).get("logo_text")
|
|
302
339
|
|
|
340
|
+
# first stop
|
|
341
|
+
|
|
303
342
|
fs = next(iter(i for i in train["stops"] if i["station_id"] == train["start_station_id"]), {})
|
|
304
343
|
fs_station = (
|
|
305
344
|
start_station
|
|
@@ -313,6 +352,8 @@ class CLI:
|
|
|
313
352
|
fs_dep = arr_dep_to_dt(fs["departure"])
|
|
314
353
|
fs_info = f"[bold green]{fs_dep.strftime("%H:%M")} [/bold green][purple]{fs_station['name']} {self.format_position(fs["platform"], fs["track"])}[/purple]"
|
|
315
354
|
|
|
355
|
+
# last stop
|
|
356
|
+
|
|
316
357
|
ls = next(iter(i for i in train["stops"] if i["station_id"] == train["end_station_id"]), {})
|
|
317
358
|
ls_station = (
|
|
318
359
|
start_station
|
|
@@ -338,21 +379,23 @@ class CLI:
|
|
|
338
379
|
parts = []
|
|
339
380
|
brands = self.storage.get_cache("brands") or self.storage.set_cache("brands", self.client.get_brands())
|
|
340
381
|
for train in trains:
|
|
341
|
-
time = train["departure"] if type == 1 else train["arrival"]
|
|
382
|
+
time, color = (train["departure"], "green") if type == 1 else (train["arrival"], "yellow")
|
|
342
383
|
assert time
|
|
343
384
|
brand = next(iter(i for i in brands if i["id"] == train["brand_id"]), {}).get("logo_text")
|
|
344
385
|
parts.append(
|
|
345
|
-
f"[bold
|
|
386
|
+
f"[bold {color}]{time[11:16]}[/bold {color}] [red]{brand}[/red] {train["train_full_name"]}[purple] {train["stations"][0]["name"]} {self.format_position(train["platform"], train["track"])}[/purple]"
|
|
346
387
|
)
|
|
347
388
|
return "\n".join(parts)
|
|
348
389
|
|
|
349
|
-
def train_route_table(self,
|
|
390
|
+
def train_route_table(self, stops: list[TrainStop]):
|
|
350
391
|
parts = []
|
|
351
|
-
|
|
392
|
+
last_real_distance = stops[0]["distance"]
|
|
393
|
+
for stop in stops:
|
|
352
394
|
arr = arr_dep_to_dt(stop["arrival"])
|
|
353
395
|
dep = arr_dep_to_dt(stop["departure"])
|
|
396
|
+
distance = stop["distance"] - last_real_distance
|
|
354
397
|
parts.append(
|
|
355
|
-
f"[white underline]{
|
|
398
|
+
f"[white underline]{distance / 1000:^5.1f}km[/white underline] [bold green]{arr.strftime("%H:%M")}[/bold green] - [bold red]{dep.strftime("%H:%M")}[/bold red] [purple]{stop["station_display_name"]} {self.format_position(stop["platform"])} [/purple]"
|
|
356
399
|
)
|
|
357
400
|
return "\n".join(parts)
|
|
358
401
|
|
|
@@ -455,7 +498,17 @@ def main():
|
|
|
455
498
|
type=lambda s: parse_datetime(s),
|
|
456
499
|
default=datetime.now(),
|
|
457
500
|
)
|
|
458
|
-
train_route.
|
|
501
|
+
train_route.add_argument(
|
|
502
|
+
"-c",
|
|
503
|
+
"--closest",
|
|
504
|
+
help="ignores date, fetches closest date from the train calendar",
|
|
505
|
+
action="store_true",
|
|
506
|
+
default=False,
|
|
507
|
+
)
|
|
508
|
+
train_route.add_argument(
|
|
509
|
+
"-s", "--show_stations", help="limit the result to A->B", action="extend", nargs=2, type=str, default=None
|
|
510
|
+
)
|
|
511
|
+
train_route.set_defaults(func=cli.train_info, pass_=["brand", "name", "date", "closest", "show_stations"])
|
|
459
512
|
|
|
460
513
|
train_calendar = subparsers.add_parser(
|
|
461
514
|
"traincalendar",
|
|
@@ -471,8 +524,11 @@ def main():
|
|
|
471
524
|
aliases=["td", "tid", "id", "idpoc"],
|
|
472
525
|
help="Allows you to show the train's route given it's koleo ID",
|
|
473
526
|
)
|
|
527
|
+
train_detail.add_argument(
|
|
528
|
+
"-s", "--show_stations", help="limit the result to A->B", action="extend", nargs=2, type=str, default=None
|
|
529
|
+
)
|
|
474
530
|
train_detail.add_argument("train_id", help="The koleo ID", type=int)
|
|
475
|
-
train_detail.set_defaults(func=cli.train_detail, pass_=["train_id"])
|
|
531
|
+
train_detail.set_defaults(func=cli.train_detail, pass_=["train_id", "show_stations"])
|
|
476
532
|
|
|
477
533
|
stations = subparsers.add_parser(
|
|
478
534
|
"stations", aliases=["s", "find", "f", "stacje", "ls", "q"], help="Allows you to find stations by their name"
|
|
@@ -524,7 +580,9 @@ def main():
|
|
|
524
580
|
type=int,
|
|
525
581
|
default=1,
|
|
526
582
|
)
|
|
527
|
-
connections.set_defaults(
|
|
583
|
+
connections.set_defaults(
|
|
584
|
+
func=cli.connections, pass_=["start", "end", "brands", "date", "direct", "purchasable", "length"]
|
|
585
|
+
)
|
|
528
586
|
|
|
529
587
|
args = parser.parse_args()
|
|
530
588
|
|
|
@@ -546,5 +604,5 @@ def main():
|
|
|
546
604
|
else:
|
|
547
605
|
args.func(**{k: v for k, v in args.__dict__.items() if k in getattr(args, "pass_", [])})
|
|
548
606
|
|
|
549
|
-
if storage.
|
|
607
|
+
if storage.dirty:
|
|
550
608
|
storage.save()
|
|
@@ -7,15 +7,14 @@ from sys import platform
|
|
|
7
7
|
from time import time
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def get_adequate_config_path():
|
|
10
|
+
def get_adequate_config_path() -> str:
|
|
11
11
|
if platform == "darwin":
|
|
12
12
|
# i dont fucking know nor want to
|
|
13
13
|
return "~/Library/Preferences/koleo-cli/data.json"
|
|
14
|
-
|
|
14
|
+
if "win" in platform:
|
|
15
15
|
# same with this
|
|
16
16
|
return "%USERPROFILE%\\AppData\\Local\\koleo-cli\\data.json"
|
|
17
|
-
|
|
18
|
-
return "~/.config/koleo-cli.json"
|
|
17
|
+
return "~/.config/koleo-cli.json"
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
DEFAULT_CONFIG_PATH = get_adequate_config_path()
|
|
@@ -35,11 +34,15 @@ class Storage:
|
|
|
35
34
|
self._path: str
|
|
36
35
|
self._dirty = False
|
|
37
36
|
|
|
37
|
+
@property
|
|
38
|
+
def dirty(self) -> bool:
|
|
39
|
+
return self._dirty
|
|
40
|
+
|
|
38
41
|
@classmethod
|
|
39
42
|
def load(cls, *, path: str = DEFAULT_CONFIG_PATH) -> t.Self:
|
|
40
43
|
expanded = ospath.expanduser(path)
|
|
41
44
|
if ospath.exists(expanded):
|
|
42
|
-
with open(expanded
|
|
45
|
+
with open(expanded) as f:
|
|
43
46
|
data = load(f)
|
|
44
47
|
else:
|
|
45
48
|
data = {}
|
|
@@ -49,10 +52,10 @@ class Storage:
|
|
|
49
52
|
|
|
50
53
|
def get_cache(self, id: str) -> t.Any | None:
|
|
51
54
|
if self.disable_cache:
|
|
52
|
-
return
|
|
55
|
+
return None
|
|
53
56
|
cache_result = self.cache.get(id)
|
|
54
57
|
if not cache_result:
|
|
55
|
-
return
|
|
58
|
+
return None
|
|
56
59
|
expiry, item = cache_result
|
|
57
60
|
if expiry > time():
|
|
58
61
|
return item
|
|
@@ -146,7 +146,7 @@ class TrainDetail(t.TypedDict):
|
|
|
146
146
|
train_nr: int
|
|
147
147
|
name: str | None
|
|
148
148
|
train_full_name: str
|
|
149
|
-
run_desc: str # "09.09-15.09 - w pt - nd; 16.09-29.09, 14.10-03.11 - codziennie;
|
|
149
|
+
run_desc: str # "09.09-15.09 - w pt - nd; 16.09-29.09, 14.10-03.11 - codziennie;"
|
|
150
150
|
carrier_id: int
|
|
151
151
|
brand_id: int
|
|
152
152
|
train_name: int # wtf
|
|
@@ -70,7 +70,7 @@ NUMERAL_TO_ARABIC = {
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
def convert_platform_number(number: str | None) -> int | None | str:
|
|
73
|
-
if number and number[-1] in "abcdefghi":
|
|
73
|
+
if number and number[-1] in "abcdefghi": # just to be safe...
|
|
74
74
|
arabic = NUMERAL_TO_ARABIC.get(number[:-1])
|
|
75
75
|
return f"{arabic}{number[-1]}" if arabic else None
|
|
76
76
|
return NUMERAL_TO_ARABIC.get(number)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: koleo-cli
|
|
3
|
-
Version: 0.2.137.
|
|
3
|
+
Version: 0.2.137.17
|
|
4
4
|
Summary: Koleo CLI
|
|
5
5
|
Home-page: https://github.com/lzgirlcat/koleo-cli
|
|
6
6
|
Author: Zoey !
|
|
@@ -14,8 +14,21 @@ Classifier: Operating System :: OS Independent
|
|
|
14
14
|
Requires-Python: >=3.12
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: rich
|
|
18
|
-
Requires-Dist: requests
|
|
17
|
+
Requires-Dist: rich~=13.7
|
|
18
|
+
Requires-Dist: requests~=2.32
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: keywords
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: maintainer-email
|
|
28
|
+
Dynamic: project-url
|
|
29
|
+
Dynamic: requires-dist
|
|
30
|
+
Dynamic: requires-python
|
|
31
|
+
Dynamic: summary
|
|
19
32
|
|
|
20
33
|
# Koleo CLI
|
|
21
34
|
[](https://pypi.org/project/koleo-cli)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|