labfreed 0.2.5a22__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 -85
  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.5a22.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.5a22.dist-info → labfreed-0.2.6.dist-info}/licenses/LICENSE +21 -21
  43. labfreed-0.2.5a22.dist-info/RECORD +0 -44
  44. {labfreed-0.2.5a22.dist-info → labfreed-0.2.6.dist-info}/WHEEL +0 -0
@@ -1,85 +1,97 @@
1
- import logging
2
- from typing import Self
3
- import yaml
4
- from requests import get
5
-
6
-
7
-
8
- from labfreed.pac_cat.pac_cat import PAC_CAT
9
- from labfreed.pac_id.pac_id import PAC_ID
10
- from labfreed.pac_id_resolver.services import ServiceGroup
11
- from labfreed.pac_id_resolver.cit_v1 import CIT_v1
12
- from labfreed.pac_id_resolver.cit_v2 import CIT_v2
13
-
14
-
15
-
16
- ''' Configure pdoc'''
17
- __all__ = ["PAC_ID_Resolver"]
18
-
19
- def load_cit(path):
20
- with open(path, 'r') as f:
21
- s = f.read()
22
- return _cit_from_str(s)
23
-
24
-
25
- def _cit_from_str(s:str, issuer:str='') -> CIT_v1|CIT_v2:
26
- try:
27
- cit_yml= yaml.safe_load(s)
28
- cit2 = CIT_v2.from_yaml(cit_yml)
29
- except Exception:
30
- cit2 = None
31
-
32
- try:
33
- cit1 = CIT_v1.from_csv(s, issuer)
34
- except Exception:
35
- cit1 = None
36
-
37
- cit = cit2 or cit1 or None
38
- return cit
39
-
40
- def _get_issuer_cit(issuer:str):
41
- '''Gets the issuer's cit.'''
42
- url = 'HTTPS://PAC.' + issuer + '/coupling-information-table'
43
- try:
44
- r = get(url, timeout=2)
45
- if r.status_code < 400:
46
- cit_str = r.text
47
- else:
48
- logging.error(f"Could not get CIT form {issuer}")
49
- cit_str = None
50
- except Exception:
51
- logging.error(f"Could not get CIT form {issuer}")
52
- cit_str = None
53
- cit = _cit_from_str(cit_str, issuer=issuer)
54
- return cit
55
-
56
-
57
-
58
- class PAC_ID_Resolver():
59
- def __init__(self, cits:list[CIT_v2|CIT_v1]=None) -> Self:
60
- '''Initialize the resolver with coupling information tables'''
61
- if not cits:
62
- cits = []
63
- self._cits = cits
64
-
65
-
66
- def resolve(self, pac_id:PAC_ID|str, check_service_status=True) -> list[ServiceGroup]:
67
- '''Resolve a PAC-ID'''
68
- if isinstance(pac_id, str):
69
- pac_id = PAC_CAT.from_url(pac_id)
70
-
71
- if issuer_cit := _get_issuer_cit(pac_id.issuer):
72
- self._cits.append(issuer_cit)
73
-
74
- matches = [cit.evaluate_pac_id(pac_id) for cit in self._cits]
75
-
76
- if check_service_status:
77
- for m in matches:
78
- m.update_states()
79
- return matches
80
-
81
-
82
-
83
- if __name__ == '__main__':
84
- r = PAC_ID_Resolver()
85
- r.resolve()
1
+ from functools import lru_cache
2
+ import logging
3
+ import traceback
4
+ from typing import Self
5
+ import yaml
6
+ from requests import get
7
+
8
+
9
+
10
+ from labfreed.pac_cat.pac_cat import PAC_CAT
11
+ from labfreed.pac_id.pac_id import PAC_ID
12
+ from labfreed.pac_id_resolver.services import ServiceGroup
13
+ from labfreed.pac_id_resolver.cit_v1 import CIT_v1
14
+ from labfreed.pac_id_resolver.cit_v2 import CIT_v2
15
+
16
+
17
+
18
+ ''' Configure pdoc'''
19
+ __all__ = ["PAC_ID_Resolver"]
20
+
21
+ def load_cit(path):
22
+ with open(path, 'r') as f:
23
+ s = f.read()
24
+ return cit_from_str(s)
25
+
26
+
27
+ def cit_from_str(s:str, origin:str='') -> CIT_v1|CIT_v2:
28
+ try:
29
+ cit2 = CIT_v2.from_yaml(s)
30
+ cit_version = 'v2'
31
+ except Exception:
32
+ cit2 = None
33
+ try:
34
+ cit1 = CIT_v1.from_csv(s, origin)
35
+ cit_version = 'v1'
36
+ except Exception:
37
+ cit1 = None
38
+
39
+ cit = cit2 or cit1 or None
40
+ return cit
41
+
42
+ @lru_cache
43
+ def _get_issuer_cit(issuer:str):
44
+ '''Gets the issuer's cit.'''
45
+ url = 'HTTPS://PAC.' + issuer + '/coupling-information-table'
46
+ try:
47
+ r = get(url, timeout=2)
48
+ if r.status_code < 400:
49
+ cit_str = r.text
50
+ else:
51
+ logging.error(f"Could not get CIT form {issuer}")
52
+ cit_str = None
53
+ except Exception:
54
+ logging.error(f"Could not get CIT form {issuer}")
55
+ cit_str = None
56
+ cit = cit_from_str(cit_str, origin=issuer)
57
+ return cit
58
+
59
+
60
+
61
+ class PAC_ID_Resolver():
62
+ def __init__(self, cits:list[CIT_v2|CIT_v1]=None) -> Self:
63
+ '''Initialize the resolver with coupling information tables'''
64
+ if not cits:
65
+ cits = []
66
+ self._cits = cits
67
+
68
+
69
+ def resolve(self, pac_url:PAC_ID|str, check_service_status=True, use_issuer_cit=True) -> list[ServiceGroup]:
70
+ '''Resolve a PAC-ID'''
71
+ if isinstance(pac_url, str):
72
+ pac_id = PAC_CAT.from_url(pac_url)
73
+ pac_id_catless = PAC_ID.from_url(pac_url, try_pac_cat=False)
74
+
75
+ cits = self._cits.copy()
76
+ if use_issuer_cit:
77
+ if issuer_cit := _get_issuer_cit(pac_id.issuer):
78
+ cits.append(issuer_cit)
79
+
80
+ matches = []
81
+ for cit in cits:
82
+ if isinstance(cit, CIT_v1):
83
+ # cit v1 has no concept of categories and implied keys. It would treat these segments as value segment
84
+ matches.append(cit.evaluate_pac_id(pac_id_catless))
85
+ else:
86
+ matches.append(cit.evaluate_pac_id(pac_id))
87
+
88
+ if check_service_status:
89
+ for m in matches:
90
+ m.update_states()
91
+ return matches
92
+
93
+
94
+
95
+ if __name__ == '__main__':
96
+ r = PAC_ID_Resolver()
97
+ r.resolve()
@@ -1,80 +1,80 @@
1
-
2
- from enum import auto, Enum
3
-
4
- from pydantic import Field
5
- from requests import RequestException, get, head
6
-
7
- from concurrent.futures import ThreadPoolExecutor, as_completed
8
-
9
- from rich import print
10
- from rich.table import Table
11
-
12
- from labfreed.labfreed_infrastructure import LabFREED_BaseModel
13
-
14
-
15
- class ServiceStatus(Enum):
16
- ACTIVE = auto()
17
- INACTIVE = auto()
18
- UNKNOWN = auto()
19
-
20
- class Service(LabFREED_BaseModel):
21
- service_name: str
22
- application_intents:list[str]
23
- service_type:str
24
- url:str
25
- status:ServiceStatus =ServiceStatus.UNKNOWN
26
-
27
- def check_service_status(self):
28
- '''Checks the availability of the service.'''
29
- try:
30
- r = head(self.url, timeout=2)
31
- if r.status_code < 400:
32
- self.status = ServiceStatus.ACTIVE
33
- else:
34
- self.status = ServiceStatus.INACTIVE
35
- except RequestException as e:
36
- print(f"Request failed: {e}")
37
- self.status = ServiceStatus.INACTIVE
38
-
39
-
40
- class ServiceGroup(LabFREED_BaseModel):
41
- """ Services with common origin. The result of resolving a PAC-ID against a CIT"""
42
- origin: str = ""
43
- services: list[Service] = Field(default_factory=list)
44
-
45
- def update_states(self):
46
- '''Triggers each service to check if the url can be reached'''
47
- if not _has_internet_connection():
48
- raise ConnectionError("No Internet Connection")
49
- with ThreadPoolExecutor(max_workers=10) as executor:
50
- futures = [executor.submit(s.check_service_status) for s in self.services]
51
- for _ in as_completed(futures):
52
- pass # just wait for all to finish
53
-
54
-
55
-
56
- def __str__(self):
57
- out = [f'CIT (origin {self.origin})']
58
- for s in self.services:
59
- out.append(f'{s.service_name}\t\t\t{s.url}')
60
- return '\n'.join(out)
61
-
62
- def print(self):
63
- table = Table(title=f"Services from origin '{self.origin}")
64
-
65
- table.add_column("Service Name")
66
- table.add_column("URL")
67
- table.add_column('Reachable')
68
-
69
- for s in self.services:
70
- table.add_row(s.service_name, s.url, s.status.name)
71
-
72
- print(table)
73
-
74
-
75
- def _has_internet_connection():
76
- try:
77
- get("https://1.1.1.1", timeout=3)
78
- return True
79
- except RequestException:
1
+
2
+ from enum import auto, Enum
3
+
4
+ from pydantic import Field
5
+ from requests import RequestException, get, head
6
+
7
+ from concurrent.futures import ThreadPoolExecutor, as_completed
8
+
9
+ from rich import print
10
+ from rich.table import Table
11
+
12
+ from labfreed.labfreed_infrastructure import LabFREED_BaseModel
13
+
14
+
15
+ class ServiceStatus(Enum):
16
+ ACTIVE = auto()
17
+ INACTIVE = auto()
18
+ UNKNOWN = auto()
19
+
20
+ class Service(LabFREED_BaseModel):
21
+ service_name: str
22
+ application_intents:list[str]
23
+ service_type:str
24
+ url:str
25
+ status:ServiceStatus =ServiceStatus.UNKNOWN
26
+
27
+ def check_service_status(self):
28
+ '''Checks the availability of the service.'''
29
+ try:
30
+ r = head(self.url, timeout=2)
31
+ if r.status_code < 400:
32
+ self.status = ServiceStatus.ACTIVE
33
+ else:
34
+ self.status = ServiceStatus.INACTIVE
35
+ except RequestException as e:
36
+ print(f"Request failed: {e}")
37
+ self.status = ServiceStatus.INACTIVE
38
+
39
+
40
+ class ServiceGroup(LabFREED_BaseModel):
41
+ """ Services with common origin. The result of resolving a PAC-ID against a CIT"""
42
+ origin: str = ""
43
+ services: list[Service] = Field(default_factory=list)
44
+
45
+ def update_states(self):
46
+ '''Triggers each service to check if the url can be reached'''
47
+ if not _has_internet_connection():
48
+ raise ConnectionError("No Internet Connection")
49
+ with ThreadPoolExecutor(max_workers=10) as executor:
50
+ futures = [executor.submit(s.check_service_status) for s in self.services]
51
+ for _ in as_completed(futures):
52
+ pass # just wait for all to finish
53
+
54
+
55
+
56
+ def __str__(self):
57
+ out = [f'CIT (origin {self.origin})']
58
+ for s in self.services:
59
+ out.append(f'{s.service_name}\t\t\t{s.url}')
60
+ return '\n'.join(out)
61
+
62
+ def print(self):
63
+ table = Table(title=f"Services from origin '{self.origin}")
64
+
65
+ table.add_column("Service Name")
66
+ table.add_column("URL")
67
+ table.add_column('Reachable')
68
+
69
+ for s in self.services:
70
+ table.add_row(s.service_name, s.url, s.status.name)
71
+
72
+ print(table)
73
+
74
+
75
+ def _has_internet_connection():
76
+ try:
77
+ get("https://1.1.1.1", timeout=3)
78
+ return True
79
+ except RequestException:
80
80
  return False
labfreed/qr/__init__.py CHANGED
@@ -1 +1 @@
1
- from .generate_qr import save_qr_with_markers # noqa: F401
1
+ from .generate_qr import save_qr_with_markers # noqa: F401