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.
- labfreed/PAC_CAT/data_model.py +26 -8
- labfreed/QR_Generator/generate_qr.py +450 -0
- labfreed/TREX/data_model.py +1 -0
- labfreed/__init__.py +1 -1
- {labfreed-0.0.15.dist-info → labfreed-0.0.17.dist-info}/METADATA +49 -38
- {labfreed-0.0.15.dist-info → labfreed-0.0.17.dist-info}/RECORD +8 -8
- {labfreed-0.0.15.dist-info → labfreed-0.0.17.dist-info}/WHEEL +1 -1
- labfreed/PAC_CAT/data_model copy.py +0 -232
- {labfreed-0.0.15.dist-info → labfreed-0.0.17.dist-info}/licenses/LICENSE +0 -0
labfreed/PAC_CAT/data_model.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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(
|
|
349
|
+
class Data_Result(Data_Abstract):
|
|
332
350
|
key: str = Field(default='-DR', frozen=True)
|
|
333
351
|
|
|
334
|
-
class Data_Method(
|
|
352
|
+
class Data_Method(Data_Abstract):
|
|
335
353
|
key: str = Field(default='-DM', frozen=True)
|
|
336
354
|
|
|
337
|
-
class Data_Calibration(
|
|
355
|
+
class Data_Calibration(Data_Abstract):
|
|
338
356
|
key: str = Field(default='-DC', frozen=True)
|
|
339
357
|
|
|
340
|
-
class Data_Progress(
|
|
358
|
+
class Data_Progress(Data_Abstract):
|
|
341
359
|
key: str = Field(default='-DP', frozen=True)
|
|
342
360
|
|
|
343
|
-
class Data_Static(
|
|
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
|
+
|
labfreed/TREX/data_model.py
CHANGED
labfreed/__init__.py
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: labfreed
|
|
3
|
-
Version: 0.0.
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
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(
|
|
91
|
-
|
|
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.
|
|
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=
|
|
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
|
|
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=
|
|
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.
|
|
20
|
-
labfreed-0.0.
|
|
21
|
-
labfreed-0.0.
|
|
22
|
-
labfreed-0.0.
|
|
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,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
|
-
|
|
File without changes
|