labfreed 0.2.8__py3-none-any.whl → 0.2.9__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 (44) hide show
  1. labfreed/__init__.py +11 -11
  2. labfreed/labfreed_infrastructure.py +258 -258
  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 +155 -155
  12. labfreed/pac_id/url_serializer.py +85 -84
  13. labfreed/pac_id_resolver/__init__.py +2 -2
  14. labfreed/pac_id_resolver/cit_common.py +81 -81
  15. labfreed/pac_id_resolver/cit_v1.py +244 -244
  16. labfreed/pac_id_resolver/cit_v2.py +313 -313
  17. labfreed/pac_id_resolver/resolver.py +97 -97
  18. labfreed/pac_id_resolver/services.py +82 -82
  19. labfreed/qr/__init__.py +1 -1
  20. labfreed/qr/generate_qr.py +422 -422
  21. labfreed/trex/__init__.py +16 -16
  22. labfreed/trex/python_convenience/__init__.py +3 -3
  23. labfreed/trex/python_convenience/data_table.py +87 -87
  24. labfreed/trex/python_convenience/pyTREX.py +248 -248
  25. labfreed/trex/python_convenience/quantity.py +66 -66
  26. labfreed/trex/table_segment.py +245 -245
  27. labfreed/trex/trex.py +69 -69
  28. labfreed/trex/trex_base_models.py +209 -209
  29. labfreed/trex/value_segments.py +99 -99
  30. labfreed/utilities/base36.py +82 -82
  31. labfreed/well_known_extensions/__init__.py +4 -4
  32. labfreed/well_known_extensions/default_extension_interpreters.py +6 -6
  33. labfreed/well_known_extensions/display_name_extension.py +40 -40
  34. labfreed/well_known_extensions/trex_extension.py +30 -30
  35. labfreed/well_known_keys/gs1/__init__.py +5 -5
  36. labfreed/well_known_keys/gs1/gs1.py +3 -3
  37. labfreed/well_known_keys/labfreed/well_known_keys.py +15 -15
  38. labfreed/well_known_keys/unece/__init__.py +3 -3
  39. labfreed/well_known_keys/unece/unece_units.py +67 -67
  40. {labfreed-0.2.8.dist-info → labfreed-0.2.9.dist-info}/METADATA +11 -8
  41. labfreed-0.2.9.dist-info/RECORD +45 -0
  42. {labfreed-0.2.8.dist-info → labfreed-0.2.9.dist-info}/licenses/LICENSE +21 -21
  43. labfreed-0.2.8.dist-info/RECORD +0 -45
  44. {labfreed-0.2.8.dist-info → labfreed-0.2.9.dist-info}/WHEEL +0 -0
