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.
@@ -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
- from .well_known_segment_keys import WellKnownSegmentKeys
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 WellKnownSegmentKeys]:
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 Category(BaseModelWithValidationMessages):
98
- key:str|None = None
99
- segments: list[IDSegment]
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.segments:
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.segments) - 1 # account for "/" separating the segments
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
- class PACID_With_Extensions(BaseModelWithValidationMessages):
241
- pac_id: PACID
242
- extensions: list[Extension] = Field(default_factory=list)
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)