labfreed 1.0.0a7__tar.gz → 1.0.0a9__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.
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/PKG-INFO +1 -1
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/__init__.py +1 -1
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_extended/app/app_infrastructure.py +1 -1
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_extended/app/pac_info/pac_info.py +14 -6
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/client/attribute_cache.py +2 -2
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/client/client.py +2 -2
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/pythonic/attribute_server_factory.py +2 -2
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/server/attribute_data_sources.py +5 -2
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/server/server.py +9 -7
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/.github/workflows/pypi-publish.yml +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/.github/workflows/run-tests.yml +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/CHANGELOG.md +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/LICENSE +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/README.md +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_extended/app/formatted_print.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_extended/app/pac_info/html_renderer/external-link.svg +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_extended/app/pac_info/html_renderer/macros.jinja.html +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_extended/app/pac_info/html_renderer/pac-info-style.css +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_extended/app/pac_info/html_renderer/pac_info.jinja.html +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_extended/app/pac_info/html_renderer/pac_info_card.jinja.html +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/labfreed_infrastructure.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/api_data_models/request.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/api_data_models/response.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/api_data_models/server_capabilities_response.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/client/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/pythonic/excel_attribute_data_source.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/pythonic/py_attributes.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/pythonic/py_dict_data_source.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/server/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/server/translation_data_sources.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/well_knonw_attribute_keys.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_cat/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_cat/category_base.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_cat/pac_cat.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_cat/predefined_categories.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id/extension.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id/id_segment.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id/pac_id.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id/url_parser.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id/url_serializer.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id_resolver/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id_resolver/cit_common.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id_resolver/cit_v1.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id_resolver/cit_v2.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id_resolver/resolver.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_id_resolver/services.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/qr/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/qr/generate_qr.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/pythonic/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/pythonic/data_table.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/pythonic/pyTREX.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/pythonic/quantity.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/table_segment.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/trex.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/trex_base_models.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/trex/value_segments.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/utilities/base36.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/utilities/ensure_utc_time.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/utilities/translations.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_extensions/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_extensions/default_extension_interpreters.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_extensions/display_name_extension.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_extensions/trex_extension.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_keys/gs1/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_keys/gs1/gs1_ai_enum_sorted.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_keys/labfreed/well_known_keys.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_keys/unece/UneceUnits.json +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_keys/unece/__init__.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_keys/unece/unece_units.py +0 -0
- {labfreed-1.0.0a7 → labfreed-1.0.0a9}/pyproject.toml +0 -0
|
@@ -71,7 +71,7 @@ class Labfreed_App_Infrastructure():
|
|
|
71
71
|
ags = {ag.key: pyAttributeGroup.from_attribute_group(ag) for ag in self._attribute_client.get_attributes(url, pac_id=pac.to_url(include_extensions=False), language_preferences=self._language_preferences)}
|
|
72
72
|
if ags:
|
|
73
73
|
attribute_groups.update(ags)
|
|
74
|
-
pac_info.
|
|
74
|
+
pac_info.attribute_groups = attribute_groups
|
|
75
75
|
|
|
76
76
|
return pac_info
|
|
77
77
|
|
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
from urllib.parse import urlparse
|
|
6
6
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|
7
7
|
from pydantic import BaseModel, Field
|
|
8
|
-
from labfreed.pac_attributes.pythonic.py_attributes import pyAttribute, pyAttributeGroup, pyAttributes, pyReference
|
|
8
|
+
from labfreed.pac_attributes.pythonic.py_attributes import pyAttribute, pyAttributeGroup, pyAttributes, pyReference, pyResource
|
|
9
9
|
from labfreed.pac_attributes.well_knonw_attribute_keys import MetaAttributeKeys
|
|
10
10
|
from labfreed.pac_cat.pac_cat import PAC_CAT
|
|
11
11
|
from labfreed.pac_id.pac_id import PAC_ID
|
|
@@ -20,7 +20,7 @@ class PacInfo(BaseModel):
|
|
|
20
20
|
"""A convenient collection of information about a PAC-ID"""
|
|
21
21
|
pac_id:PAC_ID
|
|
22
22
|
user_handovers: list[ServiceGroup] = Field(default_factory=list)
|
|
23
|
-
|
|
23
|
+
attribute_groups:dict[str, pyAttributeGroup] = Field(default_factory=dict)
|
|
24
24
|
|
|
25
25
|
@property
|
|
26
26
|
def pac_url(self):
|
|
@@ -44,8 +44,10 @@ class PacInfo(BaseModel):
|
|
|
44
44
|
|
|
45
45
|
@property
|
|
46
46
|
def image_url(self) -> str:
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
image_attr = self._all_attributes.get(MetaAttributeKeys.IMAGE.value)
|
|
48
|
+
if isinstance(image_attr.value, pyResource):
|
|
49
|
+
return image_attr.value.root
|
|
50
|
+
if isinstance(image_attr.value, str):
|
|
49
51
|
return image_attr.value
|
|
50
52
|
|
|
51
53
|
|
|
@@ -68,12 +70,18 @@ class PacInfo(BaseModel):
|
|
|
68
70
|
def safety_pictograms(self) -> dict[str, pyAttribute]:
|
|
69
71
|
pictogram_attributes = {k: a for k, a in self._all_attributes.items() if "https://labfreed.org/ghs/pictogram/" in a.key}
|
|
70
72
|
return pictogram_attributes
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def qualification_state(self) -> pyAttribute:
|
|
77
|
+
if state := self._all_attributes.get("https://labfreed.org/qualification/status"):
|
|
78
|
+
return state
|
|
71
79
|
|
|
72
80
|
|
|
73
81
|
@cached_property
|
|
74
82
|
def _all_attributes(self) -> dict[str, pyAttribute]:
|
|
75
83
|
out = {}
|
|
76
|
-
for ag in self.
|
|
84
|
+
for ag in self.attribute_groups.values():
|
|
77
85
|
out.update(ag.attributes)
|
|
78
86
|
return out
|
|
79
87
|
|
|
@@ -105,7 +113,7 @@ class PacInfo(BaseModel):
|
|
|
105
113
|
|
|
106
114
|
|
|
107
115
|
printout.title1("Attributes")
|
|
108
|
-
for ag in self.
|
|
116
|
+
for ag in self.attribute_groups.values():
|
|
109
117
|
printout.title2(f'{ag.label} (from {ag.origin})')
|
|
110
118
|
for v in ag.attributes.values():
|
|
111
119
|
v:pyAttribute
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
from datetime import datetime, timedelta
|
|
3
|
+
from datetime import UTC, datetime, timedelta
|
|
4
4
|
from typing import Literal, Protocol
|
|
5
5
|
|
|
6
6
|
|
|
@@ -18,7 +18,7 @@ class CacheableAttributeGroup(AttributeGroup):
|
|
|
18
18
|
if self.value_from is None:
|
|
19
19
|
return False
|
|
20
20
|
else:
|
|
21
|
-
return ( datetime.now() - timedelta(
|
|
21
|
+
return ( datetime.now(tz=UTC) - timedelta(minutes=accept_cache_for_minutes)) > self.value_from
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from datetime import datetime
|
|
4
|
+
from datetime import UTC, datetime
|
|
5
5
|
from typing import Protocol, runtime_checkable
|
|
6
6
|
|
|
7
7
|
import requests
|
|
@@ -156,7 +156,7 @@ class AttributeClient():
|
|
|
156
156
|
origin=server_url,
|
|
157
157
|
language=r.language,
|
|
158
158
|
label=ag.label,
|
|
159
|
-
value_from=datetime.now(tz=
|
|
159
|
+
value_from=datetime.now(tz=UTC))
|
|
160
160
|
for ag in ag_for_pac.attribute_groups
|
|
161
161
|
]
|
|
162
162
|
self.cache_store.update(server_url, pac_from_response, ags)
|
{labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/pythonic/attribute_server_factory.py
RENAMED
|
@@ -93,7 +93,7 @@ class AttributeFlaskApp(Flask):
|
|
|
93
93
|
def capabilities():
|
|
94
94
|
doc_text = current_app.config.get('DOC_TEXT', "")
|
|
95
95
|
capabilities = request_handler.capabilities()
|
|
96
|
-
authentication_required = bool(current_app.config
|
|
96
|
+
authentication_required = bool(current_app.config.get('AUTHENTICATOR'))
|
|
97
97
|
example_request = AttributeRequestPayload(pac_ids=['HTTPS://PAC.METTORIUS.COM/EXAMPLE'], language_preferences=['fr', 'de']).model_dump_json(indent=2, exclude_none=True, exclude_unset=True)
|
|
98
98
|
server_address = request.url.rstrip('/')
|
|
99
99
|
response = f'''
|
|
@@ -109,7 +109,7 @@ class AttributeFlaskApp(Flask):
|
|
|
109
109
|
<h2>How to use</h2>
|
|
110
110
|
Make a <b>POST</b> request to <a href="{server_address}">{server_address}</a> with the following body:
|
|
111
111
|
<pre>{example_request}</pre>
|
|
112
|
-
Consult
|
|
112
|
+
Consult <a href="https://github.com/ApiniLabs/PAC-Attributes"> the specification </a> for details. <br>
|
|
113
113
|
|
|
114
114
|
|
|
115
115
|
{'This server <b> requires authentication </b> ' if authentication_required else ''}
|
{labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/server/attribute_data_sources.py
RENAMED
|
@@ -31,12 +31,13 @@ class AttributeGroupDataSource(ABC):
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class Dict_DataSource(AttributeGroupDataSource):
|
|
34
|
-
def __init__(self, data:dict[str, list[AttributeBase]], uses_pac_cat_short_form=True, *args, **kwargs):
|
|
34
|
+
def __init__(self, data:dict[str, list[AttributeBase]], uses_pac_cat_short_form=True, pac_to_key: callable = None, *args, **kwargs):
|
|
35
35
|
if not all([isinstance(e, list) for e in data.values()]):
|
|
36
36
|
raise ValueError('Invalid data')
|
|
37
37
|
|
|
38
38
|
self._data = data
|
|
39
39
|
self.uses_pac_cat_short_form = uses_pac_cat_short_form
|
|
40
|
+
self._pac_to_key = pac_to_key
|
|
40
41
|
|
|
41
42
|
super().__init__(*args, **kwargs)
|
|
42
43
|
|
|
@@ -53,7 +54,9 @@ class Dict_DataSource(AttributeGroupDataSource):
|
|
|
53
54
|
except:
|
|
54
55
|
... # might as well try to match the original input
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
|
|
58
|
+
lookup_key = self._pac_to_key(pac_url) if self._pac_to_key else pac_url
|
|
59
|
+
attributes = self._data.get(lookup_key)
|
|
57
60
|
if not attributes:
|
|
58
61
|
return None
|
|
59
62
|
|
|
@@ -134,20 +134,22 @@ class AttributeServerRequestHandler():
|
|
|
134
134
|
if dn := self._get_display_name_for_key(ag.key, language):
|
|
135
135
|
ag.label = dn
|
|
136
136
|
else:
|
|
137
|
-
ag.label =
|
|
138
|
-
re.sub(r'([a-z])([A-Z])', r'\1 \2',
|
|
139
|
-
re.sub('-_', '',
|
|
140
|
-
ag.key.split('/')[-1])
|
|
141
|
-
)
|
|
142
|
-
)
|
|
137
|
+
ag.label = self.fallback_label(ag.key)
|
|
143
138
|
rich.print(f"[yellow]WARNING:[/yellow] No translation for '{ag.key}' in '{language}'. Falling back to '{ag.label}'")
|
|
144
139
|
for a in ag.attributes:
|
|
145
140
|
if dn := self._get_display_name_for_key(a.key, language):
|
|
146
141
|
a.label = dn
|
|
147
142
|
else:
|
|
148
|
-
a.label = a.key
|
|
143
|
+
a.label = self.fallback_label(a.key)
|
|
149
144
|
rich.print(f"[yellow]WARNING:[/yellow] No translation for '{a.key}' in '{language}'. Falling back to '{a.label}' ")
|
|
150
145
|
|
|
146
|
+
|
|
147
|
+
def fallback_label(self, key:str):
|
|
148
|
+
l = key.split('/')[-1]
|
|
149
|
+
l = re.sub(r'([a-z])([A-Z])', r'\1 \2', l)
|
|
150
|
+
l = re.sub(r'[-_]', ' ', l)
|
|
151
|
+
l = string.capwords(l)
|
|
152
|
+
return l
|
|
151
153
|
|
|
152
154
|
|
|
153
155
|
def _get_display_name_for_key(self, key, language:str):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/pythonic/py_dict_data_source.py
RENAMED
|
File without changes
|
|
File without changes
|
{labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/pac_attributes/server/translation_data_sources.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{labfreed-1.0.0a7 → labfreed-1.0.0a9}/labfreed/well_known_extensions/display_name_extension.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|