@@ -1,156 +1,156 @@
1
-
2
-
3
- import logging
4
- import re
5
- from types import MappingProxyType
6
-
7
- from labfreed.labfreed_infrastructure import LabFREED_ValidationError
8
-
9
- from labfreed.pac_id.id_segment import IDSegment
10
- from labfreed.pac_id.extension import Extension
11
-
12
- from labfreed.pac_cat import PAC_CAT
13
- from labfreed.well_known_extensions import default_extension_interpreters
14
-
15
-
16
- from typing import TYPE_CHECKING
17
- if TYPE_CHECKING:
18
- # only imported during type checking
19
- from labfreed.pac_id import PAC_ID
20
- from labfreed.pac_cat import PAC_CAT
21
-
22
- class PAC_Parser():
23
- '''@private
24
- Knows how to parse a PAC-ID.
25
- From a SW engineering perspective it would be best to have no dependencies from other modules to pac_id.
26
- However from a Python users convenience perspective it is better to have one place where a pac url can be parsed and magically the extensions are in a meaningful type (e.g. TREX in TREX aware format) and categories are known of possible.
27
-
28
- >> We have given priority to convenient usage and therefore chose to have dependencies from pac_id to pac_cat and well_known_extensions
29
- '''
30
-
31
- @classmethod
32
- def from_url(cls, pac_url:str,
33
- *,
34
- extension_interpreters = 'default',
35
- try_pac_cat = True,
36
- suppress_validation_errors=False
37
- ) -> "PAC_ID":
38
- """Parses a PAC-ID with extensions
39
-
40
- Args:
41
- pac_url (str): pac id with optional extensions: e.g. HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/ABC*SUM$TREX/A$T.A:ABC
42
-
43
- Raises:
44
- LabFREED_ValidationError: When validation fails. Note,that with suppress_errors no such error is raises
45
-
46
- Returns:
47
- PACID including extensions. If possible PAC-CAT is applied and extensions are cast to a known type, which knows how to inetrprete the data
48
- """
49
- if extension_interpreters == 'default':
50
- extension_interpreters = default_extension_interpreters
51
-
52
- if '*' in pac_url:
53
- id_str, ext_str = pac_url.split('*', 1)
54
- else:
55
- id_str = pac_url
56
- ext_str = ""
57
-
58
- pac_id = cls._parse_pac_id(id_str)
59
-
60
- # try converting to PAC-CAT. This can fail, in which case a regular PAC-ID is returned
61
- if try_pac_cat:
62
- try:
63
- pac_cat = PAC_CAT.from_pac_id(pac_id)
64
- if pac_cat.categories:
65
- pac_id = pac_cat
66
- except LabFREED_ValidationError:
67
- pass
68
-
69
- extensions = cls._parse_extensions(ext_str)
70
- if extensions and extension_interpreters:
71
- for i, e in enumerate(extensions):
72
- if interpreter := extension_interpreters.get(e.type):
73
- extensions[i] = interpreter.from_extension(e)
74
- pac_id.extensions = extensions
75
-
76
- if not pac_id.is_valid and not suppress_validation_errors:
77
- logging.error(pac_id.print_validation_messages())
78
- raise LabFREED_ValidationError(validation_msgs = pac_id._get_nested_validation_messages())
79
-
80
- return pac_id
81
-
82
- @classmethod
83
- def _parse_pac_id(cls,id_str:str) -> "PAC_ID":
84
- # m = re.match('(HTTPS://)?(PAC.)?(?P<issuer>.+?\..+?)/(?P<identifier>.*)', id_str)
85
- m = re.match('(HTTPS://)?(PAC.)?(?P<issuer>.+?)/(?P<identifier>.*)', id_str)
86
- d = m.groupdict()
87
-
88
- id_segments = list()
89
- id_segments = cls._parse_id_segments(d.get('identifier'))
90
-
91
- from labfreed.pac_id import PAC_ID
92
- pac = PAC_ID(issuer= d.get('issuer'),
93
- identifier=id_segments
94
- )
95
-
96
- return pac
97
-
98
- @classmethod
99
- def _parse_id_segments(cls, identifier:str):
100
- if not identifier:
101
- return []
102
-
103
- id_segments = list()
104
- if len(identifier) > 0 and identifier[0] == '/':
105
- identifier = identifier[1:]
106
- for s in identifier.split('/'):
107
- tmp = s.split(':')
108
-
109
- if len(tmp) == 1:
110
- segment = IDSegment(value=tmp[0])
111
- elif len(tmp) == 2:
112
- segment = IDSegment(key=tmp[0], value=tmp[1])
113
- else:
114
- raise ValueError(f'invalid segment: {s}')
115
-
116
- id_segments.append(segment)
117
- return id_segments
118
-
119
-
120
- @classmethod
121
- def _parse_extensions(cls, extensions_str:str|None) -> list["Extension"]:
122
-
123
- extensions = list()
124
-
125
- if not extensions_str:
126
- return extensions
127
-
128
- defaults = MappingProxyType(
129
- {
130
- 0: { 'name': 'N', 'type': 'N'},
131
- 1: { 'name': 'SUM', 'type': 'TREX'}
132
- }
133
- )
134
- for i, e in enumerate(extensions_str.split('*')):
135
- if e == '': #this will happen if first extension starts with *
136
- continue
137
- d = re.match('((?P<name>.+)\$(?P<type>.+)/)?(?P<data>.+)', e).groupdict()
138
-
139
- name = d.get('name')
140
- type = d.get('type')
141
- data = d.get('data')
142
-
143
- if name:
144
- defaults = None # once a name was specified no longer assign defaults
145
- else:
146
- if defaults:
147
- name = defaults.get(i).get('name')
148
- type = defaults.get(i).get('type')
149
- else:
150
- raise ValueError('extension number {i}, must have name and type')
151
-
152
- #convert to subtype if they were given
153
- e = Extension.create(name=name, type=type, data=data)
154
- extensions.append(e)
155
-
1
+
2
+
3
+ import logging
4
+ import re
5
+ from types import MappingProxyType
6
+
7
+ from labfreed.labfreed_infrastructure import LabFREED_ValidationError
8
+
9
+ from labfreed.pac_id.id_segment import IDSegment
10
+ from labfreed.pac_id.extension import Extension
11
+
12
+ from labfreed.pac_cat import PAC_CAT
13
+ from labfreed.well_known_extensions import default_extension_interpreters
14
+
15
+
16
+ from typing import TYPE_CHECKING
17
+ if TYPE_CHECKING:
18
+ # only imported during type checking
19
+ from labfreed.pac_id import PAC_ID
20
+ from labfreed.pac_cat import PAC_CAT
21
+
22
+ class PAC_Parser():
23
+ '''@private
24
+ Knows how to parse a PAC-ID.
25
+ From a SW engineering perspective it would be best to have no dependencies from other modules to pac_id.
26
+ However from a Python users convenience perspective it is better to have one place where a pac url can be parsed and magically the extensions are in a meaningful type (e.g. TREX in TREX aware format) and categories are known of possible.
27
+
28
+ >> We have given priority to convenient usage and therefore chose to have dependencies from pac_id to pac_cat and well_known_extensions
29
+ '''
30
+
31
+ @classmethod
32
+ def from_url(cls, pac_url:str,
33
+ *,
34
+ extension_interpreters = 'default',
35
+ try_pac_cat = True,
36
+ suppress_validation_errors=False
37
+ ) -> "PAC_ID":
38
+ """Parses a PAC-ID with extensions
39
+
40
+ Args:
41
+ pac_url (str): pac id with optional extensions: e.g. HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/ABC*SUM$TREX/A$T.A:ABC
42
+
43
+ Raises:
44
+ LabFREED_ValidationError: When validation fails. Note,that with suppress_errors no such error is raises
45
+
46
+ Returns:
47
+ PACID including extensions. If possible PAC-CAT is applied and extensions are cast to a known type, which knows how to inetrprete the data
48
+ """
49
+ if extension_interpreters == 'default':
50
+ extension_interpreters = default_extension_interpreters
51
+
52
+ if '*' in pac_url:
53
+ id_str, ext_str = pac_url.split('*', 1)
54
+ else:
55
+ id_str = pac_url
56
+ ext_str = ""
57
+
58
+ pac_id = cls._parse_pac_id(id_str)
59
+
60
+ # try converting to PAC-CAT. This can fail, in which case a regular PAC-ID is returned
61
+ if try_pac_cat:
62
+ try:
63
+ pac_cat = PAC_CAT.from_pac_id(pac_id)
64
+ if pac_cat.categories:
65
+ pac_id = pac_cat
66
+ except LabFREED_ValidationError:
67
+ pass
68
+
69
+ extensions = cls._parse_extensions(ext_str)
70
+ if extensions and extension_interpreters:
71
+ for i, e in enumerate(extensions):
72
+ if interpreter := extension_interpreters.get(e.type):
73
+ extensions[i] = interpreter.from_extension(e)
74
+ pac_id.extensions = extensions
75
+
76
+ if not pac_id.is_valid and not suppress_validation_errors:
77
+ logging.error(pac_id.print_validation_messages())
78
+ raise LabFREED_ValidationError(validation_msgs = pac_id._get_nested_validation_messages())
79
+
80
+ return pac_id
81
+
82
+ @classmethod
83
+ def _parse_pac_id(cls,id_str:str) -> "PAC_ID":
84
+ # m = re.match('(HTTPS://)?(PAC.)?(?P<issuer>.+?\..+?)/(?P<identifier>.*)', id_str)
85
+ m = re.match('(HTTPS://)?(PAC.)?(?P<issuer>.+?)/(?P<identifier>.*)', id_str)
86
+ d = m.groupdict()
87
+
88
+ id_segments = list()
89
+ id_segments = cls._parse_id_segments(d.get('identifier'))
90
+
91
+ from labfreed.pac_id import PAC_ID
92
+ pac = PAC_ID(issuer= d.get('issuer'),
93
+ identifier=id_segments
94
+ )
95
+
96
+ return pac
97
+
98
+ @classmethod
99
+ def _parse_id_segments(cls, identifier:str):
100
+ if not identifier:
101
+ return []
102
+
103
+ id_segments = list()
104
+ if len(identifier) > 0 and identifier[0] == '/':
105
+ identifier = identifier[1:]
106
+ for s in identifier.split('/'):
107
+ tmp = s.split(':')
108
+
109
+ if len(tmp) == 1:
110
+ segment = IDSegment(value=tmp[0])
111
+ elif len(tmp) == 2:
112
+ segment = IDSegment(key=tmp[0], value=tmp[1])
113
+ else:
114
+ raise ValueError(f'invalid segment: {s}')
115
+
116
+ id_segments.append(segment)
117
+ return id_segments
118
+
119
+
120
+ @classmethod
121
+ def _parse_extensions(cls, extensions_str:str|None) -> list["Extension"]:
122
+
123
+ extensions = list()
124
+
125
+ if not extensions_str:
126
+ return extensions
127
+
128
+ defaults = MappingProxyType(
129
+ {
130
+ 0: { 'name': 'N', 'type': 'N'},
131
+ 1: { 'name': 'SUM', 'type': 'TREX'}
132
+ }
133
+ )
134
+ for i, e in enumerate(extensions_str.split('*')):
135
+ if e == '': #this will happen if first extension starts with *
136
+ continue
137
+ d = re.match('((?P<name>.+)\$(?P<type>.+)/)?(?P<data>.+)', e).groupdict()
138
+
139
+ name = d.get('name')
140
+ type = d.get('type')
141
+ data = d.get('data')
142
+
143
+ if name:
144
+ defaults = None # once a name was specified no longer assign defaults
145
+ else:
146
+ if defaults:
147
+ name = defaults.get(i).get('name')
148
+ type = defaults.get(i).get('type')
149
+ else:
150
+ raise ValueError('extension number {i}, must have name and type')
151
+
152
+ #convert to subtype if they were given
153
+ e = Extension.create(name=name, type=type, data=data)
154
+ extensions.append(e)
155
+
156
156
  return extensions
