labfreed 0.2.6a3__tar.gz → 0.2.6a5__tar.gz

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 (50) hide show
  1. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/PKG-INFO +1 -1
  2. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/__init__.py +1 -1
  3. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/labfreed_infrastructure.py +2 -2
  4. labfreed-0.2.6a5/labfreed/pac_id_resolver/cit_common.py +82 -0
  5. labfreed-0.2.6a5/labfreed/pac_id_resolver/cit_v1.py +248 -0
  6. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id_resolver/cit_v2.py +8 -3
  7. labfreed-0.2.6a3/labfreed/pac_id_resolver/cit_v1.py +0 -152
  8. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  9. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/.github/workflows/pypi-publish.yml +0 -0
  10. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/.github/workflows/run-tests.yml +0 -0
  11. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/CHANGELOG.md +0 -0
  12. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/LICENSE +0 -0
  13. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/README.md +0 -0
  14. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_cat/__init__.py +0 -0
  15. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_cat/category_base.py +0 -0
  16. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_cat/pac_cat.py +0 -0
  17. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_cat/predefined_categories.py +0 -0
  18. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id/__init__.py +0 -0
  19. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id/extension.py +0 -0
  20. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id/id_segment.py +0 -0
  21. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id/pac_id.py +0 -0
  22. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id/url_parser.py +0 -0
  23. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id/url_serializer.py +0 -0
  24. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id_resolver/__init__.py +0 -0
  25. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id_resolver/resolver.py +0 -0
  26. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/pac_id_resolver/services.py +0 -0
  27. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/qr/__init__.py +0 -0
  28. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/qr/generate_qr.py +0 -0
  29. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/__init__.py +0 -0
  30. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/python_convenience/__init__.py +0 -0
  31. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/python_convenience/data_table.py +0 -0
  32. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/python_convenience/pyTREX.py +0 -0
  33. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/python_convenience/quantity.py +0 -0
  34. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/table_segment.py +0 -0
  35. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/trex.py +0 -0
  36. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/trex_base_models.py +0 -0
  37. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/trex/value_segments.py +0 -0
  38. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/utilities/base36.py +0 -0
  39. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_extensions/__init__.py +0 -0
  40. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_extensions/default_extension_interpreters.py +0 -0
  41. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_extensions/display_name_extension.py +0 -0
  42. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_extensions/trex_extension.py +0 -0
  43. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_keys/gs1/__init__.py +0 -0
  44. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_keys/gs1/gs1.py +0 -0
  45. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_keys/gs1/gs1_ai_enum_sorted.py +0 -0
  46. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_keys/labfreed/well_known_keys.py +0 -0
  47. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_keys/unece/UneceUnits.json +0 -0
  48. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_keys/unece/__init__.py +0 -0
  49. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/labfreed/well_known_keys/unece/unece_units.py +0 -0
  50. {labfreed-0.2.6a3 → labfreed-0.2.6a5}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: labfreed
3
- Version: 0.2.6a3
3
+ Version: 0.2.6a5
4
4
  Summary: Python implementation of LabFREED building blocks
5
5
  Author-email: Reto Thürer <thuerer.r@buchi.com>
6
6
  Requires-Python: >=3.11
@@ -2,7 +2,7 @@
2
2
  Python implementation of LabFREED building blocks
