labfreed 0.0.9__py2.py3-none-any.whl → 0.0.11__py2.py3-none-any.whl
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/DisplayNameExtension/DisplayNameExtension.py +5 -2
- labfreed/PAC_CAT/data_model copy.py +232 -0
- labfreed/PAC_CAT/data_model.py +319 -59
- labfreed/PAC_ID/data_model.py +42 -112
- labfreed/PAC_ID/extensions.py +55 -0
- labfreed/TREX/data_model.py +316 -396
- labfreed/TREX/parse.py +1 -69
- labfreed/TREX/unece_units.py +17 -1
- labfreed/__init__.py +1 -1
- labfreed/{PAC_ID/parse.py → parse_pac.py} +104 -59
- labfreed/utilities/base36.py +29 -13
- labfreed/utilities/extension_intertpreters.py +4 -0
- labfreed/utilities/utility_types.py +103 -0
- labfreed/{PAC_ID/well_known_segment_keys.py → utilities/well_known_keys.py} +1 -1
- labfreed/validation.py +3 -1
- {labfreed-0.0.9.dist-info → labfreed-0.0.11.dist-info}/METADATA +1 -1
- labfreed-0.0.11.dist-info/RECORD +22 -0
- labfreed/PAC_ID/serialize.py +0 -60
- labfreed/TREX/serialize.py +0 -3
- labfreed/conversion_tools/uncertainty.py +0 -32
- labfreed/conversion_tools/unit_utilities.py +0 -109
- labfreed-0.0.9.dist-info/RECORD +0 -22
- {labfreed-0.0.9.dist-info → labfreed-0.0.11.dist-info}/WHEEL +0 -0
- {labfreed-0.0.9.dist-info → labfreed-0.0.11.dist-info}/licenses/LICENSE +0 -0
labfreed/PAC_ID/data_model.py
CHANGED
|
@@ -4,7 +4,8 @@ from typing_extensions import Self
|
|
|
4
4
|
from pydantic import Field, ValidationInfo, computed_field, conlist, model_validator, field_validator
|
|
5
5
|
|
|
6
6
|
from abc import ABC, abstractproperty, abstractstaticmethod
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
from ..utilities.well_known_keys import WellKnownKeys
|
|
8
9
|
from labfreed.validation import BaseModelWithValidationMessages, ValidationMessage, hsegment_pattern, domain_name_pattern
|
|
9
10
|
|
|
10
11
|
|
|
@@ -51,7 +52,7 @@ class IDSegment(BaseModelWithValidationMessages):
|
|
|
51
52
|
)
|
|
52
53
|
|
|
53
54
|
# Segment key should be in Well know keys
|
|
54
|
-
if key and key not in [k.value for k in
|
|
55
|
+
if key and key not in [k.value for k in WellKnownKeys]:
|
|
55
56
|
self.add_validation_message(
|
|
56
57
|
source=f"id segment key {key}",
|
|
57
58
|
type="Recommendation",
|
|
@@ -90,63 +91,24 @@ class IDSegment(BaseModelWithValidationMessages):
|
|
|
90
91
|
)
|
|
91
92
|
|
|
92
93
|
return self
|
|
93
|
-
|
|
94
|
+
|
|
94
95
|
|
|
95
|
-
|
|
96
96
|
|
|
97
|
-
class
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
class Identifier(BaseModelWithValidationMessages):
|
|
103
|
-
segments: conlist(IDSegment, min_length=1) = Field(..., exclude=True) # type: ignore # exclude=True prevents this from being serialized by Pydantic
|
|
97
|
+
class PACID(BaseModelWithValidationMessages):
|
|
98
|
+
issuer:str
|
|
99
|
+
identifier: conlist(IDSegment, min_length=1) = Field(..., default_factory=list()) # type: ignore # exclude=True prevents this from being serialized by Pydantic
|
|
104
100
|
|
|
105
|
-
@computed_field
|
|
106
|
-
@property
|
|
107
|
-
def categories(self) -> list[Category]:
|
|
108
|
-
categories = list()
|
|
109
|
-
c = Category(segments=[])
|
|
110
|
-
categories.append(c)
|
|
111
|
-
for s in self.segments:
|
|
112
|
-
# new category starts with "-"
|
|
113
|
-
if s.value[0] == '-':
|
|
114
|
-
cat_key = s.value
|
|
115
|
-
c = Category(key=cat_key, segments=[])
|
|
116
|
-
categories.append(c)
|
|
117
|
-
else:
|
|
118
|
-
c.segments.append(s)
|
|
119
|
-
|
|
120
|
-
# the first category might have no segments. remove categories without segments
|
|
121
|
-
if not categories[0].segments:
|
|
122
|
-
categories = categories[1:]
|
|
123
|
-
|
|
124
|
-
return categories
|
|
125
|
-
|
|
126
|
-
@model_validator(mode='after')
|
|
127
|
-
def check_keys_are_unique_in_each_category(self) -> Self:
|
|
128
|
-
for c in self.categories:
|
|
129
|
-
keys = [s.key for s in c.segments if s.key]
|
|
130
|
-
duplicate_keys = [k for k in set(keys) if keys.count(k) > 1]
|
|
131
|
-
if duplicate_keys:
|
|
132
|
-
for k in duplicate_keys:
|
|
133
|
-
self.add_validation_message(
|
|
134
|
-
source=f"identifier {k}",
|
|
135
|
-
type="Error",
|
|
136
|
-
msg=f"Duplicate key {k} in category {c.key}",
|
|
137
|
-
highlight_pattern = k
|
|
138
|
-
)
|
|
139
|
-
return self
|
|
140
101
|
|
|
141
102
|
@model_validator(mode='after')
|
|
142
103
|
def check_length(self) -> Self:
|
|
143
104
|
l = 0
|
|
144
|
-
for s in self.
|
|
105
|
+
for s in self.identifier:
|
|
106
|
+
s:IDSegment = s
|
|
145
107
|
if s.key:
|
|
146
108
|
l += len(s.key)
|
|
147
109
|
l += 1 # for ":"
|
|
148
110
|
l += len(s.value)
|
|
149
|
-
l += len(self.
|
|
111
|
+
l += len(self.identifier) - 1 # account for "/" separating the segments
|
|
150
112
|
|
|
151
113
|
if l > 256:
|
|
152
114
|
self.add_validation_message(
|
|
@@ -157,62 +119,6 @@ class Identifier(BaseModelWithValidationMessages):
|
|
|
157
119
|
)
|
|
158
120
|
return self
|
|
159
121
|
|
|
160
|
-
@staticmethod
|
|
161
|
-
def from_categories(categories:list[Category]) :
|
|
162
|
-
segments = list()
|
|
163
|
-
for c in categories:
|
|
164
|
-
if c.key:
|
|
165
|
-
segments.append(IDSegment(value=c.key))
|
|
166
|
-
segments.extend(c.segments)
|
|
167
|
-
return Identifier(segments=segments)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
class Extension(ABC, BaseModelWithValidationMessages):
|
|
172
|
-
|
|
173
|
-
@abstractproperty
|
|
174
|
-
def name(self)->str:
|
|
175
|
-
pass
|
|
176
|
-
|
|
177
|
-
@abstractproperty
|
|
178
|
-
def type(self)->str:
|
|
179
|
-
pass
|
|
180
|
-
|
|
181
|
-
@abstractproperty
|
|
182
|
-
def data(self)->str:
|
|
183
|
-
pass
|
|
184
|
-
|
|
185
|
-
@abstractstaticmethod
|
|
186
|
-
def from_spec_fields(name, type, data):
|
|
187
|
-
pass
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
class UnknownExtension(Extension):
|
|
191
|
-
name_:str
|
|
192
|
-
type_:str
|
|
193
|
-
data_:str
|
|
194
|
-
|
|
195
|
-
@property
|
|
196
|
-
def name(self)->str:
|
|
197
|
-
return self.name_
|
|
198
|
-
|
|
199
|
-
@property
|
|
200
|
-
def type(self)->str:
|
|
201
|
-
return self.type_
|
|
202
|
-
|
|
203
|
-
@property
|
|
204
|
-
def data(self)->str:
|
|
205
|
-
return self.data_
|
|
206
|
-
|
|
207
|
-
@staticmethod
|
|
208
|
-
def from_spec_fields(name, type, data):
|
|
209
|
-
return UnknownExtension(name_=name, type_=type, data_=data)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
class PACID(BaseModelWithValidationMessages):
|
|
214
|
-
issuer:str
|
|
215
|
-
identifier: Identifier
|
|
216
122
|
|
|
217
123
|
@model_validator(mode="after")
|
|
218
124
|
def validate_issuer(self):
|
|
@@ -221,7 +127,6 @@ class PACID(BaseModelWithValidationMessages):
|
|
|
221
127
|
source="PAC-ID",
|
|
222
128
|
type="Error",
|
|
223
129
|
highlight_pattern=self.issuer,
|
|
224
|
-
highlight_sub=not_recommended_chars,
|
|
225
130
|
msg=f"Issuer must be a valid domain name. "
|
|
226
131
|
)
|
|
227
132
|
|
|
@@ -237,11 +142,36 @@ class PACID(BaseModelWithValidationMessages):
|
|
|
237
142
|
return self
|
|
238
143
|
|
|
239
144
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
145
|
+
@model_validator(mode='after')
|
|
146
|
+
def check_identifier_segment_keys_are_unique(self) -> Self:
|
|
147
|
+
keys = [s.key for s in self.identifier if s.key]
|
|
148
|
+
duplicate_keys = [k for k in set(keys) if keys.count(k) > 1]
|
|
149
|
+
if duplicate_keys:
|
|
150
|
+
for k in duplicate_keys:
|
|
151
|
+
self.add_validation_message(
|
|
152
|
+
source=f"identifier {k}",
|
|
153
|
+
type="Recommendation",
|
|
154
|
+
msg=f"Duplicate segment key {k}. This will probably lead to undefined behaviour",
|
|
155
|
+
highlight_pattern = k
|
|
156
|
+
)
|
|
157
|
+
return self
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def __str__(self):
|
|
161
|
+
id_segments = ''
|
|
162
|
+
for s in self.identifier:
|
|
163
|
+
s:IDSegment = s
|
|
164
|
+
if s.key:
|
|
165
|
+
id_segments += f'/{s.key}:{s.value}'
|
|
166
|
+
else:
|
|
167
|
+
id_segments += f'/{s.value}'
|
|
168
|
+
|
|
169
|
+
out = f"HTTPS://PAC.{self.issuer}{id_segments}"
|
|
170
|
+
return out
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def serialize(self):
|
|
174
|
+
return str(self)
|
|
175
|
+
|
|
176
|
+
|
|
247
177
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
from abc import ABC, abstractproperty, abstractstaticmethod
|
|
3
|
+
from types import MappingProxyType
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
|
|
7
|
+
from labfreed.validation import BaseModelWithValidationMessages
|
|
8
|
+
from labfreed.PAC_ID.data_model import PACID
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Extension(ABC, BaseModelWithValidationMessages):
|
|
14
|
+
|
|
15
|
+
@abstractproperty
|
|
16
|
+
def name(self)->str:
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@abstractproperty
|
|
20
|
+
def type(self)->str:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractproperty
|
|
24
|
+
def data(self)->str:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
@abstractstaticmethod
|
|
28
|
+
def from_spec_fields(*, name, type, data):
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
def __str__(self):
|
|
32
|
+
return f'{self.name}${self.type}/{self.data}'
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class UnknownExtension(Extension):
|
|
37
|
+
name_:str
|
|
38
|
+
type_:str
|
|
39
|
+
data_:str
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def name(self)->str:
|
|
43
|
+
return self.name_
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def type(self)->str:
|
|
47
|
+
return self.type_
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def data(self)->str:
|
|
51
|
+
return self.data_
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def from_spec_fields(*, name, type, data):
|
|
55
|
+
return UnknownExtension(name_=name, type_=type, data_=data)
|