@@ -1,84 +1,85 @@
1
- from labfreed.pac_cat.pac_cat import PAC_CAT
2
- from labfreed.pac_cat.predefined_categories import PredefinedCategory
3
- from labfreed.pac_id.id_segment import IDSegment
4
- from labfreed.pac_id.extension import Extension
5
- from labfreed.pac_id import PAC_ID
6
-
7
-
8
- class PACID_Serializer():
9
- '''Represents a PAC-ID including it's extensions'''
10
-
11
- @classmethod
12
- def to_url(cls, pac:PAC_ID, use_short_notation:bool|None=None, uppercase_only=False) -> str:
13
- """Serializes the PAC-ID including extensions.
14
-
15
- Args:
16
- use_short_notation (bool|None, optional): None (default): Preserves the identifier as is. Extensions use short form
17
- True: forces short notation for categories and extensions
18
- False: forces long notation for categories and extensions
19
- uppercase_only (bool, optional): Forces all uppercase letters (results in smaller QR)..
20
-
21
- Returns:
22
- str: Something like this HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/ABC*SUM$TREX/A$T.A:ABC
23
-
24
- """
25
- identifier_str = cls._serialize_identifier(pac, use_short_notation=use_short_notation)
26
-
27
- use_short_notation_for_extensions = True if use_short_notation is None else use_short_notation
28
- extensions_str = cls._serialize_extensions(pac.extensions, use_short_notation=use_short_notation_for_extensions)
29
- out = f"HTTPS://PAC.{pac.issuer}{identifier_str}{extensions_str}"
30
-
31
- if uppercase_only:
32
- out = out.upper()
33
- return out
34
-
35
- @classmethod
36
- def _serialize_identifier(cls, pac:PAC_ID|PAC_CAT, use_short_notation:None|bool=None):
37
- ''' Serializes the PAC-ID'''
38
-
39
- if isinstance(pac, PAC_CAT) and use_short_notation is not None:
40
- for c in pac.categories:
41
- segments = [IDSegment(value=c.key)]
42
- if isinstance(c, PredefinedCategory):
43
- segments += c._get_segments(use_short_notation=use_short_notation)
44
- else:
45
- segments += c.segments
46
- else:
47
- segments = pac.identifier
48
-
49
- identifier_str = ''
50
- for s in segments:
51
- s:IDSegment = s
52
- if s.key:
53
- identifier_str += f'/{s.key}:{s.value}'
54
- else:
55
- identifier_str += f'/{s.value}'
56
- return identifier_str
57
-
58
-
59
- @classmethod
60
- def _serialize_extensions(cls, extensions:list[Extension], use_short_notation):
61
- out = ''
62
- short_notation = use_short_notation
63
- for i, e in enumerate(extensions):
64
-
65
- if short_notation and i==0:
66
- if e.name=='N':
67
- out += f'*{e.data}'
68
- continue
69
- else:
70
- short_notation = False
71
- if short_notation and i==1:
72
- if e.name=='SUM':
73
- out += f'*{e.data}'
74
- continue
75
- else:
76
- short_notation = False
77
-
78
- out += f'*{e.name}${e.type}/{e.data}'
79
- return out
80
-
81
-
82
-
83
-
84
-
1
+ from labfreed.pac_cat.pac_cat import PAC_CAT
2
+ from labfreed.pac_cat.predefined_categories import PredefinedCategory
3
+ from labfreed.pac_id.id_segment import IDSegment
4
+ from labfreed.pac_id.extension import Extension
5
+ from labfreed.pac_id import PAC_ID
6
+
7
+
8
+ class PACID_Serializer():
9
+ '''Represents a PAC-ID including it's extensions'''
10
+
11
+ @classmethod
12
+ def to_url(cls, pac:PAC_ID, use_short_notation:bool|None=None, uppercase_only=False) -> str:
13
+ """Serializes the PAC-ID including extensions.
14
+
15
+ Args:
16
+ use_short_notation (bool|None, optional): None (default): Preserves the identifier as is. Extensions use short form
17
+ True: forces short notation for categories and extensions
18
+ False: forces long notation for categories and extensions
19
+ uppercase_only (bool, optional): Forces all uppercase letters (results in smaller QR)..
20
+
21
+ Returns:
22
+ str: Something like this HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/ABC*SUM$TREX/A$T.A:ABC
23
+
24
+ """
25
+ identifier_str = cls._serialize_identifier(pac, use_short_notation=use_short_notation)
26
+
27
+ use_short_notation_for_extensions = True if use_short_notation is None else use_short_notation
28
+ extensions_str = cls._serialize_extensions(pac.extensions, use_short_notation=use_short_notation_for_extensions)
29
+ out = f"HTTPS://PAC.{pac.issuer}{identifier_str}{extensions_str}"
30
+
31
+ if uppercase_only:
32
+ out = out.upper()
33
+ return out
34
+
35
+ @classmethod
36
+ def _serialize_identifier(cls, pac:PAC_ID|PAC_CAT, use_short_notation:None|bool=None):
37
+ ''' Serializes the PAC-ID'''
38
+
39
+ if isinstance(pac, PAC_CAT) and use_short_notation is not None:
40
+ segments = []
41
+ for c in pac.categories:
42
+ segments.append(IDSegment(value=c.key))
43
+ if isinstance(c, PredefinedCategory):
44
+ segments += c._get_segments(use_short_notation=use_short_notation)
45
+ else:
46
+ segments += c.segments
47
+ else:
48
+ segments = pac.identifier
49
+
50
+ identifier_str = ''
51
+ for s in segments:
52
+ s:IDSegment = s
53
+ if s.key:
54
+ identifier_str += f'/{s.key}:{s.value}'
55
+ else:
56
+ identifier_str += f'/{s.value}'
57
+ return identifier_str
58
+
59
+
60
+ @classmethod
61
+ def _serialize_extensions(cls, extensions:list[Extension], use_short_notation):
62
+ out = ''
63
+ short_notation = use_short_notation
64
+ for i, e in enumerate(extensions):
65
+
66
+ if short_notation and i==0:
67
+ if e.name=='N':
68
+ out += f'*{e.data}'
69
+ continue
70
+ else:
71
+ short_notation = False
72
+ if short_notation and i==1:
73
+ if e.name=='SUM':
74
+ out += f'*{e.data}'
75
+ continue
76
+ else:
77
+ short_notation = False
78
+
79
+ out += f'*{e.name}${e.type}/{e.data}'
80
+ return out
81
+
82
+
83
+
84
+
85
+
@@ -1,2 +1,2 @@
1
- from .resolver import PAC_ID_Resolver, load_cit # noqa: F401
2
- from .services import ServiceGroup # noqa: F401
1
+ from .resolver import PAC_ID_Resolver, load_cit # noqa: F401
2
+ from .services import ServiceGroup # noqa: F401
@@ -1,82 +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
-
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
82