3
3
  '''
4
4
 
5
- __version__ = "0.2.6a3"
5
+ __version__ = "0.2.6a5"
6
6
 
7
7
  from labfreed.pac_id import * # noqa: F403
8
8
  from labfreed.pac_cat import * # noqa: F403
@@ -194,9 +194,9 @@ class LabFREED_BaseModel(PDOC_Workaround_Base):
194
194
  formatted_msg = list()
195
195
  for m in self.validation_messages():
196
196
  if m.level == ValidationMsgLevel.ERROR:
197
- color = 'red'
197
+ color = '#d70000'
198
198
  else:
199
- color = 'orange'
199
+ color = '#d78700'
200
200
 
201
201
  match target:
202
202
  case 'markdown':
@@ -0,0 +1,82 @@
1
+ from enum import Enum
2
+ import re
3
+ from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMsgLevel, _quote_texts
4
+
5
+
6
+
7
+ class ServiceType(Enum):
8
+ USER_HANDOVER_GENERIC = 'userhandover-generic'
9
+ ATTRIBUTE_SERVICE_GENERIC = 'attributes-generic'
10
+
11
+
12
+ def _validate_service_name(service_name):
13
+ msg_dict = []
14
+ if not_allowed_chars := set(re.sub(r'[A-Za-z0-9\-\x20]', '', service_name)):
15
+ msg_dict.append( {
16
+ "level": ValidationMsgLevel.ERROR,
17
+ "msg": f'Service name ontains invalid characters {_quote_texts(not_allowed_chars)}',
18
+ "highlight_sub": not_allowed_chars
19
+ }
20
+ )
21
+
22
+ if len(service_name) == 0 or len(service_name) > 255:
23
+ msg_dict.append( {
24
+ "level": ValidationMsgLevel.ERROR,
25
+ "msg": 'Service name must be at least one and maximum 255 characters long'
26
+ }
27
+ )
28
+ return msg_dict
29
+
30
+
31
+ def _validate_application_intent(intent):
32
+ msg_dict = []
33
+ if re.fullmatch('.*-generic$', intent):
34
+ msg_dict.append( {
35
+ "level": ValidationMsgLevel.ERROR,
36
+ "msg": "Application intent ends with '-generic'. This is not permitted, since it is reserved for future uses'",
37
+ "highlight_sub": [intent]
38
+ }
39
+ )
40
+
41
+ if not_allowed_chars := set(re.sub(r'[A-Za-z0-9\-]', '', intent)):
42
+ msg_dict.append( {
43
+ "level": ValidationMsgLevel.ERROR,
44
+ "msg": f'Application intent contains invalid characters {_quote_texts(not_allowed_chars)}',
45
+ "highlight_sub": not_allowed_chars
46
+ }
47
+ )
48
+
49
+ if len(intent) == 0 or len(intent) > 255:
50
+ msg_dict.append( {
51
+ "level": ValidationMsgLevel.ERROR,
52
+ "source": f'Application intent {intent}',
53
+ "msg": 'Must be at least one and maximum 255 characters long'
54
+ }
55
+ )
56
+ return msg_dict
57
+
58
+
59
+ def _validate_service_type(service_type):
60
+ msg_dict = []
61
+ if isinstance(service_type, ServiceType):
62
+ service_type= service_type.value
63
+ else:
64
+ service_type= service_type
65
+ allowed_types = [ServiceType.ATTRIBUTE_SERVICE_GENERIC.value, ServiceType.USER_HANDOVER_GENERIC.value]
66
+ if service_type not in allowed_types:
67
+ msg_dict.append( {
68
+ "level": ValidationMsgLevel.ERROR,
69
+ "msg": f'Invalid service type. Must be {_quote_texts(allowed_types)} must be at least one and maximum 255 characters long',
70
+ "highlight_sub": service_type
71
+ }
72
+ )
73
+ return msg_dict
74
+
75
+
76
+ def _add_msg_to_cit_entry_model(msg_dict, model):
77
+ for m in msg_dict:
78
+ m.update({"source": model.service_name})
79
+ model._add_validation_message(**m)
80
+ return model
81
+
82
+
@@ -0,0 +1,248 @@
1
+
2
+ from enum import Enum
3
+ import logging
4
+ import re
5
+ import traceback
6
+
7
+ from pydantic import Field, model_validator
8
+ from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMessage, ValidationMsgLevel
9
+ from labfreed.pac_id.pac_id import PAC_ID
10
+ from labfreed.pac_id_resolver.services import Service, ServiceGroup
11
+ from labfreed.pac_id_resolver.cit_common import ( _add_msg_to_cit_entry_model,
12
+ _validate_service_name,
13
+ _validate_application_intent,
14
+ _validate_service_type,
15
+ ServiceType)
16
+
17
+
18
+
19
+ class CITEntry_v1(LabFREED_BaseModel):
20
+ applicable_if: str = Field(..., min_length=1)
21
+ service_name: str = Field(..., min_length=1)
22
+ application_intent:str = Field(..., min_length=1)
23
+ service_type:ServiceType|str
24
+ template_url:str = Field(..., min_length=1)
25
+
26
+
27
+ @model_validator(mode='after')
28
+ def _validate_model(self):
29
+ if self.applicable_if:
30
+ conditions = self.applicable_if.split(';')
31
+ for c in conditions:
32
+ if '=' in c:
33
+ query, expected = c.split('=')
34
+ query = query.strip()
35
+ else:
36
+ query = c.strip()
37
+
38
+ try:
39
+ # use this function to check if the pattern is valid. it returns a PatternError if not
40
+ _find_pattern_in_pac(query, '')
41
+ except PatternError:
42
+ self._add_validation_message(
43
+ level=ValidationMsgLevel.ERROR,
44
+ source=f'Service {self.service_name}',
45
+ msg=f'Applicable if contains invalid pattern {query}',
46
+ highlight_sub=query
47
+ )
48
+ except Exception:
49
+ pass # if no PatternError everything is fine
50
+ return self
51
+
52
+ @model_validator(mode='after')
53
+ def _validate_service_name(self):
54
+ msg_dict= _validate_service_name(self.service_name)
55
+ return _add_msg_to_cit_entry_model(msg_dict, self)
56
+
57
+
58
+ @model_validator(mode='after')
59
+ def _validate_application_intent(self):
60
+ msg_dict= _validate_application_intent(self.application_intent)
61
+ return _add_msg_to_cit_entry_model(msg_dict, self)
62
+
63
+
64
+ @model_validator(mode='after')
65
+ def _validate_service_type(self):
66
+ msg_dict= _validate_service_type(self.service_type)
67
+ return _add_msg_to_cit_entry_model(msg_dict, self)
68
+
69
+
70
+
71
+
72
+
73
+
74
+ class CIT_v1(LabFREED_BaseModel):
75
+ origin:str = ''
76
+ entries:list[CITEntry_v1]
77
+
78
+
79
+ @classmethod
80
+ def from_csv(cls, csv:str, origin=''):
81
+ lines = csv.splitlines()
82
+ entries = list()
83
+ errors = list()
84
+ for line in lines:
85
+ if not line: # empty line
86
+ continue
87
+ if line.strip()[0] == '#': #comment line
88
+ continue
89
+ if 'Service Name' in line.strip() : #header line
90
+ continue
91
+
92
+ cols = [c.strip() for c in line.split('\t')]
93
+ if len(cols) < 5:
94
+ logging.error(f'invalid line {line}')
95
+ msg = ValidationMessage(
96
+ level=ValidationMsgLevel.ERROR,
97
+ source='CIT line',
98
+ source_id=0,
99
+ msg=f'Invalid line in CIT. There are {5 - len(cols)} columns missing.',
100
+ highlight_sub_patterns=line
101
+ )
102
+ errors.append(msg)
103
+ continue
104
+ if len(cols) > 5:
105
+ logging.error(f'invalid line {line}')
106
+ msg = ValidationMessage(
107
+ level=ValidationMsgLevel.ERROR,
108
+ source='CIT line',
109
+ source_id=0,
110
+ msg=f'Invalid line in CIT. There are {len(cols) -5} too many columns',
111
+ highlight_sub_patterns=line
112
+ )
113
+ errors.append(msg)
114
+ continue
115
+ try:
116
+
117
+ entry = CITEntry_v1(
118
+ service_name = cols[0],
119
+ application_intent = cols[1],
120
+ service_type = cols[2],
121
+ applicable_if = cols[3],
122
+ template_url = cols[4]
123
+ )
124
+ entries.append(entry)
125
+ except ValueError:
126
+ logging.error(f'invalid line {line}')
127
+ msg = ValidationMessage(
128
+ level=ValidationMsgLevel.ERROR,
129
+ source='CIT line',
130
+ source_id=0,
131
+ msg='Invalid line in CIT.',
132
+ highlight_sub_patterns=line
133
+ )
134
+ errors.append(msg)
135
+
136
+ cit = CIT_v1(origin=origin, entries=entries)
137
+ if not cit.is_valid:
138
+ errors.insert(0,
139
+ ValidationMessage(
140
+ level=ValidationMsgLevel.WARNING,
141
+ source='CIT ',
142
+ source_id=0,
143
+ msg='Invalid lines in CIT. The lines were ignored. The rest of the CIT is still functional',
144
+ highlight_sub_patterns=''
145
+ )
146
+ )
147
+ cit._validation_messages.extend(errors)
148
+ cit._csv_original = csv
149
+ return cit
150
+
151
+ def evaluate_pac_id(self, pac:PAC_ID):
152
+ if type(pac) is not PAC_ID:
153
+ raise ValueError('CIT v1 does only handle PAC-IDs. PAC-CAT it does not know what to do')
154
+ cit_evaluated = ServiceGroup(origin=self.origin)
155
+ for e in self.entries:
156
+ if e.errors():
157
+ continue #make this stable against errors in the cit
158
+
159
+ conditions = e.applicable_if.split(';')
160
+ conditions_evaluated = list()
161
+ for c in conditions:
162
+ if '=' in c:
163
+ query, expected = c.split('=')
164
+ value = _find_pattern_in_pac(query.strip(), pac)
165
+ conditions_evaluated.append(value == expected.strip())
166
+ else:
167
+ query = c.strip()
168
+ found = _find_pattern_in_pac(query, pac)
169
+ conditions_evaluated.append(found)
170
+ is_applicable = all(conditions_evaluated)
171
+
172
+ if not is_applicable:
173
+ continue
174
+
175
+ url = re.sub(r"\{([^}]+)\}", lambda v: _find_pattern_in_pac(v.group(0), pac), e.template_url)
176
+ cit_evaluated.services.append(Service(
177
+ service_name=e.service_name,
178
+ application_intents= [ e.application_intent ],
179
+ service_type=e.service_type,
180
+ url = url
181
+ )
182
+ )
183
+ return cit_evaluated
184
+
185
+
186
+
187
+ def __str__(self):
188
+ if csv:=self._csv_original:
189
+ return csv
190
+
191
+ s = "# coupling information table version: 1.0\n"
192
+ s += "Service Name\tApplication Intent\tService Type\tApplicable If\tTemplate Url\n"
193
+ for e in self.entries:
194
+ s += '\t'.join([e.service_name, e.application_intent, e.service_type.value, e.applicable_if, e.template_url]) + '\n'
195
+ return s
196
+
197
+
198
+
199
+ def _find_pattern_in_pac(value, pac:PAC_ID|str):
200
+ if not isinstance(pac, str):
201
+ pac_url =pac.to_url()
202
+ else:
203
+ pac_url = pac
204
+
205
+ if value == '{isu}':
206
+ return pac.issuer
207
+
208
+ elif value == '{pac}':
209
+ return pac_url.split('*')[0]
210
+
211
+ elif value == '{id}':
212
+ m = re.match(r'^HTTPS://.+?/(.+?)(\*.*)*$', pac_url)
213
+ return m.group(1) if m else None
214
+
215
+ elif m := re.match(r'\{idSeg(\d+)\}', value):
216
+ i = int(m.group(1)) - 1 # CIT is 1 based
217
+ seg = pac.identifier[i] if i < len(pac.identifier) else None
218
+ if seg:
219
+ return f"{(seg.key + ':') if seg.key else ''}{seg.value}"
220
+
221
+ elif m := re.match(r'\{idVal(\w+)\}', value):
222
+ k = m.group(1)
223
+ seg = [s for s in pac.identifier if s.key and s.key == k]
224
+ if seg:
225
+ seg = seg[0]
226
+ return seg.value
227
+ else:
228
+ return None
229
+
230
+ elif value == '{ext}':
231
+ m = re.match(r'^.*?(\*.*)*$', pac_url)
232
+ ext_str = m.group(1) if m else None
233
+ return m.group(1)[1:] if ext_str else None
234
+
235
+ elif m := re.match(r'\{ext(\d+)\}', value):
236
+ i = int(m.group(1)) - 1 # CIT is 1 based
237
+ extensions = pac_url.split('*')
238
+ extensions.pop(0)# first element is not extension
239
+ return extensions[i] if i < len(extensions) else None
240
+ else:
241
+ raise PatternError(f'{value} is not a recognized pattern for applicable if')
242
+
243
+ class PatternError(ValueError):
244
+ pass
245
+
246
+
247
+
248
+
@@ -9,6 +9,12 @@ import jsonpath_ng.ext as jsonpath
9
9
 
10
10
  from labfreed.pac_id_resolver.services import Service, ServiceGroup
11
11
  from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMsgLevel, _quote_texts
12
+ from labfreed.pac_id_resolver.cit_common import ( _add_msg_to_cit_entry_model,
13
+ _validate_service_name,
14
+ _validate_application_intent,
15
+ _validate_service_type,
16
+ ServiceType)
17
+
12
18
 
13
19
  __all__ = [
14
20
  "CIT_v2",
@@ -16,9 +22,6 @@ __all__ = [
16
22
  "CITEntry_v2"
17
23
  ]
18
24
 
19
- class ServiceType(Enum):
20
- USER_HANDOVER_GENERIC = 'userhandover-generic'
21
- ATTRIBUTE_SERVICE_GENERIC = 'attributes-generic'
22
25
 
23
26
 
24
27
  class CITEntry_v2(LabFREED_BaseModel):
@@ -142,6 +145,8 @@ class CIT_v2(LabFREED_BaseModel):
142
145
  continue
143
146
 
144
147
  for e in block.entries:
148
+ if e.errors():
149
+ continue #make this stable against errors in the cit
145
150
  url = self._eval_url_template(pac_id_json, e.template_url)
146
151
  cit_evaluated.services.append(Service(
147
152
  service_name=e.service_name,
@@ -1,152 +0,0 @@
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:PAC_ID):
70
- if not type(pac) is PAC_ID:
71
- raise ValueError(f'CIT v1 does only handle PAC-IDs. PAC-CAT it does not know what to do')
72
- cit_evaluated = ServiceGroup(origin=self.origin)
73
- for e in self.entries:
74
- conditions = e.applicable_if.split(';')
75
- conditions_evaluated = list()
76
- for c in conditions:
77
- if '=' in c:
78
- query, expected = c.split('=')
79
- value = self._find_in_pac(query.strip(), pac)
80
- conditions_evaluated.append(value == expected.strip())
81
- else:
82
- query = c.strip()
83
- found = self._find_in_pac(query, pac)
84
- conditions_evaluated.append(found)
85
- is_applicable = all(conditions_evaluated)
86
-
87
- if not is_applicable:
88
- continue
89
-
90
- url = re.sub(r"\{([^}]+)\}", lambda v: self._find_in_pac(v.group(0), pac), e.template_url)
91
- cit_evaluated.services.append(Service(
92
- service_name=e.service_name,
93
- application_intents= [ e.application_intent ],
94
- service_type=e.service_type,
95
- url = url
96
- )
97
- )
98
- return cit_evaluated
99
-
100
- def _find_in_pac(self, value, pac:PAC_ID):
101
- pac_url =pac.to_url()
102
- if value == '{isu}':
103
- return pac.issuer
104
-
105
- elif value == '{pac}':
106
- return pac_url.split('*')[0]
107
-
108
- elif value == '{id}':
109
- m = re.match(r'^HTTPS://.+?/(.+?)(\*.*)*$', pac_url)
110
- return m.group(1) if m else None
111
-
112
- elif m := re.match(r'\{idSeg(\d+)\}', value):
113
- i = int(m.group(1)) - 1 # CIT is 1 based
114
- seg = pac.identifier[i] if i < len(pac.identifier) else None
115
- if seg:
116
- return f"{(seg.key + ':') if seg.key else ''}{seg.value}"
117
-
118
- elif m := re.match(r'\{idVal(\w+)\}', value):
119
- k = m.group(1)
120
- seg = [s for s in pac.identifier if s.key and s.key == k]
121
- if seg:
122
- seg = seg[0]
123
- return seg.value
124
- else:
125
- return None
126
-
127
- elif value == '{ext}':
128
- m = re.match(r'^.*?(\*.*)*$', pac_url)
129
- ext_str = m.group(1) if m else None
130
- return m.group(1)[1:] if ext_str else None
131
-
132
- elif m := re.match(r'\{ext(\d+)\}', value):
133
- i = int(m.group(1)) - 1 # CIT is 1 based
134
- extensions = pac_url.split('*')
135
- extensions.pop(0)# first element is not extension
136
- return extensions[i] if i < len(extensions) else None
137
- else:
138
- return None
139
-
140
-
141
-
142
-
143
-
144
- def __str__(self):
145
- if csv:=self._csv_original:
146
- return csv
147
-
148
- s = "# coupling information table version: 1.0\n"
149
- s += "Service Name\tApplication Intent\tService Type\tApplicable If\tTemplate Url\n"
150
- for e in self.entries:
151
- s += '\t'.join([e.service_name, e.application_intent, e.service_type.value, e.applicable_if, e.template_url]) + '\n'
152
- return s
File without changes
File without changes
File without changes
File without changes