labfreed 0.2.5a21__py3-none-any.whl → 0.2.6__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 -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 +155 -153
  12. labfreed/pac_id/url_serializer.py +84 -80
  13. labfreed/pac_id_resolver/__init__.py +2 -2
  14. labfreed/pac_id_resolver/cit_common.py +82 -0
  15. labfreed/pac_id_resolver/cit_v1.py +245 -149
  16. labfreed/pac_id_resolver/cit_v2.py +313 -303
  17. labfreed/pac_id_resolver/resolver.py +97 -81
  18. labfreed/pac_id_resolver/services.py +79 -79
  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.5a21.dist-info → labfreed-0.2.6.dist-info}/METADATA +37 -21
  41. labfreed-0.2.6.dist-info/RECORD +45 -0
  42. {labfreed-0.2.5a21.dist-info → labfreed-0.2.6.dist-info}/licenses/LICENSE +21 -21
  43. labfreed-0.2.5a21.dist-info/RECORD +0 -44
  44. {labfreed-0.2.5a21.dist-info → labfreed-0.2.6.dist-info}/WHEEL +0 -0
@@ -1,51 +1,51 @@
1
-
2
- from typing import Any
3
- from pydantic import PrivateAttr, computed_field, model_validator
4
- from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMsgLevel
5
- from labfreed.pac_id.id_segment import IDSegment
6
-
7
-
8
- class Category(LabFREED_BaseModel):
9
- '''
10
- Represents a category. \n
11
- This is the base class for categories. If possible a more specific category should be used.
12
- '''
13
- key:str
14
- '''The category key, e.g. "-MD"'''
15
- _segments: list[IDSegment] = PrivateAttr(default_factory=list)
16
-
17
-
18
- @computed_field
19
- @property
20
- def segments(self) -> list[IDSegment]:
21
- return self._segments
22
-
23
- def __init__(self, **data: Any):
24
- '''@private'''
25
- # Pop the user-provided value for computed segments
26
- input_segments = data.pop("segments", None)
27
- super().__init__(**data)
28
- self._segments = input_segments
29
-
30
- @model_validator(mode='after')
31
- def _warn_unusual_category_key(self):
32
- ''' this base class is instantiated only if the key is not a known category key'''
33
- if type(self) is Category:
34
- self._add_validation_message(
35
- source=f"Category {self.key}",
36
- level = ValidationMsgLevel.RECOMMENDATION,
37
- msg=f'Category key {self.key} is not a well known key. It is recommended to use well known keys only',
38
- highlight_pattern = f"{self.key}"
39
- )
40
- return self
41
-
42
-
43
- def __str__(self):
44
- 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)])
45
- return s
46
-
47
-
48
-
49
-
50
-
51
-
1
+
2
+ from typing import Any
3
+ from pydantic import PrivateAttr, computed_field, model_validator
4
+ from labfreed.labfreed_infrastructure import LabFREED_BaseModel, ValidationMsgLevel
5
+ from labfreed.pac_id.id_segment import IDSegment
6
+
7
+
8
+ class Category(LabFREED_BaseModel):
9
+ '''
10
+ Represents a category. \n
11
+ This is the base class for categories. If possible a more specific category should be used.
12
+ '''
13
+ key:str
14
+ '''The category key, e.g. "-MD"'''
15
+ _segments: list[IDSegment] = PrivateAttr(default_factory=list)
16
+
17
+
18
+ @computed_field
19
+ @property
20
+ def segments(self) -> list[IDSegment]:
21
+ return self._segments
22
+
23
+ def __init__(self, **data: Any):
24
+ '''@private'''
25
+ # Pop the user-provided value for computed segments
26
+ input_segments = data.pop("segments", None)
27
+ super().__init__(**data)
28
+ self._segments = input_segments
29
+
30
+ @model_validator(mode='after')
31
+ def _warn_unusual_category_key(self):
32
+ ''' this base class is instantiated only if the key is not a known category key'''
33
+ if type(self) is Category:
34
+ self._add_validation_message(
35
+ source=f"Category {self.key}",
36
+ level = ValidationMsgLevel.RECOMMENDATION,
37
+ msg=f'Category key {self.key} is not a well known key. It is recommended to use well known keys only',
38
+ highlight_pattern = f"{self.key}"
39
+ )
40
+ return self
41
+
42
+
43
+ def __str__(self):
44
+ 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)])
45
+ return s
46
+
47
+
48
+
49
+
50
+
51
+
@@ -1,150 +1,150 @@
1
- from __future__ import annotations # optional in 3.11, but recommended for consistency
2
-
3
- from typing import Self
4
- from pydantic import computed_field, model_validator
5
-
6
- from rich import print
7
- from rich.text import Text
8
- from rich.table import Table
9
-
10
- from labfreed.labfreed_infrastructure import ValidationMsgLevel
11
-
12
- from labfreed.pac_cat.category_base import Category
13
- from labfreed.pac_cat.predefined_categories import category_key_to_class_map
14
- from labfreed.pac_id.id_segment import IDSegment
15
- from labfreed.pac_id.pac_id import PAC_ID
16
-
17
- ''' Configure pdoc'''
18
-
19
-
20
- class PAC_CAT(PAC_ID):
21
- '''
22
- Extends a PAC-ID with interpretation of the identifier as categories
23
- '''
24
- @computed_field
25
- @property
26
- def categories(self) -> list[Category]:
27
- '''The categories present in the PAC-ID's identifier'''
28
- category_segments = self._split_segments_by_category(self.identifier)
29
- categories = list()
30
- for c in category_segments:
31
- categories.append(self._cat_from_cat_segments(c))
32
- return categories
33
-
34
-
35
-
36
- def get_category(self, key) -> Category:
37
- """Helper to get a category by key
38
- """
39
- tmp = [c for c in self.categories if c.key == key]
40
- if not tmp:
41
- return None
42
- return tmp[0]
43
-
44
-
45
- @classmethod
46
- def from_categories(cls, issuer:str, categories:list[Category]) -> PAC_CAT:
47
- identifier = list()
48
- for category in categories:
49
- identifier.append(IDSegment(value=category.key))
50
- identifier.extend(category.segments)
51
- return PAC_CAT(issuer=issuer, identifier=identifier)
52
-
53
-
54
- @classmethod
55
- def from_pac_id(cls, pac_id:PAC_ID) -> Self:
56
- '''Constructs a PAC-CAT from a PAC-ID'''
57
- return PAC_CAT(issuer=pac_id.issuer, identifier=pac_id.identifier)
58
-
59
-
60
-
61
- def to_pac_id(self) -> PAC_ID:
62
- return PAC_ID(issuer=self.issuer, identifier=self.identifier)
63
-
64
-
65
- @classmethod
66
- def _cat_from_cat_segments(cls, segments:list[IDSegment]) -> Category:
67
- segments = segments.copy()
68
- category_key = segments[0].value
69
- segments.pop(0)
70
-
71
- known_cat = category_key_to_class_map.get(category_key)
72
-
73
- if not known_cat:
74
- return Category(key=category_key, segments=segments)
75
-
76
- # implicit segment keys
77
- model_dict = {v.alias: None for k, v in known_cat.model_fields.items() if v.alias and k not in ['key','additional_segments']}
78
- for k, seg in zip(model_dict.keys(), segments.copy()):
79
- if seg.key:
80
- break
81
- model_dict[k] = seg.value
82
- segments.pop(0)
83
-
84
- # try to fill model keys if not already set
85
- for s in segments.copy():
86
- if s.key in model_dict.keys() and not model_dict.get(s.key):
87
- model_dict[s.key] = s.value
88
- segments.remove(s)
89
-
90
- model_dict['additional_segments'] = segments
91
- model_dict['key'] = category_key
92
- cat= known_cat(**model_dict)
93
- return cat
94
-
95
- @staticmethod
96
- def _split_segments_by_category(segments:list[IDSegment]) -> list[list[IDSegment]]:
97
- category_segments = list()
98
- c = list()
99
- for s in segments:
100
- # new category starts with "-"
101
- if s.value[0] == '-':
102
- c = [s]
103
- category_segments.append(c)
104
- else:
105
- c.append(s)
106
-
107
- # first cat can be empty > remove
108
- category_segments = [c for c in category_segments if len(c) > 0]
109
-
110
- return category_segments
111
-
112
-
113
- @model_validator(mode='after')
114
- def _check_keys_are_unique_in_each_category(self) -> Self:
115
- for c in self.categories:
116
- keys = [s.key for s in c.segments if s.key]
117
- duplicate_keys = [k for k in set(keys) if keys.count(k) > 1]
118
- if duplicate_keys:
119
- for k in duplicate_keys:
120
- self._add_validation_message(
121
- source=f"identifier {k}",
122
- level = ValidationMsgLevel.ERROR,
123
- msg=f"Duplicate key {k} in category {c.key}",
124
- highlight_pattern = k
125
- )
126
- return self
127
-
128
- def print_categories(self):
129
- table = Table(title=f'Categories in {str(self)}', show_header=False)
130
- table.add_column('0')
131
- table.add_column('1')
132
- for i, c in enumerate(self.categories):
133
- if i == 0:
134
- title = Text('Main Category', style='bold')
135
- else:
136
- title = Text('Category', style='bold')
137
-
138
- table.add_row(title)
139
-
140
- for field_name, field_info in c.model_fields.items():
141
- if not getattr(c, field_name):
142
- continue
143
- table.add_row(f"{field_name} ({field_info.alias or ''})",
144
- f" {getattr(c, field_name)}"
145
- )
146
- table.add_section()
147
- print(table)
148
-
149
-
150
-
1
+ from __future__ import annotations # optional in 3.11, but recommended for consistency
2
+
3
+ from typing import Self
4
+ from pydantic import computed_field, model_validator
5
+
6
+ from rich import print
7
+ from rich.text import Text
8
+ from rich.table import Table
9
+
10
+ from labfreed.labfreed_infrastructure import ValidationMsgLevel
11
+
12
+ from labfreed.pac_cat.category_base import Category
13
+ from labfreed.pac_cat.predefined_categories import category_key_to_class_map
14
+ from labfreed.pac_id.id_segment import IDSegment
15
+ from labfreed.pac_id.pac_id import PAC_ID
16
+
17
+ ''' Configure pdoc'''
18
+
19
+
20
+ class PAC_CAT(PAC_ID):
21
+ '''
22
+ Extends a PAC-ID with interpretation of the identifier as categories
23
+ '''
24
+ @computed_field
25
+ @property
26
+ def categories(self) -> list[Category]:
27
+ '''The categories present in the PAC-ID's identifier'''
28
+ category_segments = self._split_segments_by_category(self.identifier)
29
+ categories = list()
30
+ for c in category_segments:
31
+ categories.append(self._cat_from_cat_segments(c))
32
+ return categories
33
+
34
+
35
+
36
+ def get_category(self, key) -> Category:
37
+ """Helper to get a category by key
38
+ """
39
+ tmp = [c for c in self.categories if c.key == key]
40
+ if not tmp:
41
+ return None
42
+ return tmp[0]
43
+
44
+
45
+ @classmethod
46
+ def from_categories(cls, issuer:str, categories:list[Category]) -> PAC_CAT:
47
+ identifier = list()
48
+ for category in categories:
49
+ identifier.append(IDSegment(value=category.key))
50
+ identifier.extend(category.segments)
51
+ return PAC_CAT(issuer=issuer, identifier=identifier)
52
+
53
+
54
+ @classmethod
55
+ def from_pac_id(cls, pac_id:PAC_ID) -> Self:
56
+ '''Constructs a PAC-CAT from a PAC-ID'''
57
+ return PAC_CAT(issuer=pac_id.issuer, identifier=pac_id.identifier)
58
+
59
+
60
+
61
+ def to_pac_id(self) -> PAC_ID:
62
+ return PAC_ID(issuer=self.issuer, identifier=self.identifier)
63
+
64
+
65
+ @classmethod
66
+ def _cat_from_cat_segments(cls, segments:list[IDSegment]) -> Category:
67
+ segments = segments.copy()
68
+ category_key = segments[0].value
69
+ segments.pop(0)
70
+
71
+ known_cat = category_key_to_class_map.get(category_key)
72
+
73
+ if not known_cat:
74
+ return Category(key=category_key, segments=segments)
75
+
76
+ # implicit segment keys
77
+ model_dict = {v.alias: None for k, v in known_cat.model_fields.items() if v.alias and k not in ['key','additional_segments']}
78
+ for k, seg in zip(model_dict.keys(), segments.copy()):
79
+ if seg.key:
80
+ break
81
+ model_dict[k] = seg.value
82
+ segments.pop(0)
83
+
84
+ # try to fill model keys if not already set
85
+ for s in segments.copy():
86
+ if s.key in model_dict.keys() and not model_dict.get(s.key):
87
+ model_dict[s.key] = s.value
88
+ segments.remove(s)
89
+
90
+ model_dict['additional_segments'] = segments
91
+ model_dict['key'] = category_key
92
+ cat= known_cat(**model_dict)
93
+ return cat
94
+
95
+ @staticmethod
96
+ def _split_segments_by_category(segments:list[IDSegment]) -> list[list[IDSegment]]:
97
+ category_segments = list()
98
+ c = list()
99
+ for s in segments:
100
+ # new category starts with "-"
101
+ if s.value[0] == '-':
102
+ c = [s]
103
+ category_segments.append(c)
104
+ else:
105
+ c.append(s)
106
+
107
+ # first cat can be empty > remove
108
+ category_segments = [c for c in category_segments if len(c) > 0]
109
+
110
+ return category_segments
111
+
112
+
113
+ @model_validator(mode='after')
114
+ def _check_keys_are_unique_in_each_category(self) -> Self:
115
+ for c in self.categories:
116
+ keys = [s.key for s in c.segments if s.key]
117
+ duplicate_keys = [k for k in set(keys) if keys.count(k) > 1]
118
+ if duplicate_keys:
119
+ for k in duplicate_keys:
120
+ self._add_validation_message(
121
+ source=f"identifier {k}",
122
+ level = ValidationMsgLevel.ERROR,
123
+ msg=f"Duplicate key {k} in category {c.key}",
124
+ highlight_pattern = k
125
+ )
126
+ return self
127
+
128
+ def print_categories(self):
129
+ table = Table(title=f'Categories in {str(self)}', show_header=False)
130
+ table.add_column('0')
131
+ table.add_column('1')
132
+ for i, c in enumerate(self.categories):
133
+ if i == 0:
134
+ title = Text('Main Category', style='bold')
135
+ else:
136
+ title = Text('Category', style='bold')
137
+
138
+ table.add_row(title)
139
+
140
+ for field_name, field_info in c.model_fields.items():
141
+ if not getattr(c, field_name):
142
+ continue
143
+ table.add_row(f"{field_name} ({field_info.alias or ''})",
144
+ f" {getattr(c, field_name)}"
145
+ )
146
+ table.add_section()
147
+ print(table)
148
+
149
+
150
+