labfreed 0.2.4__py3-none-any.whl → 0.2.5__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.

Files changed (43) hide show
  1. labfreed/__init__.py +11 -11
  2. labfreed/labfreed_infrastructure.py +256 -256
  3. labfreed/pac_cat/__init__.py +19 -19
  4. labfreed/pac_cat/category_base.py +51 -51
  5. labfreed/pac_cat/pac_cat.py +150 -150
  6. labfreed/pac_cat/predefined_categories.py +200 -200
  7. labfreed/pac_id/__init__.py +19 -19
  8. labfreed/pac_id/extension.py +48 -48
  9. labfreed/pac_id/id_segment.py +89 -89
  10. labfreed/pac_id/pac_id.py +140 -140
  11. labfreed/pac_id/url_parser.py +153 -153
  12. labfreed/pac_id/url_serializer.py +80 -80
  13. labfreed/pac_id_resolver/__init__.py +2 -2
  14. labfreed/pac_id_resolver/cit_v1.py +150 -149
  15. labfreed/pac_id_resolver/cit_v2.py +303 -303
  16. labfreed/pac_id_resolver/resolver.py +86 -81
  17. labfreed/pac_id_resolver/services.py +79 -79
  18. labfreed/qr/__init__.py +1 -1
  19. labfreed/qr/generate_qr.py +422 -422
  20. labfreed/trex/__init__.py +16 -16
  21. labfreed/trex/python_convenience/__init__.py +3 -3
  22. labfreed/trex/python_convenience/data_table.py +87 -44
  23. labfreed/trex/python_convenience/pyTREX.py +248 -241
  24. labfreed/trex/python_convenience/quantity.py +66 -46
  25. labfreed/trex/table_segment.py +245 -244
  26. labfreed/trex/trex.py +69 -69
  27. labfreed/trex/trex_base_models.py +209 -210
  28. labfreed/trex/value_segments.py +99 -101
  29. labfreed/utilities/base36.py +82 -82
  30. labfreed/well_known_extensions/__init__.py +4 -4
  31. labfreed/well_known_extensions/default_extension_interpreters.py +6 -6
  32. labfreed/well_known_extensions/display_name_extension.py +40 -40
  33. labfreed/well_known_extensions/trex_extension.py +30 -30
  34. labfreed/well_known_keys/gs1/__init__.py +5 -5
  35. labfreed/well_known_keys/gs1/gs1.py +3 -3
  36. labfreed/well_known_keys/labfreed/well_known_keys.py +15 -15
  37. labfreed/well_known_keys/unece/__init__.py +3 -3
  38. labfreed/well_known_keys/unece/unece_units.py +67 -67
  39. {labfreed-0.2.4.dist-info → labfreed-0.2.5.dist-info}/METADATA +21 -9
  40. labfreed-0.2.5.dist-info/RECORD +44 -0
  41. {labfreed-0.2.4.dist-info → labfreed-0.2.5.dist-info}/licenses/LICENSE +21 -21
  42. labfreed-0.2.4.dist-info/RECORD +0 -44
  43. {labfreed-0.2.4.dist-info → labfreed-0.2.5.dist-info}/WHEEL +0 -0
