labfreed 0.0.20__py2.py3-none-any.whl → 0.1.0__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/IO/parse_pac.py +1 -1
- labfreed/PAC_CAT/data_model.py +2 -2
- labfreed/PAC_ID/data_model.py +1 -1
- labfreed/PAC_ID_Resolver/cit.yaml +92 -0
- labfreed/PAC_ID_Resolver/data_types.py +59 -0
- labfreed/PAC_ID_Resolver/resolver.py +221 -0
- labfreed/__init__.py +1 -1
- labfreed/validation.py +5 -1
- {labfreed-0.0.20.dist-info → labfreed-0.1.0.dist-info}/METADATA +41 -5
- {labfreed-0.0.20.dist-info → labfreed-0.1.0.dist-info}/RECORD +12 -9
- {labfreed-0.0.20.dist-info → labfreed-0.1.0.dist-info}/WHEEL +0 -0
- {labfreed-0.0.20.dist-info → labfreed-0.1.0.dist-info}/licenses/LICENSE +0 -0
labfreed/IO/parse_pac.py
CHANGED
|
@@ -19,7 +19,7 @@ from ..validation import ValidationMessage, LabFREEDValidationError
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class PACID_With_Extensions(BaseModelWithValidationMessages):
|
|
22
|
-
pac_id: PACID
|
|
22
|
+
pac_id: PACID = Field(serialization_alias='pac')
|
|
23
23
|
extensions: list[Extension] = Field(default_factory=list)
|
|
24
24
|
|
|
25
25
|
def __str__(self):
|
labfreed/PAC_CAT/data_model.py
CHANGED
|
@@ -14,7 +14,7 @@ class PAC_CAT(PACID):
|
|
|
14
14
|
'''
|
|
15
15
|
Extends a PAC-ID with interpretation of the identifier as categories
|
|
16
16
|
'''
|
|
17
|
-
categories:list[Category] = Field(default_factory=list
|
|
17
|
+
categories:list[Category] = Field(default_factory=list)
|
|
18
18
|
|
|
19
19
|
@property
|
|
20
20
|
def identifier(self) -> list[IDSegment]:
|
|
@@ -175,7 +175,7 @@ class Category(BaseModelWithValidationMessages):
|
|
|
175
175
|
"populate_by_name": True
|
|
176
176
|
}
|
|
177
177
|
key:str
|
|
178
|
-
additional_segments: list[IDSegment] = Field(default_factory=list)
|
|
178
|
+
additional_segments: list[IDSegment] = Field(default_factory=list, exclude=True)
|
|
179
179
|
|
|
180
180
|
@computed_field
|
|
181
181
|
@property
|
labfreed/PAC_ID/data_model.py
CHANGED
|
@@ -96,7 +96,7 @@ class IDSegment(BaseModelWithValidationMessages):
|
|
|
96
96
|
|
|
97
97
|
class PACID(BaseModelWithValidationMessages):
|
|
98
98
|
issuer:str
|
|
99
|
-
identifier: conlist(IDSegment, min_length=1) = Field(..., default_factory=list
|
|
99
|
+
identifier: conlist(IDSegment, min_length=1) = Field(..., default_factory=list) # type: ignore # exclude=True prevents this from being serialized by Pydantic
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
@model_validator(mode='after')
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
origin: PAC.METTORIUS.COM
|
|
2
|
+
|
|
3
|
+
macros:
|
|
4
|
+
shop: &shop
|
|
5
|
+
service_type: userhandover-generic
|
|
6
|
+
service_name: Shop
|
|
7
|
+
application_intents:
|
|
8
|
+
- showdevicemanual-apinilabs
|
|
9
|
+
template_url: https://mettorius.com/shop/an={$.pac.identifier.categories[1].segments['240'].value}
|
|
10
|
+
|
|
11
|
+
manual: &manual
|
|
12
|
+
service_type: userhandover-generic
|
|
13
|
+
service_name: Manual
|
|
14
|
+
application_intents:
|
|
15
|
+
- showdevicemanual-apinilabs
|
|
16
|
+
template_url: https://mettorius.com/om/an={$..*['240'].value}
|
|
17
|
+
|
|
18
|
+
CoA: &coa
|
|
19
|
+
service_type: userhandover-generic
|
|
20
|
+
service_name: CoA
|
|
21
|
+
application_intents:
|
|
22
|
+
- showCoA-apinilabs
|
|
23
|
+
template_url: https://mettorius.com/downloads/an={$..*['240'].value}
|
|
24
|
+
|
|
25
|
+
dummy: &dummy
|
|
26
|
+
service_type: userhandover-generic
|
|
27
|
+
application_intents:
|
|
28
|
+
- dummy
|
|
29
|
+
template_url: https://mettorius.com/om/an={$..*['240'].value}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
cit:
|
|
33
|
+
# Test
|
|
34
|
+
- if: mettorius.com == $.pac.issuer
|
|
35
|
+
entries:
|
|
36
|
+
- <<: *shop
|
|
37
|
+
- <<: *manual
|
|
38
|
+
|
|
39
|
+
# Instruments
|
|
40
|
+
- if: mettorius.com == $.pac.issuer AND $.pac.id.categories['-MD']
|
|
41
|
+
entries:
|
|
42
|
+
- <<: *shop
|
|
43
|
+
- <<: *manual
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Consumables
|
|
47
|
+
- if: mettorius.com == $.pac.issuer AND $.pac.id.categories['-MC']
|
|
48
|
+
entries:
|
|
49
|
+
- <<: *shop
|
|
50
|
+
- <<: *manual
|
|
51
|
+
- <<: *coa
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Showcase for logic
|
|
56
|
+
##############################
|
|
57
|
+
|
|
58
|
+
# multiline string
|
|
59
|
+
- if: "($.pac.issuer == mettorius.com)
|
|
60
|
+
AND $.pac.id.categories['-MD']"
|
|
61
|
+
entries:
|
|
62
|
+
- <<: *dummy
|
|
63
|
+
service_name: multiline applicable_if
|
|
64
|
+
|
|
65
|
+
# folded string
|
|
66
|
+
- if: |
|
|
67
|
+
($.pac.issuer == mettorius.com)
|
|
68
|
+
AND $.pac.id.categories['-MD']
|
|
69
|
+
entries:
|
|
70
|
+
- <<: *dummy
|
|
71
|
+
service_name: folded applicable_if
|
|
72
|
+
|
|
73
|
+
# multiline string
|
|
74
|
+
- if: |
|
|
75
|
+
NOT NOT ($.pac.issuer == mettorius.com)
|
|
76
|
+
AND $.pac.id.categories['-MD']
|
|
77
|
+
entries:
|
|
78
|
+
- <<: *dummy
|
|
79
|
+
service_name: multiline applicable_if
|
|
80
|
+
|
|
81
|
+
- if: NOT ($.pac.issuer != METTORIUS.COM)
|
|
82
|
+
entries:
|
|
83
|
+
- <<: *dummy
|
|
84
|
+
service_name: _3
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field, field_validator
|
|
2
|
+
from rich import print
|
|
3
|
+
from rich.table import Table
|
|
4
|
+
|
|
5
|
+
from labfreed.validation import BaseModelWithValidationMessages
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CITEntry(BaseModelWithValidationMessages):
|
|
9
|
+
service_name: str
|
|
10
|
+
application_intents:list[str]
|
|
11
|
+
service_type:str
|
|
12
|
+
template_url:str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CITBlock(BaseModelWithValidationMessages):
|
|
16
|
+
applicable_if: str = Field(default='True', alias='if')
|
|
17
|
+
entries: list[CITEntry]
|
|
18
|
+
|
|
19
|
+
@field_validator('applicable_if', mode='before')
|
|
20
|
+
@classmethod
|
|
21
|
+
def convert_if(cls, v):
|
|
22
|
+
return v if v is not None else 'True'
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class CIT(BaseModelWithValidationMessages):
|
|
26
|
+
origin: str = ''
|
|
27
|
+
macros:dict = Field(default_factory=dict)
|
|
28
|
+
cit: list[CITBlock] = Field(default_factory=list)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Service(BaseModelWithValidationMessages):
|
|
34
|
+
service_name: str
|
|
35
|
+
application_intents:list[str]
|
|
36
|
+
service_type:str
|
|
37
|
+
url:str
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class CITEvaluated(BaseModelWithValidationMessages):
|
|
41
|
+
origin: str = ""
|
|
42
|
+
services: list[Service] = Field(default_factory=list)
|
|
43
|
+
|
|
44
|
+
def __str__(self):
|
|
45
|
+
out = [f'CIT (origin {self.origin})']
|
|
46
|
+
for s in self.services:
|
|
47
|
+
out.append(f'{s.service_name}\t\t\t{s.url}')
|
|
48
|
+
return '\n'.join(out)
|
|
49
|
+
|
|
50
|
+
def print(self):
|
|
51
|
+
table = Table(title=f"Services from origin '{self.origin}")
|
|
52
|
+
|
|
53
|
+
table.add_column("Service Name")
|
|
54
|
+
table.add_column("URL")
|
|
55
|
+
|
|
56
|
+
for s in self.services:
|
|
57
|
+
table.add_row(s.service_name, s.url)
|
|
58
|
+
|
|
59
|
+
print(table)
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import yaml
|
|
4
|
+
import json
|
|
5
|
+
import jsonpath_ng.ext as jsonpath
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
from labfreed.IO.parse_pac import PAC_Parser, PACID_With_Extensions
|
|
9
|
+
from labfreed.PAC_ID_Resolver.data_types import CIT, CITEntry, CITEvaluated, Service
|
|
10
|
+
|
|
11
|
+
from labfreed.PAC_ID_Resolver.non_needed.query_tools import JSONPathTools
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def load_cit(path):
|
|
15
|
+
with open(path, 'r') as f:
|
|
16
|
+
cit = yaml.safe_load(f)
|
|
17
|
+
cit = CIT.model_validate(cit)
|
|
18
|
+
return cit
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PAC_ID_Resolver():
|
|
22
|
+
def __init__(self, cits:list[CIT]=None):
|
|
23
|
+
if not cits:
|
|
24
|
+
cits = []
|
|
25
|
+
self.cits = cits
|
|
26
|
+
|
|
27
|
+
# load the default cit
|
|
28
|
+
dir = os.path.dirname(__file__)
|
|
29
|
+
fn ='cit.yaml'
|
|
30
|
+
p = os.path.join(dir, fn)
|
|
31
|
+
with open(p, 'r') as f:
|
|
32
|
+
cit = yaml.safe_load(f)
|
|
33
|
+
cit = CIT.model_validate(cit)
|
|
34
|
+
self.cits.append(cit)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def resolve(self, pac_id:PACID_With_Extensions|str):
|
|
38
|
+
if isinstance(pac_id, str):
|
|
39
|
+
pac_id = PAC_Parser().parse(pac_id)
|
|
40
|
+
|
|
41
|
+
pac_id_json = pac_id.model_dump(by_alias=True)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# dir = os.path.dirname(__file__)
|
|
45
|
+
# p = os.path.join(dir, 'pac-id.json')
|
|
46
|
+
# with open(p , 'r') as f:
|
|
47
|
+
# _json = f.read()
|
|
48
|
+
# pac_id_json = json.loads(_json)
|
|
49
|
+
|
|
50
|
+
matches = [self._evaluate_against_cit(pac_id_json, cit) for cit in self.cits]
|
|
51
|
+
return matches
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _evaluate_against_cit(self, pac_id_json, cit:CIT):
|
|
55
|
+
cit_evaluated = CITEvaluated(origin=cit.origin)
|
|
56
|
+
for block in cit.cit:
|
|
57
|
+
_, is_applicable = self._evaluate_applicable_if(pac_id_json, block.applicable_if)
|
|
58
|
+
if not is_applicable:
|
|
59
|
+
continue
|
|
60
|
+
|
|
61
|
+
for e in block.entries:
|
|
62
|
+
url = self.eval_url_template(pac_id_json, e.template_url)
|
|
63
|
+
cit_evaluated.services.append(Service(
|
|
64
|
+
service_name=e.service_name,
|
|
65
|
+
application_intents=e.application_intents,
|
|
66
|
+
service_type=e.service_type,
|
|
67
|
+
url = url
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
return cit_evaluated
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _evaluate_applicable_if(self, pac_id_json:str, expression) -> tuple[str, bool]:
|
|
74
|
+
expression = self._apply_convenience_substitutions(expression)
|
|
75
|
+
|
|
76
|
+
tokens = self._tokenize_jsonpath_expression(expression)
|
|
77
|
+
expression_for_eval = self._expression_from_tokens(pac_id_json, tokens)
|
|
78
|
+
applicable = eval(expression_for_eval, {}, {})
|
|
79
|
+
|
|
80
|
+
return expression_for_eval, applicable
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _apply_convenience_substitutions(self, query):
|
|
84
|
+
''' applies a few substitutions, which enable abbreviated syntax.'''
|
|
85
|
+
|
|
86
|
+
# allow access to array elements by key
|
|
87
|
+
q_mod = re.sub(r"\[('.+?')\]", r"[?(@.key == \1)]", query )
|
|
88
|
+
|
|
89
|
+
# allow shorter path
|
|
90
|
+
# substitutions = [
|
|
91
|
+
# (r'(?<=^)id', 'pac.id'),
|
|
92
|
+
# (r'(?<=^)cat', 'pac.id.cat'),
|
|
93
|
+
# (r'(?<=\.)id(?=\.)', 'identifier'),
|
|
94
|
+
# (r'(?<=\.)cat$', 'categories'),
|
|
95
|
+
# (r'(?<=\.)cat(?=\[)', 'categories'),
|
|
96
|
+
# (r'(?<=\.)seg$', 'segments'),
|
|
97
|
+
# (r'(?<=\.)seg(?=\[)', 'segments'),
|
|
98
|
+
# (r'(?<=^)isu', 'pac.isu'),
|
|
99
|
+
# (r'(?<=\.)isu', 'issuer'),
|
|
100
|
+
# (r'(?<=^)ext', 'pac.ext'),
|
|
101
|
+
# (r'(?<=\.)ext(?=$)', 'extensions'),
|
|
102
|
+
# (r'(?<=\.)ext(?=\[)', 'extensions'),
|
|
103
|
+
# ]
|
|
104
|
+
# for sub in substitutions:
|
|
105
|
+
# q_mod = re.sub(sub[0], sub[1], q_mod)
|
|
106
|
+
|
|
107
|
+
return q_mod
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _tokenize_jsonpath_expression(self, expr: str):
|
|
111
|
+
token_pattern = re.compile(
|
|
112
|
+
r"""
|
|
113
|
+
(?P<LPAREN>\() |
|
|
114
|
+
(?P<RPAREN>\)) |
|
|
115
|
+
(?P<LOGIC>\bAND\b|\bOR\b|\bNOT\b) |
|
|
116
|
+
(?P<OPERATOR>==|!=|<=|>=|<|>) |
|
|
117
|
+
(?P<JSONPATH>
|
|
118
|
+
\$ # starts with $
|
|
119
|
+
(?:
|
|
120
|
+
[^\s\[\]()]+ # path segments, dots, etc.
|
|
121
|
+
|
|
|
122
|
+
\[ # open bracket
|
|
123
|
+
(?: # non-capturing group
|
|
124
|
+
[^\[\]]+ # anything but brackets
|
|
125
|
+
|
|
|
126
|
+
\[[^\[\]]*\] # nested brackets (1 level)
|
|
127
|
+
)*
|
|
128
|
+
\]
|
|
129
|
+
)+ # one or more bracket/segment blocks
|
|
130
|
+
) |
|
|
131
|
+
(?P<LITERAL>
|
|
132
|
+
[A-Za-z_][\w\.\-]*[A-Za-z0-9] # domain-like literals
|
|
133
|
+
)
|
|
134
|
+
""",
|
|
135
|
+
re.VERBOSE
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
tokens = []
|
|
139
|
+
pos = 0
|
|
140
|
+
while pos < len(expr):
|
|
141
|
+
match = token_pattern.match(expr, pos)
|
|
142
|
+
if match:
|
|
143
|
+
group_type = match.lastgroup
|
|
144
|
+
value = match.group().strip()
|
|
145
|
+
tokens.append((value, group_type))
|
|
146
|
+
pos = match.end()
|
|
147
|
+
elif expr[pos].isspace():
|
|
148
|
+
pos += 1 # skip whitespace
|
|
149
|
+
else:
|
|
150
|
+
raise SyntaxError(f"Unexpected character at position {pos}: {expr[pos]}")
|
|
151
|
+
|
|
152
|
+
return tokens
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _expression_from_tokens(self, pac_id_json:str, tokens: tuple[str, str]):
|
|
156
|
+
out = []
|
|
157
|
+
for i in range(len(tokens)):
|
|
158
|
+
prev_token = tokens[i-1] if i > 0 else (None, None)
|
|
159
|
+
curr_token = tokens[i]
|
|
160
|
+
next_token = tokens[i+1] if i < len(tokens)-1 else (None, None)
|
|
161
|
+
if curr_token[1] == 'JSONPATH':
|
|
162
|
+
res = self._evaluate_jsonpath(pac_id_json, curr_token[0])
|
|
163
|
+
|
|
164
|
+
if prev_token[1] == 'OPERATOR' or next_token[1] == 'OPERATOR':
|
|
165
|
+
# if token is part of comparison return the value of the node
|
|
166
|
+
if len(res) == 0:
|
|
167
|
+
out.append('""')
|
|
168
|
+
else:
|
|
169
|
+
out.append(f'"{res[0].upper()}"')
|
|
170
|
+
else:
|
|
171
|
+
# if token is not part of comparison evaluate to boolean
|
|
172
|
+
if len(res) == 0:
|
|
173
|
+
out.append(False)
|
|
174
|
+
else:
|
|
175
|
+
out.append(True)
|
|
176
|
+
|
|
177
|
+
elif curr_token[1] == 'LOGIC':
|
|
178
|
+
out.append(curr_token[0].lower())
|
|
179
|
+
|
|
180
|
+
elif curr_token[1] == 'LITERAL':
|
|
181
|
+
t = curr_token[0]
|
|
182
|
+
if t[0] != '"':
|
|
183
|
+
t = '"' + t
|
|
184
|
+
if t[-1] != '"':
|
|
185
|
+
t = t + '"'
|
|
186
|
+
out.append(t.upper())
|
|
187
|
+
else:
|
|
188
|
+
out.append(curr_token[0])
|
|
189
|
+
|
|
190
|
+
s = ' '.join([str(e) for e in out])
|
|
191
|
+
return s
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def eval_url_template(self, pac_id_json, url_template):
|
|
197
|
+
url = url_template
|
|
198
|
+
placeholders = re.findall(r'\{(.+?)\}', url_template)
|
|
199
|
+
for placeholder in placeholders:
|
|
200
|
+
expanded_placeholder = self._apply_convenience_substitutions(placeholder)
|
|
201
|
+
res = self._evaluate_jsonpath(pac_id_json, expanded_placeholder) or ['']
|
|
202
|
+
url = url.replace(f'{{{placeholder}}}', str(res[0]))
|
|
203
|
+
# res = self.substitute_jsonpath_expressions(expanded_placeholder, Patterns.jsonpath.value, as_bool=False)
|
|
204
|
+
# url = url.replace(f'{{{placeholder}}}', res)
|
|
205
|
+
return url
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _evaluate_jsonpath(self, pac_id_json, jp_query):
|
|
211
|
+
jsonpath_expr = jsonpath.parse(jp_query)
|
|
212
|
+
matches = [match.value for match in jsonpath_expr.find(pac_id_json)]
|
|
213
|
+
return matches
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if __name__ == '__main__':
|
|
220
|
+
r = PAC_ID_Resolver()
|
|
221
|
+
r.resolve()
|
labfreed/__init__.py
CHANGED
labfreed/validation.py
CHANGED
|
@@ -15,7 +15,7 @@ class ValidationMessage(BaseModel):
|
|
|
15
15
|
problem_msg:str
|
|
16
16
|
recommendation_msg: str = ""
|
|
17
17
|
highlight:str = "" #this can be used to highlight problematic parts
|
|
18
|
-
highlight_sub:list[str] = Field(default_factory=list
|
|
18
|
+
highlight_sub:list[str] = Field(default_factory=list)
|
|
19
19
|
|
|
20
20
|
@property
|
|
21
21
|
def emphazised_highlight(self):
|
|
@@ -124,6 +124,10 @@ class BaseModelWithValidationMessages(BaseModel):
|
|
|
124
124
|
]
|
|
125
125
|
)
|
|
126
126
|
)
|
|
127
|
+
|
|
128
|
+
if not msgs:
|
|
129
|
+
print('All clear!')
|
|
130
|
+
return
|
|
127
131
|
|
|
128
132
|
for m in msgs:
|
|
129
133
|
if m.type.casefold() == "error":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: labfreed
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
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
|
|
@@ -38,11 +38,16 @@ pip install labfreed
|
|
|
38
38
|
## Usage Examples
|
|
39
39
|
> ⚠️ **Note:** These examples are building on each other. Imports and parsing are not repeated in each example.
|
|
40
40
|
<!-- BEGIN EXAMPLES -->
|
|
41
|
+
```python
|
|
42
|
+
# import built ins
|
|
43
|
+
import os
|
|
44
|
+
```
|
|
41
45
|
### Parse a simple PAC-ID
|
|
42
46
|
|
|
43
47
|
```python
|
|
44
48
|
from labfreed.IO.parse_pac import PAC_Parser
|
|
45
49
|
|
|
50
|
+
|
|
46
51
|
# Parse the PAC-ID
|
|
47
52
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
48
53
|
pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
@@ -69,7 +74,7 @@ pac_id.print_validation_messages(target='markdown')
|
|
|
69
74
|
>>
|
|
70
75
|
>> Recommendation in id segment value bal500
|
|
71
76
|
>> HTTPS://PAC.METTORIUS.COM/-MD/🔸b🔸🔸a🔸🔸l🔸500/@1234
|
|
72
|
-
>> Characters b l
|
|
77
|
+
>> Characters a b l should not be used.
|
|
73
78
|
>>
|
|
74
79
|
>> Recommendation in id segment value @1234
|
|
75
80
|
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/🔸@🔸1234
|
|
@@ -190,8 +195,9 @@ trex.print_validation_messages(target='markdown')
|
|
|
190
195
|
>> ---------------------------------------
|
|
191
196
|
>>
|
|
192
197
|
>> Error in TREX table column Date
|
|
193
|
-
>> DEMO$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:D🔸a🔸🔸t🔸🔸e🔸$T.D:OK$T.B:COMMENT$T.A::1:
|
|
194
|
-
>>
|
|
198
|
+
>> DEMO$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:D🔸a🔸🔸t🔸🔸e🔸$T.D:OK$T.B:COMMENT$T.A::1:20250410T094130.847:T:FOO::1.1:20250410T094130.847:T:BAR::1.3
|
|
199
|
+
>> :20250410T094130.847:F:BLUBB
|
|
200
|
+
>> Column header key contains invalid characters: t,a,e
|
|
195
201
|
```
|
|
196
202
|
```python
|
|
197
203
|
# there is an error. 'Date' uses lower case. Lets fix it
|
|
@@ -210,7 +216,34 @@ pac_str = pac_with_trex.serialize()
|
|
|
210
216
|
print(pac_str)
|
|
211
217
|
```
|
|
212
218
|
```text
|
|
213
|
-
>> HTTPS://PAC.METTORIUS.COM/21:1234*DEMO$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:DATE$T.D:OK$T.B:COMMENT$T.A::1:
|
|
219
|
+
>> HTTPS://PAC.METTORIUS.COM/21:1234*DEMO$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:DATE$T.D:OK$T.B:COMMENT$T.A::1:20250410T094130.847:T:FOO::1.1:20250410T094130.847:T:BAR::1.3:20250410T094130.847:F:BLUBB
|
|
220
|
+
```
|
|
221
|
+
## PAC-ID Resolver
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
from labfreed.PAC_ID_Resolver.resolver import PAC_ID_Resolver, load_cit
|
|
225
|
+
# Get a CIT
|
|
226
|
+
dir = os.path.dirname(__file__)
|
|
227
|
+
p = os.path.join(dir, 'cit_mine.yaml')
|
|
228
|
+
cit = load_cit(p)
|
|
229
|
+
|
|
230
|
+
# validate the CIT
|
|
231
|
+
cit.is_valid()
|
|
232
|
+
cit.print_validation_messages()
|
|
233
|
+
```
|
|
234
|
+
```text
|
|
235
|
+
>> [Error during execution: name '__file__' is not defined]
|
|
236
|
+
```
|
|
237
|
+
```python
|
|
238
|
+
# resolve a pac id
|
|
239
|
+
service_groups = PAC_ID_Resolver(cits=[cit]).resolve(pac_with_trex)
|
|
240
|
+
for sg in service_groups:
|
|
241
|
+
sg.print()
|
|
242
|
+
|
|
243
|
+
5
|
|
244
|
+
```
|
|
245
|
+
```text
|
|
246
|
+
>> [Error during execution: name 'cit' is not defined]
|
|
214
247
|
```
|
|
215
248
|
<!-- END EXAMPLES -->
|
|
216
249
|
|
|
@@ -218,6 +251,9 @@ print(pac_str)
|
|
|
218
251
|
|
|
219
252
|
## Change Log
|
|
220
253
|
|
|
254
|
+
### v0.1.0
|
|
255
|
+
- DRAFT Support for PAC-ID Resolver
|
|
256
|
+
|
|
221
257
|
### v0.0.20
|
|
222
258
|
- bugfix in TREX table to dict conversion
|
|
223
259
|
- markdown compatible validation printing
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
labfreed/__init__.py,sha256=
|
|
2
|
-
labfreed/validation.py,sha256=
|
|
1
|
+
labfreed/__init__.py,sha256=LebroXmoov8_KunUmdQn2n6f793Y9WSU58Q9C_6Dxz4,87
|
|
2
|
+
labfreed/validation.py,sha256=PW08_mVpp27Bju3MblACHXupAXbl60GjRaSGXw161pU,6442
|
|
3
3
|
labfreed/DisplayNameExtension/DisplayNameExtension.py,sha256=l9JZY2eRS0V-H5h3-WXIHiiBJuljns-_e_t9Bp84_CU,1155
|
|
4
4
|
labfreed/IO/generate_qr.py,sha256=wdZSf51Id03xSY8liK2RfB7WyGAw9O4s0VhZzrkAa-g,16680
|
|
5
|
-
labfreed/IO/parse_pac.py,sha256=
|
|
5
|
+
labfreed/IO/parse_pac.py,sha256=fZKNWuVGnYZCY0k6xVB1JOmLN5g6D8RW5CIq6-6Y9KM,6288
|
|
6
6
|
labfreed/PAC_CAT/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
7
|
-
labfreed/PAC_CAT/data_model.py,sha256=
|
|
7
|
+
labfreed/PAC_CAT/data_model.py,sha256=qPrpzooI5tmH9P5JxfHWn0Ruung66gJ9KojCu5lXVzY,14320
|
|
8
8
|
labfreed/PAC_ID/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
labfreed/PAC_ID/data_model.py,sha256=
|
|
9
|
+
labfreed/PAC_ID/data_model.py,sha256=vALf8thR4zq7WrVZaKnIiS8hGBJ7UuKoy2heOY97tOs,7481
|
|
10
10
|
labfreed/PAC_ID/extensions.py,sha256=YKIE-aFf1jdL4sqCqUe3txjnP8-dA2zCJrT5lBSjvuE,1092
|
|
11
|
+
labfreed/PAC_ID_Resolver/cit.yaml,sha256=-UcP-vKwhwGmYZVkVOjPZWEwHPzxUDcTFZFVM2_zMF0,2017
|
|
12
|
+
labfreed/PAC_ID_Resolver/data_types.py,sha256=i9F4FzLdAUpcFIX9fg9bLFRqQRe0E2ptb17etdtsj_c,1609
|
|
13
|
+
labfreed/PAC_ID_Resolver/resolver.py,sha256=2EKpDEzOM8Ri-Gy5cKVE6aoHsVFRqZE9fd_llG4wrFI,8178
|
|
11
14
|
labfreed/TREX/UneceUnits.json,sha256=kwfQSp_nTuWbADfBBgqTWrvPl6XtM5SedEVLbMJrM7M,898953
|
|
12
15
|
labfreed/TREX/data_model.py,sha256=tGgjp76wbS1MSS1Ep842CZyintsbecTZrlapj8WwGH8,29704
|
|
13
16
|
labfreed/TREX/parse.py,sha256=86962VEJpkrTcT436iFIB5dNed5WHABzpjxRjkA3PXo,2043
|
|
@@ -15,7 +18,7 @@ labfreed/TREX/unece_units.py,sha256=scPKdsPzY1neAdFOhA08_tRZaR-yplM8mBhIzzDqZBk,
|
|
|
15
18
|
labfreed/utilities/base36.py,sha256=_yX8aQ1OwrK5tnJU1NUEzQSFGr9xAVnNvPObpNzCPYs,2895
|
|
16
19
|
labfreed/utilities/utility_types.py,sha256=dM0qZgshF3cHJThVzia7UIAOdkNLKukAaaduLqKSaMY,2195
|
|
17
20
|
labfreed/utilities/well_known_keys.py,sha256=nqk66kHdSwJTJfMKlP-xQbBglS8F_NoWsGkfOVITFN0,331
|
|
18
|
-
labfreed-0.0.
|
|
19
|
-
labfreed-0.0.
|
|
20
|
-
labfreed-0.0.
|
|
21
|
-
labfreed-0.0.
|
|
21
|
+
labfreed-0.1.0.dist-info/licenses/LICENSE,sha256=gHFOv9FRKHxO8cInP3YXyPoJnuNeqrvcHjaE_wPSsQ8,1100
|
|
22
|
+
labfreed-0.1.0.dist-info/WHEEL,sha256=Dyt6SBfaasWElUrURkknVFAZDHSTwxg3PaTza7RSbkY,100
|
|
23
|
+
labfreed-0.1.0.dist-info/METADATA,sha256=bTILYvmhLnxvXo2HM9EBlwmOQttglU5Hc-Bk9dKKWcY,7625
|
|
24
|
+
labfreed-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|