koleo-cli 0.2.137.4__py3-none-any.whl → 0.2.137.6__py3-none-any.whl
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/api.py +0 -2
- koleo/cli.py +104 -73
- koleo/storage.py +6 -2
- koleo/types.py +7 -7
- koleo/utils.py +7 -1
- koleo_cli-0.2.137.6.dist-info/METADATA +72 -0
- koleo_cli-0.2.137.6.dist-info/RECORD +12 -0
- koleo_cli-0.2.137.4.dist-info/METADATA +0 -18
- koleo_cli-0.2.137.4.dist-info/RECORD +0 -12
- {koleo_cli-0.2.137.4.dist-info → koleo_cli-0.2.137.6.dist-info}/WHEEL +0 -0
- {koleo_cli-0.2.137.4.dist-info → koleo_cli-0.2.137.6.dist-info}/entry_points.txt +0 -0
- {koleo_cli-0.2.137.4.dist-info → koleo_cli-0.2.137.6.dist-info}/top_level.txt +0 -0
koleo/api.py
CHANGED
koleo/cli.py
CHANGED
|
@@ -7,11 +7,11 @@ from rich.traceback import install
|
|
|
7
7
|
|
|
8
8
|
from .api import KoleoAPI
|
|
9
9
|
from .storage import DEFAULT_CONFIG_PATH, Storage
|
|
10
|
-
from .types import TrainDetailResponse, TrainOnStationInfo
|
|
11
|
-
from .utils import convert_platform_number, name_to_slug, parse_datetime
|
|
10
|
+
from .types import ExtendedBaseStationInfo, TrainDetailResponse, TrainOnStationInfo
|
|
11
|
+
from .utils import RemainderString, arr_dep_to_dt, convert_platform_number, name_to_slug, parse_datetime
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
install(show_locals=
|
|
14
|
+
install(show_locals=True, max_frames=2)
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class CLI:
|
|
@@ -28,7 +28,7 @@ class CLI:
|
|
|
28
28
|
|
|
29
29
|
def print(self, text, *args, **kwargs):
|
|
30
30
|
if self.no_color:
|
|
31
|
-
result = re.sub(r
|
|
31
|
+
result = re.sub(r"\[[^\]]*\]", "", text)
|
|
32
32
|
print(result)
|
|
33
33
|
else:
|
|
34
34
|
self.console.print(text, *args, **kwargs)
|
|
@@ -55,9 +55,8 @@ class CLI:
|
|
|
55
55
|
|
|
56
56
|
def get_departures(self, station_id: int, date: datetime):
|
|
57
57
|
cache_id = f"dep-{station_id}-{date.strftime("%Y-%m-%d")}"
|
|
58
|
-
trains = (
|
|
59
|
-
self.
|
|
60
|
-
self.storage.set_cache(cache_id, self.client.get_departures(station_id, date))
|
|
58
|
+
trains = self.storage.get_cache(cache_id) or self.storage.set_cache(
|
|
59
|
+
cache_id, self.client.get_departures(station_id, date)
|
|
61
60
|
)
|
|
62
61
|
trains = [
|
|
63
62
|
i
|
|
@@ -70,9 +69,8 @@ class CLI:
|
|
|
70
69
|
|
|
71
70
|
def get_arrivals(self, station_id: int, date: datetime):
|
|
72
71
|
cache_id = f"arr-{station_id}-{date.strftime("%Y-%m-%d")}"
|
|
73
|
-
trains = (
|
|
74
|
-
self.
|
|
75
|
-
self.storage.set_cache(cache_id, self.client.get_arrivals(station_id, date))
|
|
72
|
+
trains = self.storage.get_cache(cache_id) or self.storage.set_cache(
|
|
73
|
+
cache_id, self.client.get_arrivals(station_id, date)
|
|
76
74
|
)
|
|
77
75
|
trains = [
|
|
78
76
|
i
|
|
@@ -99,22 +97,23 @@ class CLI:
|
|
|
99
97
|
if query:
|
|
100
98
|
stations = self.client.find_station(query)
|
|
101
99
|
else:
|
|
102
|
-
stations = (
|
|
103
|
-
self.
|
|
104
|
-
self.storage.set_cache("stations", self.client.get_stations())
|
|
100
|
+
stations = self.storage.get_cache("stations") or self.storage.set_cache(
|
|
101
|
+
"stations", self.client.get_stations()
|
|
105
102
|
)
|
|
106
103
|
for st in stations:
|
|
107
|
-
self.print(
|
|
104
|
+
self.print(
|
|
105
|
+
f"[bold blue][link=https://koleo.pl/dworzec-pkp/{st["name_slug"]}]{st["name"]}[/bold blue] ID: {st["id"]}[/link]"
|
|
106
|
+
)
|
|
108
107
|
|
|
109
108
|
def train_info(self, brand: str, name: str, date: datetime):
|
|
110
109
|
brand = brand.upper().strip()
|
|
111
|
-
|
|
112
|
-
if
|
|
113
|
-
number = int(
|
|
110
|
+
name_parts = name.split(" ")
|
|
111
|
+
if len(name_parts) == 1 and name_parts[0].isnumeric():
|
|
112
|
+
number = int(name_parts[0])
|
|
114
113
|
train_name = ""
|
|
115
|
-
elif len(
|
|
116
|
-
number
|
|
117
|
-
|
|
114
|
+
elif len(name) > 1:
|
|
115
|
+
number = int(name_parts.pop(0))
|
|
116
|
+
train_name = " ".join(name_parts)
|
|
118
117
|
else:
|
|
119
118
|
raise ValueError("Invalid train name!")
|
|
120
119
|
brands = self.storage.get_cache("brands") or self.storage.set_cache("brands", self.client.get_brands())
|
|
@@ -124,20 +123,28 @@ class CLI:
|
|
|
124
123
|
raise ValueError("Invalid brand name!")
|
|
125
124
|
brand = res
|
|
126
125
|
cache_id = f"tc-{brand}-{number}-{name}"
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
try:
|
|
127
|
+
train_calendars = self.storage.get_cache(cache_id) or self.storage.set_cache(
|
|
128
|
+
cache_id, self.client.get_train_calendars(brand, number, train_name)
|
|
129
|
+
)
|
|
130
|
+
except self.client.errors.KoleoNotFound:
|
|
131
|
+
self.print(f'[bold red]Train not found: nr={number}, name="{train_name}"[/bold red]')
|
|
132
|
+
exit(2)
|
|
130
133
|
train_id = train_calendars["train_calendars"][0]["date_train_map"][date.strftime("%Y-%m-%d")]
|
|
131
134
|
train_details = self.client.get_train(train_id)
|
|
132
135
|
brand = next(iter(i for i in brands if i["id"] == train_details["train"]["brand_id"]), {}).get("logo_text", "")
|
|
133
136
|
parts = [f"[red]{brand}[/red] [bold blue]{train_details["train"]["train_full_name"]}[/bold blue]"]
|
|
134
137
|
route_start = arr_dep_to_dt(train_details["stops"][0]["departure"])
|
|
135
138
|
route_end = arr_dep_to_dt(train_details["stops"][-1]["arrival"])
|
|
136
|
-
if route_end.hour < route_start.hour or (
|
|
139
|
+
if route_end.hour < route_start.hour or (
|
|
140
|
+
route_end.hour == route_start.hour and route_end.minute < route_end.minute
|
|
141
|
+
):
|
|
137
142
|
route_end += timedelta(days=1)
|
|
138
143
|
travel_time = route_end - route_start
|
|
139
144
|
speed = train_details["stops"][-1]["distance"] / 1000 / travel_time.seconds * 3600
|
|
140
|
-
parts.append(
|
|
145
|
+
parts.append(
|
|
146
|
+
f"[white] {travel_time.seconds//3600}h{(travel_time.seconds % 3600)/60:.0f}m {speed:^4.1f}km/h [/white]"
|
|
147
|
+
)
|
|
141
148
|
vehicle_types: dict[str, str] = {
|
|
142
149
|
stop["station_display_name"]: stop["vehicle_type"]
|
|
143
150
|
for stop in train_details["stops"]
|
|
@@ -162,24 +169,27 @@ class CLI:
|
|
|
162
169
|
if not brands:
|
|
163
170
|
connection_brands = [i["id"] for i in api_brands]
|
|
164
171
|
else:
|
|
165
|
-
connection_brands = [
|
|
172
|
+
connection_brands = [
|
|
173
|
+
i["id"]
|
|
174
|
+
for i in api_brands
|
|
175
|
+
if i["name"].lower().strip() in brands or i["logo_text"].lower().strip() in brands
|
|
176
|
+
]
|
|
166
177
|
if not connection_brands:
|
|
167
178
|
self.print(f'[bold red]No brands match: "{', '.join(brands)}"[/bold red]')
|
|
168
179
|
exit(2)
|
|
169
180
|
connections = self.client.get_connections(
|
|
170
|
-
start_station["name_slug"],
|
|
171
|
-
end_station["name_slug"],
|
|
172
|
-
connection_brands,
|
|
173
|
-
date,
|
|
174
|
-
direct,
|
|
175
|
-
purchasable
|
|
181
|
+
start_station["name_slug"], end_station["name_slug"], connection_brands, date, direct, purchasable
|
|
176
182
|
)
|
|
177
|
-
parts = [
|
|
183
|
+
parts = [
|
|
184
|
+
f"[bold blue]{start_station["name"]} → {end_station["name"]} at {date.strftime("%H:%M %d-%m")}[/bold blue]"
|
|
185
|
+
]
|
|
178
186
|
for i in connections:
|
|
179
187
|
arr = arr_dep_to_dt(i["arrival"])
|
|
180
188
|
dep = arr_dep_to_dt(i["departure"])
|
|
181
189
|
travel_time = (arr - dep).seconds
|
|
182
|
-
parts.append(
|
|
190
|
+
parts.append(
|
|
191
|
+
f"[bold green][link=https://koleo.pl/travel-options/{i["id"]}]{dep.strftime("%H:%M")} - {arr.strftime("%H:%M")}[/bold green] {travel_time//3600}h{(travel_time % 3600)/60:.0f}m {i['distance']}km: [/link]"
|
|
192
|
+
)
|
|
183
193
|
if i["constriction_info"]:
|
|
184
194
|
for constriction in i["constriction_info"]:
|
|
185
195
|
parts.append(f" [bold red]- {constriction} [/bold red]")
|
|
@@ -187,14 +197,17 @@ class CLI:
|
|
|
187
197
|
train = i["trains"][0]
|
|
188
198
|
stop = next(iter(i for i in train["stops"] if i["station_id"] == train["start_station_id"]), {})
|
|
189
199
|
stop_station = (
|
|
190
|
-
start_station
|
|
191
|
-
|
|
192
|
-
|
|
200
|
+
start_station
|
|
201
|
+
if stop["station_id"] == start_station["id"]
|
|
202
|
+
else self.storage.get_cache(f"st-{stop['station_id']}")
|
|
203
|
+
or self.storage.set_cache(
|
|
204
|
+
f"st-{stop['station_id']}", self.client.get_station_by_id(stop["station_id"])
|
|
205
|
+
)
|
|
193
206
|
)
|
|
194
|
-
platform = convert_platform_number(stop["platform"]) if stop["platform"] else ""
|
|
195
|
-
position_info = f"{platform}/{stop["track"]}" if stop["track"] else platform
|
|
196
207
|
brand = next(iter(i for i in api_brands if i["id"] == train["brand_id"]), {}).get("logo_text")
|
|
197
|
-
parts[-1]+=
|
|
208
|
+
parts[-1] += (
|
|
209
|
+
f" [red]{brand}[/red] {train["train_full_name"]}[purple] {stop_station['name']} {self.format_position(stop["platform"], stop["track"])}[/purple]"
|
|
210
|
+
)
|
|
198
211
|
else:
|
|
199
212
|
previous_arrival: datetime | None = None
|
|
200
213
|
for train in i["trains"]:
|
|
@@ -202,29 +215,35 @@ class CLI:
|
|
|
202
215
|
|
|
203
216
|
fs = next(iter(i for i in train["stops"] if i["station_id"] == train["start_station_id"]), {})
|
|
204
217
|
fs_station = (
|
|
205
|
-
start_station
|
|
206
|
-
|
|
207
|
-
|
|
218
|
+
start_station
|
|
219
|
+
if fs["station_id"] == start_station["id"]
|
|
220
|
+
else self.storage.get_cache(f"st-{fs['station_id']}")
|
|
221
|
+
or self.storage.set_cache(
|
|
222
|
+
f"st-{fs['station_id']}", self.client.get_station_by_id(fs["station_id"])
|
|
223
|
+
)
|
|
208
224
|
)
|
|
209
|
-
|
|
210
|
-
fs_arr = arr_dep_to_dt(fs["arrival"])
|
|
225
|
+
# fs_arr = arr_dep_to_dt(fs["arrival"])
|
|
211
226
|
fs_dep = arr_dep_to_dt(fs["departure"])
|
|
212
|
-
fs_info = f"[bold green]{fs_dep.strftime("%H:%M")} [/bold green][purple]{fs_station['name']} {
|
|
227
|
+
fs_info = f"[bold green]{fs_dep.strftime("%H:%M")} [/bold green][purple]{fs_station['name']} {self.format_position(fs["platform"], fs["track"])}[/purple]"
|
|
213
228
|
|
|
214
229
|
ls = next(iter(i for i in train["stops"] if i["station_id"] == train["end_station_id"]), {})
|
|
215
230
|
ls_station = (
|
|
216
|
-
start_station
|
|
217
|
-
|
|
218
|
-
|
|
231
|
+
start_station
|
|
232
|
+
if ls["station_id"] == start_station["id"]
|
|
233
|
+
else self.storage.get_cache(f"st-{ls['station_id']}")
|
|
234
|
+
or self.storage.set_cache(
|
|
235
|
+
f"st-{ls['station_id']}", self.client.get_station_by_id(ls["station_id"])
|
|
236
|
+
)
|
|
219
237
|
)
|
|
220
|
-
ls_platform = convert_platform_number(ls["platform"]) if ls["platform"] else ""
|
|
221
238
|
ls_arr = arr_dep_to_dt(ls["arrival"])
|
|
222
|
-
ls_dep = arr_dep_to_dt(ls["departure"])
|
|
223
|
-
ls_info = f"[bold green]{ls_arr.strftime("%H:%M")} [/bold green][purple]{ls_station['name']} {
|
|
239
|
+
# ls_dep = arr_dep_to_dt(ls["departure"])
|
|
240
|
+
ls_info = f"[bold green]{ls_arr.strftime("%H:%M")} [/bold green][purple]{ls_station['name']} {self.format_position(ls["platform"], ls["track"])}[/purple]"
|
|
224
241
|
connection_time = (fs_dep - previous_arrival).seconds if previous_arrival else ""
|
|
225
242
|
previous_arrival = ls_arr
|
|
226
243
|
if connection_time:
|
|
227
|
-
parts.append(
|
|
244
|
+
parts.append(
|
|
245
|
+
f" {connection_time//3600}h{(connection_time % 3600)/60:.0f}m at [purple]{fs_station['name']}[/purple]"
|
|
246
|
+
)
|
|
228
247
|
parts.append(f" [red]{brand}[/red] {train["train_full_name"]} {fs_info} - {ls_info}")
|
|
229
248
|
self.print("\n".join(parts))
|
|
230
249
|
|
|
@@ -235,10 +254,8 @@ class CLI:
|
|
|
235
254
|
time = train["departure"] if type == 1 else train["arrival"]
|
|
236
255
|
assert time
|
|
237
256
|
brand = next(iter(i for i in brands if i["id"] == train["brand_id"]), {}).get("logo_text")
|
|
238
|
-
platform = convert_platform_number(train["platform"]) if train["platform"] else ""
|
|
239
|
-
position_info = f"{platform}/{train["track"]}" if train["track"] else platform
|
|
240
257
|
parts.append(
|
|
241
|
-
f"[bold green]{time[11:16]}[/bold green] [red]{brand}[/red] {train["train_full_name"]}[purple] {train["stations"][0]["name"]} {
|
|
258
|
+
f"[bold green]{time[11:16]}[/bold green] [red]{brand}[/red] {train["train_full_name"]}[purple] {train["stations"][0]["name"]} {self.format_position(train["platform"], train["track"])}[/purple]"
|
|
242
259
|
)
|
|
243
260
|
return "\n".join(parts)
|
|
244
261
|
|
|
@@ -247,12 +264,17 @@ class CLI:
|
|
|
247
264
|
for stop in train["stops"]:
|
|
248
265
|
arr = arr_dep_to_dt(stop["arrival"])
|
|
249
266
|
dep = arr_dep_to_dt(stop["departure"])
|
|
250
|
-
platform = convert_platform_number(stop["platform"]) or ""
|
|
251
267
|
parts.append(
|
|
252
|
-
f"[white underline]{stop["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"]} {platform} [/purple]"
|
|
268
|
+
f"[white underline]{stop["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]"
|
|
253
269
|
)
|
|
254
270
|
return "\n".join(parts)
|
|
255
271
|
|
|
272
|
+
def format_position(self, platform: str, track: str | None = None):
|
|
273
|
+
res = str(convert_platform_number(platform)) or "" if not self.storage.use_roman_numerals else platform
|
|
274
|
+
if track is not None and track != "":
|
|
275
|
+
res += f"/{track}"
|
|
276
|
+
return res
|
|
277
|
+
|
|
256
278
|
def get_station(self, station: str) -> ExtendedBaseStationInfo:
|
|
257
279
|
slug = name_to_slug(station)
|
|
258
280
|
try:
|
|
@@ -263,20 +285,24 @@ class CLI:
|
|
|
263
285
|
self.print(f'[bold red]Station not found: "{station}"[/bold red]')
|
|
264
286
|
exit(2)
|
|
265
287
|
|
|
288
|
+
|
|
266
289
|
def main():
|
|
267
290
|
cli = CLI()
|
|
268
291
|
|
|
269
292
|
parser = ArgumentParser("koleo", description="Koleo CLI")
|
|
270
293
|
parser.add_argument("-c", "--config", help="Custom config path.", default=DEFAULT_CONFIG_PATH)
|
|
271
|
-
parser.add_argument("--nocolor", help="Disable color output", action="store_true", default=False)
|
|
272
|
-
subparsers = parser.add_subparsers(title="actions", required=False)
|
|
294
|
+
parser.add_argument("--nocolor", help="Disable color output and formatting", action="store_true", default=False)
|
|
295
|
+
subparsers = parser.add_subparsers(title="actions", required=False) # type: ignore
|
|
273
296
|
|
|
274
|
-
departures = subparsers.add_parser(
|
|
297
|
+
departures = subparsers.add_parser(
|
|
298
|
+
"departures", aliases=["d", "dep", "odjazdy", "o"], help="Allows you to list station departures"
|
|
299
|
+
)
|
|
275
300
|
departures.add_argument(
|
|
276
301
|
"station",
|
|
277
302
|
help="The station name",
|
|
278
303
|
default=None,
|
|
279
|
-
nargs="
|
|
304
|
+
nargs="*",
|
|
305
|
+
action=RemainderString,
|
|
280
306
|
)
|
|
281
307
|
departures.add_argument(
|
|
282
308
|
"-d",
|
|
@@ -288,12 +314,15 @@ def main():
|
|
|
288
314
|
departures.add_argument("-s", "--save", help="save the station as your default one", action="store_true")
|
|
289
315
|
departures.set_defaults(func=cli.full_departures, pass_=["station", "date"])
|
|
290
316
|
|
|
291
|
-
arrivals = subparsers.add_parser(
|
|
317
|
+
arrivals = subparsers.add_parser(
|
|
318
|
+
"arrivals", aliases=["a", "arr", "przyjazdy", "p"], help="Allows you to list station departures"
|
|
319
|
+
)
|
|
292
320
|
arrivals.add_argument(
|
|
293
321
|
"station",
|
|
294
322
|
help="The station name",
|
|
295
323
|
default=None,
|
|
296
|
-
nargs="
|
|
324
|
+
nargs="*",
|
|
325
|
+
action=RemainderString,
|
|
297
326
|
)
|
|
298
327
|
arrivals.add_argument(
|
|
299
328
|
"-d",
|
|
@@ -311,7 +340,7 @@ def main():
|
|
|
311
340
|
help="Allows you to show the train's route",
|
|
312
341
|
)
|
|
313
342
|
train_route.add_argument("brand", help="The brand name", type=str)
|
|
314
|
-
train_route.add_argument("name", help="The train name",
|
|
343
|
+
train_route.add_argument("name", help="The train name", nargs="+", action=RemainderString)
|
|
315
344
|
train_route.add_argument(
|
|
316
345
|
"-d",
|
|
317
346
|
"--date",
|
|
@@ -321,12 +350,15 @@ def main():
|
|
|
321
350
|
)
|
|
322
351
|
train_route.set_defaults(func=cli.train_info, pass_=["brand", "name", "date"])
|
|
323
352
|
|
|
324
|
-
stations = subparsers.add_parser(
|
|
353
|
+
stations = subparsers.add_parser(
|
|
354
|
+
"stations", aliases=["s", "find", "f", "stacje", "ls", "q"], help="Allows you to find stations by their name"
|
|
355
|
+
)
|
|
325
356
|
stations.add_argument(
|
|
326
357
|
"query",
|
|
327
358
|
help="The station name",
|
|
328
359
|
default=None,
|
|
329
|
-
nargs="
|
|
360
|
+
nargs="*",
|
|
361
|
+
action=RemainderString,
|
|
330
362
|
)
|
|
331
363
|
stations.set_defaults(func=cli.find_station, pass_=["query"])
|
|
332
364
|
|
|
@@ -345,22 +377,21 @@ def main():
|
|
|
345
377
|
default=datetime.now(),
|
|
346
378
|
)
|
|
347
379
|
connections.add_argument(
|
|
348
|
-
"-b",
|
|
349
|
-
"--brands",
|
|
350
|
-
help="Brands to include",
|
|
351
|
-
action="extend", nargs="+", type=str, default=[]
|
|
380
|
+
"-b", "--brands", help="Brands to include", action="extend", nargs="+", type=str, default=[]
|
|
352
381
|
)
|
|
353
382
|
connections.add_argument(
|
|
354
383
|
"-f",
|
|
355
384
|
"--direct",
|
|
356
385
|
help="whether or not the result should only include direct trains",
|
|
357
|
-
action="store_true",
|
|
386
|
+
action="store_true",
|
|
387
|
+
default=False,
|
|
358
388
|
)
|
|
359
389
|
connections.add_argument(
|
|
360
390
|
"-p",
|
|
361
391
|
"--purchasable",
|
|
362
392
|
help="whether or not the result should only trains purchasable on koleo",
|
|
363
|
-
action="store_true",
|
|
393
|
+
action="store_true",
|
|
394
|
+
default=False,
|
|
364
395
|
)
|
|
365
396
|
connections.set_defaults(func=cli.connections, pass_=["start", "end", "brands", "date", "direct", "purchasable"])
|
|
366
397
|
|
koleo/storage.py
CHANGED
|
@@ -27,9 +27,9 @@ T = t.TypeVar("T")
|
|
|
27
27
|
@dataclass
|
|
28
28
|
class Storage:
|
|
29
29
|
favourite_station: str | None = None
|
|
30
|
-
last_searched_connections: list[tuple[str, str]] = field(default_factory=list)
|
|
31
|
-
last_searched_stations: list[str] = field(default_factory=list)
|
|
32
30
|
cache: dict[str, tuple[int, t.Any]] = field(default_factory=dict)
|
|
31
|
+
disable_cache: bool = False
|
|
32
|
+
use_roman_numerals: bool = False
|
|
33
33
|
|
|
34
34
|
def __post_init__(self):
|
|
35
35
|
self._path: str
|
|
@@ -47,6 +47,8 @@ class Storage:
|
|
|
47
47
|
return storage
|
|
48
48
|
|
|
49
49
|
def get_cache(self, id: str) -> t.Any | None:
|
|
50
|
+
if self.disable_cache:
|
|
51
|
+
return
|
|
50
52
|
cache_result = self.cache.get(id)
|
|
51
53
|
if not cache_result:
|
|
52
54
|
return
|
|
@@ -58,6 +60,8 @@ class Storage:
|
|
|
58
60
|
self.save()
|
|
59
61
|
|
|
60
62
|
def set_cache(self, id: str, item: T, ttl: int = 86400) -> T:
|
|
63
|
+
if self.disable_cache:
|
|
64
|
+
return item
|
|
61
65
|
self.cache[id] = (int(time() + ttl), item)
|
|
62
66
|
self.save()
|
|
63
67
|
return item
|
koleo/types.py
CHANGED
|
@@ -179,8 +179,8 @@ class TrainDetailResponse(t.TypedDict):
|
|
|
179
179
|
|
|
180
180
|
|
|
181
181
|
class ConnectionTrainStop(t.TypedDict):
|
|
182
|
-
arrival: TimeDict | str
|
|
183
|
-
departure: TimeDict | str
|
|
182
|
+
arrival: TimeDict | str # WTF KOLEO!!!!
|
|
183
|
+
departure: TimeDict | str # WTF KOLEO!!!!
|
|
184
184
|
distance: int
|
|
185
185
|
in_path: bool
|
|
186
186
|
station_id: int
|
|
@@ -196,8 +196,8 @@ class ConnectionTrainStop(t.TypedDict):
|
|
|
196
196
|
|
|
197
197
|
|
|
198
198
|
class ConnectiontrainDetail(TrainDetail):
|
|
199
|
-
arrival: TimeDict | str
|
|
200
|
-
departure: TimeDict | str
|
|
199
|
+
arrival: TimeDict | str # WTF KOLEO!!!!
|
|
200
|
+
departure: TimeDict | str # WTF KOLEO!!!!
|
|
201
201
|
stops: list[ConnectionTrainStop]
|
|
202
202
|
bookable: bool
|
|
203
203
|
train_attribute_ids: list[int]
|
|
@@ -225,8 +225,8 @@ class ConnectionDetail(t.TypedDict):
|
|
|
225
225
|
brand_ids: list[int]
|
|
226
226
|
start_station_id: int
|
|
227
227
|
end_station_id: int
|
|
228
|
-
arrival: TimeDict | str
|
|
229
|
-
departure: TimeDict | str
|
|
228
|
+
arrival: TimeDict | str # WTF KOLEO!!!!
|
|
229
|
+
departure: TimeDict | str # WTF KOLEO!!!!
|
|
230
230
|
bookable: bool
|
|
231
231
|
special_event_slug: str | None
|
|
232
232
|
is_advanced_travel_options: bool
|
|
@@ -234,4 +234,4 @@ class ConnectionDetail(t.TypedDict):
|
|
|
234
234
|
max_passengers_count: bool
|
|
235
235
|
constriction_info: list[str]
|
|
236
236
|
is_estimated_timetable_available: bool
|
|
237
|
-
trains: list[ConnectiontrainDetail]
|
|
237
|
+
trains: list[ConnectiontrainDetail]
|
koleo/utils.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from argparse import Action
|
|
1
2
|
from datetime import datetime, time, timedelta
|
|
2
3
|
|
|
3
4
|
from .types import TimeDict
|
|
@@ -64,9 +65,14 @@ NUMERAL_TO_ARABIC = {
|
|
|
64
65
|
"X": 10,
|
|
65
66
|
"XI": 11, # wtf poznań???
|
|
66
67
|
"XII": 12, # just to be safe
|
|
67
|
-
"BUS": "BUS"
|
|
68
|
+
"BUS": "BUS",
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
|
|
71
72
|
def convert_platform_number(number: str) -> int | None | str:
|
|
72
73
|
return NUMERAL_TO_ARABIC.get(number)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class RemainderString(Action):
|
|
77
|
+
def __call__(self, _, namespace, values: list[str], __):
|
|
78
|
+
setattr(namespace, self.dest, " ".join(values) if values else self.default)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: koleo-cli
|
|
3
|
+
Version: 0.2.137.6
|
|
4
|
+
Summary: Koleo CLI
|
|
5
|
+
Home-page: https://github.com/lzgirlcat/koleo-cli
|
|
6
|
+
Author: Zoey !
|
|
7
|
+
Maintainer-email: cb98uzhd@duck.com
|
|
8
|
+
License: GNU General Public License v3.0
|
|
9
|
+
Project-URL: Source (GitHub), https://github.com/lzgirlcat/koleo-cli
|
|
10
|
+
Project-URL: Issue Tracker, https://github.com/lzgirlcat/koleo-cli/issues
|
|
11
|
+
Keywords: koleo,timetable,trains,rail,poland
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: rich==13.7.1
|
|
17
|
+
Requires-Dist: requests==2.31.0
|
|
18
|
+
|
|
19
|
+
[](https://pypi.org/project/koleo-cli)
|
|
20
|
+
[](https://pypi.org/project/koleo-cli)
|
|
21
|
+
|
|
22
|
+
# Koleo CLI
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
install via pip by running
|
|
28
|
+
|
|
29
|
+
`pip install koleo-cli`
|
|
30
|
+
|
|
31
|
+
## it currently allows you to:
|
|
32
|
+
- get departures/arrival list for a station
|
|
33
|
+
- get train info given its number and name(pull requests are welcome if you know how to get a train object by just the number)
|
|
34
|
+
- find a station or list all known stations
|
|
35
|
+
- find a connection from station a to b, with filtering by operators
|
|
36
|
+
- save a station as your favourite to quickly check it's departures
|
|
37
|
+
|
|
38
|
+
additionally you can also use the KoleoAPI wrapper directly in your own projects, all returns are fully typed using `typing.TypedDict`
|
|
39
|
+
|
|
40
|
+
## MY(possibly controversial) design choices:
|
|
41
|
+
- platforms and track numbers are shown using arabic numerals instead of roman
|
|
42
|
+
- you can change it by adding `use_roman_numerals: true` to your config.json file
|
|
43
|
+
- most api queries are cached for 24h
|
|
44
|
+
- you can change it by adding `disable_cache: true` to your config.json file
|
|
45
|
+
- the cli.py code is really dirty but printing formatted data is hard :<
|
|
46
|
+
|
|
47
|
+
pull requests are welcome!!
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
usage: koleo [-h] [-c CONFIG] [--nocolor] {departures,d,dep,odjazdy,o,arrivals,a,arr,przyjazdy,p,trainroute,r,tr,t,poc,pociąg,stations,s,find,f,stacje,ls,connections,do,z,szukaj,path} ...
|
|
51
|
+
|
|
52
|
+
Koleo CLI
|
|
53
|
+
|
|
54
|
+
options:
|
|
55
|
+
-h, --help show this help message and exit
|
|
56
|
+
-c CONFIG, --config CONFIG
|
|
57
|
+
Custom config path.
|
|
58
|
+
--nocolor Disable color output and formatting
|
|
59
|
+
|
|
60
|
+
actions:
|
|
61
|
+
{departures,d,dep,odjazdy,o,arrivals,a,arr,przyjazdy,p,trainroute,r,tr,t,poc,pociąg,stations,s,find,f,stacje,ls,connections,do,z,szukaj,path}
|
|
62
|
+
departures (d, dep, odjazdy, o)
|
|
63
|
+
Allows you to list station departures
|
|
64
|
+
arrivals (a, arr, przyjazdy, p)
|
|
65
|
+
Allows you to list station departures
|
|
66
|
+
trainroute (r, tr, t, poc, pociąg)
|
|
67
|
+
Allows you to show the train's route
|
|
68
|
+
stations (s, find, f, stacje, ls)
|
|
69
|
+
Allows you to find stations by their name
|
|
70
|
+
connections (do, z, szukaj, path)
|
|
71
|
+
Allows you to search for connections from a to b
|
|
72
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
koleo/__init__.py,sha256=N_IkOBZCSPCCw31Hu72CFys707PziGFmXpNVl0CXAz8,47
|
|
2
|
+
koleo/__main__.py,sha256=wu5N2wk8mvBgyvr2ghmQf4prezAe0_i-p123VVreyYc,62
|
|
3
|
+
koleo/api.py,sha256=07PSwLFmirdJ_JhPBJ7rO1nv_v90njIcwmOoxT4P_4M,5708
|
|
4
|
+
koleo/cli.py,sha256=n8g4ebPfAKDEjv78bBcvQSwQS8m4_OMlc3iKNXxgHL8,18618
|
|
5
|
+
koleo/storage.py,sha256=_VztM8d3YTnmZOR9JvOsobThrQhb4gEzT1azC8N7baY,2024
|
|
6
|
+
koleo/types.py,sha256=pjVCIH39rUNeipazeRKOuTRCWoslLdbGivKiQmfd5Pw,5226
|
|
7
|
+
koleo/utils.py,sha256=CsYWNf3IPhHJln445tzXSA7r2z3NpmqVSmw8Rrb7YT0,1822
|
|
8
|
+
koleo_cli-0.2.137.6.dist-info/METADATA,sha256=F3nw8KGs1gyKBALLor-jJrNfxEkUCyl_EgVA3KI42VM,3055
|
|
9
|
+
koleo_cli-0.2.137.6.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
10
|
+
koleo_cli-0.2.137.6.dist-info/entry_points.txt,sha256=LtCidkVDq8Zd7-fxpRbys1Xa9LTHMZwXVbdcQEscdes,41
|
|
11
|
+
koleo_cli-0.2.137.6.dist-info/top_level.txt,sha256=AlWdXotkRYzHpFfOBYi6xOXl1H0zq4-tqtZ2XivoWB4,6
|
|
12
|
+
koleo_cli-0.2.137.6.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: koleo-cli
|
|
3
|
-
Version: 0.2.137.4
|
|
4
|
-
Summary: Koleo CLI
|
|
5
|
-
Home-page: https://github.com/lzgirlcat/koleo-cli
|
|
6
|
-
Author: Zoey !
|
|
7
|
-
Maintainer-email: cb98uzhd@duck.com
|
|
8
|
-
License: GNU General Public License v3.0
|
|
9
|
-
Project-URL: Source (GitHub), https://github.com/lzgirlcat/koleo-cli
|
|
10
|
-
Project-URL: Issue Tracker, https://github.com/lzgirlcat/koleo-cli/issues
|
|
11
|
-
Keywords: koleo,timetable,trains,rail,poland
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
14
|
-
Requires-Python: >=3.12
|
|
15
|
-
Description-Content-Type: text/markdown
|
|
16
|
-
Requires-Dist: rich==13.7.1
|
|
17
|
-
Requires-Dist: requests==2.31.0
|
|
18
|
-
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
koleo/__init__.py,sha256=N_IkOBZCSPCCw31Hu72CFys707PziGFmXpNVl0CXAz8,47
|
|
2
|
-
koleo/__main__.py,sha256=wu5N2wk8mvBgyvr2ghmQf4prezAe0_i-p123VVreyYc,62
|
|
3
|
-
koleo/api.py,sha256=3pVcAMnCzaDIgakxagmKOZpph8JU5p6agXKGw550rkw,5710
|
|
4
|
-
koleo/cli.py,sha256=o_6tUy8odM-CqSqpEJMJFTGx1QJnPwu-kIXzrjH5VpI,18098
|
|
5
|
-
koleo/storage.py,sha256=l48A8zsP3t77nFZA23dDncoeyV_VlhJ1RvM3xjWug2Q,2001
|
|
6
|
-
koleo/types.py,sha256=PQDDaTF9Q6ZylcOupWrOWg0qWMqRrNhMOE5m_bl8fVo,5219
|
|
7
|
-
koleo/utils.py,sha256=ejJpHnFYDPbxa3Wd_q92cTkwbkXhGvwFGKoGITBSrdY,1615
|
|
8
|
-
koleo_cli-0.2.137.4.dist-info/METADATA,sha256=rBTsWkw7oG5GU5kjGtZktysGFC9smmvohueArb-YE8w,626
|
|
9
|
-
koleo_cli-0.2.137.4.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
10
|
-
koleo_cli-0.2.137.4.dist-info/entry_points.txt,sha256=LtCidkVDq8Zd7-fxpRbys1Xa9LTHMZwXVbdcQEscdes,41
|
|
11
|
-
koleo_cli-0.2.137.4.dist-info/top_level.txt,sha256=AlWdXotkRYzHpFfOBYi6xOXl1H0zq4-tqtZ2XivoWB4,6
|
|
12
|
-
koleo_cli-0.2.137.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|