labfreed 0.2.0b2__tar.gz → 0.2.2__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/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
- labfreed-0.2.2/.github/workflows/run-tests.yml +25 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/CHANGELOG.md +6 -6
- {labfreed-0.2.0b2 → labfreed-0.2.2}/PKG-INFO +64 -34
- {labfreed-0.2.0b2 → labfreed-0.2.2}/README.md +62 -33
- labfreed-0.2.2/labfreed/__init__.py +11 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/labfreed_infrastructure.py +22 -8
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_cat/__init__.py +4 -1
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_cat/category_base.py +1 -1
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_cat/pac_cat.py +4 -13
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_cat/predefined_categories.py +11 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id_resolver/cit_v1.py +1 -1
- {labfreed-0.2.0b2 → labfreed-0.2.2}/pyproject.toml +1 -0
- labfreed-0.2.0b2/labfreed/__init__.py +0 -8
- {labfreed-0.2.0b2 → labfreed-0.2.2}/.github/workflows/pypi-publish.yml +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/LICENSE +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id/__init__.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id/extension.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id/id_segment.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id/pac_id.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id/url_parser.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id/url_serializer.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id_resolver/__init__.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id_resolver/cit_v2.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id_resolver/resolver.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/pac_id_resolver/services.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/qr/__init__.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/qr/generate_qr.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/__init__.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/python_convenience/__init__.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/python_convenience/data_table.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/python_convenience/pyTREX.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/python_convenience/quantity.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/table_segment.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/trex.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/trex_base_models.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/trex/value_segments.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/utilities/base36.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_extensions/__init__.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_extensions/default_extension_interpreters.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_extensions/display_name_extension.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_extensions/trex_extension.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_keys/gs1/__init__.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_keys/gs1/gs1.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_keys/gs1/gs1_ai_enum_sorted.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_keys/labfreed/well_known_keys.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_keys/unece/UneceUnits.json +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_keys/unece/__init__.py +0 -0
- {labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_keys/unece/unece_units.py +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Create a report to help us improve
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
**Describe the bug**
|
|
11
|
+
A clear and concise description of what the bug is.
|
|
12
|
+
|
|
13
|
+
**To Reproduce**
|
|
14
|
+
Steps to reproduce the behavior:
|
|
15
|
+
1. Go to '...'
|
|
16
|
+
2. Click on '....'
|
|
17
|
+
3. Scroll down to '....'
|
|
18
|
+
4. See error
|
|
19
|
+
|
|
20
|
+
**Expected behavior**
|
|
21
|
+
A clear and concise description of what you expected to happen.
|
|
22
|
+
|
|
23
|
+
**Screenshots**
|
|
24
|
+
If applicable, add screenshots to help explain your problem.
|
|
25
|
+
|
|
26
|
+
**Environment(please complete the following information):**
|
|
27
|
+
- Python version[e.g. 22]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
**Additional context**
|
|
31
|
+
Add any other context about the problem here.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Test Labfreed
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v3
|
|
14
|
+
- name: Set up Python
|
|
15
|
+
uses: actions/setup-python@v4
|
|
16
|
+
with:
|
|
17
|
+
python-version: '3.11'
|
|
18
|
+
|
|
19
|
+
- name: Install project with dev dependencies
|
|
20
|
+
run: |
|
|
21
|
+
pip install flit
|
|
22
|
+
flit install --deps develop
|
|
23
|
+
|
|
24
|
+
- name: Run tests
|
|
25
|
+
run: pytest
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
## Change Log
|
|
2
|
+
### v0.2.2
|
|
3
|
+
- minor changes for better access of subfunctions. No change in existing API
|
|
4
|
+
|
|
5
|
+
### v0.2.1
|
|
6
|
+
- improved docu. no code changes
|
|
7
|
+
|
|
2
8
|
### v0.2.0b2
|
|
3
9
|
- improvements in api consistency and ease of use
|
|
4
10
|
- restructured code for better separation of concerns
|
|
@@ -19,11 +25,5 @@
|
|
|
19
25
|
- QR generation
|
|
20
26
|
- ok-ish test coverage
|
|
21
27
|
|
|
22
|
-
# Attributions
|
|
23
|
-
The following tools were used:
|
|
24
|
-
- [pdoc](https://pdoc.dev/) was a great help with generating documentation
|
|
25
|
-
- [Pydantic](https://docs.pydantic.dev/latest/)
|
|
26
|
-
- json with UNECE units from (https://github.com/quadient/unece-units/blob/main/python/src/unece_excel_parser/parsedUneceUnits.json)
|
|
27
|
-
- json with GS1 codes from (https://ref.gs1.org/ai/GS1_Application_Identifiers.jsonld)
|
|
28
28
|
|
|
29
29
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: labfreed
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
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
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
9
|
Classifier: Programming Language :: Python
|
|
9
10
|
Classifier: Programming Language :: Python :: 3
|
|
10
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -30,11 +31,8 @@ Provides-Extra: dev
|
|
|
30
31
|
|
|
31
32
|
# LabFREED for Python
|
|
32
33
|
|
|
33
|
-
[](https://pypi.org/project/labfreed/)  [](https://github.com/retothuerer/LabFREED/actions/workflows/run-tests.yml) [](LICENSE)
|
|
34
35
|
|
|
35
|
-
<!--
|
|
36
|
-
[](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml)
|
|
37
|
-
-->
|
|
38
36
|
|
|
39
37
|
This is a Python implementation of [LabFREED](https://labfreed.wega-it.com) building blocks.
|
|
40
38
|
|
|
@@ -72,14 +70,13 @@ pip install labfreed
|
|
|
72
70
|
# import built ins
|
|
73
71
|
import os
|
|
74
72
|
|
|
75
|
-
|
|
73
|
+
|
|
76
74
|
```
|
|
77
75
|
### Parse a simple PAC-ID
|
|
78
76
|
|
|
79
77
|
```python
|
|
80
78
|
# Parse the PAC-ID
|
|
81
|
-
from labfreed
|
|
82
|
-
from labfreed import PAC_ID, LabFREED_ValidationError # noqa: E402, F811
|
|
79
|
+
from labfreed import PAC_ID, LabFREED_ValidationError
|
|
83
80
|
|
|
84
81
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
85
82
|
try:
|
|
@@ -98,36 +95,36 @@ Note that the PAC-ID -- while valid -- uses characters which are not recommended
|
|
|
98
95
|
There is a nice function to highlight problems
|
|
99
96
|
|
|
100
97
|
```python
|
|
101
|
-
pac.print_validation_messages(
|
|
98
|
+
pac.print_validation_messages()
|
|
102
99
|
```
|
|
103
100
|
```text
|
|
104
101
|
>> Validation Results
|
|
105
102
|
>> ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
106
103
|
>> │ RECOMMENDATION in id segment value bal500 │
|
|
107
|
-
>> │ Characters 'b','
|
|
104
|
+
>> │ Characters 'b','l','a' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
108
105
|
>> │ │
|
|
109
|
-
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240
|
|
106
|
+
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:👉bal👈500/21:@1234 │
|
|
110
107
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
111
108
|
>> │ RECOMMENDATION in id segment value @1234 │
|
|
112
109
|
>> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
113
110
|
>> │ │
|
|
114
|
-
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21
|
|
111
|
+
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:👉@👈1234 │
|
|
115
112
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
116
113
|
>> │ RECOMMENDATION in id segment value bal500 │
|
|
117
|
-
>> │ Characters 'b','
|
|
114
|
+
>> │ Characters 'b','l','a' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
118
115
|
>> │ │
|
|
119
|
-
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240
|
|
116
|
+
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:👉bal👈500/21:@1234 │
|
|
120
117
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
121
118
|
>> │ RECOMMENDATION in id segment value @1234 │
|
|
122
119
|
>> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
123
120
|
>> │ │
|
|
124
|
-
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21
|
|
121
|
+
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:👉@👈1234 │
|
|
125
122
|
>> └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
126
123
|
```
|
|
127
124
|
### Save as QR Code
|
|
128
125
|
|
|
129
126
|
```python
|
|
130
|
-
from labfreed.qr import save_qr_with_markers
|
|
127
|
+
from labfreed.qr import save_qr_with_markers
|
|
131
128
|
|
|
132
129
|
save_qr_with_markers(pac_str, fmt='png')
|
|
133
130
|
```
|
|
@@ -142,7 +139,7 @@ PAC-CAT defines a (optional) way how the identifier is structured.
|
|
|
142
139
|
PAC_ID.from_url() automatically converts to PAC-CAT if possible.
|
|
143
140
|
|
|
144
141
|
```python
|
|
145
|
-
from labfreed
|
|
142
|
+
from labfreed import PAC_CAT
|
|
146
143
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-DR/XQ908756/-MD/bal500/@1234'
|
|
147
144
|
pac = PAC_ID.from_url(pac_str)
|
|
148
145
|
if isinstance(pac, PAC_CAT):
|
|
@@ -198,8 +195,8 @@ print(f'WEIGHT = {v.value}')
|
|
|
198
195
|
#### Create PAC-ID
|
|
199
196
|
|
|
200
197
|
```python
|
|
201
|
-
from labfreed
|
|
202
|
-
from labfreed.well_known_keys.labfreed.well_known_keys import WellKnownKeys
|
|
198
|
+
from labfreed import PAC_ID, IDSegment
|
|
199
|
+
from labfreed.well_known_keys.labfreed.well_known_keys import WellKnownKeys
|
|
203
200
|
|
|
204
201
|
pac = PAC_ID(issuer='METTORIUS.COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
|
|
205
202
|
pac_str = pac.to_url()
|
|
@@ -213,10 +210,10 @@ TREX can conveniently be created from a python dictionary.
|
|
|
213
210
|
Note that utility types for Quantity (number with unit) and table are needed
|
|
214
211
|
|
|
215
212
|
```python
|
|
216
|
-
from datetime import datetime
|
|
217
|
-
from labfreed.trex.python_convenience
|
|
218
|
-
from labfreed.trex.python_convenience
|
|
219
|
-
from labfreed.trex.python_convenience
|
|
213
|
+
from datetime import datetime
|
|
214
|
+
from labfreed.trex.python_convenience import pyTREX
|
|
215
|
+
from labfreed.trex.python_convenience import DataTable
|
|
216
|
+
from labfreed.trex.python_convenience import Quantity
|
|
220
217
|
|
|
221
218
|
# Value segments of different type
|
|
222
219
|
segments = {
|
|
@@ -241,40 +238,40 @@ trex = mydata.to_trex()
|
|
|
241
238
|
|
|
242
239
|
|
|
243
240
|
# Validation also works the same way for TREX
|
|
244
|
-
trex.print_validation_messages(
|
|
241
|
+
trex.print_validation_messages()
|
|
245
242
|
```
|
|
246
243
|
```text
|
|
247
244
|
>> Validation Results
|
|
248
245
|
>> ┌────────────────────────────────────────────────────────────┐
|
|
249
246
|
>> │ ERROR in TREX table column Date │
|
|
250
|
-
>> │ Column header key contains invalid characters: '
|
|
247
|
+
>> │ Column header key contains invalid characters: 'e','t','a' │
|
|
251
248
|
>> │ │
|
|
252
249
|
>> │ STOP$T.D:20240505T1306 │
|
|
253
250
|
>> │ +TEMP$KEL:10.15 │
|
|
254
251
|
>> │ +OK$T.B:F │
|
|
255
252
|
>> │ +COMMENT$T.A:FOO │
|
|
256
253
|
>> │ +COMMENT2$T.T:QMDTNXIKU │
|
|
257
|
-
>> │ +TABLE$$DURATION$HUR:
|
|
258
|
-
>> │ 1:
|
|
259
|
-
>> │ 1.1:
|
|
260
|
-
>> │ 1.3:
|
|
254
|
+
>> │ +TABLE$$DURATION$HUR:D👉ate👈$T.D:OK$T.B:COMMENT$T.A:: │
|
|
255
|
+
>> │ 1:20250424T200626.801:T:FOO:: │
|
|
256
|
+
>> │ 1.1:20250424T200626.801:T:BAR:: │
|
|
257
|
+
>> │ 1.3:20250424T200626.801:F:BLUBB │
|
|
261
258
|
>> └────────────────────────────────────────────────────────────┘
|
|
262
259
|
```
|
|
263
260
|
#### Combine PAC-ID and TREX and serialize
|
|
264
261
|
|
|
265
262
|
```python
|
|
266
|
-
from labfreed.well_known_extensions import TREX_Extension
|
|
263
|
+
from labfreed.well_known_extensions import TREX_Extension
|
|
267
264
|
pac.extensions = [TREX_Extension(name='MYTREX', trex=trex)]
|
|
268
265
|
pac_str = pac.to_url()
|
|
269
266
|
print(pac_str)
|
|
270
267
|
```
|
|
271
268
|
```text
|
|
272
|
-
>> 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:QMDTNXIKU+TABLE$$DURATION$HUR:Date$T.D:OK$T.B:COMMENT$T.A::1:
|
|
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:QMDTNXIKU+TABLE$$DURATION$HUR:Date$T.D:OK$T.B:COMMENT$T.A::1:20250424T200626.801:T:FOO::1.1:20250424T200626.801:T:BAR::1.3:20250424T200626.801:F:BLUBB
|
|
273
270
|
```
|
|
274
271
|
## PAC-ID Resolver
|
|
275
272
|
|
|
276
273
|
```python
|
|
277
|
-
from labfreed
|
|
274
|
+
from labfreed import PAC_ID_Resolver, load_cit
|
|
278
275
|
# Get a CIT
|
|
279
276
|
dir = os.path.join(os.getcwd(), 'examples')
|
|
280
277
|
p = os.path.join(dir, 'cit_mine.yaml')
|
|
@@ -282,7 +279,7 @@ cit = load_cit(p)
|
|
|
282
279
|
|
|
283
280
|
# validate the CIT
|
|
284
281
|
cit.is_valid
|
|
285
|
-
cit.print_validation_messages(
|
|
282
|
+
cit.print_validation_messages()
|
|
286
283
|
```
|
|
287
284
|
```python
|
|
288
285
|
# get a second cit
|
|
@@ -325,6 +322,39 @@ for sg in service_groups:
|
|
|
325
322
|
|
|
326
323
|
|
|
327
324
|
|
|
325
|
+
<!-- BEGIN CHANGELOG -->
|
|
328
326
|
## Change Log
|
|
329
|
-
|
|
327
|
+
### v0.2.2
|
|
328
|
+
- minor changes for better access of subfunctions. No change in existing API
|
|
329
|
+
|
|
330
|
+
### v0.2.1
|
|
331
|
+
- improved docu. no code changes
|
|
332
|
+
|
|
333
|
+
### v0.2.0b2
|
|
334
|
+
- improvements in api consistency and ease of use
|
|
335
|
+
- restructured code for better separation of concerns
|
|
336
|
+
- support for coupling information table v1
|
|
337
|
+
|
|
338
|
+
### v0.1.1
|
|
339
|
+
- minor internal improvements and bugfixes
|
|
340
|
+
|
|
341
|
+
### v0.1.0
|
|
342
|
+
- DRAFT Support for PAC-ID Resolver
|
|
343
|
+
|
|
344
|
+
### v0.0.20
|
|
345
|
+
- bugfix in TREX table to dict conversion
|
|
346
|
+
- markdown compatible validation printing
|
|
347
|
+
|
|
348
|
+
### v0.0.19
|
|
349
|
+
- supports PAC-ID, PAC-CAT, TREX and DisplayName
|
|
350
|
+
- QR generation
|
|
351
|
+
- ok-ish test coverage
|
|
352
|
+
<!-- END CHANGELOG -->
|
|
353
|
+
|
|
354
|
+
# Attributions
|
|
355
|
+
The following tools were used:
|
|
356
|
+
- [pdoc](https://pdoc.dev/) was a great help with generating documentation
|
|
357
|
+
- [Pydantic](https://docs.pydantic.dev/latest/)
|
|
358
|
+
- json with UNECE units from (https://github.com/quadient/unece-units/blob/main/python/src/unece_excel_parser/parsedUneceUnits.json)
|
|
359
|
+
- json with GS1 codes from (https://ref.gs1.org/ai/GS1_Application_Identifiers.jsonld)
|
|
330
360
|
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
# LabFREED for Python
|
|
2
2
|
|
|
3
|
-
[](https://pypi.org/project/labfreed/)  [](https://github.com/retothuerer/LabFREED/actions/workflows/run-tests.yml) [](LICENSE)
|
|
4
4
|
|
|
5
|
-
<!--
|
|
6
|
-
[](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml)
|
|
7
|
-
-->
|
|
8
5
|
|
|
9
6
|
This is a Python implementation of [LabFREED](https://labfreed.wega-it.com) building blocks.
|
|
10
7
|
|
|
@@ -42,14 +39,13 @@ pip install labfreed
|
|
|
42
39
|
# import built ins
|
|
43
40
|
import os
|
|
44
41
|
|
|
45
|
-
|
|
42
|
+
|
|
46
43
|
```
|
|
47
44
|
### Parse a simple PAC-ID
|
|
48
45
|
|
|
49
46
|
```python
|
|
50
47
|
# Parse the PAC-ID
|
|
51
|
-
from labfreed
|
|
52
|
-
from labfreed import PAC_ID, LabFREED_ValidationError # noqa: E402, F811
|
|
48
|
+
from labfreed import PAC_ID, LabFREED_ValidationError
|
|
53
49
|
|
|
54
50
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
55
51
|
try:
|
|
@@ -68,36 +64,36 @@ Note that the PAC-ID -- while valid -- uses characters which are not recommended
|
|
|
68
64
|
There is a nice function to highlight problems
|
|
69
65
|
|
|
70
66
|
```python
|
|
71
|
-
pac.print_validation_messages(
|
|
67
|
+
pac.print_validation_messages()
|
|
72
68
|
```
|
|
73
69
|
```text
|
|
74
70
|
>> Validation Results
|
|
75
71
|
>> ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
76
72
|
>> │ RECOMMENDATION in id segment value bal500 │
|
|
77
|
-
>> │ Characters 'b','
|
|
73
|
+
>> │ Characters 'b','l','a' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
78
74
|
>> │ │
|
|
79
|
-
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240
|
|
75
|
+
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:👉bal👈500/21:@1234 │
|
|
80
76
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
81
77
|
>> │ RECOMMENDATION in id segment value @1234 │
|
|
82
78
|
>> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
83
79
|
>> │ │
|
|
84
|
-
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21
|
|
80
|
+
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:👉@👈1234 │
|
|
85
81
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
86
82
|
>> │ RECOMMENDATION in id segment value bal500 │
|
|
87
|
-
>> │ Characters 'b','
|
|
83
|
+
>> │ Characters 'b','l','a' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
88
84
|
>> │ │
|
|
89
|
-
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240
|
|
85
|
+
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:👉bal👈500/21:@1234 │
|
|
90
86
|
>> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
91
87
|
>> │ RECOMMENDATION in id segment value @1234 │
|
|
92
88
|
>> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
|
|
93
89
|
>> │ │
|
|
94
|
-
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21
|
|
90
|
+
>> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:👉@👈1234 │
|
|
95
91
|
>> └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
96
92
|
```
|
|
97
93
|
### Save as QR Code
|
|
98
94
|
|
|
99
95
|
```python
|
|
100
|
-
from labfreed.qr import save_qr_with_markers
|
|
96
|
+
from labfreed.qr import save_qr_with_markers
|
|
101
97
|
|
|
102
98
|
save_qr_with_markers(pac_str, fmt='png')
|
|
103
99
|
```
|
|
@@ -112,7 +108,7 @@ PAC-CAT defines a (optional) way how the identifier is structured.
|
|
|
112
108
|
PAC_ID.from_url() automatically converts to PAC-CAT if possible.
|
|
113
109
|
|
|
114
110
|
```python
|
|
115
|
-
from labfreed
|
|
111
|
+
from labfreed import PAC_CAT
|
|
116
112
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-DR/XQ908756/-MD/bal500/@1234'
|
|
117
113
|
pac = PAC_ID.from_url(pac_str)
|
|
118
114
|
if isinstance(pac, PAC_CAT):
|
|
@@ -168,8 +164,8 @@ print(f'WEIGHT = {v.value}')
|
|
|
168
164
|
#### Create PAC-ID
|
|
169
165
|
|
|
170
166
|
```python
|
|
171
|
-
from labfreed
|
|
172
|
-
from labfreed.well_known_keys.labfreed.well_known_keys import WellKnownKeys
|
|
167
|
+
from labfreed import PAC_ID, IDSegment
|
|
168
|
+
from labfreed.well_known_keys.labfreed.well_known_keys import WellKnownKeys
|
|
173
169
|
|
|
174
170
|
pac = PAC_ID(issuer='METTORIUS.COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
|
|
175
171
|
pac_str = pac.to_url()
|
|
@@ -183,10 +179,10 @@ TREX can conveniently be created from a python dictionary.
|
|
|
183
179
|
Note that utility types for Quantity (number with unit) and table are needed
|
|
184
180
|
|
|
185
181
|
```python
|
|
186
|
-
from datetime import datetime
|
|
187
|
-
from labfreed.trex.python_convenience
|
|
188
|
-
from labfreed.trex.python_convenience
|
|
189
|
-
from labfreed.trex.python_convenience
|
|
182
|
+
from datetime import datetime
|
|
183
|
+
from labfreed.trex.python_convenience import pyTREX
|
|
184
|
+
from labfreed.trex.python_convenience import DataTable
|
|
185
|
+
from labfreed.trex.python_convenience import Quantity
|
|
190
186
|
|
|
191
187
|
# Value segments of different type
|
|
192
188
|
segments = {
|
|
@@ -211,40 +207,40 @@ trex = mydata.to_trex()
|
|
|
211
207
|
|
|
212
208
|
|
|
213
209
|
# Validation also works the same way for TREX
|
|
214
|
-
trex.print_validation_messages(
|
|
210
|
+
trex.print_validation_messages()
|
|
215
211
|
```
|
|
216
212
|
```text
|
|
217
213
|
>> Validation Results
|
|
218
214
|
>> ┌────────────────────────────────────────────────────────────┐
|
|
219
215
|
>> │ ERROR in TREX table column Date │
|
|
220
|
-
>> │ Column header key contains invalid characters: '
|
|
216
|
+
>> │ Column header key contains invalid characters: 'e','t','a' │
|
|
221
217
|
>> │ │
|
|
222
218
|
>> │ STOP$T.D:20240505T1306 │
|
|
223
219
|
>> │ +TEMP$KEL:10.15 │
|
|
224
220
|
>> │ +OK$T.B:F │
|
|
225
221
|
>> │ +COMMENT$T.A:FOO │
|
|
226
222
|
>> │ +COMMENT2$T.T:QMDTNXIKU │
|
|
227
|
-
>> │ +TABLE$$DURATION$HUR:
|
|
228
|
-
>> │ 1:
|
|
229
|
-
>> │ 1.1:
|
|
230
|
-
>> │ 1.3:
|
|
223
|
+
>> │ +TABLE$$DURATION$HUR:D👉ate👈$T.D:OK$T.B:COMMENT$T.A:: │
|
|
224
|
+
>> │ 1:20250424T200626.801:T:FOO:: │
|
|
225
|
+
>> │ 1.1:20250424T200626.801:T:BAR:: │
|
|
226
|
+
>> │ 1.3:20250424T200626.801:F:BLUBB │
|
|
231
227
|
>> └────────────────────────────────────────────────────────────┘
|
|
232
228
|
```
|
|
233
229
|
#### Combine PAC-ID and TREX and serialize
|
|
234
230
|
|
|
235
231
|
```python
|
|
236
|
-
from labfreed.well_known_extensions import TREX_Extension
|
|
232
|
+
from labfreed.well_known_extensions import TREX_Extension
|
|
237
233
|
pac.extensions = [TREX_Extension(name='MYTREX', trex=trex)]
|
|
238
234
|
pac_str = pac.to_url()
|
|
239
235
|
print(pac_str)
|
|
240
236
|
```
|
|
241
237
|
```text
|
|
242
|
-
>> 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:QMDTNXIKU+TABLE$$DURATION$HUR:Date$T.D:OK$T.B:COMMENT$T.A::1:
|
|
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:QMDTNXIKU+TABLE$$DURATION$HUR:Date$T.D:OK$T.B:COMMENT$T.A::1:20250424T200626.801:T:FOO::1.1:20250424T200626.801:T:BAR::1.3:20250424T200626.801:F:BLUBB
|
|
243
239
|
```
|
|
244
240
|
## PAC-ID Resolver
|
|
245
241
|
|
|
246
242
|
```python
|
|
247
|
-
from labfreed
|
|
243
|
+
from labfreed import PAC_ID_Resolver, load_cit
|
|
248
244
|
# Get a CIT
|
|
249
245
|
dir = os.path.join(os.getcwd(), 'examples')
|
|
250
246
|
p = os.path.join(dir, 'cit_mine.yaml')
|
|
@@ -252,7 +248,7 @@ cit = load_cit(p)
|
|
|
252
248
|
|
|
253
249
|
# validate the CIT
|
|
254
250
|
cit.is_valid
|
|
255
|
-
cit.print_validation_messages(
|
|
251
|
+
cit.print_validation_messages()
|
|
256
252
|
```
|
|
257
253
|
```python
|
|
258
254
|
# get a second cit
|
|
@@ -295,5 +291,38 @@ for sg in service_groups:
|
|
|
295
291
|
|
|
296
292
|
|
|
297
293
|
|
|
294
|
+
<!-- BEGIN CHANGELOG -->
|
|
298
295
|
## Change Log
|
|
299
|
-
|
|
296
|
+
### v0.2.2
|
|
297
|
+
- minor changes for better access of subfunctions. No change in existing API
|
|
298
|
+
|
|
299
|
+
### v0.2.1
|
|
300
|
+
- improved docu. no code changes
|
|
301
|
+
|
|
302
|
+
### v0.2.0b2
|
|
303
|
+
- improvements in api consistency and ease of use
|
|
304
|
+
- restructured code for better separation of concerns
|
|
305
|
+
- support for coupling information table v1
|
|
306
|
+
|
|
307
|
+
### v0.1.1
|
|
308
|
+
- minor internal improvements and bugfixes
|
|
309
|
+
|
|
310
|
+
### v0.1.0
|
|
311
|
+
- DRAFT Support for PAC-ID Resolver
|
|
312
|
+
|
|
313
|
+
### v0.0.20
|
|
314
|
+
- bugfix in TREX table to dict conversion
|
|
315
|
+
- markdown compatible validation printing
|
|
316
|
+
|
|
317
|
+
### v0.0.19
|
|
318
|
+
- supports PAC-ID, PAC-CAT, TREX and DisplayName
|
|
319
|
+
- QR generation
|
|
320
|
+
- ok-ish test coverage
|
|
321
|
+
<!-- END CHANGELOG -->
|
|
322
|
+
|
|
323
|
+
# Attributions
|
|
324
|
+
The following tools were used:
|
|
325
|
+
- [pdoc](https://pdoc.dev/) was a great help with generating documentation
|
|
326
|
+
- [Pydantic](https://docs.pydantic.dev/latest/)
|
|
327
|
+
- json with UNECE units from (https://github.com/quadient/unece-units/blob/main/python/src/unece_excel_parser/parsedUneceUnits.json)
|
|
328
|
+
- json with GS1 codes from (https://ref.gs1.org/ai/GS1_Application_Identifiers.jsonld)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Python implementation of LabFREED building blocks
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
__version__ = "0.2.2"
|
|
6
|
+
|
|
7
|
+
from labfreed.pac_id import * # noqa: F403
|
|
8
|
+
from labfreed.pac_cat import * # noqa: F403
|
|
9
|
+
from labfreed.pac_id_resolver import * # noqa: F403
|
|
10
|
+
from labfreed.trex import * # noqa: F403
|
|
11
|
+
from labfreed.labfreed_infrastructure import * # noqa: F403
|
|
@@ -177,7 +177,7 @@ class LabFREED_BaseModel(PDOC_Workaround_Base):
|
|
|
177
177
|
|
|
178
178
|
|
|
179
179
|
def print_validation_messages(self, target='console'):
|
|
180
|
-
msgs = self.
|
|
180
|
+
msgs = self.format_validation_messages(target=target)
|
|
181
181
|
|
|
182
182
|
table = Table(title="Validation Results", show_header=False, title_justify='left')
|
|
183
183
|
|
|
@@ -185,12 +185,29 @@ class LabFREED_BaseModel(PDOC_Workaround_Base):
|
|
|
185
185
|
return table.add_column(s, vertical='top')
|
|
186
186
|
col("-")
|
|
187
187
|
|
|
188
|
-
|
|
189
188
|
if not msgs:
|
|
190
189
|
table.add_row('All clear!', end_section=True)
|
|
191
190
|
return
|
|
192
191
|
|
|
193
192
|
for m in msgs:
|
|
193
|
+
table.add_row(m)
|
|
194
|
+
table.add_section()
|
|
195
|
+
|
|
196
|
+
logging.info(table)
|
|
197
|
+
print(table)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def format_validation_messages(self, target='console') -> list[str]:
|
|
201
|
+
"""Format validation messages
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
target (str, optional): Target format: 'markdown', 'console', 'html', 'html_styled'.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
list[str]: formated messages
|
|
208
|
+
"""
|
|
209
|
+
formatted_msg = list()
|
|
210
|
+
for m in self.validation_messages():
|
|
194
211
|
if m.level == ValidationMsgLevel.ERROR:
|
|
195
212
|
color = 'red'
|
|
196
213
|
else:
|
|
@@ -213,12 +230,9 @@ class LabFREED_BaseModel(PDOC_Workaround_Base):
|
|
|
213
230
|
txt = f'[bold {color}]{m.level.name} [/bold {color}] in {m.source}'
|
|
214
231
|
txt += '\n' + f'{m.msg}'
|
|
215
232
|
txt += '\n\n' + emphazised_highlight
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
logging.info(table)
|
|
221
|
-
print(table)
|
|
233
|
+
|
|
234
|
+
formatted_msg.append(txt)
|
|
235
|
+
return formatted_msg
|
|
222
236
|
|
|
223
237
|
|
|
224
238
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
from .pac_cat import PAC_CAT
|
|
2
2
|
from .category_base import Category
|
|
3
|
-
from .predefined_categories import
|
|
3
|
+
from .predefined_categories import (
|
|
4
|
+
Material_Device, Material_Substance, Material_Consumable, Material_Misc, Data_Method, Data_Result, Data_Progress,
|
|
5
|
+
Data_Calibration, Data_Abstract, category_key_to_class_map
|
|
6
|
+
)
|
|
4
7
|
|
|
5
8
|
__all__ = [
|
|
6
9
|
"PAC_CAT",
|
|
@@ -41,7 +41,7 @@ class Category(LabFREED_BaseModel):
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def __str__(self):
|
|
44
|
-
s = '\n'.join( [f
|
|
44
|
+
s = '\n'.join( [f"{field_name} \t ({field_info.alias or ''}): \t {getattr(self, field_name)}" for field_name, field_info in self.model_fields.items() if getattr(self, field_name)])
|
|
45
45
|
return s
|
|
46
46
|
|
|
47
47
|
|
|
@@ -10,7 +10,7 @@ from rich.table import Table
|
|
|
10
10
|
from labfreed.labfreed_infrastructure import ValidationMsgLevel
|
|
11
11
|
|
|
12
12
|
from labfreed.pac_cat.category_base import Category
|
|
13
|
-
from labfreed.pac_cat.predefined_categories import
|
|
13
|
+
from labfreed.pac_cat.predefined_categories import category_key_to_class_map
|
|
14
14
|
from labfreed.pac_id.id_segment import IDSegment
|
|
15
15
|
from labfreed.pac_id.pac_id import PAC_ID
|
|
16
16
|
|
|
@@ -68,18 +68,7 @@ class PAC_CAT(PAC_ID):
|
|
|
68
68
|
category_key = segments[0].value
|
|
69
69
|
segments.pop(0)
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
'-MD': Material_Device,
|
|
73
|
-
'-MS': Material_Substance,
|
|
74
|
-
'-MC': Material_Consumable,
|
|
75
|
-
'-MM': Material_Misc,
|
|
76
|
-
'-DM': Data_Method,
|
|
77
|
-
'-DR': Data_Result,
|
|
78
|
-
'-DC': Data_Calibration,
|
|
79
|
-
'-DP': Data_Progress,
|
|
80
|
-
'-DS': Data_Static
|
|
81
|
-
}
|
|
82
|
-
known_cat = mapping.get(category_key)
|
|
71
|
+
known_cat = category_key_to_class_map.get(category_key)
|
|
83
72
|
|
|
84
73
|
if not known_cat:
|
|
85
74
|
return Category(key=category_key, segments=segments)
|
|
@@ -157,3 +146,5 @@ class PAC_CAT(PAC_ID):
|
|
|
157
146
|
table.add_section()
|
|
158
147
|
print(table)
|
|
159
148
|
|
|
149
|
+
|
|
150
|
+
|
|
@@ -188,3 +188,14 @@ class Data_Static(Data_Abstract):
|
|
|
188
188
|
''' Category segments, which are not defined in the specification'''
|
|
189
189
|
|
|
190
190
|
|
|
191
|
+
category_key_to_class_map = {
|
|
192
|
+
'-MD': Material_Device,
|
|
193
|
+
'-MS': Material_Substance,
|
|
194
|
+
'-MC': Material_Consumable,
|
|
195
|
+
'-MM': Material_Misc,
|
|
196
|
+
'-DM': Data_Method,
|
|
197
|
+
'-DR': Data_Result,
|
|
198
|
+
'-DC': Data_Calibration,
|
|
199
|
+
'-DP': Data_Progress,
|
|
200
|
+
'-DS': Data_Static
|
|
201
|
+
}
|
|
@@ -110,7 +110,7 @@ class CIT_v1(LabFREED_BaseModel):
|
|
|
110
110
|
i = int(m.group(1)) - 1 # CIT is 1 based
|
|
111
111
|
seg = pac.identifier[i] if i < len(pac.identifier) else None
|
|
112
112
|
if seg:
|
|
113
|
-
return f"{(seg.key + ':') if seg.key else
|
|
113
|
+
return f"{(seg.key + ':') if seg.key else ''}{seg.value}"
|
|
114
114
|
|
|
115
115
|
elif m := re.match(r'\{idVal(\w+)\}', value):
|
|
116
116
|
k = m.group(1)
|
|
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.0b2 → labfreed-0.2.2}/labfreed/well_known_extensions/default_extension_interpreters.py
RENAMED
|
File without changes
|
{labfreed-0.2.0b2 → labfreed-0.2.2}/labfreed/well_known_extensions/display_name_extension.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
|