labfreed 0.0.14__tar.gz → 0.0.15__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.0.15/PKG-INFO +171 -0
- labfreed-0.0.15/README.md +162 -0
- labfreed-0.0.15/examples.py +126 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/__init__.py +1 -1
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/parse_pac.py +6 -6
- {labfreed-0.0.14 → labfreed-0.0.15}/tests/test_(de)_serialization_incl_extension/test__parse.py +5 -5
- {labfreed-0.0.14 → labfreed-0.0.15}/tests/test_PAC_CAT/test_PAC_CAT_parse.py +14 -14
- {labfreed-0.0.14 → labfreed-0.0.15}/tests/test_PAC_ID/test_pac_id_parse.py +10 -10
- labfreed-0.0.15/update_readme.py +63 -0
- labfreed-0.0.14/PKG-INFO +0 -161
- labfreed-0.0.14/README.md +0 -152
- labfreed-0.0.14/examples.py +0 -114
- labfreed-0.0.14/update_readme.py +0 -27
- {labfreed-0.0.14 → labfreed-0.0.15}/.vscode/launch.json +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/.vscode/settings.json +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/LICENSE +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/DisplayNameExtension/DisplayNameExtension.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/PAC_CAT/__init__.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/PAC_CAT/data_model copy.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/PAC_CAT/data_model.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/PAC_ID/__init__.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/PAC_ID/data_model.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/PAC_ID/extensions.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/TREX/UneceUnits.json +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/TREX/data_model.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/TREX/parse.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/TREX/unece_units.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/utilities/base36.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/utilities/extension_intertpreters.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/utilities/utility_types.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/utilities/well_known_keys.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/labfreed/validation.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/main.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/publish.ps1 +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/publish.sh +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/publish_commands +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/pyproject.toml +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/pytest.ini +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/tests/test_(de)_serialization_incl_extension/test__serialize.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/tests/test_PAC_CAT/test_PAC_CAT_serialize.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/tests/test_PAC_ID/test_PAC_ID_serialize.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/tests/test_TREX/test_TREX_parse.py +0 -0
- {labfreed-0.0.14 → labfreed-0.0.15}/tests/test_TREX/test_TREX_serialize.py +0 -0
labfreed-0.0.15/PKG-INFO
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: labfreed
|
|
3
|
+
Version: 0.0.15
|
|
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
|
+
|
|
10
|
+
# LabFREED for Python
|
|
11
|
+
|
|
12
|
+
[](LICENSE) [](https://pypi.org/project/labfreed/) 
|
|
13
|
+
|
|
14
|
+
<!--
|
|
15
|
+
[](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml)
|
|
16
|
+
-->
|
|
17
|
+
|
|
18
|
+
This is a Python implementation of [LabFREED](www.labfreed.wega-it.com) building blocks.
|
|
19
|
+
|
|
20
|
+
## Supported Building Blocks
|
|
21
|
+
- PAC-ID
|
|
22
|
+
- PAC-CAT
|
|
23
|
+
- TREX
|
|
24
|
+
- Display Extension
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
You can install LabFREED from [PyPI](https://pypi.org/project/labfreed/) using pip:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install labfreed
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Usage Examples
|
|
35
|
+
<!-- BEGIN EXAMPLES -->
|
|
36
|
+
```python
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Parse a simple PAC-ID
|
|
41
|
+
The
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from labfreed.parse_pac import PAC_Parser
|
|
45
|
+
|
|
46
|
+
# Parse the PAC-ID
|
|
47
|
+
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
48
|
+
pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
49
|
+
|
|
50
|
+
# Check validity of this PAC-ID
|
|
51
|
+
pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
52
|
+
is_valid = pac_id.is_valid()
|
|
53
|
+
print('PAC-ID is valid: {is_valid}')
|
|
54
|
+
# >> PAC-ID is valid: {is_valid}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Show recommendations:
|
|
58
|
+
Note that the PAC-ID, while valid uses characters, which are not recommended (results in larger QR code).
|
|
59
|
+
There is a nice function to highlight problems
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
pac_id.print_validation_messages()
|
|
63
|
+
# >>
|
|
64
|
+
# =======================================
|
|
65
|
+
# Validation Results
|
|
66
|
+
# ---------------------------------------
|
|
67
|
+
|
|
68
|
+
# Recommendation in id segment value bal500
|
|
69
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
70
|
+
# Characters a b l should not be used.
|
|
71
|
+
|
|
72
|
+
# Recommendation in id segment value @1234
|
|
73
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
74
|
+
# Characters @ should not be used.
|
|
75
|
+
|
|
76
|
+
# Warning in Category -MD
|
|
77
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
78
|
+
# Category key -MD is not a well known key. It is recommended to use well known keys only
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Parse a PAC-ID with extensions
|
|
82
|
+
PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/WM633OV3E5DGJW2BEG0PDM1EA7*SUM$TREX/WEIGHT$GRM:67.89'
|
|
86
|
+
pac_id = PAC_Parser().parse(pac_str)
|
|
87
|
+
|
|
88
|
+
# Display Name
|
|
89
|
+
display_names = pac_id.get_extension('N') # display name has name 'N'
|
|
90
|
+
print(f'\n {display_names}')
|
|
91
|
+
# >> Display names: My Balance ❤️
|
|
92
|
+
|
|
93
|
+
# TREX
|
|
94
|
+
trexes = pac_id.get_extension_of_type('TREX')
|
|
95
|
+
trex = trexes[0] # there could be multiple trexes. In this example there is only one, though
|
|
96
|
+
v = trex.get_segment('WEIGHT').to_python_type()
|
|
97
|
+
print(f'WEIGHT = {v}')
|
|
98
|
+
# >> WEIGHT = 67.89 g
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Create a PAC-ID with Extensions
|
|
102
|
+
|
|
103
|
+
#### Create PAC-ID
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from labfreed.PAC_ID.data_model import PACID, IDSegment
|
|
107
|
+
from labfreed.utilities.well_known_keys import WellKnownKeys
|
|
108
|
+
|
|
109
|
+
pac_id = PACID(issuer='METTORIUS:COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
|
|
110
|
+
pac_str = pac_id.serialize()
|
|
111
|
+
pac_str = pac_id.serialize()
|
|
112
|
+
print(pac_str)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Create a TREX
|
|
116
|
+
TREX can conveniently be created from a python dictionary.
|
|
117
|
+
Note that utility types for Quantity (number with unit) and table are needed
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from datetime import datetime
|
|
121
|
+
from labfreed.TREX.data_model import TREX
|
|
122
|
+
from labfreed.utilities.utility_types import Quantity, DataTable, Unit
|
|
123
|
+
|
|
124
|
+
# Create TREX
|
|
125
|
+
trex = TREX(name_='DEMO')
|
|
126
|
+
# Add value segments of different type
|
|
127
|
+
trex.update(
|
|
128
|
+
{
|
|
129
|
+
'STOP': datetime(year=2024,month=5,day=5,hour=13,minute=6),
|
|
130
|
+
'TEMP': Quantity(value=10.15, unit=Unit(name='kelvin', symbol='K')),
|
|
131
|
+
'OK':False,
|
|
132
|
+
'COMMENT': 'FOO',
|
|
133
|
+
'COMMENT2':'£'
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Create a table
|
|
138
|
+
table = DataTable(['DURATION', 'DATE', 'OK', 'COMMENT'])
|
|
139
|
+
table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
|
|
140
|
+
table.append([ 1.1, datetime.now(), True, 'BAR'])
|
|
141
|
+
table.append([ 1.3, datetime.now(), False, 'BLUBB'])
|
|
142
|
+
#add the table to the trex
|
|
143
|
+
trex.update({'TABLE': table})
|
|
144
|
+
|
|
145
|
+
# Validation also works the same way for TREX
|
|
146
|
+
if trex.get_nested_validation_messages():
|
|
147
|
+
trex.print_validation_messages()
|
|
148
|
+
|
|
149
|
+
# Side Note: The TREX can be turned back into a dict
|
|
150
|
+
d = trex.dict()
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Combine PAC-ID and TREX and serialize
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
from labfreed.parse_pac import PACID_With_Extensions
|
|
157
|
+
|
|
158
|
+
pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
|
|
159
|
+
pac_str = pac_with_trex.serialize()
|
|
160
|
+
print(pac_str)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
<!-- END EXAMPLES -->
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
## Change Log
|
|
168
|
+
|
|
169
|
+
### v0.0.9
|
|
170
|
+
- supports PAC-ID, PAC-CAT, TREX and DisplayName
|
|
171
|
+
- ok-ish test coverage
|
|
@@ -0,0 +1,162 @@
|
|
|
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](www.labfreed.wega-it.com) building blocks.
|
|
10
|
+
|
|
11
|
+
## Supported Building Blocks
|
|
12
|
+
- PAC-ID
|
|
13
|
+
- PAC-CAT
|
|
14
|
+
- TREX
|
|
15
|
+
- Display Extension
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
You can install LabFREED from [PyPI](https://pypi.org/project/labfreed/) using pip:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install labfreed
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Usage Examples
|
|
26
|
+
<!-- BEGIN EXAMPLES -->
|
|
27
|
+
```python
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Parse a simple PAC-ID
|
|
32
|
+
The
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from labfreed.parse_pac import PAC_Parser
|
|
36
|
+
|
|
37
|
+
# Parse the PAC-ID
|
|
38
|
+
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
39
|
+
pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
40
|
+
|
|
41
|
+
# Check validity of this PAC-ID
|
|
42
|
+
pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
43
|
+
is_valid = pac_id.is_valid()
|
|
44
|
+
print('PAC-ID is valid: {is_valid}')
|
|
45
|
+
# >> PAC-ID is valid: {is_valid}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Show recommendations:
|
|
49
|
+
Note that the PAC-ID, while valid uses characters, which are not recommended (results in larger QR code).
|
|
50
|
+
There is a nice function to highlight problems
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
pac_id.print_validation_messages()
|
|
54
|
+
# >>
|
|
55
|
+
# =======================================
|
|
56
|
+
# Validation Results
|
|
57
|
+
# ---------------------------------------
|
|
58
|
+
|
|
59
|
+
# Recommendation in id segment value bal500
|
|
60
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
61
|
+
# Characters a b l should not be used.
|
|
62
|
+
|
|
63
|
+
# Recommendation in id segment value @1234
|
|
64
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
65
|
+
# Characters @ should not be used.
|
|
66
|
+
|
|
67
|
+
# Warning in Category -MD
|
|
68
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
69
|
+
# Category key -MD is not a well known key. It is recommended to use well known keys only
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Parse a PAC-ID with extensions
|
|
73
|
+
PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/WM633OV3E5DGJW2BEG0PDM1EA7*SUM$TREX/WEIGHT$GRM:67.89'
|
|
77
|
+
pac_id = PAC_Parser().parse(pac_str)
|
|
78
|
+
|
|
79
|
+
# Display Name
|
|
80
|
+
display_names = pac_id.get_extension('N') # display name has name 'N'
|
|
81
|
+
print(f'\n {display_names}')
|
|
82
|
+
# >> Display names: My Balance ❤️
|
|
83
|
+
|
|
84
|
+
# TREX
|
|
85
|
+
trexes = pac_id.get_extension_of_type('TREX')
|
|
86
|
+
trex = trexes[0] # there could be multiple trexes. In this example there is only one, though
|
|
87
|
+
v = trex.get_segment('WEIGHT').to_python_type()
|
|
88
|
+
print(f'WEIGHT = {v}')
|
|
89
|
+
# >> WEIGHT = 67.89 g
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Create a PAC-ID with Extensions
|
|
93
|
+
|
|
94
|
+
#### Create PAC-ID
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from labfreed.PAC_ID.data_model import PACID, IDSegment
|
|
98
|
+
from labfreed.utilities.well_known_keys import WellKnownKeys
|
|
99
|
+
|
|
100
|
+
pac_id = PACID(issuer='METTORIUS:COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
|
|
101
|
+
pac_str = pac_id.serialize()
|
|
102
|
+
pac_str = pac_id.serialize()
|
|
103
|
+
print(pac_str)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### Create a TREX
|
|
107
|
+
TREX can conveniently be created from a python dictionary.
|
|
108
|
+
Note that utility types for Quantity (number with unit) and table are needed
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from datetime import datetime
|
|
112
|
+
from labfreed.TREX.data_model import TREX
|
|
113
|
+
from labfreed.utilities.utility_types import Quantity, DataTable, Unit
|
|
114
|
+
|
|
115
|
+
# Create TREX
|
|
116
|
+
trex = TREX(name_='DEMO')
|
|
117
|
+
# Add value segments of different type
|
|
118
|
+
trex.update(
|
|
119
|
+
{
|
|
120
|
+
'STOP': datetime(year=2024,month=5,day=5,hour=13,minute=6),
|
|
121
|
+
'TEMP': Quantity(value=10.15, unit=Unit(name='kelvin', symbol='K')),
|
|
122
|
+
'OK':False,
|
|
123
|
+
'COMMENT': 'FOO',
|
|
124
|
+
'COMMENT2':'£'
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Create a table
|
|
129
|
+
table = DataTable(['DURATION', 'DATE', 'OK', 'COMMENT'])
|
|
130
|
+
table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
|
|
131
|
+
table.append([ 1.1, datetime.now(), True, 'BAR'])
|
|
132
|
+
table.append([ 1.3, datetime.now(), False, 'BLUBB'])
|
|
133
|
+
#add the table to the trex
|
|
134
|
+
trex.update({'TABLE': table})
|
|
135
|
+
|
|
136
|
+
# Validation also works the same way for TREX
|
|
137
|
+
if trex.get_nested_validation_messages():
|
|
138
|
+
trex.print_validation_messages()
|
|
139
|
+
|
|
140
|
+
# Side Note: The TREX can be turned back into a dict
|
|
141
|
+
d = trex.dict()
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### Combine PAC-ID and TREX and serialize
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from labfreed.parse_pac import PACID_With_Extensions
|
|
148
|
+
|
|
149
|
+
pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
|
|
150
|
+
pac_str = pac_with_trex.serialize()
|
|
151
|
+
print(pac_str)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
<!-- END EXAMPLES -->
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
## Change Log
|
|
159
|
+
|
|
160
|
+
### v0.0.9
|
|
161
|
+
- supports PAC-ID, PAC-CAT, TREX and DisplayName
|
|
162
|
+
- ok-ish test coverage
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
'''
|
|
2
|
+
### Parse a simple PAC-ID
|
|
3
|
+
The
|
|
4
|
+
'''
|
|
5
|
+
from labfreed.parse_pac import PAC_Parser
|
|
6
|
+
|
|
7
|
+
# Parse the PAC-ID
|
|
8
|
+
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
9
|
+
pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
10
|
+
|
|
11
|
+
# Check validity of this PAC-ID
|
|
12
|
+
pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
13
|
+
is_valid = pac_id.is_valid()
|
|
14
|
+
print('PAC-ID is valid: {is_valid}')
|
|
15
|
+
# >> PAC-ID is valid: {is_valid}
|
|
16
|
+
|
|
17
|
+
'''
|
|
18
|
+
Show recommendations:
|
|
19
|
+
Note that the PAC-ID, while valid uses characters, which are not recommended (results in larger QR code).
|
|
20
|
+
There is a nice function to highlight problems
|
|
21
|
+
'''
|
|
22
|
+
pac_id.print_validation_messages()
|
|
23
|
+
# >>
|
|
24
|
+
# =======================================
|
|
25
|
+
# Validation Results
|
|
26
|
+
# ---------------------------------------
|
|
27
|
+
|
|
28
|
+
# Recommendation in id segment value bal500
|
|
29
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
30
|
+
# Characters a b l should not be used.
|
|
31
|
+
|
|
32
|
+
# Recommendation in id segment value @1234
|
|
33
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
34
|
+
# Characters @ should not be used.
|
|
35
|
+
|
|
36
|
+
# Warning in Category -MD
|
|
37
|
+
# HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
38
|
+
# Category key -MD is not a well known key. It is recommended to use well known keys only
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
'''
|
|
43
|
+
### Parse a PAC-ID with extensions
|
|
44
|
+
PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
|
|
45
|
+
'''
|
|
46
|
+
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/WM633OV3E5DGJW2BEG0PDM1EA7*SUM$TREX/WEIGHT$GRM:67.89'
|
|
47
|
+
pac_id = PAC_Parser().parse(pac_str)
|
|
48
|
+
|
|
49
|
+
# Display Name
|
|
50
|
+
display_names = pac_id.get_extension('N') # display name has name 'N'
|
|
51
|
+
print(f'\n {display_names}')
|
|
52
|
+
# >> Display names: My Balance ❤️
|
|
53
|
+
|
|
54
|
+
# TREX
|
|
55
|
+
trexes = pac_id.get_extension_of_type('TREX')
|
|
56
|
+
trex = trexes[0] # there could be multiple trexes. In this example there is only one, though
|
|
57
|
+
v = trex.get_segment('WEIGHT').to_python_type()
|
|
58
|
+
print(f'WEIGHT = {v}')
|
|
59
|
+
# >> WEIGHT = 67.89 g
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
'''
|
|
64
|
+
### Create a PAC-ID with Extensions
|
|
65
|
+
|
|
66
|
+
#### Create PAC-ID
|
|
67
|
+
'''
|
|
68
|
+
from labfreed.PAC_ID.data_model import PACID, IDSegment
|
|
69
|
+
from labfreed.utilities.well_known_keys import WellKnownKeys
|
|
70
|
+
|
|
71
|
+
pac_id = PACID(issuer='METTORIUS:COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
|
|
72
|
+
pac_str = pac_id.serialize()
|
|
73
|
+
pac_str = pac_id.serialize()
|
|
74
|
+
print(pac_str)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
'''
|
|
78
|
+
#### Create a TREX
|
|
79
|
+
TREX can conveniently be created from a python dictionary.
|
|
80
|
+
Note that utility types for Quantity (number with unit) and table are needed
|
|
81
|
+
'''
|
|
82
|
+
from datetime import datetime
|
|
83
|
+
from labfreed.TREX.data_model import TREX
|
|
84
|
+
from labfreed.utilities.utility_types import Quantity, DataTable, Unit
|
|
85
|
+
|
|
86
|
+
# Create TREX
|
|
87
|
+
trex = TREX(name_='DEMO')
|
|
88
|
+
# Add value segments of different type
|
|
89
|
+
trex.update(
|
|
90
|
+
{
|
|
91
|
+
'STOP': datetime(year=2024,month=5,day=5,hour=13,minute=6),
|
|
92
|
+
'TEMP': Quantity(value=10.15, unit=Unit(name='kelvin', symbol='K')),
|
|
93
|
+
'OK':False,
|
|
94
|
+
'COMMENT': 'FOO',
|
|
95
|
+
'COMMENT2':'£'
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Create a table
|
|
100
|
+
table = DataTable(['DURATION', 'DATE', 'OK', 'COMMENT'])
|
|
101
|
+
table.append([Quantity(value=1, unit=Unit(symbol='h', name='hour')), datetime.now(), True, 'FOO'])
|
|
102
|
+
table.append([ 1.1, datetime.now(), True, 'BAR'])
|
|
103
|
+
table.append([ 1.3, datetime.now(), False, 'BLUBB'])
|
|
104
|
+
#add the table to the trex
|
|
105
|
+
trex.update({'TABLE': table})
|
|
106
|
+
|
|
107
|
+
# Validation also works the same way for TREX
|
|
108
|
+
if trex.get_nested_validation_messages():
|
|
109
|
+
trex.print_validation_messages()
|
|
110
|
+
|
|
111
|
+
# Side Note: The TREX can be turned back into a dict
|
|
112
|
+
d = trex.dict()
|
|
113
|
+
|
|
114
|
+
'''
|
|
115
|
+
#### Combine PAC-ID and TREX and serialize
|
|
116
|
+
'''
|
|
117
|
+
from labfreed.parse_pac import PACID_With_Extensions
|
|
118
|
+
|
|
119
|
+
pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
|
|
120
|
+
pac_str = pac_with_trex.serialize()
|
|
121
|
+
print(pac_str)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
@@ -49,7 +49,7 @@ class PACID_With_Extensions(BaseModelWithValidationMessages):
|
|
|
49
49
|
@classmethod
|
|
50
50
|
def deserialize(cls, url, extension_interpreters ):
|
|
51
51
|
parser = PAC_Parser(extension_interpreters)
|
|
52
|
-
return parser.
|
|
52
|
+
return parser.parse(url)
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
|
|
@@ -87,15 +87,15 @@ class PAC_Parser():
|
|
|
87
87
|
def __init__(self, extension_interpreters:dict[str, Extension]=None):
|
|
88
88
|
self.extension_interpreters = extension_interpreters or {'TREX': TREX, 'N': DisplayNames}
|
|
89
89
|
|
|
90
|
-
def
|
|
90
|
+
def parse(self, pac_url:str) -> PACID_With_Extensions:
|
|
91
91
|
if '*' in pac_url:
|
|
92
92
|
id_str, ext_str = pac_url.split('*', 1)
|
|
93
93
|
else:
|
|
94
94
|
id_str = pac_url
|
|
95
95
|
ext_str = ""
|
|
96
96
|
|
|
97
|
-
pac_id = self.
|
|
98
|
-
extensions = self.
|
|
97
|
+
pac_id = self._parse_pac_id(id_str)
|
|
98
|
+
extensions = self._parse_extensions(ext_str)
|
|
99
99
|
|
|
100
100
|
pac_with_extension = PACID_With_Extensions(pac_id=pac_id, extensions=extensions)
|
|
101
101
|
if not pac_with_extension.is_valid():
|
|
@@ -104,7 +104,7 @@ class PAC_Parser():
|
|
|
104
104
|
return pac_with_extension
|
|
105
105
|
|
|
106
106
|
|
|
107
|
-
def
|
|
107
|
+
def _parse_pac_id(self,id_str:str) -> PACID:
|
|
108
108
|
m = re.match(f'(HTTPS://)?(PAC.)?(?P<issuer>.+?\..+?)/(?P<identifier>.*)', id_str)
|
|
109
109
|
d = m.groupdict()
|
|
110
110
|
|
|
@@ -148,7 +148,7 @@ class PAC_Parser():
|
|
|
148
148
|
|
|
149
149
|
|
|
150
150
|
|
|
151
|
-
def
|
|
151
|
+
def _parse_extensions(self, extensions_str:str|None) -> list[Extension]:
|
|
152
152
|
|
|
153
153
|
extensions = list()
|
|
154
154
|
|
{labfreed-0.0.14 → labfreed-0.0.15}/tests/test_(de)_serialization_incl_extension/test__parse.py
RENAMED
|
@@ -11,7 +11,7 @@ parser = PAC_Parser()
|
|
|
11
11
|
|
|
12
12
|
# Extensions
|
|
13
13
|
def test_valid_extensions():
|
|
14
|
-
pac = parser.
|
|
14
|
+
pac = parser.parse(valid_base + valid_standard_segments + "*name1$t1/data1*name2$t2/data2")
|
|
15
15
|
extensions = pac.extensions
|
|
16
16
|
ext: Extension = extensions[0]
|
|
17
17
|
assert ext.name == 'name1'
|
|
@@ -45,7 +45,7 @@ def test_known_extension_types_are_parsed():
|
|
|
45
45
|
'KNOWN_EXTENSION': ExtensionMockType,
|
|
46
46
|
}
|
|
47
47
|
parser_with_known_extension = PAC_Parser(extension_interpreters)
|
|
48
|
-
pac = parser_with_known_extension.
|
|
48
|
+
pac = parser_with_known_extension.parse(valid_base + valid_standard_segments + "*name1$KNOWN_EXTENSION/data1")
|
|
49
49
|
extensions= pac.extensions
|
|
50
50
|
ext: Extension = extensions[0]
|
|
51
51
|
assert isinstance(ext, ExtensionMockType)
|
|
@@ -55,7 +55,7 @@ def test_known_extension_types_are_parsed():
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
def test_imply_display_name_and_summary_extension():
|
|
58
|
-
pac = parser.
|
|
58
|
+
pac = parser.parse(valid_base + valid_standard_segments + "*data1*data2")
|
|
59
59
|
extensions = pac.extensions
|
|
60
60
|
ext: Extension = extensions[0]
|
|
61
61
|
assert ext.name == 'N'
|
|
@@ -67,13 +67,13 @@ def test_imply_display_name_and_summary_extension():
|
|
|
67
67
|
|
|
68
68
|
def test_stop_imply_extensions_after_explicit():
|
|
69
69
|
with pytest.raises(Exception):
|
|
70
|
-
pac = parser.
|
|
70
|
+
pac = parser.parse(valid_base + valid_standard_segments + "*N$T/data1*data2")
|
|
71
71
|
pac.extensions
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def test_extension_parsing():
|
|
75
75
|
s = '*NAME$MYFORMAT/AUGDSJGTZFRDGJHDSFRTZGHJAAUTZSGADT*NAME$ANOTHERFORMAT/BLUBBER'
|
|
76
|
-
extensions = parser.
|
|
76
|
+
extensions = parser._parse_extensions(s)
|
|
77
77
|
ext: Extension = extensions[0]
|
|
78
78
|
assert ext.name == 'NAME'
|
|
79
79
|
assert ext.type == 'MYFORMAT'
|
|
@@ -16,27 +16,27 @@ parser = PAC_Parser()
|
|
|
16
16
|
|
|
17
17
|
# Identifier Segments Categories (Recommendation)
|
|
18
18
|
def test_basic_valid_category():
|
|
19
|
-
pac = parser.
|
|
19
|
+
pac = parser.parse(valid_base + "-DM/21:VAL")
|
|
20
20
|
cat: Category = pac.pac_id.categories[0]
|
|
21
21
|
assert cat.key == '-DM'
|
|
22
22
|
assert cat.segments[0].key == '21'
|
|
23
23
|
assert cat.segments[0].value == 'VAL'
|
|
24
24
|
|
|
25
25
|
def test_if_no_category_is_specified_default_to_unnamed_category():
|
|
26
|
-
pac = parser.
|
|
26
|
+
pac = parser.parse(valid_base + "KEY:VAL")
|
|
27
27
|
cat: Category = pac.pac_id.categories[0]
|
|
28
28
|
assert cat.key == None
|
|
29
29
|
assert cat.segments[0].key == 'KEY'
|
|
30
30
|
assert cat.segments[0].value == 'VAL'
|
|
31
31
|
|
|
32
32
|
def test_missing_dash_in_category_name_is_interpreted_as_unnamed_segment():
|
|
33
|
-
pac = parser.
|
|
33
|
+
pac = parser.parse(valid_base + "DM/21:VAL")
|
|
34
34
|
cat: Category = pac.pac_id.categories[0]
|
|
35
35
|
assert cat.key == None
|
|
36
36
|
assert cat.segments[0].value == 'DM'
|
|
37
37
|
|
|
38
38
|
def test_category_with_multiple_segments():
|
|
39
|
-
pac = parser.
|
|
39
|
+
pac = parser.parse(valid_base + "-MX/KEY0:VAL0/VAL1/KEY2:VAL2")
|
|
40
40
|
cat: Category = pac.pac_id.categories[0]
|
|
41
41
|
assert cat.key == '-MX'
|
|
42
42
|
|
|
@@ -53,7 +53,7 @@ def test_category_with_multiple_segments():
|
|
|
53
53
|
assert seg.value == "VAL2"
|
|
54
54
|
|
|
55
55
|
def test_two_categories():
|
|
56
|
-
pac = parser.
|
|
56
|
+
pac = parser.parse(valid_base + "-DX/KEY:VAL/-MX/KEY:VAL")
|
|
57
57
|
cat: Category = pac.pac_id.categories[0]
|
|
58
58
|
assert cat.key == '-DX'
|
|
59
59
|
assert cat.segments[0].key == 'KEY'
|
|
@@ -65,7 +65,7 @@ def test_two_categories():
|
|
|
65
65
|
assert cat.segments[0].value == 'VAL'
|
|
66
66
|
|
|
67
67
|
def test_three_categories():
|
|
68
|
-
pac = parser.
|
|
68
|
+
pac = parser.parse(valid_base + "-DX/KEY0:VAL0/-MX/KEY1:VAL1/-CAT/KEY2:VAL2")
|
|
69
69
|
pac = pac.pac_id
|
|
70
70
|
cat: Category = pac.categories[0]
|
|
71
71
|
assert cat.key == '-DX'
|
|
@@ -83,13 +83,13 @@ def test_three_categories():
|
|
|
83
83
|
assert cat.segments[0].value == 'VAL2'
|
|
84
84
|
|
|
85
85
|
def test_implied_segments_of_MD_category():
|
|
86
|
-
pac = parser.
|
|
86
|
+
pac = parser.parse(valid_base + "-MD/0/1")
|
|
87
87
|
cat: Category = pac.pac_id.categories[0]
|
|
88
88
|
assert cat.segments[0].key == '240'
|
|
89
89
|
assert cat.segments[1].key == '21'
|
|
90
90
|
|
|
91
91
|
def test_implied_segments_of_MS_category():
|
|
92
|
-
pac = parser.
|
|
92
|
+
pac = parser.parse(valid_base + "-MS/0/1/2/3/4")
|
|
93
93
|
cat: Category = pac.pac_id.categories[0]
|
|
94
94
|
assert cat.segments[0].key == '240'
|
|
95
95
|
assert cat.segments[1].key == '10'
|
|
@@ -98,7 +98,7 @@ def test_implied_segments_of_MS_category():
|
|
|
98
98
|
assert cat.segments[4].key == '250'
|
|
99
99
|
|
|
100
100
|
def test_implied_segments_of_MC_category():
|
|
101
|
-
pac = parser.
|
|
101
|
+
pac = parser.parse(valid_base + "-MC/0/1/2/3/4")
|
|
102
102
|
cat: Category = pac.pac_id.categories[0]
|
|
103
103
|
assert cat.segments[0].key == '240'
|
|
104
104
|
assert cat.segments[1].key == '10'
|
|
@@ -107,7 +107,7 @@ def test_implied_segments_of_MC_category():
|
|
|
107
107
|
assert cat.segments[4].key == '250'
|
|
108
108
|
|
|
109
109
|
def test_implied_segments_of_MM_category():
|
|
110
|
-
pac = parser.
|
|
110
|
+
pac = parser.parse(valid_base + "-MM/0/1/2/3/4")
|
|
111
111
|
cat: Category = pac.pac_id.categories[0]
|
|
112
112
|
assert cat.segments[0].key == '240'
|
|
113
113
|
assert cat.segments[1].key == '10'
|
|
@@ -116,7 +116,7 @@ def test_implied_segments_of_MM_category():
|
|
|
116
116
|
assert cat.segments[4].key == '250'
|
|
117
117
|
|
|
118
118
|
def test_stop_implying_segments_after_an_explicit_one_is_found():
|
|
119
|
-
pac = parser.
|
|
119
|
+
pac = parser.parse(valid_base + "-MS/0/1/KEY:2/3/4")
|
|
120
120
|
cat: Category = pac.pac_id.categories[0]
|
|
121
121
|
assert cat.segments[0].key == '240'
|
|
122
122
|
assert cat.segments[1].key == '10'
|
|
@@ -125,7 +125,7 @@ def test_stop_implying_segments_after_an_explicit_one_is_found():
|
|
|
125
125
|
assert cat.segments[4].key == None
|
|
126
126
|
|
|
127
127
|
def test_more_segments_than_implicit_keys():
|
|
128
|
-
pac = parser.
|
|
128
|
+
pac = parser.parse(valid_base + "-MD/IMPLIED1/IMPLIED2/ADDITIONAL")
|
|
129
129
|
cat: Category = pac.pac_id.categories[0]
|
|
130
130
|
assert cat.segments[2].key == None
|
|
131
131
|
|
|
@@ -135,9 +135,9 @@ def test_more_segments_than_implicit_keys():
|
|
|
135
135
|
|
|
136
136
|
def test_mandatory_fields_of_MD_category():
|
|
137
137
|
with pytest.raises(LabFREEDValidationError):
|
|
138
|
-
pac = parser.
|
|
138
|
+
pac = parser.parse(valid_base + "-MD/KEY:VAL")
|
|
139
139
|
|
|
140
|
-
pac:PAC_CAT = parser.
|
|
140
|
+
pac:PAC_CAT = parser.parse(valid_base + "-MD/21:1234/KEY:VAL/240:BAL500").pac_id
|
|
141
141
|
assert pac.get_category('-MD').serial_number == '1234'
|
|
142
142
|
assert pac.get_category('-MD').model_number == 'BAL500'
|
|
143
143
|
|