labfreed 0.0.15__py2.py3-none-any.whl → 0.0.17__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.

Potentially problematic release.


This version of labfreed might be problematic. Click here for more details.

@@ -138,6 +138,19 @@ class PAC_CAT(PACID):
138
138
  )
139
139
  return self
140
140
 
141
+ def print_categories(self):
142
+ s = ''
143
+ for i, c in enumerate(self.categories):
144
+ if i == 0:
145
+ title = 'Main Category\n----------'
146
+ else:
147
+ title = 'Category\n------ '
148
+
149
+ s += f'{title}\n'
150
+ s += str(c)
151
+ s += '\n'
152
+ print(s)
153
+
141
154
 
142
155
  # @classmethod
143
156
  # def from_categories(cls, issuer:str, categories:list[Category]):
@@ -198,6 +211,11 @@ class Category(BaseModelWithValidationMessages):
198
211
  return self
199
212
 
200
213
 
214
+ def __str__(self):
215
+ 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)])
216
+ return s
217
+
218
+
201
219
  # def to_identifier_category(self, use_short_notation=False):
202
220
  # '''Creates a Category with the correct segments.
203
221
  # Segments are in order of the Pydantic model fields.
@@ -261,14 +279,14 @@ class Material_Device(Category):
261
279
  self.add_validation_message(
262
280
  source=f"Category {self.key}",
263
281
  type="Error",
264
- msg=f'Category key {self.key} is missing mandatory field Model NUmber',
282
+ msg=f'Category key {self.key} is missing mandatory field Model Number',
265
283
  highlight_pattern = f"{self.key}"
266
284
  )
267
285
  if not self.serial_number:
268
286
  self.add_validation_message(
269
287
  source=f"Category {self.key}",
270
288
  type="Error",
271
- msg=f'Category key {self.key} is missing mandatory field Serial NUmber',
289
+ msg=f'Category key {self.key} is missing mandatory field Serial Number',
272
290
  highlight_pattern = f"{self.key}"
273
291
  )
274
292
 
@@ -286,7 +304,7 @@ class Material_Substance(Category):
286
304
  self.add_validation_message(
287
305
  source=f"Category {self.key}",
288
306
  type="Error",
289
- msg=f'Category key {self.key} is missing mandatory field Product NUmber',
307
+ msg=f'Category key {self.key} is missing mandatory field Product Number',
290
308
  highlight_pattern = f"{self.key}"
291
309
  )
292
310
 
@@ -328,19 +346,19 @@ class Data_Abstract(Category, ABC):
328
346
  highlight_pattern = f"{self.key}"
329
347
  )
330
348
 
331
- class Data_Result(Category):
349
+ class Data_Result(Data_Abstract):
332
350
  key: str = Field(default='-DR', frozen=True)
333
351
 
334
- class Data_Method(Category):
352
+ class Data_Method(Data_Abstract):
335
353
  key: str = Field(default='-DM', frozen=True)
336
354
 
337
- class Data_Calibration(Category):
355
+ class Data_Calibration(Data_Abstract):
338
356
  key: str = Field(default='-DC', frozen=True)
339
357
 
340
- class Data_Progress(Category):
358
+ class Data_Progress(Data_Abstract):
341
359
  key: str = Field(default='-DP', frozen=True)
342
360
 
343
- class Data_Static(Category):
361
+ class Data_Static(Data_Abstract):
344
362
  key: str = Field(default='-DS', frozen=True)
345
363
 
346
364
 
