labfreed 0.1.0__tar.gz → 0.1.1__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.

Files changed (45) hide show
  1. labfreed-0.1.1/PKG-INFO +279 -0
  2. labfreed-0.1.1/README.md +265 -0
  3. {labfreed-0.1.0 → labfreed-0.1.1}/examples.py +1 -1
  4. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/IO/parse_pac.py +4 -3
  5. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_CAT/data_model.py +39 -19
  6. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID/data_model.py +20 -25
  7. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID_Resolver/cit.yaml +1 -1
  8. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID_Resolver/data_types.py +27 -1
  9. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/TREX/data_model.py +14 -14
  10. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/__init__.py +1 -1
  11. labfreed-0.1.1/labfreed/validation.py +243 -0
  12. {labfreed-0.1.0 → labfreed-0.1.1}/main.py +5 -1
  13. {labfreed-0.1.0 → labfreed-0.1.1}/update_readme.py +4 -1
  14. labfreed-0.1.0/PKG-INFO +0 -266
  15. labfreed-0.1.0/README.md +0 -252
  16. labfreed-0.1.0/labfreed/validation.py +0 -159
  17. {labfreed-0.1.0 → labfreed-0.1.1}/.vscode/launch.json +0 -0
  18. {labfreed-0.1.0 → labfreed-0.1.1}/.vscode/settings.json +0 -0
  19. {labfreed-0.1.0 → labfreed-0.1.1}/LICENSE +0 -0
  20. {labfreed-0.1.0 → labfreed-0.1.1}/cit_mine.yaml +0 -0
  21. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/DisplayNameExtension/DisplayNameExtension.py +0 -0
  22. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/IO/generate_qr.py +0 -0
  23. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_CAT/__init__.py +0 -0
  24. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID/__init__.py +0 -0
  25. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID/extensions.py +0 -0
  26. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID_Resolver/resolver.py +0 -0
  27. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/TREX/UneceUnits.json +0 -0
  28. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/TREX/parse.py +0 -0
  29. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/TREX/unece_units.py +0 -0
  30. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/utilities/base36.py +0 -0
  31. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/utilities/utility_types.py +0 -0
  32. {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/utilities/well_known_keys.py +0 -0
  33. {labfreed-0.1.0 → labfreed-0.1.1}/publish.ps1 +0 -0
  34. {labfreed-0.1.0 → labfreed-0.1.1}/publish.sh +0 -0
  35. {labfreed-0.1.0 → labfreed-0.1.1}/publish_commands +0 -0
  36. {labfreed-0.1.0 → labfreed-0.1.1}/pyproject.toml +0 -0
  37. {labfreed-0.1.0 → labfreed-0.1.1}/pytest.ini +0 -0
  38. {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_(de)_serialization_incl_extension/test__parse.py +0 -0
  39. {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_(de)_serialization_incl_extension/test__serialize.py +0 -0
  40. {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_PAC_CAT/test_PAC_CAT_parse.py +0 -0
  41. {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_PAC_CAT/test_PAC_CAT_serialize.py +0 -0
  42. {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_PAC_ID/test_PAC_ID_serialize.py +0 -0
  43. {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_PAC_ID/test_pac_id_parse.py +0 -0
  44. {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_TREX/test_TREX_parse.py +0 -0
  45. {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_TREX/test_TREX_serialize.py +0 -0
@@ -0,0 +1,279 @@
1
+ Metadata-Version: 2.4
2
+ Name: labfreed
3
+ Version: 0.1.1
4
+ Summary: Python implementation of LabFREED building blocks
5
+ Author-email: Reto Thürer <thuerer.r@buchi.com>
6
+ Description-Content-Type: text/markdown
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Requires-Dist: numpy>=2.2.4
10
+ Requires-Dist: pydantic>=2.11.3
11
+ Requires-Dist: segno>=1.6.6
12
+ Requires-Dist: typer>=0.15.2
13
+
14
+ # LabFREED for Python
15
+
16
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![PyPI](https://img.shields.io/pypi/v/labfreed.svg)](https://pypi.org/project/labfreed/) ![Python Version](https://img.shields.io/pypi/pyversions/labfreed)
17
+
18
+ <!--
19
+ [![Tests](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml/badge.svg)](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml)
20
+ -->
21
+
22
+ This is a Python implementation of [LabFREED](https://labfreed.wega-it.com) building blocks.
23
+
24
+ ## Supported Building Blocks
25
+ - PAC-ID
26
+ - PAC-CAT
27
+ - TREX
28
+ - Display Extension
29
+ - PAC-ID Resolver
30
+
31
+ ## Installation
32
+ You can install LabFREED from [PyPI](https://pypi.org/project/labfreed/) using pip:
33
+
34
+ ```bash
35
+ pip install labfreed
36
+ ```
37
+
38
+
39
+ ## Usage Examples
40
+ > ⚠️ **Note:** These examples are building on each other. Imports and parsing are not repeated in each example.
41
+ <!-- BEGIN EXAMPLES -->
42
+ ```python
43
+ # import built ins
44
+ import os
45
+ ```
46
+ ### Parse a simple PAC-ID
47
+
48
+ ```python
49
+ from labfreed.IO.parse_pac import PAC_Parser
50
+
51
+
52
+ # Parse the PAC-ID
53
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
54
+ pac_id = PAC_Parser().parse(pac_str).pac_id
55
+
56
+ # Check validity of this PAC-ID
57
+ is_valid = pac_id.is_valid()
58
+ print(f'PAC-ID is valid: {is_valid}')
59
+ ```
60
+ ```text
61
+ >> PAC-ID is valid: True
62
+ ```
63
+ ### Show recommendations:
64
+ Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
65
+ There is a nice function to highlight problems
66
+
67
+ ```python
68
+ pac_id.print_validation_messages(target='markdown')
69
+ ```
70
+ ```text
71
+ >> Validation Results
72
+ >> ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
73
+ >> │ RECOMMENDATION │
74
+ >> │ Characters l a b should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
75
+ >> │ HTTPS://PAC.METTORIUS.COM/-MD/🔸b🔸🔸a🔸🔸l🔸500/@1234 │
76
+ >> ├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
77
+ >> │ RECOMMENDATION │
78
+ >> │ Characters @ should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
79
+ >> │ HTTPS://PAC.METTORIUS.COM/-MD/bal500/🔸@🔸1234 │
80
+ >> └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
81
+ ```
82
+ ### Save as QR Code
83
+
84
+ ```python
85
+ from labfreed.IO.generate_qr import save_qr_with_markers
86
+
87
+ save_qr_with_markers(pac_str, fmt='png')
88
+ ```
89
+ ```text
90
+ >> Large QR: Provided URL is not alphanumeric!
91
+ >> Size: 29
92
+ >> Version: 3
93
+ >> Error Level: M
94
+ ```
95
+ ### PAC-CAT
96
+
97
+ ```python
98
+ from labfreed.PAC_CAT.data_model import PAC_CAT
99
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-DR/XQ908756/-MD/bal500/@1234'
100
+ pac_id = PAC_Parser().parse(pac_str).pac_id
101
+ if isinstance(pac_id, PAC_CAT):
102
+ pac_id.print_categories()
103
+ ```
104
+ ```text
105
+ >> Categories in
106
+ >> HTTPS://PAC.METTORIUS.COM/-DR/XQ90
107
+ >> 8756/-MD/bal500/@1234
108
+ >> ┌────────────────────┬───────────┐
109
+ >> │ Main Category │ │
110
+ >> │ key () │ -DR │
111
+ >> │ id (21) │ XQ908756 │
112
+ >> ├────────────────────┼───────────┤
113
+ >> │ Category │ │
114
+ >> │ key () │ -MD │
115
+ >> │ model_number (240) │ bal500 │
116
+ >> │ serial_number (21) │ @1234 │
117
+ >> └────────────────────┴───────────┘
118
+ ```
119
+ ### Parse a PAC-ID with extensions
120
+ PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
121
+
122
+ ```python
123
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/WM633OV3E5DGJW2BEG0PDM1EA7*SUM$TREX/WEIGHT$GRM:67.89'
124
+ pac_id = PAC_Parser().parse(pac_str)
125
+
126
+ # Display Name
127
+ display_names = pac_id.get_extension('N') # display name has name 'N'
128
+ print(display_names)
129
+ ```
130
+ ```text
131
+ >> Display names: My Balance ❤️
132
+ ```
133
+ ```python
134
+ # TREX
135
+ trexes = pac_id.get_extension_of_type('TREX')
136
+ trex = trexes[0] # there could be multiple trexes. In this example there is only one, though
137
+ v = trex.get_segment('WEIGHT').to_python_type()
138
+ print(f'WEIGHT = {v}')
139
+ ```
140
+ ```text
141
+ >> WEIGHT = 67.89 g
142
+ ```
143
+ ### Create a PAC-ID with Extensions
144
+
145
+ #### Create PAC-ID
146
+
147
+ ```python
148
+ from labfreed.PAC_ID.data_model import PACID, IDSegment
149
+ from labfreed.utilities.well_known_keys import WellKnownKeys
150
+
151
+ pac_id = PACID(issuer='METTORIUS.COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
152
+ pac_str = pac_id.serialize()
153
+ print(pac_str)
154
+ ```
155
+ ```text
156
+ >> HTTPS://PAC.METTORIUS.COM/21:1234
157
+ ```
158
+ #### Create a TREX
159
+ TREX can conveniently be created from a python dictionary.
160
+ Note that utility types for Quantity (number with unit) and table are needed
161
+
162
+ ```python
163
+ from datetime import datetime
164
+ from labfreed.TREX.data_model import TREX
165
+ from labfreed.utilities.utility_types import Quantity, DataTable, Unit
166
+
167
+ # Create TREX
168
+ trex = TREX(name_='DEMO')
169
+ # Add value segments of different type
170
+ trex.update(
171
+ {
172
+ 'STOP': datetime(year=2024,month=5,day=5,hour=13,minute=6),
173
+ 'TEMP': Quantity(value=10.15, unit=Unit(name='kelvin', symbol='K')),
174
+ 'OK':False,
175
+ 'COMMENT': 'FOO',
176
+ 'COMMENT2':'£'
177
+ }
178
+ )
179
+
180
+ # Create a table
181
+ table = DataTable(['DURATION', 'Date', 'OK', 'COMMENT'])
182
+ table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
183
+ table.append([ 1.1, datetime.now(), True, 'BAR'])
184
+ table.append([ 1.3, datetime.now(), False, 'BLUBB'])
185
+ #add the table to the trex
186
+ trex.update({'TABLE': table})
187
+
188
+ # Validation also works the same way for TREX
189
+ trex.print_validation_messages(target='markdown')
190
+ ```
191
+ ```text
192
+ >> Validation Results
193
+ >> ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
194
+ >> │ ERROR │
195
+ >> │ Column header key contains invalid characters: e,a,t │
196
+ >> │ DEMO$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:D🔸a🔸🔸t🔸🔸e🔸$T.D:OK$T.B:COMMENT$T.A::1:20250411T090300.103:T:FOO::1… │
197
+ >> └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
198
+ ```
199
+ ```python
200
+ # there is an error. 'Date' uses lower case. Lets fix it
201
+ d = trex.dict()
202
+ d['TABLE'].col_names[1] = 'DATE'
203
+ trex = TREX(name_='DEMO')
204
+ trex.update(d)
205
+ ```
206
+ #### Combine PAC-ID and TREX and serialize
207
+
208
+ ```python
209
+ from labfreed.IO.parse_pac import PACID_With_Extensions
210
+
211
+ pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
212
+ pac_str = pac_with_trex.serialize()
213
+ print(pac_str)
214
+ ```
215
+ ```text
216
+ >> HTTPS://PAC.METTORIUS.COM/21:1234*DEMO$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:20250411T090300.103:T:FOO::1.1:20250411T090300.103:T:BAR::1.3:20250411T090300.103:F:BLUBB
217
+ ```
218
+ ## PAC-ID Resolver
219
+
220
+ ```python
221
+ from labfreed.PAC_ID_Resolver.resolver import PAC_ID_Resolver, load_cit
222
+ # Get a CIT
223
+ dir = os.path.dirname(__file__)
224
+ p = os.path.join(dir, 'cit_mine.yaml')
225
+ cit = load_cit(p)
226
+
227
+ # validate the CIT
228
+ cit.is_valid()
229
+ cit.print_validation_messages()
230
+ ```
231
+ ```python
232
+ # resolve a pac id
233
+ service_groups = PAC_ID_Resolver(cits=[cit]).resolve(pac_with_trex)
234
+ for sg in service_groups:
235
+ sg.update_states()
236
+ sg.print()
237
+
238
+ 5
239
+ ```
240
+ ```text
241
+ >> Request failed: HTTPSConnectionPool(host='aaaaaaaaaaaa.mettorius.com.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL:
242
+ >> SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1028)')))
243
+ >> Services from origin 'MINE
244
+ >> ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
245
+ >> ┃ Service Name ┃ URL ┃ Reachable ┃
246
+ >> ┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
247
+ >> │ AAAAAAAAAAAAAAAAAAhhhhhh │ https://AAAAAAAAAAAA.METTORIUS.COM.com/ │ INACTIVE │
248
+ >> └──────────────────────────┴─────────────────────────────────────────┴───────────┘
249
+ >> Services from origin 'PAC.METTORIUS.COM
250
+ >> ┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
251
+ >> ┃ Service Name ┃ URL ┃ Reachable ┃
252
+ >> ┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
253
+ >> │ Shop │ https://mettorius.com/shop/an= │ INACTIVE │
254
+ >> │ Manual │ https://mettorius.com/om/an= │ INACTIVE │
255
+ >> │ _3 │ https://mettorius.com/ │ ACTIVE │
256
+ >> └──────────────┴────────────────────────────────┴───────────┘
257
+ ```
258
+ <!-- END EXAMPLES -->
259
+
260
+
261
+
262
+ ## Change Log
263
+
264
+ ### v0.1.1
265
+ - minor internal improvements and bugfixes
266
+
267
+ ### v0.1.0
268
+ - DRAFT Support for PAC-ID Resolver
269
+
270
+ ### v0.0.20
271
+ - bugfix in TREX table to dict conversion
272
+ - markdown compatible validation printing
273
+
274
+ ### v0.0.19
275
+ - supports PAC-ID, PAC-CAT, TREX and DisplayName
276
+ - QR generation
277
+ - ok-ish test coverage
278
+
279
+
@@ -0,0 +1,265 @@
1
+ # LabFREED for Python
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![PyPI](https://img.shields.io/pypi/v/labfreed.svg)](https://pypi.org/project/labfreed/) ![Python Version](https://img.shields.io/pypi/pyversions/labfreed)
4
+
5
+ <!--
6
+ [![Tests](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml/badge.svg)](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml)
7
+ -->
8
+
9
+ This is a Python implementation of [LabFREED](https://labfreed.wega-it.com) building blocks.
10
+
11
+ ## Supported Building Blocks
12
+ - PAC-ID
13
+ - PAC-CAT
14
+ - TREX
15
+ - Display Extension
16
+ - PAC-ID Resolver
17
+
18
+ ## Installation
19
+ You can install LabFREED from [PyPI](https://pypi.org/project/labfreed/) using pip:
20
+
21
+ ```bash
22
+ pip install labfreed
23
+ ```
24
+
25
+
26
+ ## Usage Examples
27
+ > ⚠️ **Note:** These examples are building on each other. Imports and parsing are not repeated in each example.
28
+ <!-- BEGIN EXAMPLES -->
29
+ ```python
30
+ # import built ins
31
+ import os
32
+ ```
33
+ ### Parse a simple PAC-ID
34
+
35
+ ```python
36
+ from labfreed.IO.parse_pac import PAC_Parser
37
+
38
+
39
+ # Parse the PAC-ID
40
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
41
+ pac_id = PAC_Parser().parse(pac_str).pac_id
42
+
43
+ # Check validity of this PAC-ID
44
+ is_valid = pac_id.is_valid()
45
+ print(f'PAC-ID is valid: {is_valid}')
46
+ ```
47
+ ```text
48
+ >> PAC-ID is valid: True
49
+ ```
50
+ ### Show recommendations:
51
+ Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
52
+ There is a nice function to highlight problems
53
+
54
+ ```python
55
+ pac_id.print_validation_messages(target='markdown')
56
+ ```
57
+ ```text
58
+ >> Validation Results
59
+ >> ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
60
+ >> │ RECOMMENDATION │
61
+ >> │ Characters l a b should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
62
+ >> │ HTTPS://PAC.METTORIUS.COM/-MD/🔸b🔸🔸a🔸🔸l🔸500/@1234 │
63
+ >> ├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
64
+ >> │ RECOMMENDATION │
65
+ >> │ Characters @ should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
66
+ >> │ HTTPS://PAC.METTORIUS.COM/-MD/bal500/🔸@🔸1234 │
67
+ >> └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
68
+ ```
69
+ ### Save as QR Code
70
+
71
+ ```python
72
+ from labfreed.IO.generate_qr import save_qr_with_markers
73
+
74
+ save_qr_with_markers(pac_str, fmt='png')
75
+ ```
76
+ ```text
77
+ >> Large QR: Provided URL is not alphanumeric!
78
+ >> Size: 29
79
+ >> Version: 3
80
+ >> Error Level: M
81
+ ```
82
+ ### PAC-CAT
83
+
84
+ ```python
85
+ from labfreed.PAC_CAT.data_model import PAC_CAT
86
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-DR/XQ908756/-MD/bal500/@1234'
87
+ pac_id = PAC_Parser().parse(pac_str).pac_id
88
+ if isinstance(pac_id, PAC_CAT):
89
+ pac_id.print_categories()
90
+ ```
91
+ ```text
92
+ >> Categories in
93
+ >> HTTPS://PAC.METTORIUS.COM/-DR/XQ90
94
+ >> 8756/-MD/bal500/@1234
95
+ >> ┌────────────────────┬───────────┐
96
+ >> │ Main Category │ │
97
+ >> │ key () │ -DR │
98
+ >> │ id (21) │ XQ908756 │
99
+ >> ├────────────────────┼───────────┤
100
+ >> │ Category │ │
101
+ >> │ key () │ -MD │
102
+ >> │ model_number (240) │ bal500 │
103
+ >> │ serial_number (21) │ @1234 │
104
+ >> └────────────────────┴───────────┘
105
+ ```
106
+ ### Parse a PAC-ID with extensions
107
+ PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
108
+
109
+ ```python
110
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/WM633OV3E5DGJW2BEG0PDM1EA7*SUM$TREX/WEIGHT$GRM:67.89'
111
+ pac_id = PAC_Parser().parse(pac_str)
112
+
113
+ # Display Name
114
+ display_names = pac_id.get_extension('N') # display name has name 'N'
115
+ print(display_names)
116
+ ```
117
+ ```text
118
+ >> Display names: My Balance ❤️
119
+ ```
120
+ ```python
121
+ # TREX
122
+ trexes = pac_id.get_extension_of_type('TREX')
123
+ trex = trexes[0] # there could be multiple trexes. In this example there is only one, though
124
+ v = trex.get_segment('WEIGHT').to_python_type()
125
+ print(f'WEIGHT = {v}')
126
+ ```
127
+ ```text
128
+ >> WEIGHT = 67.89 g
129
+ ```
130
+ ### Create a PAC-ID with Extensions
131
+
132
+ #### Create PAC-ID
133
+
134
+ ```python
135
+ from labfreed.PAC_ID.data_model import PACID, IDSegment
136
+ from labfreed.utilities.well_known_keys import WellKnownKeys
137
+
138
+ pac_id = PACID(issuer='METTORIUS.COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
139
+ pac_str = pac_id.serialize()
140
+ print(pac_str)
141
+ ```
142
+ ```text
143
+ >> HTTPS://PAC.METTORIUS.COM/21:1234
144
+ ```
145
+ #### Create a TREX
146
+ TREX can conveniently be created from a python dictionary.
147
+ Note that utility types for Quantity (number with unit) and table are needed
148
+
149
+ ```python
150
+ from datetime import datetime
151
+ from labfreed.TREX.data_model import TREX
152
+ from labfreed.utilities.utility_types import Quantity, DataTable, Unit
153
+
154
+ # Create TREX
155
+ trex = TREX(name_='DEMO')
156
+ # Add value segments of different type
157
+ trex.update(
158
+ {
159
+ 'STOP': datetime(year=2024,month=5,day=5,hour=13,minute=6),
160
+ 'TEMP': Quantity(value=10.15, unit=Unit(name='kelvin', symbol='K')),
161
+ 'OK':False,
162
+ 'COMMENT': 'FOO',
163
+ 'COMMENT2':'£'
164
+ }
165
+ )
166
+
167
+ # Create a table
168
+ table = DataTable(['DURATION', 'Date', 'OK', 'COMMENT'])
169
+ table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
170
+ table.append([ 1.1, datetime.now(), True, 'BAR'])
171
+ table.append([ 1.3, datetime.now(), False, 'BLUBB'])
172
+ #add the table to the trex
173
+ trex.update({'TABLE': table})
174
+
175
+ # Validation also works the same way for TREX
176
+ trex.print_validation_messages(target='markdown')
177
+ ```
178
+ ```text
179
+ >> Validation Results
180
+ >> ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
181
+ >> │ ERROR │
182
+ >> │ Column header key contains invalid characters: e,a,t │
183
+ >> │ DEMO$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:D🔸a🔸🔸t🔸🔸e🔸$T.D:OK$T.B:COMMENT$T.A::1:20250411T090300.103:T:FOO::1… │
184
+ >> └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
185
+ ```
186
+ ```python
187
+ # there is an error. 'Date' uses lower case. Lets fix it
188
+ d = trex.dict()
189
+ d['TABLE'].col_names[1] = 'DATE'
190
+ trex = TREX(name_='DEMO')
191
+ trex.update(d)
192
+ ```
193
+ #### Combine PAC-ID and TREX and serialize
194
+
195
+ ```python
196
+ from labfreed.IO.parse_pac import PACID_With_Extensions
197
+
198
+ pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
199
+ pac_str = pac_with_trex.serialize()
200
+ print(pac_str)
201
+ ```
202
+ ```text
203
+ >> HTTPS://PAC.METTORIUS.COM/21:1234*DEMO$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:20250411T090300.103:T:FOO::1.1:20250411T090300.103:T:BAR::1.3:20250411T090300.103:F:BLUBB
204
+ ```
205
+ ## PAC-ID Resolver
206
+
207
+ ```python
208
+ from labfreed.PAC_ID_Resolver.resolver import PAC_ID_Resolver, load_cit
209
+ # Get a CIT
210
+ dir = os.path.dirname(__file__)
211
+ p = os.path.join(dir, 'cit_mine.yaml')
212
+ cit = load_cit(p)
213
+
214
+ # validate the CIT
215
+ cit.is_valid()
216
+ cit.print_validation_messages()
217
+ ```
218
+ ```python
219
+ # resolve a pac id
220
+ service_groups = PAC_ID_Resolver(cits=[cit]).resolve(pac_with_trex)
221
+ for sg in service_groups:
222
+ sg.update_states()
223
+ sg.print()
224
+
225
+ 5
226
+ ```
227
+ ```text
228
+ >> Request failed: HTTPSConnectionPool(host='aaaaaaaaaaaa.mettorius.com.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL:
229
+ >> SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1028)')))
230
+ >> Services from origin 'MINE
231
+ >> ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
232
+ >> ┃ Service Name ┃ URL ┃ Reachable ┃
233
+ >> ┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
234
+ >> │ AAAAAAAAAAAAAAAAAAhhhhhh │ https://AAAAAAAAAAAA.METTORIUS.COM.com/ │ INACTIVE │
235
+ >> └──────────────────────────┴─────────────────────────────────────────┴───────────┘
236
+ >> Services from origin 'PAC.METTORIUS.COM
237
+ >> ┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
238
+ >> ┃ Service Name ┃ URL ┃ Reachable ┃
239
+ >> ┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
240
+ >> │ Shop │ https://mettorius.com/shop/an= │ INACTIVE │
241
+ >> │ Manual │ https://mettorius.com/om/an= │ INACTIVE │
242
+ >> │ _3 │ https://mettorius.com/ │ ACTIVE │
243
+ >> └──────────────┴────────────────────────────────┴───────────┘
244
+ ```
245
+ <!-- END EXAMPLES -->
246
+
247
+
248
+
249
+ ## Change Log
250
+
251
+ ### v0.1.1
252
+ - minor internal improvements and bugfixes
253
+
254
+ ### v0.1.0
255
+ - DRAFT Support for PAC-ID Resolver
256
+
257
+ ### v0.0.20
258
+ - bugfix in TREX table to dict conversion
259
+ - markdown compatible validation printing
260
+
261
+ ### v0.0.19
262
+ - supports PAC-ID, PAC-CAT, TREX and DisplayName
263
+ - QR generation
264
+ - ok-ish test coverage
265
+
@@ -11,7 +11,6 @@ pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
11
11
  pac_id = PAC_Parser().parse(pac_str).pac_id
12
12
 
13
13
  # Check validity of this PAC-ID
14
- pac_id = PAC_Parser().parse(pac_str).pac_id
15
14
  is_valid = pac_id.is_valid()
16
15
  print(f'PAC-ID is valid: {is_valid}')
17
16
 
@@ -142,6 +141,7 @@ cit.print_validation_messages()
142
141
  # resolve a pac id
143
142
  service_groups = PAC_ID_Resolver(cits=[cit]).resolve(pac_with_trex)
144
143
  for sg in service_groups:
144
+ sg.update_states()
145
145
  sg.print()
146
146
 
147
147
  5
@@ -25,6 +25,7 @@ class PACID_With_Extensions(BaseModelWithValidationMessages):
25
25
  def __str__(self):
26
26
  out = str(self.pac_id)
27
27
  out += '*'.join(str(e) for e in self.extensions)
28
+ return out
28
29
 
29
30
  def get_extension_of_type(self, type:str) -> list[Extension]:
30
31
  return [e for e in self.extensions if e.type == type]
@@ -87,7 +88,7 @@ class PAC_Parser():
87
88
  def __init__(self, extension_interpreters:dict[str, Extension]=None):
88
89
  self.extension_interpreters = extension_interpreters or {'TREX': TREX, 'N': DisplayNames}
89
90
 
90
- def parse(self, pac_url:str) -> PACID_With_Extensions:
91
+ def parse(self, pac_url:str, suppress_errors=False) -> PACID_With_Extensions:
91
92
  if '*' in pac_url:
92
93
  id_str, ext_str = pac_url.split('*', 1)
93
94
  else:
@@ -98,8 +99,8 @@ class PAC_Parser():
98
99
  extensions = self._parse_extensions(ext_str)
99
100
 
100
101
  pac_with_extension = PACID_With_Extensions(pac_id=pac_id, extensions=extensions)
101
- if not pac_with_extension.is_valid():
102
- raise LabFREEDValidationError(validation_msgs = pac_with_extension.get_nested_validation_messages())
102
+ if not pac_with_extension.is_valid() and not suppress_errors:
103
+ raise LabFREEDValidationError(validation_msgs = pac_with_extension.get_nested_validation_messages(), model=pac_with_extension)
103
104
 
104
105
  return pac_with_extension
105
106