hytek-parser 2.1.0__tar.gz → 2.3.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.
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/PKG-INFO +1 -1
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/__init__.py +3 -1
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/__init__.py +2 -1
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/b_meet_parsers.py +2 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/d_swimmer_parsers.py +5 -2
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/e_event_parsers.py +3 -1
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/h_dq_parsers.py +28 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/schemas.py +20 -2
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/pyproject.toml +1 -1
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/LICENSE.md +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/README.md +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/_utils.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/export_xls/__init__.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/export_xls/_utils.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/export_xls/schemas.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/__init__.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/_utils.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/enums.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/a_file_parsers.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/c_team_parsers.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/f_relay_parsers.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/g_split_parsers.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3_parser.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hyv/__init__.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hyv/enums.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hyv/schemas.py +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/py.typed +0 -0
- {hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/types.py +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
"""A Hytek hy3 file parser."""
|
|
2
|
+
from importlib.metadata import version
|
|
3
|
+
|
|
2
4
|
from .export_xls import ExportXlsParseError, parse_event_export_xls
|
|
3
5
|
from .hy3 import HY3_LINE_PARSERS
|
|
4
6
|
from .hy3_parser import parse_hy3
|
|
@@ -15,4 +17,4 @@ __all__ = [
|
|
|
15
17
|
]
|
|
16
18
|
__author__ = "Nino Maruszewski"
|
|
17
19
|
__license__ = "MIT"
|
|
18
|
-
__version__ =
|
|
20
|
+
__version__ = version(__package__)
|
|
@@ -9,7 +9,7 @@ from .d_swimmer_parsers import d1_parser
|
|
|
9
9
|
from .e_event_parsers import e1_parser, e2_parser
|
|
10
10
|
from .f_relay_parsers import f1_parser, f2_parser, f3_parser
|
|
11
11
|
from .g_split_parsers import g1_parser
|
|
12
|
-
from .h_dq_parsers import h1_parser
|
|
12
|
+
from .h_dq_parsers import h1_parser, h2_parser
|
|
13
13
|
|
|
14
14
|
__all__ = ["HY3_LINE_PARSERS"]
|
|
15
15
|
|
|
@@ -38,4 +38,5 @@ HY3_LINE_PARSERS: dict[
|
|
|
38
38
|
"G1": g1_parser,
|
|
39
39
|
# DQ info
|
|
40
40
|
"H1": h1_parser,
|
|
41
|
+
"H2": h2_parser,
|
|
41
42
|
}
|
|
@@ -33,6 +33,8 @@ def b2_parser(
|
|
|
33
33
|
meet.masters = extract(line, 94, 2) == "06"
|
|
34
34
|
meet.type_ = select_from_enum(MeetType, extract(line, 97, 2))
|
|
35
35
|
meet.course = select_from_enum(Course, extract(line, 99, 1))
|
|
36
|
+
meet.notes = extract(line, 3, 45) or None
|
|
37
|
+
meet.sanction_number = extract(line, 109, 20) or None
|
|
36
38
|
|
|
37
39
|
file.meet = meet
|
|
38
40
|
return file
|
{hytek_parser-2.1.0 → hytek_parser-2.3.0}/hytek_parser/hy3/line_parsers/d_swimmer_parsers.py
RENAMED
|
@@ -26,9 +26,12 @@ def d1_parser(
|
|
|
26
26
|
|
|
27
27
|
# previously dropped D1 fields. Capture both per spec.
|
|
28
28
|
# citizenship: cols 113-115 (3 chars). Observed: 'USA' or blank.
|
|
29
|
-
#
|
|
29
|
+
# status: col 125 (1 char). Athlete status; observed 'N' (Normal) or blank.
|
|
30
30
|
swimmer.citizenship = extract(line, 113, 3) or None
|
|
31
|
-
swimmer.
|
|
31
|
+
swimmer.status = extract(line, 125, 1) or None
|
|
32
|
+
# class_year: cols 100-101 (2 chars). "Fr"/"So"/"Jr"/"Sr" school
|
|
33
|
+
# class in HS-meet exports; other data / blank in club exports.
|
|
34
|
+
swimmer.class_year = extract(line, 100, 2) or None
|
|
32
35
|
|
|
33
36
|
swimmer.team_code = team_code
|
|
34
37
|
|
|
@@ -66,8 +66,9 @@ def e1_parser(
|
|
|
66
66
|
# Meet Division: col 77-79 in most MM versions, col 92-93 in MM4/MM5-7.0Fa.
|
|
67
67
|
# The two are mutually exclusive; col 77 takes precedence.
|
|
68
68
|
meet_division = extract(line, 77, 3) or extract(line, 92, 2) or None
|
|
69
|
+
exhibition = extract(line, 84, 1) == "X"
|
|
69
70
|
|
|
70
|
-
event.get_or_create_entry(
|
|
71
|
+
entry = event.get_or_create_entry(
|
|
71
72
|
swimmers=entry_swimmers,
|
|
72
73
|
relay=False,
|
|
73
74
|
event_number=entry_event_number,
|
|
@@ -76,6 +77,7 @@ def e1_parser(
|
|
|
76
77
|
converted_seed_time=entry_converted_seed_time,
|
|
77
78
|
converted_seed_time_course=entry_converted_seed_time_course,
|
|
78
79
|
meet_division=meet_division,
|
|
80
|
+
exhibition=exhibition,
|
|
79
81
|
)
|
|
80
82
|
|
|
81
83
|
# Update event
|
|
@@ -47,3 +47,31 @@ def h1_parser(
|
|
|
47
47
|
file.meet.last_event = (event_num, event)
|
|
48
48
|
|
|
49
49
|
return file
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def h2_parser(
|
|
53
|
+
line: str, file: ParsedHytekFile, opts: dict[str, Any]
|
|
54
|
+
) -> ParsedHytekFile:
|
|
55
|
+
"""Parse an H2 line: the specific, human-readable DQ infraction detail.
|
|
56
|
+
|
|
57
|
+
Attaches the detail text to whichever DQ slot the preceding H1 populated
|
|
58
|
+
(finals -> swimoff -> prelim), mirroring h1_parser's resolution. Unlike H1,
|
|
59
|
+
the H2 2-char code is NOT asserted against the DQ code (it is a stroke/leg
|
|
60
|
+
sub-classification, not the same DisqualificationCode). No-op if no DQ slot
|
|
61
|
+
is set.
|
|
62
|
+
"""
|
|
63
|
+
event_num, event = file.meet.last_event
|
|
64
|
+
entry = event.last_entry
|
|
65
|
+
|
|
66
|
+
detail = extract(line, 5, 124) or None
|
|
67
|
+
|
|
68
|
+
if entry.finals_dq_info:
|
|
69
|
+
entry.finals_dq_info.info_str_detail = detail
|
|
70
|
+
elif entry.swimoff_dq_info:
|
|
71
|
+
entry.swimoff_dq_info.info_str_detail = detail
|
|
72
|
+
elif entry.prelim_dq_info:
|
|
73
|
+
entry.prelim_dq_info.info_str_detail = detail
|
|
74
|
+
|
|
75
|
+
event.last_entry = entry
|
|
76
|
+
file.meet.last_event = (event_num, event)
|
|
77
|
+
return file
|
|
@@ -38,8 +38,14 @@ class Swimmer:
|
|
|
38
38
|
|
|
39
39
|
# D1 fields previously dropped by the parser
|
|
40
40
|
citizenship: Optional[str] = None
|
|
41
|
-
# col 125;
|
|
42
|
-
|
|
41
|
+
# col 125; athlete status (Hytek MM "Status" field). Raw 1-char code — only
|
|
42
|
+
# "N" (Normal) or blank observed across ~9.25M records; other GUI statuses
|
|
43
|
+
# (Impaired/Exhibition/Foreigner/Rookie) never seen in data, so left as a
|
|
44
|
+
# raw code rather than an enum.
|
|
45
|
+
status: Optional[str] = None
|
|
46
|
+
# cols 100-101; "Fr"/"So"/"Jr"/"Sr" school class in HS-meet exports,
|
|
47
|
+
# other data / blank in club exports.
|
|
48
|
+
class_year: Optional[str] = None
|
|
43
49
|
|
|
44
50
|
|
|
45
51
|
@define
|
|
@@ -78,6 +84,7 @@ class DisqualificationInfo:
|
|
|
78
84
|
|
|
79
85
|
code: DisqualificationCode
|
|
80
86
|
info_str: Optional[str] = None
|
|
87
|
+
info_str_detail: Optional[str] = None
|
|
81
88
|
|
|
82
89
|
|
|
83
90
|
@define(init=False)
|
|
@@ -165,6 +172,7 @@ class EventEntry:
|
|
|
165
172
|
# or numeric ('0'/'1'/'2'/'3'). Stored at cols 77-79 in most MM versions,
|
|
166
173
|
# cols 92-93 in MM4/MM5-7.0Fa (read with col-77 precedence).
|
|
167
174
|
meet_division: Optional[str] = None
|
|
175
|
+
exhibition: bool = False
|
|
168
176
|
|
|
169
177
|
def __init__(
|
|
170
178
|
self,
|
|
@@ -178,6 +186,7 @@ class EventEntry:
|
|
|
178
186
|
relay_team_id: Optional[str] = None,
|
|
179
187
|
relay_swim_team_code: Optional[str] = None,
|
|
180
188
|
meet_division: Optional[str] = None,
|
|
189
|
+
exhibition: bool = False,
|
|
181
190
|
) -> None:
|
|
182
191
|
self.swimmers = swimmers
|
|
183
192
|
self.relay = relay
|
|
@@ -189,6 +198,7 @@ class EventEntry:
|
|
|
189
198
|
self.relay_team_id = relay_team_id
|
|
190
199
|
self.relay_swim_team_code = relay_swim_team_code
|
|
191
200
|
self.meet_division = meet_division
|
|
201
|
+
self.exhibition = exhibition
|
|
192
202
|
|
|
193
203
|
for course in ("prelim", "swimoff", "finals"):
|
|
194
204
|
setattr(self, f"{course}_time", None)
|
|
@@ -277,6 +287,7 @@ class Event:
|
|
|
277
287
|
relay_team_id: Optional[str] = None,
|
|
278
288
|
relay_swim_team_code: Optional[str] = None,
|
|
279
289
|
meet_division: Optional[str] = None,
|
|
290
|
+
exhibition: bool = False,
|
|
280
291
|
) -> EventEntry:
|
|
281
292
|
"""Get an event entry or create one if needed."""
|
|
282
293
|
entry = EventEntry(
|
|
@@ -290,6 +301,7 @@ class Event:
|
|
|
290
301
|
relay_team_id=relay_team_id,
|
|
291
302
|
relay_swim_team_code=relay_swim_team_code,
|
|
292
303
|
meet_division=meet_division,
|
|
304
|
+
exhibition=exhibition,
|
|
293
305
|
)
|
|
294
306
|
if self.entries and self.entries[-1].same_swimmer_entry_as(entry):
|
|
295
307
|
# P/F entries always listed together: a swimmer (individuals) or a
|
|
@@ -336,6 +348,12 @@ class Meet:
|
|
|
336
348
|
swimmers: dict[int, Swimmer]
|
|
337
349
|
events: dict[str, Event]
|
|
338
350
|
|
|
351
|
+
# Extended info (optional; populated by later parser stages). Kept at the
|
|
352
|
+
# end of the field block (not next to `facility`/`country`) because attrs
|
|
353
|
+
# forbids a defaulted field preceding the non-default fields above.
|
|
354
|
+
sanction_number: Optional[str] = None
|
|
355
|
+
notes: Optional[str] = None
|
|
356
|
+
|
|
339
357
|
# Bookeeping
|
|
340
358
|
_last_team: tuple[str, Team] = field(default=None)
|
|
341
359
|
_last_event: tuple[str, Event] = field(default=None)
|
|
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
|
|
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
|
|
File without changes
|