labfreed 0.2.2__tar.gz → 0.2.3__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 labfreed might be problematic. Click here for more details.
- {labfreed-0.2.2 → labfreed-0.2.3}/.github/workflows/pypi-publish.yml +1 -1
- {labfreed-0.2.2 → labfreed-0.2.3}/CHANGELOG.md +4 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/PKG-INFO +18 -14
- {labfreed-0.2.2 → labfreed-0.2.3}/README.md +17 -13
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/__init__.py +1 -1
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/labfreed_infrastructure.py +29 -64
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id/extension.py +3 -3
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/table_segment.py +21 -4
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/trex_base_models.py +10 -136
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/value_segments.py +2 -12
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_extensions/display_name_extension.py +1 -1
- {labfreed-0.2.2 → labfreed-0.2.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/.github/workflows/run-tests.yml +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/LICENSE +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_cat/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_cat/category_base.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_cat/pac_cat.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_cat/predefined_categories.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id/id_segment.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id/pac_id.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id/url_parser.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id/url_serializer.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id_resolver/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id_resolver/cit_v1.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id_resolver/cit_v2.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id_resolver/resolver.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/pac_id_resolver/services.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/qr/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/qr/generate_qr.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/python_convenience/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/python_convenience/data_table.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/python_convenience/pyTREX.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/python_convenience/quantity.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/trex/trex.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/utilities/base36.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_extensions/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_extensions/default_extension_interpreters.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_extensions/trex_extension.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_keys/gs1/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_keys/gs1/gs1.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_keys/gs1/gs1_ai_enum_sorted.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_keys/labfreed/well_known_keys.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_keys/unece/UneceUnits.json +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_keys/unece/__init__.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_keys/unece/unece_units.py +0 -0
- {labfreed-0.2.2 → labfreed-0.2.3}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: labfreed
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Python implementation of LabFREED building blocks
|
|
5
5
|
Author-email: Reto Thürer <thuerer.r@buchi.com>
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -100,22 +100,22 @@ pac.print_validation_messages()
|
|
|
100
100
|
```text
|
|
101
101
|
>> Validation Results
|
|
102
102
|
>> ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
103
|
-
>> │ RECOMMENDATION
|
|
104
|
-
>> │ Characters '
|
|
103
|
+
>> │ **RECOMMENDATION** in id segment value bal500 │
|
|
104
|
+
>> │ Characters 'a','l','b' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
105
105
|
>> │ │
|
|
106
106
|
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:👉bal👈500/21:@1234 │
|
|
107
107
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
108
|
-
>> │ RECOMMENDATION
|
|
108
|
+
>> │ **RECOMMENDATION** in id segment value @1234 │
|
|
109
109
|
>> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
110
110
|
>> │ │
|
|
111
111
|
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:👉@👈1234 │
|
|
112
112
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
113
|
-
>> │ RECOMMENDATION
|
|
114
|
-
>> │ Characters '
|
|
113
|
+
>> │ **RECOMMENDATION** in id segment value bal500 │
|
|
114
|
+
>> │ Characters 'a','l','b' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
115
115
|
>> │ │
|
|
116
116
|
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:👉bal👈500/21:@1234 │
|
|
117
117
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
118
|
-
>> │ RECOMMENDATION
|
|
118
|
+
>> │ **RECOMMENDATION** in id segment value @1234 │
|
|
119
119
|
>> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
120
120
|
>> │ │
|
|
121
121
|
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:👉@👈1234 │
|
|
@@ -243,18 +243,18 @@ trex.print_validation_messages()
|
|
|
243
243
|
```text
|
|
244
244
|
>> Validation Results
|
|
245
245
|
>> ┌────────────────────────────────────────────────────────────┐
|
|
246
|
-
>> │ ERROR
|
|
247
|
-
>> │ Column header key contains invalid characters: '
|
|
246
|
+
>> │ **ERROR** in TREX table column Date │
|
|
247
|
+
>> │ Column header key contains invalid characters: 'a','t','e' │
|
|
248
248
|
>> │ │
|
|
249
249
|
>> │ STOP$T.D:20240505T1306 │
|
|
250
250
|
>> │ +TEMP$KEL:10.15 │
|
|
251
251
|
>> │ +OK$T.B:F │
|
|
252
252
|
>> │ +COMMENT$T.A:FOO │
|
|
253
|
-
>> │ +COMMENT2$T.T:
|
|
253
|
+
>> │ +COMMENT2$T.T:12G3 │
|
|
254
254
|
>> │ +TABLE$$DURATION$HUR:D👉ate👈$T.D:OK$T.B:COMMENT$T.A:: │
|
|
255
|
-
>> │ 1:
|
|
256
|
-
>> │ 1.1:
|
|
257
|
-
>> │ 1.3:
|
|
255
|
+
>> │ 1:20250425T081731.192:T:FOO:: │
|
|
256
|
+
>> │ 1.1:20250425T081731.192:T:BAR:: │
|
|
257
|
+
>> │ 1.3:20250425T081731.192:F:BLUBB │
|
|
258
258
|
>> └────────────────────────────────────────────────────────────┘
|
|
259
259
|
```
|
|
260
260
|
#### Combine PAC-ID and TREX and serialize
|
|
@@ -266,7 +266,7 @@ pac_str = pac.to_url()
|
|
|
266
266
|
print(pac_str)
|
|
267
267
|
```
|
|
268
268
|
```text
|
|
269
|
-
>> HTTPS://PAC.METTORIUS.COM/21:1234*MYTREX$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:
|
|
269
|
+
>> HTTPS://PAC.METTORIUS.COM/21:1234*MYTREX$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:Date$T.D:OK$T.B:COMMENT$T.A::1:20250425T081731.192:T:FOO::1.1:20250425T081731.192:T:BAR::1.3:20250425T081731.192:F:BLUBB
|
|
270
270
|
```
|
|
271
271
|
## PAC-ID Resolver
|
|
272
272
|
|
|
@@ -324,6 +324,10 @@ for sg in service_groups:
|
|
|
324
324
|
|
|
325
325
|
<!-- BEGIN CHANGELOG -->
|
|
326
326
|
## Change Log
|
|
327
|
+
### v0.2.3
|
|
328
|
+
- improvements in formatting of validation messages
|
|
329
|
+
- bugfix in DisplayNameExtension
|
|
330
|
+
|
|
327
331
|
### v0.2.2
|
|
328
332
|
- minor changes for better access of subfunctions. No change in existing API
|
|
329
333
|
|
|
@@ -69,22 +69,22 @@ pac.print_validation_messages()
|
|
|
69
69
|
```text
|
|
70
70
|
>> Validation Results
|
|
71
71
|
>> ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
72
|
-
>> │ RECOMMENDATION
|
|
73
|
-
>> │ Characters '
|
|
72
|
+
>> │ **RECOMMENDATION** in id segment value bal500 │
|
|
73
|
+
>> │ Characters 'a','l','b' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
74
74
|
>> │ │
|
|
75
75
|
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:👉bal👈500/21:@1234 │
|
|
76
76
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
77
|
-
>> │ RECOMMENDATION
|
|
77
|
+
>> │ **RECOMMENDATION** in id segment value @1234 │
|
|
78
78
|
>> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
79
79
|
>> │ │
|
|
80
80
|
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:👉@👈1234 │
|
|
81
81
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
82
|
-
>> │ RECOMMENDATION
|
|
83
|
-
>> │ Characters '
|
|
82
|
+
>> │ **RECOMMENDATION** in id segment value bal500 │
|
|
83
|
+
>> │ Characters 'a','l','b' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
84
84
|
>> │ │
|
|
85
85
|
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:👉bal👈500/21:@1234 │
|
|
86
86
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
87
|
-
>> │ RECOMMENDATION
|
|
87
|
+
>> │ **RECOMMENDATION** in id segment value @1234 │
|
|
88
88
|
>> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
89
89
|
>> │ │
|
|
90
90
|
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:👉@👈1234 │
|
|
@@ -212,18 +212,18 @@ trex.print_validation_messages()
|
|
|
212
212
|
```text
|
|
213
213
|
>> Validation Results
|
|
214
214
|
>> ┌────────────────────────────────────────────────────────────┐
|
|
215
|
-
>> │ ERROR
|
|
216
|
-
>> │ Column header key contains invalid characters: '
|
|
215
|
+
>> │ **ERROR** in TREX table column Date │
|
|
216
|
+
>> │ Column header key contains invalid characters: 'a','t','e' │
|
|
217
217
|
>> │ │
|
|
218
218
|
>> │ STOP$T.D:20240505T1306 │
|
|
219
219
|
>> │ +TEMP$KEL:10.15 │
|
|
220
220
|
>> │ +OK$T.B:F │
|
|
221
221
|
>> │ +COMMENT$T.A:FOO │
|
|
222
|
-
>> │ +COMMENT2$T.T:
|
|
222
|
+
>> │ +COMMENT2$T.T:12G3 │
|
|
223
223
|
>> │ +TABLE$$DURATION$HUR:D👉ate👈$T.D:OK$T.B:COMMENT$T.A:: │
|
|
224
|
-
>> │ 1:
|
|
225
|
-
>> │ 1.1:
|
|
226
|
-
>> │ 1.3:
|
|
224
|
+
>> │ 1:20250425T081731.192:T:FOO:: │
|
|
225
|
+
>> │ 1.1:20250425T081731.192:T:BAR:: │
|
|
226
|
+
>> │ 1.3:20250425T081731.192:F:BLUBB │
|
|
227
227
|
>> └────────────────────────────────────────────────────────────┘
|
|
228
228
|
```
|
|
229
229
|
#### Combine PAC-ID and TREX and serialize
|
|
@@ -235,7 +235,7 @@ pac_str = pac.to_url()
|
|
|
235
235
|
print(pac_str)
|
|
236
236
|
```
|
|
237
237
|
```text
|
|
238
|
-
>> HTTPS://PAC.METTORIUS.COM/21:1234*MYTREX$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:
|
|
238
|
+
>> HTTPS://PAC.METTORIUS.COM/21:1234*MYTREX$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:Date$T.D:OK$T.B:COMMENT$T.A::1:20250425T081731.192:T:FOO::1.1:20250425T081731.192:T:BAR::1.3:20250425T081731.192:F:BLUBB
|
|
239
239
|
```
|
|
240
240
|
## PAC-ID Resolver
|
|
241
241
|
|
|
@@ -293,6 +293,10 @@ for sg in service_groups:
|
|
|
293
293
|
|
|
294
294
|
<!-- BEGIN CHANGELOG -->
|
|
295
295
|
## Change Log
|
|
296
|
+
### v0.2.3
|
|
297
|
+
- improvements in formatting of validation messages
|
|
298
|
+
- bugfix in DisplayNameExtension
|
|
299
|
+
|
|
296
300
|
### v0.2.2
|
|
297
301
|
- minor changes for better access of subfunctions. No change in existing API
|
|
298
302
|
|
|
@@ -159,22 +159,6 @@ class LabFREED_BaseModel(PDOC_Workaround_Base):
|
|
|
159
159
|
return warnings_list
|
|
160
160
|
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
def _emphasize_in(self, validation_msg, validation_node_str:str, fmt, color='black'):
|
|
164
|
-
if validation_msg.highlight_sub_patterns:
|
|
165
|
-
replacements = validation_msg.highlight_sub_patterns
|
|
166
|
-
else:
|
|
167
|
-
replacements = [validation_msg.highlight]
|
|
168
|
-
# Sort patterns by length descending to avoid subpattern clobbering
|
|
169
|
-
sorted_patterns = sorted(replacements, key=len, reverse=True)
|
|
170
|
-
# Escape the patterns for regex safety
|
|
171
|
-
escaped_patterns = [re.escape(p) for p in sorted_patterns]
|
|
172
|
-
# Create one regex pattern with alternation (longest first)
|
|
173
|
-
pattern = re.compile("|".join(escaped_patterns))
|
|
174
|
-
|
|
175
|
-
out = pattern.sub(lambda m: fmt(m.group(0)), validation_node_str)
|
|
176
|
-
return out
|
|
177
|
-
|
|
178
162
|
|
|
179
163
|
def print_validation_messages(self, target='console'):
|
|
180
164
|
msgs = self.format_validation_messages(target=target)
|
|
@@ -216,67 +200,48 @@ class LabFREED_BaseModel(PDOC_Workaround_Base):
|
|
|
216
200
|
match target:
|
|
217
201
|
case 'markdown':
|
|
218
202
|
fmt = lambda s: f'👉{s}👈' # noqa: E731
|
|
203
|
+
fmt_title = lambda s: f'**{s}**' # noqa: E731
|
|
204
|
+
br = '\n'
|
|
219
205
|
case 'console':
|
|
220
206
|
fmt = lambda s: f'[{color} bold]{s}[/{color} bold]' # noqa: E731
|
|
207
|
+
fmt_title = fmt
|
|
208
|
+
br = '\n'
|
|
221
209
|
case 'html':
|
|
222
|
-
fmt = lambda s: f'<span class="
|
|
210
|
+
fmt = lambda s: f'<span class="validation-{m.level.name.lower()}">{s}</span>' # noqa: E731
|
|
211
|
+
fmt_title = lambda s: f'<span class="validation-title">{s}</span>' # noqa: E731
|
|
212
|
+
br = '<br>'
|
|
223
213
|
case 'html_styled':
|
|
224
|
-
fmt = lambda s: f'<b style="color:{color}>{s}</b>' # noqa: E731
|
|
214
|
+
fmt = lambda s: f'<b style="color:{color}">{s}</b>' # noqa: E731
|
|
215
|
+
fmt_title = fmt
|
|
216
|
+
br = '<br>'
|
|
225
217
|
|
|
226
218
|
serialized = str(self)
|
|
227
|
-
emphazised_highlight = self._emphasize_in(m, serialized, fmt=fmt
|
|
219
|
+
emphazised_highlight = self._emphasize_in(m, serialized, fmt=fmt)
|
|
228
220
|
emphazised_highlight = emphazised_highlight.replace('👈👉','') # removes two consecutive markers, to make it cleaner
|
|
229
221
|
|
|
230
|
-
txt =
|
|
231
|
-
txt +=
|
|
232
|
-
txt +=
|
|
222
|
+
txt = f'{fmt_title(m.level.name)} in {m.source}'
|
|
223
|
+
txt += br + f'{m.msg}'
|
|
224
|
+
txt += br+br + emphazised_highlight
|
|
233
225
|
|
|
234
226
|
formatted_msg.append(txt)
|
|
235
227
|
return formatted_msg
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
228
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
# if not msgs:
|
|
254
|
-
# print('All clear!')
|
|
255
|
-
# return
|
|
256
|
-
|
|
257
|
-
# for m in msgs:
|
|
258
|
-
# if m.level.casefold() == "error":
|
|
259
|
-
# color = 'red'
|
|
260
|
-
# else:
|
|
261
|
-
# color = 'yellow'
|
|
262
|
-
|
|
263
|
-
# text = Text.from_markup(f'\n [bold {color}]{m.level} [/bold {color}] in \t {m.source}' )
|
|
264
|
-
# print(text)
|
|
265
|
-
# match target:
|
|
266
|
-
# case 'markdown':
|
|
267
|
-
# formatted_highlight = m.emphazised_highlight.replace('emph', f'🔸').replace('[/', '').replace('[', '').replace(']', '')
|
|
268
|
-
# case 'console':
|
|
269
|
-
# formatted_highlight = m.emphazised_highlight.replace('emph', f'bold {color}')
|
|
270
|
-
# case 'html':
|
|
271
|
-
# formatted_highlight = m.emphazised_highlight.replace('emph', f'b').replace('[', '<').replace(']', '>')
|
|
272
|
-
# fmtd = str_to_highlight_in.replace(m.highlight, formatted_highlight)
|
|
273
|
-
# fmtd = Text.from_markup(fmtd)
|
|
274
|
-
# print(fmtd)
|
|
275
|
-
# print(Text.from_markup(f'{m.problem_msg}'))
|
|
229
|
+
def _emphasize_in(self, validation_msg, validation_node_str:str, fmt):
|
|
230
|
+
if validation_msg.highlight_sub_patterns:
|
|
231
|
+
replacements = validation_msg.highlight_sub_patterns
|
|
232
|
+
else:
|
|
233
|
+
replacements = [validation_msg.highlight]
|
|
234
|
+
# Sort patterns by length descending to avoid subpattern clobbering
|
|
235
|
+
sorted_patterns = sorted(replacements, key=len, reverse=True)
|
|
236
|
+
# Escape the patterns for regex safety
|
|
237
|
+
escaped_patterns = [re.escape(p) for p in sorted_patterns]
|
|
238
|
+
# Create one regex pattern with alternation (longest first)
|
|
239
|
+
pattern = re.compile("|".join(escaped_patterns))
|
|
276
240
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
241
|
+
out = pattern.sub(lambda m: fmt(m.group(0)), validation_node_str)
|
|
242
|
+
return out
|
|
243
|
+
|
|
244
|
+
|
|
280
245
|
|
|
281
246
|
def _filter_errors(val_msg:list[ValidationMessage]) -> list[ValidationMessage]:
|
|
282
247
|
return [ m for m in val_msg if m.level == ValidationMsgLevel.ERROR ]
|
|
@@ -15,6 +15,8 @@ class ExtensionBase(ABC):
|
|
|
15
15
|
def data(self) -> str:
|
|
16
16
|
raise NotImplementedError("Subclasses must implement 'data'")
|
|
17
17
|
|
|
18
|
+
def __str__(self):
|
|
19
|
+
return f'{self.name}${self.type}/{self.data}'
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
|
|
@@ -43,6 +45,4 @@ class Extension(LabFREED_BaseModel,ExtensionBase):
|
|
|
43
45
|
"extra": "allow", # Allow extra keys during pre-validation
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
return f'{self.name}${self.type}/{self.data}'
|
|
48
|
-
|
|
48
|
+
|
|
@@ -8,7 +8,7 @@ from pydantic import RootModel, model_validator
|
|
|
8
8
|
from labfreed.trex.trex_base_models import Value
|
|
9
9
|
from labfreed.well_known_keys.unece.unece_units import unece_unit_codes
|
|
10
10
|
from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMsgLevel, _quote_texts
|
|
11
|
-
from labfreed.trex.trex_base_models import AlphanumericValue, BinaryValue, BoolValue, DateValue, ErrorValue, NumericValue, TREX_Segment, TextValue
|
|
11
|
+
from labfreed.trex.trex_base_models import AlphanumericValue, BinaryValue, BoolValue, DateValue, ErrorValue, NumericValue, TREX_Segment, TextValue
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class ColumnHeader(LabFREED_BaseModel):
|
|
@@ -217,11 +217,28 @@ def _deserialize_table_segment_from_trex_segment_str(trex_segment_str) -> TableS
|
|
|
217
217
|
headers.append(ColumnHeader(key=col_key, type=col_type))
|
|
218
218
|
|
|
219
219
|
data = [row.split(':') for row in body.split('::') ]
|
|
220
|
-
col_types = [h.type for h in headers]
|
|
221
220
|
# convert to correct value types
|
|
222
|
-
data_with_types = [[
|
|
221
|
+
data_with_types = [[_str_to_value_type(h.type, cv) for cv, h in zip(r, headers)] for r in data]
|
|
223
222
|
data = [ TableRow(r) for r in data_with_types]
|
|
224
223
|
|
|
225
|
-
out = TableSegment(column_headers=headers, data=
|
|
224
|
+
out = TableSegment(column_headers=headers, data=data, key=name)
|
|
225
|
+
return out
|
|
226
|
+
|
|
227
|
+
def _str_to_value_type(type_, s):
|
|
228
|
+
match type_:
|
|
229
|
+
case 'T.D':
|
|
230
|
+
out = DateValue(value=s)
|
|
231
|
+
case 'T.B':
|
|
232
|
+
out = BoolValue(value=s)
|
|
233
|
+
case 'T.A':
|
|
234
|
+
out = AlphanumericValue(value=s)
|
|
235
|
+
case 'T.T':
|
|
236
|
+
out = TextValue(value=s)
|
|
237
|
+
case 'T.X':
|
|
238
|
+
out = BinaryValue(value=s)
|
|
239
|
+
case 'E':
|
|
240
|
+
out = ErrorValue(value=s)
|
|
241
|
+
case _:
|
|
242
|
+
out = NumericValue(value=s)
|
|
226
243
|
return out
|
|
227
244
|
|
|
@@ -4,11 +4,10 @@ import re
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
from pydantic import PrivateAttr,
|
|
7
|
+
from pydantic import PrivateAttr, model_validator
|
|
8
8
|
from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMsgLevel, _quote_texts
|
|
9
|
-
from abc import ABC,
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
10
|
|
|
11
|
-
from labfreed.utilities.base36 import base36, to_base36, from_base36
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
''' Configure pdoc'''
|
|
@@ -32,22 +31,9 @@ class Value(LabFREED_BaseModel, ABC):
|
|
|
32
31
|
def serialize(self):
|
|
33
32
|
return self.value
|
|
34
33
|
|
|
35
|
-
@abstractclassmethod
|
|
36
|
-
def _from_python_type(cls, v):
|
|
37
|
-
...
|
|
38
|
-
|
|
39
|
-
@abstractmethod
|
|
40
|
-
def _value_to_python_type(self):
|
|
41
|
-
...
|
|
42
34
|
|
|
43
35
|
|
|
44
36
|
class NumericValue(Value):
|
|
45
|
-
@field_validator('value', mode='before')
|
|
46
|
-
@classmethod
|
|
47
|
-
def _from_python_type(cls, v:str| int|float):
|
|
48
|
-
if isinstance(v, str):
|
|
49
|
-
return v
|
|
50
|
-
return str(v)
|
|
51
37
|
|
|
52
38
|
@model_validator(mode='after')
|
|
53
39
|
def _validate(self):
|
|
@@ -56,7 +42,7 @@ class NumericValue(Value):
|
|
|
56
42
|
self._add_validation_message(
|
|
57
43
|
source=f"TREX numeric value {value}",
|
|
58
44
|
level=ValidationMsgLevel.ERROR,
|
|
59
|
-
msg=f"Characters {_quote_texts(not_allowed_chars)} are not allowed in quantity segment.
|
|
45
|
+
msg=f"Characters {_quote_texts(not_allowed_chars)} are not allowed in quantity segment. Must be a number.",
|
|
60
46
|
highlight_pattern = f'{value}',
|
|
61
47
|
highlight_sub=not_allowed_chars
|
|
62
48
|
)
|
|
@@ -68,36 +54,9 @@ class NumericValue(Value):
|
|
|
68
54
|
highlight_pattern = f'{value}'
|
|
69
55
|
)
|
|
70
56
|
return self
|
|
71
|
-
|
|
72
|
-
def _value_to_python_type(self) -> str:
|
|
73
|
-
v = float(self.value)
|
|
74
|
-
if '.' not in self.value and 'E' not in self.value:
|
|
75
|
-
return int(v)
|
|
76
|
-
else:
|
|
77
|
-
return v
|
|
78
|
-
|
|
79
57
|
|
|
80
58
|
class DateValue(Value):
|
|
81
59
|
_date_time_dict:dict|None = PrivateAttr(default=None)
|
|
82
|
-
@field_validator('value', mode='before')
|
|
83
|
-
@classmethod
|
|
84
|
-
def _from_python_type(cls, v:str| date|time|datetime):
|
|
85
|
-
if isinstance(v, str):
|
|
86
|
-
return v
|
|
87
|
-
|
|
88
|
-
sd = ""
|
|
89
|
-
st = ""
|
|
90
|
-
if isinstance(v, date) or isinstance(v, datetime):
|
|
91
|
-
sd = v.strftime('%Y%m%d')
|
|
92
|
-
if isinstance(v, time) or isinstance(v, datetime):
|
|
93
|
-
if v.microsecond:
|
|
94
|
-
st = v.strftime("T%H%M%S.") + f"{v.microsecond // 1000:03d}"
|
|
95
|
-
elif v.second:
|
|
96
|
-
st = v.strftime("T%H%M%S")
|
|
97
|
-
else:
|
|
98
|
-
st = v.strftime("T%H%M")
|
|
99
|
-
|
|
100
|
-
return sd + st
|
|
101
60
|
|
|
102
61
|
@model_validator(mode='after')
|
|
103
62
|
def _validate(self):
|
|
@@ -134,24 +93,8 @@ class DateValue(Value):
|
|
|
134
93
|
self._date_time_dict = d
|
|
135
94
|
return self
|
|
136
95
|
|
|
137
|
-
|
|
138
|
-
d = self._date_time_dict
|
|
139
|
-
if d.get('year') and d.get('hour'): # input is only a time
|
|
140
|
-
return datetime(**d)
|
|
141
|
-
elif d.get('year'):
|
|
142
|
-
return date(**d)
|
|
143
|
-
else:
|
|
144
|
-
return time(**d)
|
|
145
|
-
|
|
146
|
-
|
|
96
|
+
|
|
147
97
|
class BoolValue(Value):
|
|
148
|
-
@field_validator('value', mode='before')
|
|
149
|
-
@classmethod
|
|
150
|
-
def _from_python_type(cls, v:str| bool):
|
|
151
|
-
if isinstance(v, str):
|
|
152
|
-
return v
|
|
153
|
-
|
|
154
|
-
return 'T' if v else 'F'
|
|
155
98
|
|
|
156
99
|
@model_validator(mode='after')
|
|
157
100
|
def _validate(self):
|
|
@@ -164,21 +107,9 @@ class BoolValue(Value):
|
|
|
164
107
|
highlight_sub=[c for c in self.value]
|
|
165
108
|
)
|
|
166
109
|
return self
|
|
167
|
-
|
|
168
|
-
def _value_to_python_type(self) -> str:
|
|
169
|
-
if self.value == 'T':
|
|
170
|
-
return True
|
|
171
|
-
elif self.value == 'F':
|
|
172
|
-
return False
|
|
173
|
-
else:
|
|
174
|
-
Exception(f'{self} is not valid boolean. That really should not have been possible -- Contact the maintainers of the library')
|
|
175
|
-
|
|
110
|
+
|
|
176
111
|
|
|
177
112
|
class AlphanumericValue(Value):
|
|
178
|
-
@field_validator('value', mode='before')
|
|
179
|
-
@classmethod
|
|
180
|
-
def _from_python_type(cls, v:str):
|
|
181
|
-
return v
|
|
182
113
|
|
|
183
114
|
@model_validator(mode='after')
|
|
184
115
|
def _validate(self):
|
|
@@ -199,20 +130,9 @@ class AlphanumericValue(Value):
|
|
|
199
130
|
highlight_sub=not_allowed_chars
|
|
200
131
|
)
|
|
201
132
|
return self
|
|
202
|
-
|
|
203
|
-
def _value_to_python_type(self) -> str:
|
|
204
|
-
return self.value
|
|
205
|
-
|
|
133
|
+
|
|
206
134
|
|
|
207
135
|
class TextValue(Value):
|
|
208
|
-
@field_validator('value', mode='before')
|
|
209
|
-
@classmethod
|
|
210
|
-
def _from_python_type(cls, v:base36|str):
|
|
211
|
-
if isinstance(v, str):
|
|
212
|
-
logging.info('Got str for text value > converting to base36')
|
|
213
|
-
return to_base36(v).root
|
|
214
|
-
else:
|
|
215
|
-
return v.root
|
|
216
136
|
|
|
217
137
|
@model_validator(mode='after')
|
|
218
138
|
def _validate(self):
|
|
@@ -225,20 +145,9 @@ class TextValue(Value):
|
|
|
225
145
|
highlight_sub=not_allowed_chars
|
|
226
146
|
)
|
|
227
147
|
return self
|
|
228
|
-
|
|
229
|
-
def _value_to_python_type(self) -> str:
|
|
230
|
-
decoded = from_base36(self.value)
|
|
231
|
-
return decoded
|
|
232
|
-
|
|
148
|
+
|
|
233
149
|
|
|
234
150
|
class BinaryValue(Value):
|
|
235
|
-
@field_validator('value', mode='before')
|
|
236
|
-
@classmethod
|
|
237
|
-
def _from_python_type(cls, v:base36|str):
|
|
238
|
-
if isinstance(v, str):
|
|
239
|
-
return v
|
|
240
|
-
else:
|
|
241
|
-
return v.root
|
|
242
151
|
|
|
243
152
|
@model_validator(mode='after')
|
|
244
153
|
def _validate(self):
|
|
@@ -251,17 +160,9 @@ class BinaryValue(Value):
|
|
|
251
160
|
highlight_sub=not_allowed_chars
|
|
252
161
|
)
|
|
253
162
|
return self
|
|
254
|
-
|
|
255
|
-
def _value_to_python_type(self) -> bytes:
|
|
256
|
-
decoded = bytes(from_base36(self))
|
|
257
|
-
return decoded
|
|
258
|
-
|
|
163
|
+
|
|
259
164
|
|
|
260
165
|
class ErrorValue(Value):
|
|
261
|
-
@field_validator('value', mode='before')
|
|
262
|
-
@classmethod
|
|
263
|
-
def _from_python_type(cls, v:str):
|
|
264
|
-
return v
|
|
265
166
|
|
|
266
167
|
@model_validator(mode='after')
|
|
267
168
|
def _validate(self):
|
|
@@ -274,10 +175,6 @@ class ErrorValue(Value):
|
|
|
274
175
|
highlight_sub=not_allowed_chars
|
|
275
176
|
)
|
|
276
177
|
return self
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
def _value_to_python_type(self) -> str:
|
|
280
|
-
return self.value
|
|
281
178
|
|
|
282
179
|
|
|
283
180
|
class TREX_Segment(LabFREED_BaseModel, ABC):
|
|
@@ -305,31 +202,8 @@ class TREX_Segment(LabFREED_BaseModel, ABC):
|
|
|
305
202
|
|
|
306
203
|
|
|
307
204
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
def str_to_value_type(s:str, t:str):
|
|
311
|
-
match t:
|
|
312
|
-
case 'T.D':
|
|
313
|
-
v = DateValue(value=s)
|
|
314
|
-
case 'T.B':
|
|
315
|
-
v = BoolValue(value=s)
|
|
316
|
-
case 'T.A':
|
|
317
|
-
v = AlphanumericValue(value=s)
|
|
318
|
-
case 'T.T':
|
|
319
|
-
try:
|
|
320
|
-
value = base36(s)
|
|
321
|
-
except ValueError:
|
|
322
|
-
logging.error('String given as T.T contains characters which base36 should not')
|
|
323
|
-
value = s
|
|
324
|
-
v = TextValue(value=value)
|
|
325
|
-
case 'T.X':
|
|
326
|
-
v = BinaryValue(value=s)
|
|
327
|
-
case 'E' :
|
|
328
|
-
v = ErrorValue(value=s)
|
|
329
|
-
case _ :
|
|
330
|
-
v = NumericValue(value=s)
|
|
331
|
-
return v
|
|
332
|
-
|
|
205
|
+
|
|
206
|
+
|
|
333
207
|
|
|
334
208
|
|
|
335
209
|
|
|
@@ -89,19 +89,9 @@ def _deserialize_value_segment_from_trex_segment_str(trex_segment_str) -> ValueS
|
|
|
89
89
|
case 'T.A':
|
|
90
90
|
out = AlphanumericSegment(key=key, value=value, type=type_)
|
|
91
91
|
case 'T.T':
|
|
92
|
-
|
|
93
|
-
value = base36(value)
|
|
94
|
-
except ValueError:
|
|
95
|
-
logging.error('String given as T.T contains characters which base36 should not')
|
|
96
|
-
value = value
|
|
97
|
-
out = TextSegment(key=key, value=value, type=type_) # prevent repeated conversion from str to base36 and make explict that when parsing we assume the string tpo be base36 already
|
|
92
|
+
out = TextSegment(key=key, value=value, type=type_)
|
|
98
93
|
case 'T.X':
|
|
99
|
-
|
|
100
|
-
value = base36(value)
|
|
101
|
-
except ValueError:
|
|
102
|
-
logging.error('String given as T.X contains characters which base36 should not')
|
|
103
|
-
value = value
|
|
104
|
-
out = BinarySegment(key=key, value=value, type=type_) # prevent repeated conversion from str to base36 and make explict that when parsing we assume the string tpo be base36 already
|
|
94
|
+
out = BinarySegment(key=key, value=value, type=type_)
|
|
105
95
|
case 'E':
|
|
106
96
|
out = ErrorSegment(key=key, value=value, type=type_)
|
|
107
97
|
case _:
|
|
@@ -15,7 +15,7 @@ class DisplayNameExtension(ExtensionBase, LabFREED_BaseModel):
|
|
|
15
15
|
@property
|
|
16
16
|
def data(self)->str:
|
|
17
17
|
# return '/'.join([to_base36(dn) for dn in self.display_name])
|
|
18
|
-
return to_base36(self.display_name)
|
|
18
|
+
return to_base36(self.display_name).root
|
|
19
19
|
|
|
20
20
|
@staticmethod
|
|
21
21
|
def from_extension(ext:ExtensionBase) -> Self:
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{labfreed-0.2.2 → labfreed-0.2.3}/labfreed/well_known_extensions/default_extension_interpreters.py
RENAMED
|
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
|