@@ -0,0 +1,450 @@
1
+ #!/usr/bin/env python
2
+ import typer
3
+ import io
4
+ from rich import print
5
+ from typing_extensions import Annotated
6
+ import numpy as np
7
+ import segno
8
+ from segno import DataOverflowError, writers
9
+ from typing import List
10
+ from enum import Enum
11
+
12
+
13
+
14
+ class Direction(str, Enum):
15
+ LEFT_TO_RIGHT = "LTR"
16
+ TOP_TO_BOTTOM = "TTB"
17
+ RIGHT_TO_LEFT = "RTL"
18
+
19
+ # 5x5 block of bits that can be used to place decoration next to barcode.
20
+ class VisualMarker:
21
+ size = 5
22
+
23
+ def __init__(self, bits):
24
+ # true means 1 bit, false means 0 bit (eg: 1 means black, 0 means white)
25
+ self.bits = bits
26
+
27
+ marker_dict = {
28
+ 'A': bytearray([
29
+ 0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
30
+ 0x01, 0x00, 0x00, 0x00, 0x01,
31
+ 0x01, 0x01, 0x01, 0x01, 0x01,
32
+ 0x01, 0x00, 0x00, 0x00, 0x01,
33
+ 0x01, 0x00, 0x00, 0x00, 0x01,
34
+ ]),
35
+ 'B': bytearray([
36
+ 0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
37
+ 0x01, 0x00, 0x00, 0x00, 0x01,
38
+ 0x01, 0x01, 0x01, 0x01, 0x00,
39
+ 0x01, 0x00, 0x00, 0x00, 0x01,
40
+ 0x01, 0x01, 0x01, 0x01, 0x00,
41
+ ]),
42
+ 'C': bytearray([
43
+ 0x00, 0x01, 0x01, 0x01, 0x01, # preformatted
44
+ 0x01, 0x00, 0x00, 0x00, 0x00,
45
+ 0x01, 0x00, 0x00, 0x00, 0x00,
46
+ 0x01, 0x00, 0x00, 0x00, 0x00,
47
+ 0x00, 0x01, 0x01, 0x01, 0x01,
48
+ ]),
49
+ 'D': bytearray([
50
+ 0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
51
+ 0x01, 0x00, 0x00, 0x00, 0x01,
52
+ 0x01, 0x00, 0x00, 0x00, 0x01,
53
+ 0x01, 0x00, 0x00, 0x00, 0x01,
54
+ 0x01, 0x01, 0x01, 0x01, 0x00,
55
+ ]),
56
+ 'E': bytearray([
57
+ 0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
58
+ 0x01, 0x00, 0x00, 0x00, 0x00,
59
+ 0x01, 0x01, 0x01, 0x01, 0x01,
60
+ 0x01, 0x00, 0x00, 0x00, 0x00,
61
+ 0x01, 0x01, 0x01, 0x01, 0x01,
62
+ ]),
63
+ 'F': bytearray([
64
+ 0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
65
+ 0x01, 0x00, 0x00, 0x00, 0x00,
66
+ 0x01, 0x01, 0x01, 0x01, 0x01,
67
+ 0x01, 0x00, 0x00, 0x00, 0x00,
68
+ 0x01, 0x00, 0x00, 0x00, 0x00,
69
+ ]),
70
+ 'G': bytearray([
71
+ 0x00, 0x01, 0x01, 0x01, 0x01, # preformatted
72
+ 0x01, 0x00, 0x00, 0x00, 0x00,
73
+ 0x01, 0x00, 0x01, 0x01, 0x00,
74
+ 0x01, 0x00, 0x00, 0x00, 0x01,
75
+ 0x00, 0x01, 0x01, 0x01, 0x01,
76
+ ]),
77
+ 'H': bytearray([
78
+ 0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
79
+ 0x01, 0x00, 0x00, 0x00, 0x01,
80
+ 0x01, 0x01, 0x01, 0x01, 0x01,
81
+ 0x01, 0x00, 0x00, 0x00, 0x01,
82
+ 0x01, 0x00, 0x00, 0x00, 0x01,
83
+ ]),
84
+ 'I': bytearray([
85
+ 0x00, 0x00, 0x01, 0x00, 0x00, # preformatted
86
+ 0x00, 0x00, 0x01, 0x00, 0x00,
87
+ 0x00, 0x00, 0x01, 0x00, 0x00,
88
+ 0x00, 0x00, 0x01, 0x00, 0x00,
89
+ 0x00, 0x00, 0x01, 0x00, 0x00,
90
+ ]),
91
+ 'J': bytearray([
92
+ 0x00, 0x00, 0x01, 0x00, 0x00, # preformatted
93
+ 0x00, 0x00, 0x01, 0x00, 0x00,
94
+ 0x00, 0x00, 0x01, 0x00, 0x00,
95
+ 0x00, 0x00, 0x01, 0x00, 0x00,
96
+ 0x00, 0x01, 0x00, 0x00, 0x00,
97
+ ]),
98
+ 'K': bytearray([
99
+ 0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
100
+ 0x01, 0x00, 0x00, 0x01, 0x00,
101
+ 0x01, 0x01, 0x01, 0x00, 0x00,
102
+ 0x01, 0x00, 0x00, 0x01, 0x00,
103
+ 0x01, 0x00, 0x00, 0x00, 0x01,
104
+ ]),
105
+ 'L': bytearray([
106
+ 0x01, 0x00, 0x00, 0x00, 0x00, # preformatted
107
+ 0x01, 0x00, 0x00, 0x00, 0x00,
108
+ 0x01, 0x00, 0x00, 0x00, 0x00,
109
+ 0x01, 0x00, 0x00, 0x00, 0x00,
110
+ 0x01, 0x01, 0x01, 0x01, 0x01,
111
+ ]),
112
+ 'M': bytearray([
113
+ 0x01, 0x01, 0x00, 0x01, 0x01, # preformatted
114
+ 0x01, 0x00, 0x01, 0x00, 0x01,
115
+ 0x01, 0x00, 0x00, 0x00, 0x01,
116
+ 0x01, 0x00, 0x00, 0x00, 0x01,
117
+ 0x01, 0x00, 0x00, 0x00, 0x01,
118
+ ]),
119
+ 'N': bytearray([
120
+ 0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
121
+ 0x01, 0x01, 0x00, 0x00, 0x01,
122
+ 0x01, 0x00, 0x01, 0x00, 0x01,
123
+ 0x01, 0x00, 0x00, 0x01, 0x01,
124
+ 0x01, 0x00, 0x00, 0x00, 0x01,
125
+ ]),
126
+ 'O': bytearray([
127
+ 0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
128
+ 0x01, 0x00, 0x00, 0x00, 0x01,
129
+ 0x01, 0x00, 0x00, 0x00, 0x01,
130
+ 0x01, 0x00, 0x00, 0x00, 0x01,
131
+ 0x00, 0x01, 0x01, 0x01, 0x00,
132
+ ]),
133
+ 'P': bytearray([
134
+ 0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
135
+ 0x01, 0x00, 0x00, 0x00, 0x01,
136
+ 0x01, 0x01, 0x01, 0x01, 0x00,
137
+ 0x01, 0x00, 0x00, 0x00, 0x00,
138
+ 0x01, 0x00, 0x00, 0x00, 0x00,
139
+ ]),
140
+ 'Q': bytearray([
141
+ 0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
142
+ 0x01, 0x00, 0x00, 0x00, 0x01,
143
+ 0x01, 0x00, 0x01, 0x00, 0x01,
144
+ 0x01, 0x00, 0x00, 0x01, 0x00,
145
+ 0x00, 0x01, 0x01, 0x00, 0x01,
146
+ ]),
147
+ 'R': bytearray([
148
+ 0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
149
+ 0x01, 0x00, 0x00, 0x01, 0x00,
150
+ 0x01, 0x01, 0x01, 0x00, 0x00,
151
+ 0x01, 0x00, 0x00, 0x01, 0x00,
152
+ 0x01, 0x00, 0x00, 0x00, 0x01,
153
+ ]),
154
+ 'S': bytearray([
155
+ 0x00, 0x01, 0x01, 0x01, 0x01, # preformatted
156
+ 0x01, 0x00, 0x00, 0x00, 0x00,
157
+ 0x00, 0x01, 0x01, 0x01, 0x00,
158
+ 0x00, 0x00, 0x00, 0x00, 0x01,
159
+ 0x01, 0x01, 0x01, 0x01, 0x00,
160
+ ]),
161
+ 'T': bytearray([
162
+ 0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
163
+ 0x00, 0x00, 0x01, 0x00, 0x00,
164
+ 0x00, 0x00, 0x01, 0x00, 0x00,
165
+ 0x00, 0x00, 0x01, 0x00, 0x00,
166
+ 0x00, 0x00, 0x01, 0x00, 0x00,
167
+ ]),
168
+ 'U': bytearray([
169
+ 0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
170
+ 0x01, 0x00, 0x00, 0x00, 0x01,
171
+ 0x01, 0x00, 0x00, 0x00, 0x01,
172
+ 0x01, 0x00, 0x00, 0x00, 0x01,
173
+ 0x00, 0x01, 0x01, 0x01, 0x00,
174
+ ]),
175
+ 'V': bytearray([
176
+ 0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
177
+ 0x01, 0x00, 0x00, 0x00, 0x01,
178
+ 0x00, 0x01, 0x00, 0x01, 0x00,
179
+ 0x00, 0x01, 0x01, 0x01, 0x00,
180
+ 0x00, 0x00, 0x01, 0x00, 0x00,
181
+ ]),
182
+ 'W': bytearray([
183
+ 0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
184
+ 0x01, 0x00, 0x01, 0x00, 0x01,
185
+ 0x01, 0x00, 0x01, 0x00, 0x01,
186
+ 0x00, 0x01, 0x01, 0x01, 0x00,
187
+ 0x00, 0x01, 0x00, 0x01, 0x00,
188
+ ]),
189
+ 'X': bytearray([
190
+ 0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
191
+ 0x00, 0x01, 0x00, 0x01, 0x00,
192
+ 0x00, 0x00, 0x01, 0x00, 0x00,
193
+ 0x00, 0x01, 0x00, 0x01, 0x00,
194
+ 0x01, 0x00, 0x00, 0x00, 0x01,
195
+ ]),
196
+ 'Y': bytearray([
197
+ 0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
198
+ 0x01, 0x00, 0x00, 0x00, 0x01,
199
+ 0x00, 0x01, 0x01, 0x01, 0x00,
200
+ 0x00, 0x00, 0x01, 0x00, 0x00,
201
+ 0x00, 0x00, 0x01, 0x00, 0x00,
202
+ ]),
203
+ 'Z': bytearray([
204
+ 0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
205
+ 0x00, 0x00, 0x00, 0x01, 0x00,
206
+ 0x00, 0x00, 0x01, 0x00, 0x00,
207
+ 0x00, 0x01, 0x00, 0x00, 0x00,
208
+ 0x01, 0x01, 0x01, 0x01, 0x01,
209
+ ]),
210
+ '0': bytearray([
211
+ 0x00, 0x00, 0x01, 0x00, 0x00, # preformatted
212
+ 0x00, 0x01, 0x00, 0x01, 0x00,
213
+ 0x00, 0x01, 0x00, 0x01, 0x00,
214
+ 0x00, 0x01, 0x00, 0x01, 0x00,
215
+ 0x00, 0x00, 0x01, 0x00, 0x00,
216
+ ]),
217
+ '1': bytearray([
218
+ 0x00, 0x00, 0x01, 0x00, 0x00, # preformatted
219
+ 0x00, 0x01, 0x01, 0x00, 0x00,
220
+ 0x01, 0x00, 0x01, 0x00, 0x00,
221
+ 0x00, 0x00, 0x01, 0x00, 0x00,
222
+ 0x00, 0x00, 0x01, 0x00, 0x00,
223
+ ]),
224
+ '2': bytearray([
225
+ 0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
226
+ 0x01, 0x00, 0x00, 0x00, 0x01,
227
+ 0x00, 0x00, 0x01, 0x01, 0x00,
228
+ 0x00, 0x01, 0x00, 0x00, 0x00,
229
+ 0x01, 0x01, 0x01, 0x01, 0x01,
230
+ ]),
231
+ '3': bytearray([
232
+ 0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
233
+ 0x00, 0x00, 0x00, 0x00, 0x01,
234
+ 0x01, 0x01, 0x01, 0x01, 0x00,
235
+ 0x00, 0x00, 0x00, 0x00, 0x01,
236
+ 0x01, 0x01, 0x01, 0x01, 0x00,
237
+ ]),
238
+ '4': bytearray([
239
+ 0x01, 0x00, 0x00, 0x00, 0x00, # preformatted
240
+ 0x01, 0x00, 0x00, 0x01, 0x00,
241
+ 0x01, 0x01, 0x01, 0x01, 0x01,
242
+ 0x00, 0x00, 0x00, 0x01, 0x00,
243
+ 0x00, 0x00, 0x00, 0x01, 0x00,
244
+ ]),
245
+ '5': bytearray([
246
+ 0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
247
+ 0x01, 0x00, 0x00, 0x00, 0x00,
248
+ 0x01, 0x01, 0x01, 0x01, 0x00,
249
+ 0x00, 0x00, 0x00, 0x00, 0x01,
250
+ 0x01, 0x01, 0x01, 0x01, 0x00,
251
+ ]),
252
+ '6': bytearray([
253
+ 0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
254
+ 0x01, 0x00, 0x00, 0x00, 0x00,
255
+ 0x01, 0x01, 0x01, 0x01, 0x00,
256
+ 0x01, 0x00, 0x00, 0x00, 0x01,
257
+ 0x00, 0x01, 0x01, 0x01, 0x00,
258
+ ]),
259
+ '7': bytearray([
260
+ 0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
261
+ 0x00, 0x00, 0x00, 0x01, 0x00,
262
+ 0x00, 0x00, 0x01, 0x00, 0x00,
263
+ 0x00, 0x01, 0x00, 0x00, 0x00,
264
+ 0x01, 0x00, 0x00, 0x00, 0x00,
265
+ ]),
266
+ '8': bytearray([
267
+ 0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
268
+ 0x01, 0x00, 0x00, 0x00, 0x01,
269
+ 0x00, 0x01, 0x01, 0x01, 0x00,
270
+ 0x01, 0x00, 0x00, 0x00, 0x01,
271
+ 0x00, 0x01, 0x01, 0x01, 0x00,
272
+ ]),
273
+ '9': bytearray([
274
+ 0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
275
+ 0x01, 0x00, 0x00, 0x00, 0x01,
276
+ 0x00, 0x01, 0x01, 0x01, 0x01,
277
+ 0x00, 0x00, 0x00, 0x00, 0x01,
278
+ 0x00, 0x01, 0x01, 0x01, 0x00,
279
+ ]),
280
+ '.': bytearray([
281
+ 0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
282
+ 0x00, 0x00, 0x00, 0x00, 0x00,
283
+ 0x00, 0x00, 0x01, 0x00, 0x00,
284
+ 0x00, 0x00, 0x00, 0x00, 0x00,
285
+ 0x00, 0x00, 0x00, 0x00, 0x00,
286
+ ]),
287
+ ',': bytearray([
288
+ 0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
289
+ 0x00, 0x00, 0x00, 0x00, 0x00,
290
+ 0x00, 0x00, 0x00, 0x00, 0x00,
291
+ 0x00, 0x00, 0x01, 0x00, 0x00,
292
+ 0x00, 0x00, 0x01, 0x00, 0x00,
293
+ ]),
294
+ ':': bytearray([
295
+ 0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
296
+ 0x00, 0x00, 0x01, 0x00, 0x00,
297
+ 0x00, 0x00, 0x00, 0x00, 0x00,
298
+ 0x00, 0x00, 0x00, 0x00, 0x00,
299
+ 0x00, 0x00, 0x01, 0x00, 0x00,
300
+ ]),
301
+ ';': bytearray([
302
+ 0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
303
+ 0x00, 0x00, 0x01, 0x00, 0x00,
304
+ 0x00, 0x00, 0x00, 0x00, 0x00,
305
+ 0x00, 0x00, 0x01, 0x00, 0x00,
306
+ 0x00, 0x00, 0x01, 0x00, 0x00,
307
+ ]),
308
+ '-': bytearray([
309
+ 0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
310
+ 0x00, 0x00, 0x00, 0x00, 0x00,
311
+ 0x00, 0x01, 0x01, 0x01, 0x00,
312
+ 0x00, 0x00, 0x00, 0x00, 0x00,
313
+ 0x00, 0x00, 0x00, 0x00, 0x00,
314
+ ])
315
+ }
316
+
317
+ def generate_from_text(chars: str, direction:Direction, size_in_modules: int):
318
+ # fill up with "."
319
+ squares_cnt = (size_in_modules + 1) // (VisualMarker.size+1)
320
+ leftover = (size_in_modules + 1) % (VisualMarker.size+1)
321
+ if len(chars) < squares_cnt:
322
+ chars = chars + '.' * (squares_cnt - len(chars))
323
+ result: List[bytearray] = []
324
+ for char in chars[:squares_cnt]:
325
+ if char in VisualMarker.marker_dict:
326
+ marker = VisualMarker.marker_dict[char]
327
+ else:
328
+ marker = VisualMarker.marker_dict['.']
329
+ result.append(marker)
330
+ return VisualMarker.generate_from_squares(result, direction, leftover)
331
+
332
+ def generate_from_squares(marker_squares: List[bytearray], direction:Direction, padding_at_end: int):
333
+ # spacer is a column of zeros if RTL/LTR, or a row if TTB/BTT
334
+ axis = 0 if direction == Direction.TOP_TO_BOTTOM else 1
335
+ spacer_dim = (1, VisualMarker.size) if axis==0 else (VisualMarker.size, 1)
336
+ spacer = np.zeros(spacer_dim, dtype=np.uint8)
337
+ result = np.array([])
338
+ for marker in marker_squares:
339
+ if len(marker) != VisualMarker.size*VisualMarker.size:
340
+ raise ValueError("All markers must be 5x5")
341
+
342
+ np_marker = np.array(marker).reshape(VisualMarker.size, VisualMarker.size)
343
+ if result.size == 0:
344
+ # the first item doesn't need a spacer
345
+ result = np_marker
346
+ else:
347
+ # append in direction specified
348
+ if direction == Direction.RIGHT_TO_LEFT:
349
+ result = np.concatenate((np_marker, spacer, result), axis=1)
350
+ else:
351
+ result = np.concatenate((result, spacer, np_marker), axis=axis)
352
+ if(padding_at_end > 0):
353
+ padding_dim = (padding_at_end, VisualMarker.size) if axis==0 else (VisualMarker.size, padding_at_end)
354
+ padding= np.zeros(padding_dim, dtype=np.uint8)
355
+
356
+ # append in direction specified
357
+ if direction == Direction.RIGHT_TO_LEFT:
358
+ result = np.concatenate((padding, result), axis=1)
359
+ else:
360
+ result = np.concatenate((result, padding), axis=axis)
361
+ return result
362
+
363
+
364
+ app = typer.Typer()
365
+
366
+
367
+ def generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT):
368
+ if title:
369
+ #try to use standard size 10. Go bigger if 10 does not fit the data
370
+ try:
371
+ qr = segno.make_qr(url, error="L", version=10)
372
+ except DataOverflowError as e:
373
+ qr = segno.make_qr(url, error="L")
374
+ v = qr.version
375
+ else:
376
+ qr = segno.make_qr(url, error="L")
377
+ v = qr.version
378
+
379
+ if(qr.mode != "alphanumeric"):
380
+ print("[bold yellow]Large QR:[/bold yellow] Provided URL is not alphanumeric!")
381
+ block_count = len(qr.matrix)
382
+ print(f"[bold]Size:[/bold] {block_count}")
383
+ print(f"[bold]Version:[/bold] {qr.version}")
384
+ print(f"[bold]Error Level:[/bold] {qr.error}")
385
+
386
+
387
+ qr_matrix = np.array(qr.matrix)
388
+ visual_marker = VisualMarker.generate_from_text(text.upper(), direction, block_count)
389
+ if title:
390
+ title_marker = VisualMarker.generate_from_text(title.upper(), direction, block_count)
391
+
392
+ append_axis = 1 if direction == Direction.TOP_TO_BOTTOM else 0
393
+ padding_dim = (4, block_count) if append_axis==0 else (block_count, qr.default_border_size)
394
+ padding= np.zeros(padding_dim, dtype=np.uint8)
395
+ if title:
396
+ combined_matrix = np.concatenate((title_marker, padding, qr_matrix, padding, visual_marker), axis=append_axis)
397
+ else:
398
+ combined_matrix = np.concatenate((qr_matrix, padding, visual_marker), axis=append_axis)
399
+
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
+
411
+
412
+ def generate_qr_with_markers_uri(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, fmt='svg'):
413
+ combined_matrix = generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
414
+ match fmt:
415
+ case 'png':
416
+ out = segno.writers.as_png_data_uri(combined_matrix, combined_matrix.shape[::-1], border=9)
417
+ case 'svg':
418
+ out = segno.writers.as_svg_data_uri(combined_matrix, combined_matrix.shape[::-1], border=9)
419
+ return out
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
+
435
+
436
+
437
+
438
+ def main(url: Annotated[str, typer.Argument(help="The PAC-ID to be rendered as QR.")],
439
+ outfile: Annotated[typer.FileBinaryWrite, typer.Option(help="The file the qr will be written to.")] = "qr.svg",
440
+ text: Annotated[str, typer.Option(help="The text of the PAC decoration.")] = "PAC",
441
+ direction: Annotated[Direction, typer.Option(help="The position/direction of the PAC decoration.")] = Direction.TOP_TO_BOTTOM):
442
+
443
+ img = generate_qr_with_markers(url, text=text, direction=direction)
444
+ img.save('generated_codes', f"{outfile}.svg", format='svg')
445
+
446
+
447
+
448
+ if __name__ == "__main__":
449
+ typer.run(main)
450
+
@@ -654,6 +654,7 @@ class TREX(Extension, BaseModelWithValidationMessages):
654
654
  data.append(r)
