polarsteps-data-parser 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,74 +1,74 @@
1
- import time
2
- from pathlib import Path
3
-
4
- import click
5
- from dotenv import load_dotenv
6
-
7
- from polarsteps_data_parser.retrieve_step_comments import StepCommentsEnricher
8
- from polarsteps_data_parser.model import Trip, Location
9
- from polarsteps_data_parser.pdf_generator import PDFGenerator
10
- from polarsteps_data_parser.utils import load_json_from_file
11
-
12
-
13
- @click.command()
14
- @click.argument(
15
- "input-folder",
16
- type=click.Path(exists=True, dir_okay=True, file_okay=False, readable=True),
17
- )
18
- @click.option(
19
- "--output",
20
- default="Trip report.pdf",
21
- show_default=True,
22
- help="Output PDF file name",
23
- )
24
- @click.option(
25
- "--enrich-with-comments",
26
- is_flag=True,
27
- show_default=True,
28
- default=False,
29
- help="Whether to enrich the trip with comments or not.",
30
- )
31
- def cli(input_folder: str, output: str, enrich_with_comments: str) -> None:
32
- """Parse the data from a Polarsteps trip export.
33
-
34
- INPUT_FOLDER should contain the Polarsteps data export of one (!) trip. Make sure the folder contains
35
- a `trip.json` and `locations.json`.
36
- """
37
- load_dotenv()
38
-
39
- input_folder = Path(input_folder)
40
- trip_data_path = input_folder / "trip.json"
41
- location_data_path = input_folder / "locations.json"
42
-
43
- if not trip_data_path.exists() or not location_data_path.exists():
44
- log("Error: Cannot find Polarsteps trip in folder!")
45
- log("Please make sure the input folder contains a `trip.json` and a `locations.json` file. ")
46
- return
47
-
48
- log("✅ Found Polarsteps trip", color="green", bold=True)
49
- trip_data = load_json_from_file(trip_data_path)
50
- location_data = load_json_from_file(location_data_path)
51
-
52
- log("🔄 Starting to parse trip...", color="cyan")
53
- trip = Trip.from_json(trip_data)
54
-
55
- if enrich_with_comments is True:
56
- StepCommentsEnricher(input_folder).enrich(trip)
57
-
58
- [Location.from_json(data) for data in location_data["locations"]] # TODO! use location data
59
-
60
- log("🔄 Generating PDF...", color="cyan")
61
- pdf_generator = PDFGenerator(output)
62
- pdf_generator.generate_pdf(trip)
63
- log(f"✅ Generated report: {click.format_filename(output)}", color="green", bold=True)
64
-
65
-
66
- def log(message: str, color: str = "white", bold: bool = False) -> None:
67
- """Helper function to format messages."""
68
- click.echo(click.style(f"[{time.strftime('%H:%M:%S')}] {message}", fg=color, bold=bold))
69
-
70
-
71
- if __name__ == "__main__":
72
- load_dotenv()
73
-
74
- cli()
1
+ import time
2
+ from pathlib import Path
3
+
4
+ import click
5
+ from dotenv import load_dotenv
6
+
7
+ from polarsteps_data_parser.retrieve_step_comments import StepCommentsEnricher
8
+ from polarsteps_data_parser.model import Trip, Location
9
+ from polarsteps_data_parser.pdf_generator import PDFGenerator
10
+ from polarsteps_data_parser.utils import load_json_from_file
11
+
12
+
13
+ @click.command()
14
+ @click.argument(
15
+ "input-folder",
16
+ type=click.Path(exists=True, dir_okay=True, file_okay=False, readable=True),
17
+ )
18
+ @click.option(
19
+ "--output",
20
+ default="Trip report.pdf",
21
+ show_default=True,
22
+ help="Output PDF file name",
23
+ )
24
+ @click.option(
25
+ "--enrich-with-comments",
26
+ is_flag=True,
27
+ show_default=True,
28
+ default=False,
29
+ help="Whether to enrich the trip with comments or not.",
30
+ )
31
+ def cli(input_folder: str, output: str, enrich_with_comments: str) -> None:
32
+ """Parse the data from a Polarsteps trip export.
33
+
34
+ INPUT_FOLDER should contain the Polarsteps data export of one (!) trip. Make sure the folder contains
35
+ a `trip.json` and `locations.json`.
36
+ """
37
+ load_dotenv()
38
+
39
+ input_folder = Path(input_folder)
40
+ trip_data_path = input_folder / "trip.json"
41
+ location_data_path = input_folder / "locations.json"
42
+
43
+ if not trip_data_path.exists() or not location_data_path.exists():
44
+ log("Error: Cannot find Polarsteps trip in folder!")
45
+ log("Please make sure the input folder contains a `trip.json` and a `locations.json` file. ")
46
+ return
47
+
48
+ log("✅ Found Polarsteps trip", color="green", bold=True)
49
+ trip_data = load_json_from_file(trip_data_path)
50
+ location_data = load_json_from_file(location_data_path)
51
+
52
+ log("🔄 Starting to parse trip...", color="cyan")
53
+ trip = Trip.from_json(trip_data)
54
+
55
+ if enrich_with_comments is True:
56
+ StepCommentsEnricher(input_folder).enrich(trip)
57
+
58
+ [Location.from_json(data) for data in location_data["locations"]] # TODO! use location data
59
+
60
+ log("🔄 Generating PDF...", color="cyan")
61
+ pdf_generator = PDFGenerator(output)
62
+ pdf_generator.generate_pdf(trip)
63
+ log(f"✅ Generated report: {click.format_filename(output)}", color="green", bold=True)
64
+
65
+
66
+ def log(message: str, color: str = "white", bold: bool = False) -> None:
67
+ """Helper function to format messages."""
68
+ click.echo(click.style(f"[{time.strftime('%H:%M:%S')}] {message}", fg=color, bold=bold))
69
+
70
+
71
+ if __name__ == "__main__":
72
+ load_dotenv()
73
+
74
+ cli()
@@ -1,147 +1,147 @@
1
- from dataclasses import dataclass
2
- from datetime import datetime, date
3
- from pathlib import Path
4
- from typing import Self
5
-
6
- from polarsteps_data_parser.utils import parse_date, find_folder_by_id, list_files_in_folder
7
-
8
-
9
- @dataclass
10
- class Location:
11
- """Location as tracked by the travel tracker."""
12
-
13
- lat: float
14
- lon: float
15
- time: datetime
16
-
17
- @classmethod
18
- def from_json(cls, data: dict) -> Self:
19
- """Parse object from JSON data."""
20
- return Location(lat=data["lat"], lon=data["lon"], time=parse_date(data["time"]))
21
-
22
-
23
- @dataclass
24
- class StepLocation:
25
- """Location as provided by a step."""
26
-
27
- lat: float
28
- lon: float
29
- name: str
30
- country: str
31
-
32
- @classmethod
33
- def from_json(cls, data: dict) -> Self:
34
- """Parse object from JSON data."""
35
- return StepLocation(
36
- lat=data["lat"],
37
- lon=data["lon"],
38
- name=data["name"],
39
- country=data["detail"],
40
- )
41
-
42
-
43
- @dataclass
44
- class Follower:
45
- """Follower (can leave comments)."""
46
-
47
- user_id: str
48
- username: str
49
- first_name: str
50
- last_name: str
51
-
52
- @classmethod
53
- def from_json(cls, data: dict) -> Self:
54
- """Parse object from JSON data."""
55
- return Follower(
56
- user_id=data["id"],
57
- username=data["username"],
58
- first_name=data["first_name"],
59
- last_name=data["last_name"],
60
- )
61
-
62
- @property
63
- def name(self) -> str:
64
- """Name of the follower."""
65
- return f"{self.first_name} {self.last_name}"
66
-
67
-
68
- @dataclass
69
- class StepComment:
70
- """Comment connected to a step."""
71
-
72
- comment_id: str
73
- text: str
74
- date: datetime
75
- follower: Follower
76
-
77
- @classmethod
78
- def from_json(cls, data: dict) -> Self:
79
- """Parse object from JSON data."""
80
- return StepComment(
81
- comment_id=data["id"],
82
- text=data["text"],
83
- date=parse_date(data["creation_time"]),
84
- follower=Follower.from_json(data["user"]),
85
- )
86
-
87
-
88
- @dataclass
89
- class Step:
90
- """Polarsteps Step object."""
91
-
92
- step_id: str
93
- name: str
94
- description: str
95
- location: StepLocation
96
- date: date
97
- photos: list[Path]
98
- videos: list[Path]
99
- comments: list[StepComment]
100
-
101
- @classmethod
102
- def from_json(cls, data: dict) -> Self:
103
- """Parse object from JSON data."""
104
- s = Step(
105
- step_id=data["id"],
106
- name=data["name"] or data["display_name"],
107
- description=data["description"],
108
- location=StepLocation.from_json(data["location"]),
109
- date=parse_date(data["start_time"]),
110
- photos=[],
111
- videos=[],
112
- comments=[],
113
- )
114
- s.load_media()
115
- return s
116
-
117
- def load_media(self) -> None:
118
- """Load photos and videos for the step."""
119
- step_dir = find_folder_by_id(self.step_id)
120
- if step_dir is None:
121
- self.photos = []
122
- self.videos = []
123
- else:
124
- self.photos = list_files_in_folder(step_dir / "photos", dir_has_to_exist=False)
125
- self.videos = list_files_in_folder(step_dir / "videos", dir_has_to_exist=False)
126
-
127
-
128
- @dataclass
129
- class Trip:
130
- """Polarsteps trip object."""
131
-
132
- name: str
133
- start_date: datetime
134
- end_date: datetime
135
- cover_photo_path: str
136
- steps: list[Step]
137
-
138
- @classmethod
139
- def from_json(cls, data: dict) -> Self:
140
- """Parse object from JSON data."""
141
- return Trip(
142
- name=data["name"],
143
- start_date=parse_date(data.get("start_date")),
144
- end_date=parse_date(data.get("end_date")),
145
- cover_photo_path=data["cover_photo_path"],
146
- steps=[Step.from_json(step) for step in data.get("all_steps")],
147
- )
1
+ from dataclasses import dataclass
2
+ from datetime import datetime, date
3
+ from pathlib import Path
4
+ from typing import Self
5
+
6
+ from polarsteps_data_parser.utils import parse_date, find_folder_by_id, list_files_in_folder
7
+
8
+
9
+ @dataclass
10
+ class Location:
11
+ """Location as tracked by the travel tracker."""
12
+
13
+ lat: float
14
+ lon: float
15
+ time: datetime
16
+
17
+ @classmethod
18
+ def from_json(cls, data: dict) -> Self:
19
+ """Parse object from JSON data."""
20
+ return Location(lat=data["lat"], lon=data["lon"], time=parse_date(data["time"]))
21
+
22
+
23
+ @dataclass
24
+ class StepLocation:
25
+ """Location as provided by a step."""
26
+
27
+ lat: float
28
+ lon: float
29
+ name: str
30
+ country: str
31
+
32
+ @classmethod
33
+ def from_json(cls, data: dict) -> Self:
34
+ """Parse object from JSON data."""
35
+ return StepLocation(
36
+ lat=data["lat"],
37
+ lon=data["lon"],
38
+ name=data["name"],
39
+ country=data["detail"],
40
+ )
41
+
42
+
43
+ @dataclass
44
+ class Follower:
45
+ """Follower (can leave comments)."""
46
+
47
+ user_id: str
48
+ username: str
49
+ first_name: str
50
+ last_name: str
51
+
52
+ @classmethod
53
+ def from_json(cls, data: dict) -> Self:
54
+ """Parse object from JSON data."""
55
+ return Follower(
56
+ user_id=data["id"],
57
+ username=data["username"],
58
+ first_name=data["first_name"],
59
+ last_name=data["last_name"],
60
+ )
61
+
62
+ @property
63
+ def name(self) -> str:
64
+ """Name of the follower."""
65
+ return f"{self.first_name} {self.last_name}"
66
+
67
+
68
+ @dataclass
69
+ class StepComment:
70
+ """Comment connected to a step."""
71
+
72
+ comment_id: str
73
+ text: str
74
+ date: datetime
75
+ follower: Follower
76
+
77
+ @classmethod
78
+ def from_json(cls, data: dict) -> Self:
79
+ """Parse object from JSON data."""
80
+ return StepComment(
81
+ comment_id=data["id"],
82
+ text=data["text"],
83
+ date=parse_date(data["creation_time"]),
84
+ follower=Follower.from_json(data["user"]),
85
+ )
86
+
87
+
88
+ @dataclass
89
+ class Step:
90
+ """Polarsteps Step object."""
91
+
92
+ step_id: str
93
+ name: str
94
+ description: str
95
+ location: StepLocation
96
+ date: date
97
+ photos: list[Path]
98
+ videos: list[Path]
99
+ comments: list[StepComment]
100
+
101
+ @classmethod
102
+ def from_json(cls, data: dict) -> Self:
103
+ """Parse object from JSON data."""
104
+ s = Step(
105
+ step_id=data["id"],
106
+ name=data["name"] or data["display_name"],
107
+ description=data["description"],
108
+ location=StepLocation.from_json(data["location"]),
109
+ date=parse_date(data["start_time"]),
110
+ photos=[],
111
+ videos=[],
112
+ comments=[],
113
+ )
114
+ s.load_media()
115
+ return s
116
+
117
+ def load_media(self) -> None:
118
+ """Load photos and videos for the step."""
119
+ step_dir = find_folder_by_id(self.step_id)
120
+ if step_dir is None:
121
+ self.photos = []
122
+ self.videos = []
123
+ else:
124
+ self.photos = list_files_in_folder(step_dir / "photos", dir_has_to_exist=False)
125
+ self.videos = list_files_in_folder(step_dir / "videos", dir_has_to_exist=False)
126
+
127
+
128
+ @dataclass
129
+ class Trip:
130
+ """Polarsteps trip object."""
131
+
132
+ name: str
133
+ start_date: datetime
134
+ end_date: datetime
135
+ cover_photo_path: str
136
+ steps: list[Step]
137
+
138
+ @classmethod
139
+ def from_json(cls, data: dict) -> Self:
140
+ """Parse object from JSON data."""
141
+ return Trip(
142
+ name=data["name"],
143
+ start_date=parse_date(data.get("start_date")),
144
+ end_date=parse_date(data.get("end_date")),
145
+ cover_photo_path=data["cover_photo_path"],
146
+ steps=[Step.from_json(step) for step in data.get("all_steps")],
147
+ )