labfreed 0.0.18__tar.gz → 0.0.20__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.
- {labfreed-0.0.18 → labfreed-0.0.20}/PKG-INFO +71 -23
- {labfreed-0.0.18 → labfreed-0.0.20}/README.md +70 -23
- {labfreed-0.0.18 → labfreed-0.0.20}/examples.py +17 -11
- {labfreed-0.0.18/labfreed/QR_Generator → labfreed-0.0.20/labfreed/IO}/generate_qr.py +12 -37
- {labfreed-0.0.18/labfreed → labfreed-0.0.20/labfreed/IO}/parse_pac.py +2 -2
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/PAC_ID/extensions.py +0 -3
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/TREX/data_model.py +2 -2
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/__init__.py +1 -1
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/utilities/utility_types.py +1 -31
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/validation.py +8 -2
- {labfreed-0.0.18 → labfreed-0.0.20}/main.py +5 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/publish.ps1 +1 -1
- {labfreed-0.0.18 → labfreed-0.0.20}/tests/test_(de)_serialization_incl_extension/test__parse.py +1 -1
- {labfreed-0.0.18 → labfreed-0.0.20}/tests/test_(de)_serialization_incl_extension/test__serialize.py +1 -1
- {labfreed-0.0.18 → labfreed-0.0.20}/tests/test_PAC_CAT/test_PAC_CAT_parse.py +1 -1
- {labfreed-0.0.18 → labfreed-0.0.20}/tests/test_PAC_ID/test_pac_id_parse.py +1 -1
- labfreed-0.0.18/labfreed/utilities/extension_intertpreters.py +0 -4
- {labfreed-0.0.18 → labfreed-0.0.20}/.vscode/launch.json +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/.vscode/settings.json +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/LICENSE +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/DisplayNameExtension/DisplayNameExtension.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/PAC_CAT/__init__.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/PAC_CAT/data_model.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/PAC_ID/__init__.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/PAC_ID/data_model.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/TREX/UneceUnits.json +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/TREX/parse.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/TREX/unece_units.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/utilities/base36.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/labfreed/utilities/well_known_keys.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/publish.sh +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/publish_commands +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/pyproject.toml +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/pytest.ini +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/tests/test_PAC_CAT/test_PAC_CAT_serialize.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/tests/test_PAC_ID/test_PAC_ID_serialize.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/tests/test_TREX/test_TREX_parse.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/tests/test_TREX/test_TREX_serialize.py +0 -0
- {labfreed-0.0.18 → labfreed-0.0.20}/update_readme.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: labfreed
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.20
|
|
4
4
|
Summary: Python implementation of LabFREED building blocks
|
|
5
5
|
Author-email: Reto Thürer <thuerer.r@buchi.com>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -19,7 +19,7 @@ Requires-Dist: typer>=0.15.2
|
|
|
19
19
|
[](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml)
|
|
20
20
|
-->
|
|
21
21
|
|
|
22
|
-
This is a Python implementation of [LabFREED](
|
|
22
|
+
This is a Python implementation of [LabFREED](https://labfreed.wega-it.com) building blocks.
|
|
23
23
|
|
|
24
24
|
## Supported Building Blocks
|
|
25
25
|
- PAC-ID
|
|
@@ -41,7 +41,7 @@ pip install labfreed
|
|
|
41
41
|
### Parse a simple PAC-ID
|
|
42
42
|
|
|
43
43
|
```python
|
|
44
|
-
from labfreed.parse_pac import PAC_Parser
|
|
44
|
+
from labfreed.IO.parse_pac import PAC_Parser
|
|
45
45
|
|
|
46
46
|
# Parse the PAC-ID
|
|
47
47
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
@@ -53,17 +53,44 @@ is_valid = pac_id.is_valid()
|
|
|
53
53
|
print(f'PAC-ID is valid: {is_valid}')
|
|
54
54
|
```
|
|
55
55
|
```text
|
|
56
|
-
>>
|
|
56
|
+
>> PAC-ID is valid: True
|
|
57
57
|
```
|
|
58
58
|
### Show recommendations:
|
|
59
59
|
Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
|
|
60
60
|
There is a nice function to highlight problems
|
|
61
61
|
|
|
62
62
|
```python
|
|
63
|
-
pac_id.print_validation_messages()
|
|
63
|
+
pac_id.print_validation_messages(target='markdown')
|
|
64
64
|
```
|
|
65
65
|
```text
|
|
66
|
-
>>
|
|
66
|
+
>> =======================================
|
|
67
|
+
>> Validation Results
|
|
68
|
+
>> ---------------------------------------
|
|
69
|
+
>>
|
|
70
|
+
>> Recommendation in id segment value bal500
|
|
71
|
+
>> HTTPS://PAC.METTORIUS.COM/-MD/🔸b🔸🔸a🔸🔸l🔸500/@1234
|
|
72
|
+
>> Characters b l a should not be used.
|
|
73
|
+
>>
|
|
74
|
+
>> Recommendation in id segment value @1234
|
|
75
|
+
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/🔸@🔸1234
|
|
76
|
+
>> Characters @ should not be used.
|
|
77
|
+
>>
|
|
78
|
+
>> Warning in Category -MD
|
|
79
|
+
>> HTTPS://PAC.METTORIUS.COM/🔸-MD🔸/bal500/@1234
|
|
80
|
+
>> Category key -MD is not a well known key. It is recommended to use well known keys only
|
|
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
|
|
67
94
|
```
|
|
68
95
|
### PAC-CAT
|
|
69
96
|
|
|
@@ -75,7 +102,15 @@ if isinstance(pac_id, PAC_CAT):
|
|
|
75
102
|
pac_id.print_categories()
|
|
76
103
|
```
|
|
77
104
|
```text
|
|
78
|
-
>>
|
|
105
|
+
>> Main Category
|
|
106
|
+
>> ----------
|
|
107
|
+
>> key (): -DR
|
|
108
|
+
>> id (21): XQ908756
|
|
109
|
+
>> Category
|
|
110
|
+
>> ------
|
|
111
|
+
>> key (): -MD
|
|
112
|
+
>> model_number (240): bal500
|
|
113
|
+
>> serial_number (21): @1234
|
|
79
114
|
```
|
|
80
115
|
### Parse a PAC-ID with extensions
|
|
81
116
|
PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
|
|
@@ -89,7 +124,7 @@ display_names = pac_id.get_extension('N') # display name has name 'N'
|
|
|
89
124
|
print(display_names)
|
|
90
125
|
```
|
|
91
126
|
```text
|
|
92
|
-
>>
|
|
127
|
+
>> Display names: My Balance ❤️
|
|
93
128
|
```
|
|
94
129
|
```python
|
|
95
130
|
# TREX
|
|
@@ -99,7 +134,7 @@ v = trex.get_segment('WEIGHT').to_python_type()
|
|
|
99
134
|
print(f'WEIGHT = {v}')
|
|
100
135
|
```
|
|
101
136
|
```text
|
|
102
|
-
>>
|
|
137
|
+
>> WEIGHT = 67.89 g
|
|
103
138
|
```
|
|
104
139
|
### Create a PAC-ID with Extensions
|
|
105
140
|
|
|
@@ -109,12 +144,12 @@ print(f'WEIGHT = {v}')
|
|
|
109
144
|
from labfreed.PAC_ID.data_model import PACID, IDSegment
|
|
110
145
|
from labfreed.utilities.well_known_keys import WellKnownKeys
|
|
111
146
|
|
|
112
|
-
pac_id = PACID(issuer='METTORIUS
|
|
147
|
+
pac_id = PACID(issuer='METTORIUS.COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
|
|
113
148
|
pac_str = pac_id.serialize()
|
|
114
149
|
print(pac_str)
|
|
115
150
|
```
|
|
116
151
|
```text
|
|
117
|
-
>> HTTPS://PAC.METTORIUS
|
|
152
|
+
>> HTTPS://PAC.METTORIUS.COM/21:1234
|
|
118
153
|
```
|
|
119
154
|
#### Create a TREX
|
|
120
155
|
TREX can conveniently be created from a python dictionary.
|
|
@@ -139,7 +174,7 @@ trex.update(
|
|
|
139
174
|
)
|
|
140
175
|
|
|
141
176
|
# Create a table
|
|
142
|
-
table = DataTable(['DURATION', '
|
|
177
|
+
table = DataTable(['DURATION', 'Date', 'OK', 'COMMENT'])
|
|
143
178
|
table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
|
|
144
179
|
table.append([ 1.1, datetime.now(), True, 'BAR'])
|
|
145
180
|
table.append([ 1.3, datetime.now(), False, 'BLUBB'])
|
|
@@ -147,26 +182,35 @@ table.append([ 1.3, datetime.no
|
|
|
147
182
|
trex.update({'TABLE': table})
|
|
148
183
|
|
|
149
184
|
# Validation also works the same way for TREX
|
|
150
|
-
|
|
151
|
-
trex.print_validation_messages()
|
|
152
|
-
|
|
153
|
-
# Side Note: The TREX can be turned back into a dict
|
|
154
|
-
d = trex.dict()
|
|
185
|
+
trex.print_validation_messages(target='markdown')
|
|
155
186
|
```
|
|
156
187
|
```text
|
|
157
|
-
>>
|
|
188
|
+
>> =======================================
|
|
189
|
+
>> Validation Results
|
|
190
|
+
>> ---------------------------------------
|
|
191
|
+
>>
|
|
192
|
+
>> Error in TREX table column Date
|
|
193
|
+
>> 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:20250409T094048.268:T:FOO::1.1:20250409T094048.268:T:BAR::1.3:20250409T094048.268:F:BLUBB
|
|
194
|
+
>> Column header key contains invalid characters: e,t,a
|
|
195
|
+
```
|
|
196
|
+
```python
|
|
197
|
+
# there is an error. 'Date' uses lower case. Lets fix it
|
|
198
|
+
d = trex.dict()
|
|
199
|
+
d['TABLE'].col_names[1] = 'DATE'
|
|
200
|
+
trex = TREX(name_='DEMO')
|
|
201
|
+
trex.update(d)
|
|
158
202
|
```
|
|
159
203
|
#### Combine PAC-ID and TREX and serialize
|
|
160
204
|
|
|
161
205
|
```python
|
|
162
|
-
from labfreed.parse_pac import PACID_With_Extensions
|
|
206
|
+
from labfreed.IO.parse_pac import PACID_With_Extensions
|
|
163
207
|
|
|
164
208
|
pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
|
|
165
209
|
pac_str = pac_with_trex.serialize()
|
|
166
210
|
print(pac_str)
|
|
167
211
|
```
|
|
168
212
|
```text
|
|
169
|
-
>>
|
|
213
|
+
>> 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:20250409T094048.268:T:FOO::1.1:20250409T094048.268:T:BAR::1.3:20250409T094048.268:F:BLUBB
|
|
170
214
|
```
|
|
171
215
|
<!-- END EXAMPLES -->
|
|
172
216
|
|
|
@@ -174,9 +218,13 @@ print(pac_str)
|
|
|
174
218
|
|
|
175
219
|
## Change Log
|
|
176
220
|
|
|
177
|
-
### v0.0.
|
|
178
|
-
-
|
|
221
|
+
### v0.0.20
|
|
222
|
+
- bugfix in TREX table to dict conversion
|
|
223
|
+
- markdown compatible validation printing
|
|
179
224
|
|
|
180
|
-
### v0.0.
|
|
225
|
+
### v0.0.19
|
|
181
226
|
- supports PAC-ID, PAC-CAT, TREX and DisplayName
|
|
227
|
+
- QR generation
|
|
182
228
|
- ok-ish test coverage
|
|
229
|
+
|
|
230
|
+
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml)
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
|
-
This is a Python implementation of [LabFREED](
|
|
9
|
+
This is a Python implementation of [LabFREED](https://labfreed.wega-it.com) building blocks.
|
|
10
10
|
|
|
11
11
|
## Supported Building Blocks
|
|
12
12
|
- PAC-ID
|
|
@@ -28,7 +28,7 @@ pip install labfreed
|
|
|
28
28
|
### Parse a simple PAC-ID
|
|
29
29
|
|
|
30
30
|
```python
|
|
31
|
-
from labfreed.parse_pac import PAC_Parser
|
|
31
|
+
from labfreed.IO.parse_pac import PAC_Parser
|
|
32
32
|
|
|
33
33
|
# Parse the PAC-ID
|
|
34
34
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
@@ -40,17 +40,44 @@ is_valid = pac_id.is_valid()
|
|
|
40
40
|
print(f'PAC-ID is valid: {is_valid}')
|
|
41
41
|
```
|
|
42
42
|
```text
|
|
43
|
-
>>
|
|
43
|
+
>> PAC-ID is valid: True
|
|
44
44
|
```
|
|
45
45
|
### Show recommendations:
|
|
46
46
|
Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
|
|
47
47
|
There is a nice function to highlight problems
|
|
48
48
|
|
|
49
49
|
```python
|
|
50
|
-
pac_id.print_validation_messages()
|
|
50
|
+
pac_id.print_validation_messages(target='markdown')
|
|
51
51
|
```
|
|
52
52
|
```text
|
|
53
|
-
>>
|
|
53
|
+
>> =======================================
|
|
54
|
+
>> Validation Results
|
|
55
|
+
>> ---------------------------------------
|
|
56
|
+
>>
|
|
57
|
+
>> Recommendation in id segment value bal500
|
|
58
|
+
>> HTTPS://PAC.METTORIUS.COM/-MD/🔸b🔸🔸a🔸🔸l🔸500/@1234
|
|
59
|
+
>> Characters b l a should not be used.
|
|
60
|
+
>>
|
|
61
|
+
>> Recommendation in id segment value @1234
|
|
62
|
+
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/🔸@🔸1234
|
|
63
|
+
>> Characters @ should not be used.
|
|
64
|
+
>>
|
|
65
|
+
>> Warning in Category -MD
|
|
66
|
+
>> HTTPS://PAC.METTORIUS.COM/🔸-MD🔸/bal500/@1234
|
|
67
|
+
>> Category key -MD is not a well known key. It is recommended to use well known keys only
|
|
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
|
|
54
81
|
```
|
|
55
82
|
### PAC-CAT
|
|
56
83
|
|
|
@@ -62,7 +89,15 @@ if isinstance(pac_id, PAC_CAT):
|
|
|
62
89
|
pac_id.print_categories()
|
|
63
90
|
```
|
|
64
91
|
```text
|
|
65
|
-
>>
|
|
92
|
+
>> Main Category
|
|
93
|
+
>> ----------
|
|
94
|
+
>> key (): -DR
|
|
95
|
+
>> id (21): XQ908756
|
|
96
|
+
>> Category
|
|
97
|
+
>> ------
|
|
98
|
+
>> key (): -MD
|
|
99
|
+
>> model_number (240): bal500
|
|
100
|
+
>> serial_number (21): @1234
|
|
66
101
|
```
|
|
67
102
|
### Parse a PAC-ID with extensions
|
|
68
103
|
PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
|
|
@@ -76,7 +111,7 @@ display_names = pac_id.get_extension('N') # display name has name 'N'
|
|
|
76
111
|
print(display_names)
|
|
77
112
|
```
|
|
78
113
|
```text
|
|
79
|
-
>>
|
|
114
|
+
>> Display names: My Balance ❤️
|
|
80
115
|
```
|
|
81
116
|
```python
|
|
82
117
|
# TREX
|
|
@@ -86,7 +121,7 @@ v = trex.get_segment('WEIGHT').to_python_type()
|
|
|
86
121
|
print(f'WEIGHT = {v}')
|
|
87
122
|
```
|
|
88
123
|
```text
|
|
89
|
-
>>
|
|
124
|
+
>> WEIGHT = 67.89 g
|
|
90
125
|
```
|
|
91
126
|
### Create a PAC-ID with Extensions
|
|
92
127
|
|
|
@@ -96,12 +131,12 @@ print(f'WEIGHT = {v}')
|
|
|
96
131
|
from labfreed.PAC_ID.data_model import PACID, IDSegment
|
|
97
132
|
from labfreed.utilities.well_known_keys import WellKnownKeys
|
|
98
133
|
|
|
99
|
-
pac_id = PACID(issuer='METTORIUS
|
|
134
|
+
pac_id = PACID(issuer='METTORIUS.COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
|
|
100
135
|
pac_str = pac_id.serialize()
|
|
101
136
|
print(pac_str)
|
|
102
137
|
```
|
|
103
138
|
```text
|
|
104
|
-
>> HTTPS://PAC.METTORIUS
|
|
139
|
+
>> HTTPS://PAC.METTORIUS.COM/21:1234
|
|
105
140
|
```
|
|
106
141
|
#### Create a TREX
|
|
107
142
|
TREX can conveniently be created from a python dictionary.
|
|
@@ -126,7 +161,7 @@ trex.update(
|
|
|
126
161
|
)
|
|
127
162
|
|
|
128
163
|
# Create a table
|
|
129
|
-
table = DataTable(['DURATION', '
|
|
164
|
+
table = DataTable(['DURATION', 'Date', 'OK', 'COMMENT'])
|
|
130
165
|
table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
|
|
131
166
|
table.append([ 1.1, datetime.now(), True, 'BAR'])
|
|
132
167
|
table.append([ 1.3, datetime.now(), False, 'BLUBB'])
|
|
@@ -134,26 +169,35 @@ table.append([ 1.3, datetime.no
|
|
|
134
169
|
trex.update({'TABLE': table})
|
|
135
170
|
|
|
136
171
|
# Validation also works the same way for TREX
|
|
137
|
-
|
|
138
|
-
trex.print_validation_messages()
|
|
139
|
-
|
|
140
|
-
# Side Note: The TREX can be turned back into a dict
|
|
141
|
-
d = trex.dict()
|
|
172
|
+
trex.print_validation_messages(target='markdown')
|
|
142
173
|
```
|
|
143
174
|
```text
|
|
144
|
-
>>
|
|
175
|
+
>> =======================================
|
|
176
|
+
>> Validation Results
|
|
177
|
+
>> ---------------------------------------
|
|
178
|
+
>>
|
|
179
|
+
>> Error in TREX table column Date
|
|
180
|
+
>> 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:20250409T094048.268:T:FOO::1.1:20250409T094048.268:T:BAR::1.3:20250409T094048.268:F:BLUBB
|
|
181
|
+
>> Column header key contains invalid characters: e,t,a
|
|
182
|
+
```
|
|
183
|
+
```python
|
|
184
|
+
# there is an error. 'Date' uses lower case. Lets fix it
|
|
185
|
+
d = trex.dict()
|
|
186
|
+
d['TABLE'].col_names[1] = 'DATE'
|
|
187
|
+
trex = TREX(name_='DEMO')
|
|
188
|
+
trex.update(d)
|
|
145
189
|
```
|
|
146
190
|
#### Combine PAC-ID and TREX and serialize
|
|
147
191
|
|
|
148
192
|
```python
|
|
149
|
-
from labfreed.parse_pac import PACID_With_Extensions
|
|
193
|
+
from labfreed.IO.parse_pac import PACID_With_Extensions
|
|
150
194
|
|
|
151
195
|
pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
|
|
152
196
|
pac_str = pac_with_trex.serialize()
|
|
153
197
|
print(pac_str)
|
|
154
198
|
```
|
|
155
199
|
```text
|
|
156
|
-
>>
|
|
200
|
+
>> 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:20250409T094048.268:T:FOO::1.1:20250409T094048.268:T:BAR::1.3:20250409T094048.268:F:BLUBB
|
|
157
201
|
```
|
|
158
202
|
<!-- END EXAMPLES -->
|
|
159
203
|
|
|
@@ -161,9 +205,12 @@ print(pac_str)
|
|
|
161
205
|
|
|
162
206
|
## Change Log
|
|
163
207
|
|
|
164
|
-
### v0.0.
|
|
165
|
-
-
|
|
208
|
+
### v0.0.20
|
|
209
|
+
- bugfix in TREX table to dict conversion
|
|
210
|
+
- markdown compatible validation printing
|
|
166
211
|
|
|
167
|
-
### v0.0.
|
|
212
|
+
### v0.0.19
|
|
168
213
|
- supports PAC-ID, PAC-CAT, TREX and DisplayName
|
|
169
|
-
-
|
|
214
|
+
- QR generation
|
|
215
|
+
- ok-ish test coverage
|
|
216
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'''
|
|
2
2
|
### Parse a simple PAC-ID
|
|
3
3
|
'''
|
|
4
|
-
from labfreed.parse_pac import PAC_Parser
|
|
4
|
+
from labfreed.IO.parse_pac import PAC_Parser
|
|
5
5
|
|
|
6
6
|
# Parse the PAC-ID
|
|
7
7
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
@@ -17,8 +17,14 @@ print(f'PAC-ID is valid: {is_valid}')
|
|
|
17
17
|
Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
|
|
18
18
|
There is a nice function to highlight problems
|
|
19
19
|
'''
|
|
20
|
-
pac_id.print_validation_messages()
|
|
20
|
+
pac_id.print_validation_messages(target='markdown')
|
|
21
21
|
|
|
22
|
+
'''
|
|
23
|
+
### Save as QR Code
|
|
24
|
+
'''
|
|
25
|
+
from labfreed.IO.generate_qr import save_qr_with_markers
|
|
26
|
+
|
|
27
|
+
save_qr_with_markers(pac_str, fmt='png')
|
|
22
28
|
|
|
23
29
|
'''
|
|
24
30
|
### PAC-CAT
|
|
@@ -31,8 +37,6 @@ if isinstance(pac_id, PAC_CAT):
|
|
|
31
37
|
|
|
32
38
|
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
40
|
'''
|
|
37
41
|
### Parse a PAC-ID with extensions
|
|
38
42
|
PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
|
|
@@ -61,7 +65,7 @@ print(f'WEIGHT = {v}')
|
|
|
61
65
|
from labfreed.PAC_ID.data_model import PACID, IDSegment
|
|
62
66
|
from labfreed.utilities.well_known_keys import WellKnownKeys
|
|
63
67
|
|
|
64
|
-
pac_id = PACID(issuer='METTORIUS
|
|
68
|
+
pac_id = PACID(issuer='METTORIUS.COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
|
|
65
69
|
pac_str = pac_id.serialize()
|
|
66
70
|
print(pac_str)
|
|
67
71
|
|
|
@@ -89,7 +93,7 @@ trex.update(
|
|
|
89
93
|
)
|
|
90
94
|
|
|
91
95
|
# Create a table
|
|
92
|
-
table = DataTable(['DURATION', '
|
|
96
|
+
table = DataTable(['DURATION', 'Date', 'OK', 'COMMENT'])
|
|
93
97
|
table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
|
|
94
98
|
table.append([ 1.1, datetime.now(), True, 'BAR'])
|
|
95
99
|
table.append([ 1.3, datetime.now(), False, 'BLUBB'])
|
|
@@ -97,16 +101,18 @@ table.append([ 1.3, datetime.no
|
|
|
97
101
|
trex.update({'TABLE': table})
|
|
98
102
|
|
|
99
103
|
# Validation also works the same way for TREX
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
# Side Note: The TREX can be turned back into a dict
|
|
104
|
+
trex.print_validation_messages(target='markdown')
|
|
105
|
+
''''''
|
|
106
|
+
# there is an error. 'Date' uses lower case. Lets fix it
|
|
104
107
|
d = trex.dict()
|
|
108
|
+
d['TABLE'].col_names[1] = 'DATE'
|
|
109
|
+
trex = TREX(name_='DEMO')
|
|
110
|
+
trex.update(d)
|
|
105
111
|
|
|
106
112
|
'''
|
|
107
113
|
#### Combine PAC-ID and TREX and serialize
|
|
108
114
|
'''
|
|
109
|
-
from labfreed.parse_pac import PACID_With_Extensions
|
|
115
|
+
from labfreed.IO.parse_pac import PACID_With_Extensions
|
|
110
116
|
|
|
111
117
|
pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
|
|
112
118
|
pac_str = pac_with_trex.serialize()
|
|
@@ -364,16 +364,16 @@ class VisualMarker:
|
|
|
364
364
|
app = typer.Typer()
|
|
365
365
|
|
|
366
366
|
|
|
367
|
-
def
|
|
367
|
+
def _generate_qr_with_markers(qr_str, text, title, direction):
|
|
368
368
|
if title:
|
|
369
369
|
#try to use standard size 10. Go bigger if 10 does not fit the data
|
|
370
370
|
try:
|
|
371
|
-
qr = segno.make_qr(
|
|
371
|
+
qr = segno.make_qr(qr_str, error="L", version=10)
|
|
372
372
|
except DataOverflowError as e:
|
|
373
|
-
qr = segno.make_qr(
|
|
373
|
+
qr = segno.make_qr(qr_str, error="L")
|
|
374
374
|
v = qr.version
|
|
375
375
|
else:
|
|
376
|
-
qr = segno.make_qr(
|
|
376
|
+
qr = segno.make_qr(qr_str, error="L")
|
|
377
377
|
v = qr.version
|
|
378
378
|
|
|
379
379
|
if(qr.mode != "alphanumeric"):
|
|
@@ -396,42 +396,18 @@ def generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.
|
|
|
396
396
|
combined_matrix = np.concatenate((title_marker, padding, qr_matrix, padding, visual_marker), axis=append_axis)
|
|
397
397
|
else:
|
|
398
398
|
combined_matrix = np.concatenate((qr_matrix, padding, visual_marker), axis=append_axis)
|
|
399
|
-
|
|
399
|
+
|
|
400
400
|
return combined_matrix
|
|
401
|
-
|
|
402
|
-
def generate_qr_with_markers_file(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, fmt='svg', path=str):
|
|
403
|
-
combined_matrix = generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
404
|
-
outfile = f'{path}.{fmt}'
|
|
405
|
-
match fmt:
|
|
406
|
-
case 'png':
|
|
407
|
-
segno.writers.write_png(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
408
|
-
case 'svg':
|
|
409
|
-
segno.writers.write_svg(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
410
401
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
402
|
+
def save_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, fmt='png', path='qr'):
|
|
403
|
+
combined_matrix = _generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
404
|
+
outfile = f'{path}.{fmt}'
|
|
414
405
|
match fmt:
|
|
415
406
|
case 'png':
|
|
416
|
-
|
|
407
|
+
writers.write_png(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
417
408
|
case 'svg':
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
def generate_qr_with_markers_svg(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, width=None, height=None, border=9, svg_omitsize=False):
|
|
422
|
-
combined_matrix = generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
423
|
-
with io.BytesIO() as out:
|
|
424
|
-
version = combined_matrix.shape[::-1]
|
|
425
|
-
scalex = width / (version[0] + 2*border) if width else 1
|
|
426
|
-
scaley = height / (version[1] + 2*border) if height else 1
|
|
427
|
-
scale = min(scalex, scaley)
|
|
428
|
-
segno.writers.write_svg(combined_matrix, version, out, border=border,
|
|
429
|
-
xmldecl=False, svgns=True, scale=scale, omitsize=svg_omitsize
|
|
430
|
-
)
|
|
431
|
-
s = out.getvalue().decode()
|
|
432
|
-
return s
|
|
433
|
-
|
|
434
|
-
|
|
409
|
+
writers.write_svg(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
410
|
+
|
|
435
411
|
|
|
436
412
|
|
|
437
413
|
|
|
@@ -440,8 +416,7 @@ def main(url: Annotated[str, typer.Argument(help="The PAC-ID to be rendered as Q
|
|
|
440
416
|
text: Annotated[str, typer.Option(help="The text of the PAC decoration.")] = "PAC",
|
|
441
417
|
direction: Annotated[Direction, typer.Option(help="The position/direction of the PAC decoration.")] = Direction.TOP_TO_BOTTOM):
|
|
442
418
|
|
|
443
|
-
|
|
444
|
-
img.save('generated_codes', f"{outfile}.svg", format='svg')
|
|
419
|
+
save_qr_with_markers(url, text=text, direction=direction, path=outfile)
|
|
445
420
|
|
|
446
421
|
|
|
447
422
|
|
|
@@ -9,9 +9,9 @@ from labfreed.PAC_ID.extensions import Extension, UnknownExtension
|
|
|
9
9
|
from labfreed.TREX.data_model import TREX
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
from
|
|
12
|
+
from ..PAC_ID.data_model import *
|
|
13
13
|
|
|
14
|
-
from
|
|
14
|
+
from ..validation import ValidationMessage, LabFREEDValidationError
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
@@ -436,7 +436,7 @@ class TREX_Table(TREX_Segment):
|
|
|
436
436
|
self.add_validation_message(
|
|
437
437
|
source=f"Table {self.key}",
|
|
438
438
|
type="Error",
|
|
439
|
-
msg=f"Size mismatch: Table header contains {self.
|
|
439
|
+
msg=f"Size mismatch: Table header contains {self.column_names} keys, while most rows have {most_common_len}",
|
|
440
440
|
highlight_pattern = self.key
|
|
441
441
|
)
|
|
442
442
|
expected_row_len = most_common_len
|
|
@@ -527,7 +527,7 @@ class TREX_Table(TREX_Segment):
|
|
|
527
527
|
r.append(Quantity(value=e.value, unit=unit))
|
|
528
528
|
else:
|
|
529
529
|
r.append(e.value_to_python_type())
|
|
530
|
-
|
|
530
|
+
table.append(r)
|
|
531
531
|
return table
|
|
532
532
|
|
|
533
533
|
|
|
@@ -1,37 +1,7 @@
|
|
|
1
|
-
from
|
|
2
|
-
import json
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from rich import print
|
|
6
|
-
|
|
7
|
-
from typing import Any, Tuple
|
|
8
|
-
from typing_extensions import Annotated
|
|
9
|
-
from pydantic import BaseModel, AfterValidator
|
|
10
|
-
import quantities as pq
|
|
11
|
-
from quantities import units
|
|
1
|
+
from pydantic import BaseModel
|
|
12
2
|
|
|
13
3
|
from labfreed.TREX.unece_units import unece_units
|
|
14
4
|
|
|
15
|
-
def validate_unit(unit_name:str) -> str :
|
|
16
|
-
"""
|
|
17
|
-
Pydantic validator function for the unit.
|
|
18
|
-
Checks if the unit is a valid unit.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
unit (str): unit symbol, e.g. 'kg'
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
str: the input unit.
|
|
26
|
-
|
|
27
|
-
Errors:
|
|
28
|
-
raises an AssertionError if validation fails
|
|
29
|
-
"""
|
|
30
|
-
if hasattr(pq, unit_name):
|
|
31
|
-
return unit_name
|
|
32
|
-
else:
|
|
33
|
-
assert False
|
|
34
|
-
|
|
35
5
|
|
|
36
6
|
class Unit(BaseModel):
|
|
37
7
|
name: str
|
|
@@ -113,7 +113,7 @@ class BaseModelWithValidationMessages(BaseModel):
|
|
|
113
113
|
return filter_warnings(self.get_nested_validation_messages())
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
def print_validation_messages(self, str_to_highlight_in=None):
|
|
116
|
+
def print_validation_messages(self, str_to_highlight_in=None, target='console'):
|
|
117
117
|
if not str_to_highlight_in:
|
|
118
118
|
str_to_highlight_in = str(self)
|
|
119
119
|
msgs = self.get_nested_validation_messages()
|
|
@@ -133,7 +133,13 @@ class BaseModelWithValidationMessages(BaseModel):
|
|
|
133
133
|
|
|
134
134
|
text = Text.from_markup(f'\n [bold {color}]{m.type} [/bold {color}] in \t {m.source}' )
|
|
135
135
|
print(text)
|
|
136
|
-
|
|
136
|
+
match target:
|
|
137
|
+
case 'markdown':
|
|
138
|
+
formatted_highlight = m.emphazised_highlight.replace('emph', f'🔸').replace('[/', '').replace('[', '').replace(']', '')
|
|
139
|
+
case 'console':
|
|
140
|
+
formatted_highlight = m.emphazised_highlight.replace('emph', f'bold {color}')
|
|
141
|
+
case 'html':
|
|
142
|
+
formatted_highlight = m.emphazised_highlight.replace('emph', f'b').replace('[', '<').replace(']', '>')
|
|
137
143
|
fmtd = str_to_highlight_in.replace(m.highlight, formatted_highlight)
|
|
138
144
|
fmtd = Text.from_markup(fmtd)
|
|
139
145
|
print(fmtd)
|
|
@@ -9,9 +9,14 @@ from labfreed.PAC_CAT.data_model import *
|
|
|
9
9
|
from labfreed.utilities.base36 import base36
|
|
10
10
|
from labfreed.utilities.utility_types import DataTable, Quantity, Unit
|
|
11
11
|
|
|
12
|
+
from labfreed.QR_Generator.generate_qr import save_qr_with_markers
|
|
12
13
|
|
|
13
14
|
if __name__ == "__main__":
|
|
14
15
|
|
|
16
|
+
|
|
17
|
+
save_qr_with_markers('HTTPS://PAC.METTORIUS.COM/-MD/ABCG/ACG')
|
|
18
|
+
|
|
19
|
+
|
|
15
20
|
table = DataTable(['DURATION', 'DATE', 'OK', 'COMMENT'])
|
|
16
21
|
table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
|
|
17
22
|
table.append([1.1, datetime.now(), True, 'BAR'])
|
{labfreed-0.0.18 → labfreed-0.0.20}/tests/test_(de)_serialization_incl_extension/test__serialize.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from labfreed.PAC_ID.data_model import PACID, IDSegment
|
|
2
2
|
from labfreed.PAC_ID.extensions import UnknownExtension
|
|
3
|
-
from labfreed.parse_pac import PACID_With_Extensions
|
|
3
|
+
from labfreed.IO.parse_pac import PACID_With_Extensions
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
pac_id = PACID(issuer = 'mettorius.com',
|
|
@@ -2,7 +2,7 @@ import pytest
|
|
|
2
2
|
from labfreed.PAC_CAT.data_model import Category, PAC_CAT
|
|
3
3
|
from labfreed.PAC_ID.data_model import IDSegment
|
|
4
4
|
from labfreed.PAC_ID.extensions import Extension
|
|
5
|
-
from labfreed.parse_pac import PAC_Parser
|
|
5
|
+
from labfreed.IO.parse_pac import PAC_Parser
|
|
6
6
|
from labfreed.validation import LabFREEDValidationError
|
|
7
7
|
|
|
8
8
|
|
|
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
|