655
655
 
656
656
  self.segments.append(TREX_Table(key=k, column_headers=headers, data=data))
657
+ return self
657
658
 
658
659
 
659
660
  def dict(self):
labfreed/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
  Python implementation of LabFREED building blocks
3
3
  '''
4
4
 
5
- __version__ = "0.0.15"
5
+ __version__ = "0.0.17"
@@ -1,11 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: labfreed
3
- Version: 0.0.15
3
+ Version: 0.0.17
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
7
7
  License-Expression: MIT
8
8
  License-File: LICENSE
9
+ Requires-Dist: numpy>=2.2.4
10
+ Requires-Dist: pydantic>=2.11.3
11
+ Requires-Dist: segno>=1.6.6
12
+ Requires-Dist: typer>=0.15.2
9
13
 
10
14
  # LabFREED for Python
11
15
 
@@ -32,13 +36,9 @@ pip install labfreed
32
36
 
33
37
 
34
38
  ## Usage Examples
39
+ > ⚠️ **Note:** These examples are building on each other. Imports and parsing are not repeated in each example.
35
40
  <!-- BEGIN EXAMPLES -->
36
- ```python
37
-
38
- ```
39
-
40
- ### Parse a simple PAC-ID
41
- The
41
+ ### Parse a simple PAC-ID
42
42
 
43
43
  ```python
44
44
  from labfreed.parse_pac import PAC_Parser
@@ -50,34 +50,33 @@ pac_id = PAC_Parser().parse(pac_str).pac_id
50
50
  # Check validity of this PAC-ID
51
51
  pac_id = PAC_Parser().parse(pac_str).pac_id
52
52
  is_valid = pac_id.is_valid()
53
- print('PAC-ID is valid: {is_valid}')
54
- # >> PAC-ID is valid: {is_valid}
53
+ print(f'PAC-ID is valid: {is_valid}')
55
54
  ```
56
-
57
- Show recommendations:
58
- Note that the PAC-ID, while valid uses characters, which are not recommended (results in larger QR code).
55
+ ```text
56
+ >> [Error during execution: No module named 'quantities']
57
+ ```
58
+ ### Show recommendations:
59
+ Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
59
60
  There is a nice function to highlight problems
60
61
 
61
62
  ```python
62
63
  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
64
  ```
65
+ ```text
66
+ >> [Error during execution: name 'pac_id' is not defined]
67
+ ```
68
+ ### PAC-CAT
80
69
 
70
+ ```python
71
+ from labfreed.PAC_CAT.data_model import PAC_CAT
72
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-DR/XQ908756/-MD/bal500/@1234'
73
+ pac_id = PAC_Parser().parse(pac_str).pac_id
74
+ if isinstance(pac_id, PAC_CAT):
75
+ pac_id.print_categories()
76
+ ```
77
+ ```text
78
+ >> [Error during execution: name 'PAC_Parser' is not defined]
79
+ ```
81
80
  ### Parse a PAC-ID with extensions
82
81
  PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
83
82
 
@@ -87,17 +86,21 @@ pac_id = PAC_Parser().parse(pac_str)
87
86
 
88
87
  # Display Name
89
88
  display_names = pac_id.get_extension('N') # display name has name 'N'
90
- print(f'\n {display_names}')
91
- # >> Display names: My Balance ❤️
92
-
89
+ print(display_names)
90
+ ```
91
+ ```text
92
+ >> [Error during execution: name 'PAC_Parser' is not defined]
93
+ ```
94
+ ```python
93
95
  # TREX
94
96
  trexes = pac_id.get_extension_of_type('TREX')
95
97
  trex = trexes[0] # there could be multiple trexes. In this example there is only one, though
96
98
  v = trex.get_segment('WEIGHT').to_python_type()
97
99
  print(f'WEIGHT = {v}')
98
- # >> WEIGHT = 67.89 g
99
100
  ```
100
-
101
+ ```text
102
+ >> [Error during execution: name 'pac_id' is not defined]
103
+ ```
101
104
  ### Create a PAC-ID with Extensions
102
105
 
103
106
  #### Create PAC-ID
@@ -108,10 +111,11 @@ from labfreed.utilities.well_known_keys import WellKnownKeys
108
111
 
109
112
  pac_id = PACID(issuer='METTORIUS:COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
110
113
  pac_str = pac_id.serialize()
111
- pac_str = pac_id.serialize()
112
114
  print(pac_str)
113
115
  ```
114
-
116
+ ```text
117
+ >> HTTPS://PAC.METTORIUS:COM/21:1234
118
+ ```
115
119
  #### Create a TREX
116
120
  TREX can conveniently be created from a python dictionary.
117
121
  Note that utility types for Quantity (number with unit) and table are needed
@@ -149,7 +153,9 @@ if trex.get_nested_validation_messages():
149
153
  # Side Note: The TREX can be turned back into a dict
150
154
  d = trex.dict()
151
155
  ```
152
-
156
+ ```text
157
+ >> [Error during execution: No module named 'quantities']
158
+ ```
153
159
  #### Combine PAC-ID and TREX and serialize
154
160
 
155
161
  ```python
@@ -159,13 +165,18 @@ pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
159
165
  pac_str = pac_with_trex.serialize()
160
166
  print(pac_str)
161
167
  ```
162
-
168
+ ```text
169
+ >> [Error during execution: No module named 'quantities']
170
+ ```
163
171
  <!-- END EXAMPLES -->
164
172
 
165
173
 
166
174
 
167
175
  ## Change Log
168
176
 
169
- ### v0.0.9
177
+ ### v0.0.17
178
+ - dependencies are installed automatically
179
+
180
+ ### v0.0.16
170
181
  - supports PAC-ID, PAC-CAT, TREX and DisplayName
171
182
  - ok-ish test coverage
@@ -1,22 +1,22 @@
1
- labfreed/__init__.py,sha256=2kxIKF8hbBacIqi0RgHcYqemImSCpb62ejkGUuOMMkY,88
1
+ labfreed/__init__.py,sha256=TAfTqh4FzJOWk9Der7lfe4jqVigI9K9DjkkqD_IkbRk,88
2
2
  labfreed/parse_pac.py,sha256=7y65HO1A3OEr5zftiEtrCaiLLI_8LoRPtQpPcKUNVik,6251
3
3
  labfreed/validation.py,sha256=QwkZWJhAjWbPUZtJJwjVYsw9TxeFhdbZaKjrPPIpuAA,5937
4
4
  labfreed/DisplayNameExtension/DisplayNameExtension.py,sha256=l9JZY2eRS0V-H5h3-WXIHiiBJuljns-_e_t9Bp84_CU,1155
5
5
  labfreed/PAC_CAT/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
6
- labfreed/PAC_CAT/data_model copy.py,sha256=JWMVkwkX9vWZayOLOzdTHk3VZVYBuyupumNqL-cWCxU,9611
7
- labfreed/PAC_CAT/data_model.py,sha256=pcib1lEQuqejWP7dfmPUtLakz-y-zeDb9CIe94Jmz0A,13677
6
+ labfreed/PAC_CAT/data_model.py,sha256=dGwcQGLy1Dk6SFbs9utxKQKm_4ROZrXdv618APlQg7M,14308
8
7
  labfreed/PAC_ID/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
8
  labfreed/PAC_ID/data_model.py,sha256=g09qgC-TV6fjJw9VyDF6mTJ6co2i2RKZc0Z-BmiiUIQ,7483
10
9
  labfreed/PAC_ID/extensions.py,sha256=bvuZnlNKUdwsDLrPm8fyifqPn_PR4wCVkkScFnvRiuM,1158
10
+ labfreed/QR_Generator/generate_qr.py,sha256=A4Bw_UESaB_igTDV2Y7a5T7vdz2Sb3yZCfHM0qKnu0M,18091
11
11
  labfreed/TREX/UneceUnits.json,sha256=kwfQSp_nTuWbADfBBgqTWrvPl6XtM5SedEVLbMJrM7M,898953
12
- labfreed/TREX/data_model.py,sha256=_xhnYGMcMPa0uf_020epq88zqHT1wdsUPC2ELJcSRWE,29684
12
+ labfreed/TREX/data_model.py,sha256=neKYBc5_S4t-v86DSaWLq81VJF4oS6eFUch3ChPTYJA,29705
13
13
  labfreed/TREX/parse.py,sha256=86962VEJpkrTcT436iFIB5dNed5WHABzpjxRjkA3PXo,2043
14
14
  labfreed/TREX/unece_units.py,sha256=scPKdsPzY1neAdFOhA08_tRZaR-yplM8mBhIzzDqZBk,3006
15
15
  labfreed/utilities/base36.py,sha256=_yX8aQ1OwrK5tnJU1NUEzQSFGr9xAVnNvPObpNzCPYs,2895
16
16
  labfreed/utilities/extension_intertpreters.py,sha256=B3IFJLfVMJQuPfBBtX6ywlDUZEi7_x6tY4g8V7SpWSs,124
17
17
  labfreed/utilities/utility_types.py,sha256=Zhk8Mu4hHjkn1gs8oh7vOxxaT7L7wLMVG40ZOWCKGK4,2865
18
18
  labfreed/utilities/well_known_keys.py,sha256=nqk66kHdSwJTJfMKlP-xQbBglS8F_NoWsGkfOVITFN0,331
19
- labfreed-0.0.15.dist-info/licenses/LICENSE,sha256=gHFOv9FRKHxO8cInP3YXyPoJnuNeqrvcHjaE_wPSsQ8,1100
20
- labfreed-0.0.15.dist-info/WHEEL,sha256=BXjIu84EnBiZ4HkNUBN93Hamt5EPQMQ6VkF7-VZ_Pu0,100
21
- labfreed-0.0.15.dist-info/METADATA,sha256=dxqZ7E2CeiqTaYKXuDLn4mxRSv3mH9aqRH96CS2EfFw,4997
22
- labfreed-0.0.15.dist-info/RECORD,,
19
+ labfreed-0.0.17.dist-info/licenses/LICENSE,sha256=gHFOv9FRKHxO8cInP3YXyPoJnuNeqrvcHjaE_wPSsQ8,1100
20
+ labfreed-0.0.17.dist-info/WHEEL,sha256=Dyt6SBfaasWElUrURkknVFAZDHSTwxg3PaTza7RSbkY,100
21
+ labfreed-0.0.17.dist-info/METADATA,sha256=7KTV5v3dGse4ZRIZ6PVMc3fCB3j_Plooq--v9cgKjas,5382
22
+ labfreed-0.0.17.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: flit 3.11.0
2
+ Generator: flit 3.12.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
@@ -1,232 +0,0 @@
1
- # import re
2
- # from typing import Optional
3
- # from typing_extensions import Self
4
- # from pydantic import Field, ValidationInfo, computed_field, conlist, model_validator, field_validator
5
-
6
- # from abc import ABC, abstractproperty, abstractstaticmethod
7
-
8
- # from labfreed.PAC_ID.data_model import PACID
9
-
10
- # from ..utilities.well_known_keys import WellKnownKeys
11
- # from labfreed.validation import BaseModelWithValidationMessages, ValidationMessage, hsegment_pattern, domain_name_pattern
12
-
13
-
14
- # # class IDSegment(BaseModelWithValidationMessages):
15
- # # key:str|None = None
16
- # # value:str
17
-
18
- # # @model_validator(mode="after")
19
- # # def validate_segment(self):
20
- # # key = self.key or ""
21
- # # value = self.value
22
-
23
- # # # MUST be a valid hsegment according to RFC 1738, but without * (see PAC-ID Extension)
24
- # # # This means it must be true for both, key and value
25
- # # if not_allowed_chars := set(re.sub(hsegment_pattern, '', key)):
26
- # # self.add_validation_message(
27
- # # source=f"id segment key {key}",
28
- # # type="Error",
29
- # # msg=f"{' '.join(not_allowed_chars)} must not be used.",
30
- # # recommendation = "The segment key must be a valid hsegment",
31
- # # highlight_pattern = key,
32
- # # highlight_sub = not_allowed_chars
33
- # # )
34
-
35
- # # if not_allowed_chars := set(re.sub(hsegment_pattern, '', value)):
36
- # # self.add_validation_message(
37
- # # source=f"id segment key {value}",
38
- # # type="Error",
39
- # # msg=f"{' '.join(not_allowed_chars)} must not be used.",
40
- # # recommendation = "The segment key must be a valid hsegment",
41
- # # highlight_pattern = value,
42
- # # highlight_sub = not_allowed_chars
43
- # # )
44
-
45
- # # # Segment key SHOULD be limited to A-Z, 0-9, and -+..
46
- # # if not_recommended_chars := set(re.sub(r'[A-Z0-9-:+]', '', key)):
47
- # # self.add_validation_message(
48
- # # source=f"id segment key {key}",
49
- # # type="Recommendation",
50
- # # msg=f"{' '.join(not_recommended_chars)} should not be used.",
51
- # # recommendation = "SHOULD be limited to A-Z, 0-9, and -+",
52
- # # highlight_pattern = key,
53
- # # highlight_sub = not_recommended_chars
54
- # # )
55
-
56
- # # # Segment key should be in Well know keys
57
- # # if key and key not in [k.value for k in WellKnownKeys]:
58
- # # self.add_validation_message(
59
- # # source=f"id segment key {key}",
60
- # # type="Recommendation",
61
- # # msg=f"{key} is not a well known segment key.",
62
- # # recommendation = "RECOMMENDED to be a well-known id segment key.",
63
- # # highlight_pattern = key
64
- # # )
65
-
66
-
67
- # # # Segment value SHOULD be limited to A-Z, 0-9, and -+..
68
- # # if not_recommended_chars := set(re.sub(r'[A-Z0-9-:+]', '', value)):
69
- # # self.add_validation_message(
70
- # # source=f"id segment value {value}",
71
- # # type="Recommendation",
72
- # # msg=f"Characters {' '.join(not_recommended_chars)} should not be used.",
73
- # # recommendation = "SHOULD be limited to A-Z, 0-9, and -+",
74
- # # highlight_pattern = value,
75
- # # highlight_sub = not_recommended_chars
76
- # # )
77
-
78
- # # # Segment value SHOULD be limited to A-Z, 0-9, and :-+ for new designs.
79
- # # # this means that ":" in key or value is problematic
80
- # # if ':' in key:
81
- # # self.add_validation_message(
82
- # # source=f"id segment key {key}",
83
- # # type="Recommendation",
84
- # # msg=f"Character ':' should not be used in segment key, since this character is used to separate key and value this can lead to undefined behaviour.",
85
- # # highlight_pattern = key
86
- # # )
87
- # # if ':' in value:
88
- # # self.add_validation_message(
89
- # # source=f"id segment value {value}",
90
- # # type="Recommendation",
91
- # # msg=f"Character ':' should not be used in segment value, since this character is used to separate key and value this can lead to undefined behaviour.",
92
- # # highlight_pattern = value
93
- # # )
94
-
95
- # # return self
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
- # class PAC_CAT(PACID):
104
-
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
-
141
- # # @model_validator(mode='after')
142
- # # def check_length(self) -> Self:
143
- # # l = 0
144
- # # for s in self.segments:
145
- # # if s.key:
146
- # # l += len(s.key)
147
- # # l += 1 # for ":"
148
- # # l += len(s.value)
149
- # # l += len(self.segments) - 1 # account for "/" separating the segments
150
-
151
- # # if l > 256:
152
- # # self.add_validation_message(
153
- # # source=f"identifier",
154
- # # type="Error",
155
- # # msg=f'Identifier is {l} characters long, Identifier must not exceed 256 characters.',
156
- # # highlight_pattern = ""
157
- # # )
158
- # # return self
159
-
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
-
172
-
173
- # # class PACID(BaseModelWithValidationMessages):
174
- # # issuer:str
175
- # # identifier: Identifier
176
-
177
- # # @model_validator(mode="after")
178
- # # def validate_issuer(self):
179
- # # if not re.fullmatch(domain_name_pattern, self.issuer):
180
- # # self.add_validation_message(
181
- # # source="PAC-ID",
182
- # # type="Error",
183
- # # highlight_pattern=self.issuer,
184
- # # msg=f"Issuer must be a valid domain name. "
185
- # # )
186
-
187
- # # # recommendation that A-Z, 0-9, -, and . should be used
188
- # # if not_recommended_chars := set(re.sub(r'[A-Z0-9\.-]', '', self.issuer)):
189
- # # self.add_validation_message(
190
- # # source="PAC-ID",
191
- # # type="Recommendation",
192
- # # highlight_pattern=self.issuer,
193
- # # highlight_sub=not_recommended_chars,
194
- # # msg=f"Characters {' '.join(not_recommended_chars)} should not be used. Issuer SHOULD contain only the characters A-Z, 0-9, -, and . "
195
- # # )
196
- # # return self
197
-
198
- # # def __str__(self):
199
- # # id_segments = ''
200
- # # for s in self.identifier.segments:
201
- # # if s.key:
202
- # # id_segments += f'/{s.key}:{s.value}'
203
- # # else:
204
- # # id_segments += f'/{s.value}'
205
-
206
- # # out = f"HTTPS://PAC.{self.issuer}{id_segments}"
207
- # # return out
208
-
209
-
210
-
211
-
212
- # # class PACID_With_Extensions(BaseModelWithValidationMessages):
213
- # # pac_id: PACID
214
- # # extensions: list[Extension] = Field(default_factory=list)
215
-
216
- # # def __str__(self):
217
- # # out = str(self.pac_id)
218
- # # out += '*'.join(str(e) for e in self.extensions)
219
-
220
- # # def get_extension_of_type(self, type:str) -> list[Extension]:
221
- # # return [e for e in self.extensions if e.type == type]
222
-
223
- # # def get_extension(self, name:str) -> Extension|None:
224
- # # out = [e for e in self.extensions if e.name == name]
225
- # # if not out:
226
- # # return None
227
- # # return out[0]
228
-
229
-
230
-
231
-
232
-