@@ -1,149 +1,150 @@
1
-
2
- from enum import Enum
3
- import logging
4
- import re
5
-
6
- from pydantic import Field
7
- from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMessage, ValidationMsgLevel
8
- from labfreed.pac_id.pac_id import PAC_ID
9
- from labfreed.pac_id_resolver.services import Service, ServiceGroup
10
-
11
- class ServiceType(Enum):
12
- USER_HANDOVER_GENERIC = 'userhandover-generic'
13
- ATTRIBUTE_SERVICE_GENERIC = 'attributes-generic'
14
-
15
-
16
- class CITEntry_v1(LabFREED_BaseModel):
17
- applicable_if: str = Field(..., min_length=1)
18
- service_name: str = Field(..., min_length=1)
19
- application_intent:str = Field(..., min_length=1)
20
- service_type:ServiceType
21
- template_url:str = Field(..., min_length=1)
22
-
23
-
24
- class CIT_v1(LabFREED_BaseModel):
25
- origin:str = ''
26
- entries:list[CITEntry_v1]
27
-
28
-
29
- @classmethod
30
- def from_csv(cls, csv:str, origin=''):
31
- lines = csv.splitlines()
32
- entries = list()
33
- errors = list()
34
- for line in lines:
35
- if not line: # empty line
36
- continue
37
- if line.strip()[0] == '#': #comment line
38
- continue
39
- if 'Service Name' in line.strip() : #header line
40
- continue
41
-
42
- cols = [c.strip() for c in line.split('\t')]
43
- try:
44
- entry = CITEntry_v1(
45
- service_name = cols[0],
46
- application_intent = cols[1],
47
- service_type = ServiceType(cols[2]),
48
- applicable_if = cols[3],
49
- template_url = cols[4]
50
- )
51
- except ValueError:
52
- logging.error(f'invalid line {line}')
53
- msg = ValidationMessage(
54
- level=ValidationMsgLevel.WARNING,
55
- source='CIT line',
56
- source_id=0,
57
- msg='Invalid line in CIT. Line was ignored. Remaining CIT is functional.',
58
- highlight_sub_patterns=line
59
- )
60
- errors.append(msg)
61
-
62
- entries.append(entry)
63
- cit = CIT_v1(origin=origin, entries=entries)
64
- cit._validation_messages.extend(errors)
65
- cit._csv_original = csv
66
- return cit
67
-
68
- def evaluate_pac_id(self, pac):
69
- cit_evaluated = ServiceGroup(origin=self.origin)
70
- for e in self.entries:
71
- conditions = e.applicable_if.split(';')
72
- conditions_evaluated = list()
73
- for c in conditions:
74
- if '=' in c:
75
- query, expected = c.split('=')
76
- value = self._find_in_pac(query.strip(), pac)
77
- conditions_evaluated.append(value == expected.strip())
78
- else:
79
- query = c.strip()
80
- found = self._find_in_pac(query, pac)
81
- conditions_evaluated.append(found)
82
- is_applicable = all(conditions_evaluated)
83
-
84
- if not is_applicable:
85
- continue
86
-
87
- url = re.sub(r"\{([^}]+)\}", lambda v: self._find_in_pac(v.group(0), pac), e.template_url)
88
- cit_evaluated.services.append(Service(
89
- service_name=e.service_name,
90
- application_intents= [ e.application_intent ],
91
- service_type=e.service_type,
92
- url = url
93
- )
94
- )
95
- return cit_evaluated
96
-
97
- def _find_in_pac(self, value, pac:PAC_ID):
98
- pac_url =pac.to_url()
99
- if value == '{isu}':
100
- return pac.issuer
101
-
102
- elif value == '{pac}':
103
- return pac_url.split('*')[0]
104
-
105
- elif value == '{id}':
106
- m = re.match(r'^HTTPS://.+?/(.+?)(\*.*)*$', pac_url)
107
- return m.group(1) if m else None
108
-
109
- elif m := re.match(r'\{idSeg(\d+)\}', value):
110
- i = int(m.group(1)) - 1 # CIT is 1 based
111
- seg = pac.identifier[i] if i < len(pac.identifier) else None
112
- if seg:
113
- return f"{(seg.key + ':') if seg.key else ''}{seg.value}"
114
-
115
- elif m := re.match(r'\{idVal(\w+)\}', value):
116
- k = m.group(1)
117
- seg = [s for s in pac.identifier if s.key and s.key == k]
118
- if seg:
119
- seg = seg[0]
120
- return seg.value
121
- else:
122
- return None
123
-
124
- elif value == '{ext}':
125
- m = re.match(r'^.*?(\*.*)*$', pac_url)
126
- ext_str = m.group(1) if m else None
127
- return m.group(1)[1:] if ext_str else None
128
-
129
- elif m := re.match(r'\{ext(\d+)\}', value):
130
- i = int(m.group(1)) - 1 # CIT is 1 based
131
- extensions = pac_url.split('*')
132
- extensions.pop(0)# first element is not extension
133
- return extensions[i] if i < len(extensions) else None
134
- else:
135
- return None
136
-
137
-
138
-
139
-
140
-
141
- def __str__(self):
142
- if csv:=self._csv_original:
143
- return csv
144
-
145
- s = "# coupling information table version: 1.0\n"
146
- s += "Service Name\tApplication Intent\tService Type\tApplicable If\tTemplate Url\n"
147
- for e in self.entries:
148
- s += '\t'.join([e.service_name, e.application_intent, e.service_type.value, e.applicable_if, e.template_url]) + '\n'
149
- return s
1
+
2
+ from enum import Enum
3
+ import logging
4
+ import re
5
+
6
+ from pydantic import Field
7
+ from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMessage, ValidationMsgLevel
8
+ from labfreed.pac_id.pac_id import PAC_ID
9
+ from labfreed.pac_id_resolver.services import Service, ServiceGroup
10
+
11
+ class ServiceType(Enum):
12
+ USER_HANDOVER_GENERIC = 'userhandover-generic'
13
+ ATTRIBUTE_SERVICE_GENERIC = 'attributes-generic'
14
+
15
+
16
+ class CITEntry_v1(LabFREED_BaseModel):
17
+ applicable_if: str = Field(..., min_length=1)
18
+ service_name: str = Field(..., min_length=1)
19
+ application_intent:str = Field(..., min_length=1)
20
+ service_type:ServiceType
21
+ template_url:str = Field(..., min_length=1)
22
+
23
+
24
+ class CIT_v1(LabFREED_BaseModel):
25
+ origin:str = ''
26
+ entries:list[CITEntry_v1]
27
+
28
+
29
+ @classmethod
30
+ def from_csv(cls, csv:str, origin=''):
31
+ lines = csv.splitlines()
32
+ entries = list()
33
+ errors = list()
34
+ for line in lines:
35
+ if not line: # empty line
36
+ continue
37
+ if line.strip()[0] == '#': #comment line
38
+ continue
39
+ if 'Service Name' in line.strip() : #header line
40
+ continue
41
+
42
+ cols = [c.strip() for c in line.split('\t')]
43
+ try:
44
+ entry = CITEntry_v1(
45
+ service_name = cols[0],
46
+ application_intent = cols[1],
47
+ service_type = ServiceType(cols[2]),
48
+ applicable_if = cols[3],
49
+ template_url = cols[4]
50
+ )
51
+ entries.append(entry)
52
+ except ValueError:
53
+ logging.error(f'invalid line {line}')
54
+ msg = ValidationMessage(
55
+ level=ValidationMsgLevel.WARNING,
56
+ source='CIT line',
57
+ source_id=0,
58
+ msg='Invalid line in CIT. Line was ignored. Remaining CIT is functional.',
59
+ highlight_sub_patterns=line
60
+ )
61
+ errors.append(msg)
62
+
63
+
64
+ cit = CIT_v1(origin=origin, entries=entries)
65
+ cit._validation_messages.extend(errors)
66
+ cit._csv_original = csv
67
+ return cit
68
+
69
+ def evaluate_pac_id(self, pac):
70
+ cit_evaluated = ServiceGroup(origin=self.origin)
71
+ for e in self.entries:
72
+ conditions = e.applicable_if.split(';')
73
+ conditions_evaluated = list()
74
+ for c in conditions:
75
+ if '=' in c:
76
+ query, expected = c.split('=')
77
+ value = self._find_in_pac(query.strip(), pac)
78
+ conditions_evaluated.append(value == expected.strip())
79
+ else:
80
+ query = c.strip()
81
+ found = self._find_in_pac(query, pac)
82
+ conditions_evaluated.append(found)
83
+ is_applicable = all(conditions_evaluated)
84
+
85
+ if not is_applicable:
86
+ continue
87
+
88
+ url = re.sub(r"\{([^}]+)\}", lambda v: self._find_in_pac(v.group(0), pac), e.template_url)
89
+ cit_evaluated.services.append(Service(
90
+ service_name=e.service_name,
91
+ application_intents= [ e.application_intent ],
92
+ service_type=e.service_type,
93
+ url = url
94
+ )
95
+ )
96
+ return cit_evaluated
97
+
98
+ def _find_in_pac(self, value, pac:PAC_ID):
99
+ pac_url =pac.to_url()
100
+ if value == '{isu}':
101
+ return pac.issuer
102
+
103
+ elif value == '{pac}':
104
+ return pac_url.split('*')[0]
105
+
106
+ elif value == '{id}':
107
+ m = re.match(r'^HTTPS://.+?/(.+?)(\*.*)*$', pac_url)
108
+ return m.group(1) if m else None
109
+
110
+ elif m := re.match(r'\{idSeg(\d+)\}', value):
111
+ i = int(m.group(1)) - 1 # CIT is 1 based
112
+ seg = pac.identifier[i] if i < len(pac.identifier) else None
113
+ if seg:
114
+ return f"{(seg.key + ':') if seg.key else ''}{seg.value}"
115
+
116
+ elif m := re.match(r'\{idVal(\w+)\}', value):
117
+ k = m.group(1)
118
+ seg = [s for s in pac.identifier if s.key and s.key == k]
119
+ if seg:
120
+ seg = seg[0]
121
+ return seg.value
122
+ else:
123
+ return None
124
+
125
+ elif value == '{ext}':
126
+ m = re.match(r'^.*?(\*.*)*$', pac_url)
127
+ ext_str = m.group(1) if m else None
128
+ return m.group(1)[1:] if ext_str else None
129
+
130
+ elif m := re.match(r'\{ext(\d+)\}', value):
131
+ i = int(m.group(1)) - 1 # CIT is 1 based
132
+ extensions = pac_url.split('*')
133
+ extensions.pop(0)# first element is not extension
134
+ return extensions[i] if i < len(extensions) else None
135
+ else:
136
+ return None
137
+
138
+
139
+
140
+
141
+
142
+ def __str__(self):
143
+ if csv:=self._csv_original:
144
+ return csv
145
+
146
+ s = "# coupling information table version: 1.0\n"
147
+ s += "Service Name\tApplication Intent\tService Type\tApplicable If\tTemplate Url\n"
148
+ for e in self.entries:
149
+ s += '\t'.join([e.service_name, e.application_intent, e.service_type.value, e.applicable_if, e.template_url]) + '\n'
150
+ return s