oleksiisaiun_lab6_monaco 3.1__py3-none-any.whl → 5.1__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.
- oleksiisaiun_lab6_monaco/race_report.py +60 -10
- {oleksiisaiun_lab6_monaco-3.1.dist-info → oleksiisaiun_lab6_monaco-5.1.dist-info}/METADATA +2 -2
- oleksiisaiun_lab6_monaco-5.1.dist-info/RECORD +10 -0
- {oleksiisaiun_lab6_monaco-3.1.dist-info → oleksiisaiun_lab6_monaco-5.1.dist-info}/WHEEL +1 -1
- oleksiisaiun_lab6_monaco/constants.py +0 -16
- oleksiisaiun_lab6_monaco/utilities.py +0 -43
- oleksiisaiun_lab6_monaco-3.1.dist-info/RECORD +0 -12
- {oleksiisaiun_lab6_monaco-3.1.dist-info → oleksiisaiun_lab6_monaco-5.1.dist-info}/licenses/LICENSE +0 -0
- {oleksiisaiun_lab6_monaco-3.1.dist-info → oleksiisaiun_lab6_monaco-5.1.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,20 @@
|
|
1
1
|
import os
|
2
2
|
from dataclasses import dataclass
|
3
3
|
from datetime import datetime
|
4
|
-
import utilities as util
|
5
|
-
from constants import *
|
6
4
|
|
5
|
+
import re
|
6
|
+
ABBR_ROW_PATTERN = re.compile(
|
7
|
+
r"^(?P<abbr>[A-Z]{3})_(?P<driver>[A-Za-z .'-]+)_(?P<team>[A-Z0-9 &'()-]+)$"
|
8
|
+
)
|
9
|
+
|
10
|
+
START_STOP_ROW_PATTERN = re.compile(
|
11
|
+
r'^(?P<abbr>[A-Z]{3})(?P<time_event>\d{4}-\d{2}-\d{2}_\d{2}:\d{2}:\d{2}\.\d{3})$'
|
12
|
+
)
|
13
|
+
|
14
|
+
ERR_MSG__LAP_TIME_ZERO_OR_NEGATIVE="LAP_TIME_CAN_NOT_BE_ZERO_OR_NEGATIVE"
|
15
|
+
ERR_MSG__EMPTY_START_OR_STOP_TIME="EMPTY_START_OR_STOP_TIME"
|
16
|
+
ERR_MSG__INVALID_FORMAT_OF_TIME_EVENT_ROW ='INVALID_FORMAT_OF_TIME_EVENT_ROW'
|
17
|
+
ERR_PREFIX='INVALID_ABBREVIATION_ROW_'
|
7
18
|
|
8
19
|
@dataclass
|
9
20
|
class RecordData:
|
@@ -59,8 +70,50 @@ class RecordData:
|
|
59
70
|
)
|
60
71
|
|
61
72
|
|
73
|
+
def _is_valid_datetime(value: str, datetime_format: str = "%Y-%m-%d_%H:%M:%S.%f") -> bool:
|
74
|
+
try:
|
75
|
+
datetime.strptime(value, datetime_format)
|
76
|
+
return True
|
77
|
+
except ValueError:
|
78
|
+
return False
|
79
|
+
|
80
|
+
|
81
|
+
def _validate_if_file_exists(filepath) -> bool:
|
82
|
+
"""Check if the folder and file exist, raise error if not."""
|
83
|
+
if not os.path.isfile(filepath):
|
84
|
+
raise FileNotFoundError(f"File not found: {filepath}")
|
85
|
+
|
86
|
+
folder = os.path.dirname(filepath)
|
87
|
+
if folder and not os.path.exists(folder):
|
88
|
+
raise FileNotFoundError(f"Folder does not exist: {folder}")
|
89
|
+
return True
|
90
|
+
|
91
|
+
|
92
|
+
def _validate_abbreviation_row(row: str) -> RecordData:
|
93
|
+
match = ABBR_ROW_PATTERN.match(row)
|
94
|
+
if match:
|
95
|
+
driver_entry = RecordData(abbr=match.group('abbr'), driver=match.group('driver'), team=match.group('team'))
|
96
|
+
return driver_entry
|
97
|
+
|
98
|
+
return None
|
99
|
+
|
100
|
+
|
101
|
+
def _validate_start_stop_row(row: str) -> (str, datetime):
|
102
|
+
match = START_STOP_ROW_PATTERN.match(row)
|
103
|
+
if match:
|
104
|
+
abbr = match.group('abbr')
|
105
|
+
time_event_raw = match.group('time_event')
|
106
|
+
if _is_valid_datetime(time_event_raw):
|
107
|
+
time_event = datetime.strptime(time_event_raw, "%Y-%m-%d_%H:%M:%S.%f")
|
108
|
+
event_time_out = (abbr, time_event)
|
109
|
+
return event_time_out
|
110
|
+
|
111
|
+
print(f"discard row: [{row}], because {ERR_MSG__INVALID_FORMAT_OF_TIME_EVENT_ROW}")
|
112
|
+
return None # if start or stop row has invalid then a row is discarded
|
113
|
+
|
114
|
+
|
62
115
|
def _create_driver_record(row) -> RecordData:
|
63
|
-
record_driver_out =
|
116
|
+
record_driver_out = _validate_abbreviation_row(row)
|
64
117
|
if record_driver_out is None:
|
65
118
|
error_val = {row: ERR_PREFIX}
|
66
119
|
record_driver_out = RecordData(error=[error_val])
|
@@ -94,7 +147,7 @@ def _read_file_start_stop(filepath: str) -> dict[str, datetime]:
|
|
94
147
|
if not line:
|
95
148
|
continue # Skip empty lines
|
96
149
|
|
97
|
-
time_event_record =
|
150
|
+
time_event_record = _validate_start_stop_row(line)
|
98
151
|
|
99
152
|
if time_event_record is not None:
|
100
153
|
abbr = time_event_record[0]
|
@@ -115,8 +168,8 @@ def build_report(
|
|
115
168
|
list_records_good = list()
|
116
169
|
list_records_bad = list()
|
117
170
|
|
118
|
-
if (
|
119
|
-
|
171
|
+
if (_validate_if_file_exists(filepath_abbr)) and (_validate_if_file_exists(filepath_start)) and (
|
172
|
+
_validate_if_file_exists(filepath_stop)):
|
120
173
|
[dict_records_good, dict_records_bad] = _read_file_abbreviation(filepath_abbr)
|
121
174
|
|
122
175
|
dict_start = _read_file_start_stop(filepath=filepath_start)
|
@@ -167,16 +220,13 @@ def print_report(records_good: list[RecordData], records_bad: list[RecordData],
|
|
167
220
|
|
168
221
|
|
169
222
|
def main_run():
|
170
|
-
|
171
|
-
#folder = '/Users/oleksiisaiun/Documents/ALESHA/REPO/PYCHARM/GIT_FOXMINDED_LABS/TRAINING_PYTHON/python_lab_6_oop_monaco_report/data'
|
172
223
|
folder = 'data'
|
173
224
|
file_abbr = 'abbreviations.txt'
|
174
225
|
file_start = 'start.log'
|
175
226
|
file_stop = 'end.log'
|
176
227
|
|
177
|
-
|
178
228
|
data_report = build_report(folder=folder, file_abbr=file_abbr, file_start=file_start, file_stop=file_stop)
|
179
|
-
print_report(records_good=data_report[0], records_bad=data_report[1],sort_by_lap_asc=False)
|
229
|
+
print_report(records_good=data_report[0], records_bad=data_report[1], sort_by_lap_asc=False)
|
180
230
|
|
181
231
|
|
182
232
|
if __name__ == '__main__':
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: oleksiisaiun_lab6_monaco
|
3
|
-
Version:
|
3
|
+
Version: 5.1
|
4
4
|
Summary: The Python application that implements Monaco Racing Report in OOP format
|
5
5
|
Author-email: Oleksii Saiun <oleksiisaiun@example.com>
|
6
6
|
License: MIT
|
@@ -39,4 +39,4 @@ uv pip install oleksiisaiun_lab6_monaco
|
|
39
39
|
#1. Go to root folder of this package:
|
40
40
|
#2. Run command
|
41
41
|
uv build
|
42
|
-
uv publish --token pypi-
|
42
|
+
uv publish --token pypi-AgEIcHlwaS5vcmcCJDUyMzdmMjgzLTc4MGItNDhkYy1hNDRjLWNkMDZiNjczMWQ1OAACKlszLCIzM2M1MmJiZS01NzhhLTQ5NGYtYjlmOS1hYzQzZTI4NTVkZTQiXQAABiA428Uogwjs1PKhckDGrAhK0Mp8qv0-8_N7OLBIb66x1Q
|
@@ -0,0 +1,10 @@
|
|
1
|
+
oleksiisaiun_lab6_monaco/__init__.py,sha256=6RVWsHhSn20meF0sg-al1_6WHkzuH5bInJRhLhZHQ8Q,56
|
2
|
+
oleksiisaiun_lab6_monaco/race_report.py,sha256=J312tOx5THKLtbSIABfMDiZ8TO_cXfF9qXWiazBr3N8,7978
|
3
|
+
oleksiisaiun_lab6_monaco/data/abbreviations.txt,sha256=3GAAVS7XOzXvfIC90WS8pEuCKtavQwGHV97do8xJ20o,663
|
4
|
+
oleksiisaiun_lab6_monaco/data/end.log,sha256=4wE9PQZfaPeFOfKGf24XUCiNfVe2DJwbOzyDuIt7FNs,513
|
5
|
+
oleksiisaiun_lab6_monaco/data/start.log,sha256=rKe7QZzeUVN8j4KVzs11sFfGtGZUw2Zuz3z-1RA9gv8,514
|
6
|
+
oleksiisaiun_lab6_monaco-5.1.dist-info/licenses/LICENSE,sha256=SLpkaez9xkCMD5ce3l3sJM59kS962nWIiMb-jdywXlg,1070
|
7
|
+
oleksiisaiun_lab6_monaco-5.1.dist-info/METADATA,sha256=Dqlbl_eUUiwaiZUdbsGWjDAwv9zwKc0CidcZDl6kiqU,1460
|
8
|
+
oleksiisaiun_lab6_monaco-5.1.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
|
9
|
+
oleksiisaiun_lab6_monaco-5.1.dist-info/top_level.txt,sha256=M7B-GnGgDZrj10nblmrJGJMRFcOZ7d2hU_J_mijACfQ,25
|
10
|
+
oleksiisaiun_lab6_monaco-5.1.dist-info/RECORD,,
|
@@ -1,16 +0,0 @@
|
|
1
|
-
import re
|
2
|
-
|
3
|
-
|
4
|
-
ABBR_ROW_PATTERN = re.compile(
|
5
|
-
r"^(?P<abbr>[A-Z]{3})_(?P<driver>[A-Za-z .'-]+)_(?P<team>[A-Z0-9 &'()-]+)$"
|
6
|
-
)
|
7
|
-
|
8
|
-
|
9
|
-
START_STOP_ROW_PATTERN = re.compile(
|
10
|
-
r'^(?P<abbr>[A-Z]{3})(?P<time_event>\d{4}-\d{2}-\d{2}_\d{2}:\d{2}:\d{2}\.\d{3})$'
|
11
|
-
)
|
12
|
-
|
13
|
-
ERR_MSG__LAP_TIME_ZERO_OR_NEGATIVE="LAP_TIME_CAN_NOT_BE_ZERO_OR_NEGATIVE"
|
14
|
-
ERR_MSG__EMPTY_START_OR_STOP_TIME="EMPTY_START_OR_STOP_TIME"
|
15
|
-
ERR_MSG__INVALID_FORMAT_OF_TIME_EVENT_ROW ='INVALID_FORMAT_OF_TIME_EVENT_ROW'
|
16
|
-
ERR_PREFIX='INVALID_ABBREVIATION_ROW_'
|
@@ -1,43 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from datetime import datetime
|
3
|
-
from race_report import RecordData
|
4
|
-
from constants import ABBR_ROW_PATTERN,START_STOP_ROW_PATTERN,ERR_MSG__INVALID_FORMAT_OF_TIME_EVENT_ROW
|
5
|
-
|
6
|
-
def is_valid_datetime(value: str, datetime_format: str = "%Y-%m-%d_%H:%M:%S.%f") -> bool:
|
7
|
-
try:
|
8
|
-
datetime.strptime(value, datetime_format)
|
9
|
-
return True
|
10
|
-
except ValueError:
|
11
|
-
return False
|
12
|
-
|
13
|
-
def validate_if_file_exists(filepath) -> bool:
|
14
|
-
"""Check if the folder and file exist, raise error if not."""
|
15
|
-
if not os.path.isfile(filepath):
|
16
|
-
raise FileNotFoundError(f"File not found: {filepath}")
|
17
|
-
|
18
|
-
folder = os.path.dirname(filepath)
|
19
|
-
if folder and not os.path.exists(folder):
|
20
|
-
raise FileNotFoundError(f"Folder does not exist: {folder}")
|
21
|
-
return True
|
22
|
-
|
23
|
-
|
24
|
-
def validate_abbreviation_row(row: str) -> RecordData:
|
25
|
-
match = ABBR_ROW_PATTERN.match(row)
|
26
|
-
if match:
|
27
|
-
driver_entry = RecordData(abbr=match.group('abbr'), driver=match.group('driver'), team=match.group('team'))
|
28
|
-
return driver_entry
|
29
|
-
|
30
|
-
return None
|
31
|
-
|
32
|
-
def validate_start_stop_row(row: str) -> (str, datetime):
|
33
|
-
match = START_STOP_ROW_PATTERN.match(row)
|
34
|
-
if match:
|
35
|
-
abbr = match.group('abbr')
|
36
|
-
time_event_raw=match.group('time_event')
|
37
|
-
if is_valid_datetime(time_event_raw):
|
38
|
-
time_event = datetime.strptime(time_event_raw, "%Y-%m-%d_%H:%M:%S.%f")
|
39
|
-
event_time_out = (abbr, time_event)
|
40
|
-
return event_time_out
|
41
|
-
|
42
|
-
print(f"discard row: [{row}], because {ERR_MSG__INVALID_FORMAT_OF_TIME_EVENT_ROW}")
|
43
|
-
return None # if start or stop row has invalid then a row is discarded
|
@@ -1,12 +0,0 @@
|
|
1
|
-
oleksiisaiun_lab6_monaco/__init__.py,sha256=6RVWsHhSn20meF0sg-al1_6WHkzuH5bInJRhLhZHQ8Q,56
|
2
|
-
oleksiisaiun_lab6_monaco/constants.py,sha256=AhfKQOCkcLiILoQ5vf9CD-oBoPMSrXIaPiQhegg5tAw,504
|
3
|
-
oleksiisaiun_lab6_monaco/race_report.py,sha256=lyahDK62FCEsHmt6DfGJabyK63Z4643spdzsKiHfVs8,6224
|
4
|
-
oleksiisaiun_lab6_monaco/utilities.py,sha256=c3BCr1RdAsvCGNUhQW-Rx4eZszDGjFsIs_POL5BXs3M,1628
|
5
|
-
oleksiisaiun_lab6_monaco/data/abbreviations.txt,sha256=3GAAVS7XOzXvfIC90WS8pEuCKtavQwGHV97do8xJ20o,663
|
6
|
-
oleksiisaiun_lab6_monaco/data/end.log,sha256=4wE9PQZfaPeFOfKGf24XUCiNfVe2DJwbOzyDuIt7FNs,513
|
7
|
-
oleksiisaiun_lab6_monaco/data/start.log,sha256=rKe7QZzeUVN8j4KVzs11sFfGtGZUw2Zuz3z-1RA9gv8,514
|
8
|
-
oleksiisaiun_lab6_monaco-3.1.dist-info/licenses/LICENSE,sha256=SLpkaez9xkCMD5ce3l3sJM59kS962nWIiMb-jdywXlg,1070
|
9
|
-
oleksiisaiun_lab6_monaco-3.1.dist-info/METADATA,sha256=CTK3D2A6DnDqpIPk6kLYV8j1vemJ_xWcP0vJL_p0S0c,1460
|
10
|
-
oleksiisaiun_lab6_monaco-3.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
11
|
-
oleksiisaiun_lab6_monaco-3.1.dist-info/top_level.txt,sha256=M7B-GnGgDZrj10nblmrJGJMRFcOZ7d2hU_J_mijACfQ,25
|
12
|
-
oleksiisaiun_lab6_monaco-3.1.dist-info/RECORD,,
|
{oleksiisaiun_lab6_monaco-3.1.dist-info → oleksiisaiun_lab6_monaco-5.1.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
{oleksiisaiun_lab6_monaco-3.1.dist-info → oleksiisaiun_lab6_monaco-5.1.dist-info}/top_level.txt
RENAMED
File without changes
|