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.
- labfreed-0.1.1/PKG-INFO +279 -0
- labfreed-0.1.1/README.md +265 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/examples.py +1 -1
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/IO/parse_pac.py +4 -3
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_CAT/data_model.py +39 -19
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID/data_model.py +20 -25
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID_Resolver/cit.yaml +1 -1
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID_Resolver/data_types.py +27 -1
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/TREX/data_model.py +14 -14
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/__init__.py +1 -1
- labfreed-0.1.1/labfreed/validation.py +243 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/main.py +5 -1
- {labfreed-0.1.0 → labfreed-0.1.1}/update_readme.py +4 -1
- labfreed-0.1.0/PKG-INFO +0 -266
- labfreed-0.1.0/README.md +0 -252
- labfreed-0.1.0/labfreed/validation.py +0 -159
- {labfreed-0.1.0 → labfreed-0.1.1}/.vscode/launch.json +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/.vscode/settings.json +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/LICENSE +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/cit_mine.yaml +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/DisplayNameExtension/DisplayNameExtension.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/IO/generate_qr.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_CAT/__init__.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID/__init__.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID/extensions.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/PAC_ID_Resolver/resolver.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/TREX/UneceUnits.json +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/TREX/parse.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/TREX/unece_units.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/utilities/base36.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/utilities/utility_types.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/labfreed/utilities/well_known_keys.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/publish.ps1 +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/publish.sh +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/publish_commands +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/pyproject.toml +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/pytest.ini +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_(de)_serialization_incl_extension/test__parse.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_(de)_serialization_incl_extension/test__serialize.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_PAC_CAT/test_PAC_CAT_parse.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_PAC_CAT/test_PAC_CAT_serialize.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_PAC_ID/test_PAC_ID_serialize.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_PAC_ID/test_pac_id_parse.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_TREX/test_TREX_parse.py +0 -0
- {labfreed-0.1.0 → labfreed-0.1.1}/tests/test_TREX/test_TREX_serialize.py +0 -0
labfreed-0.1.1/PKG-INFO
ADDED
|
@@ -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) [](https://pypi.org/project/labfreed/) 
|
|
17
|
+
|
|
18
|
+
<!--
|
|
19
|
+
[](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
|
+
|
labfreed-0.1.1/README.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# LabFREED for Python
|
|
2
|
+
|
|
3
|
+
[](LICENSE) [](https://pypi.org/project/labfreed/) 
|
|
4
|
+
|
|
5
|
+
<!--
|
|
6
|
+
[](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
|
|