labfreed 0.1.0__tar.gz → 0.2.0__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.
Files changed (82) hide show
  1. labfreed-0.2.0/.github/workflows/pypi-publish.yml +78 -0
  2. labfreed-0.2.0/CHANGELOG.md +29 -0
  3. labfreed-0.2.0/PKG-INFO +357 -0
  4. labfreed-0.2.0/README.md +326 -0
  5. labfreed-0.2.0/labfreed/__init__.py +8 -0
  6. labfreed-0.2.0/labfreed/labfreed_infrastructure.py +276 -0
  7. labfreed-0.2.0/labfreed/pac_cat/__init__.py +17 -0
  8. labfreed-0.2.0/labfreed/pac_cat/category_base.py +51 -0
  9. labfreed-0.2.0/labfreed/pac_cat/pac_cat.py +159 -0
  10. labfreed-0.2.0/labfreed/pac_cat/predefined_categories.py +190 -0
  11. labfreed-0.2.0/labfreed/pac_id/__init__.py +19 -0
  12. labfreed-0.2.0/labfreed/pac_id/extension.py +48 -0
  13. labfreed-0.2.0/labfreed/pac_id/id_segment.py +90 -0
  14. labfreed-0.2.0/labfreed/pac_id/pac_id.py +140 -0
  15. labfreed-0.2.0/labfreed/pac_id/url_parser.py +154 -0
  16. labfreed-0.2.0/labfreed/pac_id/url_serializer.py +80 -0
  17. labfreed-0.2.0/labfreed/pac_id_resolver/__init__.py +2 -0
  18. labfreed-0.2.0/labfreed/pac_id_resolver/cit_v1.py +149 -0
  19. labfreed-0.1.0/labfreed/PAC_ID_Resolver/resolver.py → labfreed-0.2.0/labfreed/pac_id_resolver/cit_v2.py +134 -52
  20. labfreed-0.2.0/labfreed/pac_id_resolver/resolver.py +81 -0
  21. labfreed-0.2.0/labfreed/pac_id_resolver/services.py +80 -0
  22. labfreed-0.2.0/labfreed/qr/__init__.py +1 -0
  23. {labfreed-0.1.0/labfreed/IO → labfreed-0.2.0/labfreed/qr}/generate_qr.py +1 -4
  24. labfreed-0.2.0/labfreed/trex/__init__.py +16 -0
  25. labfreed-0.2.0/labfreed/trex/python_convenience/__init__.py +3 -0
  26. labfreed-0.2.0/labfreed/trex/python_convenience/data_table.py +45 -0
  27. labfreed-0.2.0/labfreed/trex/python_convenience/pyTREX.py +242 -0
  28. labfreed-0.2.0/labfreed/trex/python_convenience/quantity.py +46 -0
  29. labfreed-0.2.0/labfreed/trex/table_segment.py +227 -0
  30. labfreed-0.2.0/labfreed/trex/trex.py +69 -0
  31. labfreed-0.2.0/labfreed/trex/trex_base_models.py +336 -0
  32. labfreed-0.2.0/labfreed/trex/value_segments.py +111 -0
  33. labfreed-0.2.0/labfreed/well_known_extensions/__init__.py +5 -0
  34. labfreed-0.2.0/labfreed/well_known_extensions/default_extension_interpreters.py +7 -0
  35. labfreed-0.2.0/labfreed/well_known_extensions/display_name_extension.py +40 -0
  36. labfreed-0.2.0/labfreed/well_known_extensions/trex_extension.py +31 -0
  37. labfreed-0.2.0/labfreed/well_known_keys/gs1/__init__.py +6 -0
  38. labfreed-0.2.0/labfreed/well_known_keys/gs1/gs1.py +4 -0
  39. labfreed-0.2.0/labfreed/well_known_keys/gs1/gs1_ai_enum_sorted.py +57 -0
  40. labfreed-0.2.0/labfreed/well_known_keys/unece/__init__.py +4 -0
  41. labfreed-0.2.0/labfreed/well_known_keys/unece/unece_units.py +68 -0
  42. labfreed-0.2.0/pyproject.toml +59 -0
  43. labfreed-0.1.0/.vscode/launch.json +0 -38
  44. labfreed-0.1.0/.vscode/settings.json +0 -11
  45. labfreed-0.1.0/PKG-INFO +0 -266
  46. labfreed-0.1.0/README.md +0 -252
  47. labfreed-0.1.0/cit_mine.yaml +0 -22
  48. labfreed-0.1.0/examples.py +0 -147
  49. labfreed-0.1.0/labfreed/DisplayNameExtension/DisplayNameExtension.py +0 -37
  50. labfreed-0.1.0/labfreed/IO/parse_pac.py +0 -189
  51. labfreed-0.1.0/labfreed/PAC_CAT/__init__.py +0 -1
  52. labfreed-0.1.0/labfreed/PAC_CAT/data_model.py +0 -387
  53. labfreed-0.1.0/labfreed/PAC_ID/__init__.py +0 -0
  54. labfreed-0.1.0/labfreed/PAC_ID/data_model.py +0 -177
  55. labfreed-0.1.0/labfreed/PAC_ID/extensions.py +0 -52
  56. labfreed-0.1.0/labfreed/PAC_ID_Resolver/cit.yaml +0 -92
  57. labfreed-0.1.0/labfreed/PAC_ID_Resolver/data_types.py +0 -59
  58. labfreed-0.1.0/labfreed/TREX/data_model.py +0 -790
  59. labfreed-0.1.0/labfreed/TREX/parse.py +0 -60
  60. labfreed-0.1.0/labfreed/TREX/unece_units.py +0 -106
  61. labfreed-0.1.0/labfreed/__init__.py +0 -5
  62. labfreed-0.1.0/labfreed/utilities/utility_types.py +0 -73
  63. labfreed-0.1.0/labfreed/validation.py +0 -159
  64. labfreed-0.1.0/main.py +0 -82
  65. labfreed-0.1.0/publish.ps1 +0 -17
  66. labfreed-0.1.0/publish.sh +0 -18
  67. labfreed-0.1.0/publish_commands +0 -2
  68. labfreed-0.1.0/pyproject.toml +0 -27
  69. labfreed-0.1.0/pytest.ini +0 -2
  70. labfreed-0.1.0/tests/test_(de)_serialization_incl_extension/test__parse.py +0 -87
  71. labfreed-0.1.0/tests/test_(de)_serialization_incl_extension/test__serialize.py +0 -48
  72. labfreed-0.1.0/tests/test_PAC_CAT/test_PAC_CAT_parse.py +0 -145
  73. labfreed-0.1.0/tests/test_PAC_CAT/test_PAC_CAT_serialize.py +0 -111
  74. labfreed-0.1.0/tests/test_PAC_ID/test_PAC_ID_serialize.py +0 -15
  75. labfreed-0.1.0/tests/test_PAC_ID/test_pac_id_parse.py +0 -78
  76. labfreed-0.1.0/tests/test_TREX/test_TREX_parse.py +0 -293
  77. labfreed-0.1.0/tests/test_TREX/test_TREX_serialize.py +0 -29
  78. labfreed-0.1.0/update_readme.py +0 -93
  79. {labfreed-0.1.0 → labfreed-0.2.0}/LICENSE +0 -0
  80. {labfreed-0.1.0 → labfreed-0.2.0}/labfreed/utilities/base36.py +0 -0
  81. {labfreed-0.1.0/labfreed/utilities → labfreed-0.2.0/labfreed/well_known_keys/labfreed}/well_known_keys.py +0 -0
  82. {labfreed-0.1.0/labfreed/TREX → labfreed-0.2.0/labfreed/well_known_keys/unece}/UneceUnits.json +0 -0
@@ -0,0 +1,78 @@
1
+ # This workflow will upload a Python Package to PyPI when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
+
4
+ # This workflow uses actions that are not certified by GitHub.
5
+ # They are provided by a third-party and are governed by
6
+ # separate terms of service, privacy policy, and support
7
+ # documentation.
8
+
9
+ name: Upload Python Package
10
+
11
+ on:
12
+ release:
13
+ types: [published]
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ release-build:
20
+ runs-on: ubuntu-latest
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: "3.10"
28
+
29
+ - name: Install dependencies
30
+ run: |
31
+ python -m pip install --upgrade pip
32
+ pip install .[dev]
33
+
34
+ - name: Run Ruff linter
35
+ run: |
36
+ ruff check . || true
37
+
38
+ - name: Run tests
39
+ run: |
40
+ pytest tests
41
+
42
+ - name: Build release distributions
43
+ run: |
44
+ # NOTE: put your own distribution build steps here.
45
+ python -m pip install build
46
+ python -m build
47
+
48
+ - name: Upload distributions
49
+ uses: actions/upload-artifact@v4
50
+ with:
51
+ name: release-dists
52
+ path: dist/
53
+
54
+ pypi-publish:
55
+ runs-on: ubuntu-latest
56
+ needs:
57
+ - release-build
58
+ permissions:
59
+ # IMPORTANT: this permission is mandatory for trusted publishing
60
+ id-token: write
61
+
62
+ # Dedicated environments with protections for publishing are strongly recommended.
63
+ # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
64
+ environment:
65
+ name: pypi
66
+ url: https://pypi.org/project/labfreed/
67
+
68
+ steps:
69
+ - name: Retrieve release distributions
70
+ uses: actions/download-artifact@v4
71
+ with:
72
+ name: release-dists
73
+ path: dist/
74
+
75
+ - name: Publish release distributions to PyPI
76
+ uses: pypa/gh-action-pypi-publish@release/v1
77
+ with:
78
+ packages-dir: dist/
@@ -0,0 +1,29 @@
1
+ ## Change Log
2
+ ### v0.2.0b2
3
+ - improvements in api consistency and ease of use
4
+ - restructured code for better separation of concerns
5
+ - support for coupling information table v1
6
+
7
+ ### v0.1.1
8
+ - minor internal improvements and bugfixes
9
+
10
+ ### v0.1.0
11
+ - DRAFT Support for PAC-ID Resolver
12
+
13
+ ### v0.0.20
14
+ - bugfix in TREX table to dict conversion
15
+ - markdown compatible validation printing
16
+
17
+ ### v0.0.19
18
+ - supports PAC-ID, PAC-CAT, TREX and DisplayName
19
+ - QR generation
20
+ - ok-ish test coverage
21
+
22
+ # Attributions
23
+ The following tools were used:
24
+ - [pdoc](https://pdoc.dev/) was a great help with generating documentation
25
+ - [Pydantic](https://docs.pydantic.dev/latest/)
26
+ - json with UNECE units from (https://github.com/quadient/unece-units/blob/main/python/src/unece_excel_parser/parsedUneceUnits.json)
27
+ - json with GS1 codes from (https://ref.gs1.org/ai/GS1_Application_Identifiers.jsonld)
28
+
29
+
@@ -0,0 +1,357 @@
1
+ Metadata-Version: 2.4
2
+ Name: labfreed
3
+ Version: 0.2.0
4
+ Summary: Python implementation of LabFREED building blocks
5
+ Author-email: Reto Thürer <thuerer.r@buchi.com>
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Topic :: Scientific/Engineering
15
+ Classifier: Topic :: Utilities
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Science/Research
18
+ License-File: LICENSE
19
+ Requires-Dist: numpy>=2.2.4
20
+ Requires-Dist: pydantic>=2.11.3
21
+ Requires-Dist: segno>=1.6.6
22
+ Requires-Dist: typer>=0.15.2
23
+ Requires-Dist: PyYAML>=6.0.2
24
+ Requires-Dist: jsonpath-ng>=1.7.0
25
+ Requires-Dist: requests>=2.32.3
26
+ Requires-Dist: pytest>=8.3.5 ; extra == "dev"
27
+ Requires-Dist: pdoc>=15.0.1 ; extra == "dev"
28
+ Requires-Dist: flit>=3.12.0 ; extra == "dev"
29
+ Requires-Dist: ruff>=0.11.5 ; extra == "dev"
30
+ Provides-Extra: dev
31
+
32
+ # LabFREED for Python
33
+
34
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![PyPI](https://img.shields.io/pypi/v/labfreed.svg)](https://pypi.org/project/labfreed/) ![Python Version](https://img.shields.io/pypi/pyversions/labfreed)
35
+
36
+ <!--
37
+ [![Tests](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml/badge.svg)](https://github.com/retothuerer/LabFREED/actions/workflows/ci.yml)
38
+ -->
39
+
40
+ This is a Python implementation of [LabFREED](https://labfreed.wega-it.com) building blocks.
41
+
42
+ ## Supported Building Blocks
43
+ - PAC-ID
44
+ - Parsing
45
+ - Serialization
46
+ - PAC-CAT
47
+ - Interpretation of PAC-ID as categories
48
+ - T-REX
49
+ - Parsing
50
+ - Serialization
51
+ - Display Extension
52
+ - base36 <> str conversions
53
+ - PAC-ID Resolver
54
+ - support for CIT v1
55
+ - draft support for CIT v1 (improved version)
56
+ - combined use of multiple cit in any combination of version
57
+ - Generation of QR codes (PAC-ID with extensions)
58
+
59
+ - Validation (with Errors Recommendations)
60
+
61
+ ## Installation
62
+ You can install LabFREED from [PyPI](https://pypi.org/project/labfreed/) using pip:
63
+
64
+ ```bash
65
+ pip install labfreed
66
+ ```
67
+
68
+
69
+ ## Usage Examples
70
+ > ⚠️ **Note:** These examples are building on each other. Imports and parsing are not repeated in each example.
71
+ <!-- BEGIN EXAMPLES -->
72
+ ```python
73
+ # import built ins
74
+ import os
75
+
76
+ target = 'console'
77
+ ```
78
+ ### Parse a simple PAC-ID
79
+
80
+ ```python
81
+ # Parse the PAC-ID
82
+ from labfreed.labfreed_infrastructure import LabFREED_ValidationError # noqa: E402
83
+ from labfreed import PAC_ID, LabFREED_ValidationError # noqa: E402, F811
84
+
85
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
86
+ try:
87
+ pac = PAC_ID.from_url(pac_str)
88
+ except LabFREED_ValidationError:
89
+ pass
90
+ # Check validity of this PAC-ID
91
+ is_valid = pac.is_valid
92
+ print(f'PAC-ID is valid: {is_valid}')
93
+ ```
94
+ ```text
95
+ >> PAC-ID is valid: True
96
+ ```
97
+ ### Show recommendations:
98
+ Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
99
+ There is a nice function to highlight problems
100
+
101
+ ```python
102
+ pac.print_validation_messages(target=target)
103
+ ```
104
+ ```text
105
+ >> Validation Results
106
+ >> ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
107
+ >> │ RECOMMENDATION in id segment value bal500 │
108
+ >> │ Characters 'l','a','b' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
109
+ >> │ │
110
+ >> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:@1234 │
111
+ >> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
112
+ >> │ RECOMMENDATION in id segment value @1234 │
113
+ >> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
114
+ >> │ │
115
+ >> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:@1234 │
116
+ >> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
117
+ >> │ RECOMMENDATION in id segment value bal500 │
118
+ >> │ Characters 'l','a','b' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
119
+ >> │ │
120
+ >> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:@1234 │
121
+ >> ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
122
+ >> │ RECOMMENDATION in id segment value @1234 │
123
+ >> │ Characters '@' should not be used., Characters SHOULD be limited to upper case letters (A-Z), numbers (0-9), '-' and '+' │
124
+ >> │ │
125
+ >> │ HTTPS://PAC.METTORIUS.COM/-MD/240:bal500/21:@1234 │
126
+ >> └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
127
+ ```
128
+ ### Save as QR Code
129
+
130
+ ```python
131
+ from labfreed.qr import save_qr_with_markers # noqa: E402
132
+
133
+ save_qr_with_markers(pac_str, fmt='png')
134
+ ```
135
+ ```text
136
+ >> Large QR: Provided URL is not alphanumeric!
137
+ >> Size: 29
138
+ >> Version: 3
139
+ >> Error Level: M
140
+ ```
141
+ ### PAC-CAT
142
+ PAC-CAT defines a (optional) way how the identifier is structured.
143
+ PAC_ID.from_url() automatically converts to PAC-CAT if possible.
144
+
145
+ ```python
146
+ from labfreed.pac_cat import PAC_CAT # noqa: E402
147
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-DR/XQ908756/-MD/bal500/@1234'
148
+ pac = PAC_ID.from_url(pac_str)
149
+ if isinstance(pac, PAC_CAT):
150
+ categories = pac.categories
151
+ pac.print_categories()
152
+ ```
153
+ ```text
154
+ >> Categories in
155
+ >> HTTPS://PAC.METTORIUS.COM/-MD/240:
156
+ >> bal500/21:@1234
157
+ >> ┌────────────────────┬───────────┐
158
+ >> │ Main Category │ │
159
+ >> │ key () │ -DR │
160
+ >> │ id (21) │ XQ908756 │
161
+ >> ├────────────────────┼───────────┤
162
+ >> │ Category │ │
163
+ >> │ key () │ -MD │
164
+ >> │ model_number (240) │ bal500 │
165
+ >> │ serial_number (21) │ @1234 │
166
+ >> └────────────────────┴───────────┘
167
+ ```
168
+ ### Parse a PAC-ID with extensions
169
+ PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
170
+
171
+ ```python
172
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/BAL500/1234*N$N/WM633OV3E5DGJW2BEG0PDM1EA7*SUM$TREX/WEIGHT$GRM:67.89'
173
+ pac = PAC_ID.from_url(pac_str)
174
+ ```
175
+ #### Display Name
176
+ Note that the Extension is automatically converted to a DisplayNameExtension
177
+
178
+ ```python
179
+ display_name = pac.get_extension('N') # display name has name 'N'
180
+ print(display_name)
181
+ ```
182
+ ```text
183
+ >> Display name: My Balance ❤️
184
+ ```
185
+ #### TREX
186
+
187
+ ```python
188
+ trexes = pac.get_extension_of_type('TREX')
189
+ trex_extension = trexes[0] # there could be multiple trexes. In this example there is only one, though
190
+ trex = trex_extension.trex
191
+ v = trex.get_segment('WEIGHT')
192
+ print(f'WEIGHT = {v.value}')
193
+ ```
194
+ ```text
195
+ >> WEIGHT = 67.89
196
+ ```
197
+ ### Create a PAC-ID with Extensions
198
+
199
+ #### Create PAC-ID
200
+
201
+ ```python
202
+ from labfreed.pac_id import PAC_ID, IDSegment # noqa: E402
203
+ from labfreed.well_known_keys.labfreed.well_known_keys import WellKnownKeys # noqa: E402
204
+
205
+ pac = PAC_ID(issuer='METTORIUS.COM', identifier=[IDSegment(key=WellKnownKeys.SERIAL, value='1234')])
206
+ pac_str = pac.to_url()
207
+ print(pac_str)
208
+ ```
209
+ ```text
210
+ >> HTTPS://PAC.METTORIUS.COM/21:1234
211
+ ```
212
+ #### Create a TREX
213
+ TREX can conveniently be created from a python dictionary.
214
+ Note that utility types for Quantity (number with unit) and table are needed
215
+
216
+ ```python
217
+ from datetime import datetime # noqa: E402
218
+ from labfreed.trex.python_convenience.pyTREX import pyTREX # noqa: E402
219
+ from labfreed.trex.python_convenience.data_table import DataTable # noqa: E402
220
+ from labfreed.trex.python_convenience.quantity import Quantity # noqa: E402
221
+
222
+ # Value segments of different type
223
+ segments = {
224
+ 'STOP': datetime(year=2024,month=5,day=5,hour=13,minute=6),
225
+ 'TEMP': Quantity(value=10.15, unit= 'K'),
226
+ 'OK':False,
227
+ 'COMMENT': 'FOO',
228
+ 'COMMENT2':'£'
229
+ }
230
+ mydata = pyTREX(segments)
231
+
232
+ # Create a table
233
+ table = DataTable(col_names=['DURATION', 'Date', 'OK', 'COMMENT'])
234
+ table.append([Quantity(value=1, unit= 'hour'), datetime.now(), True, 'FOO'])
235
+ table.append([ 1.1, datetime.now(), True, 'BAR'])
236
+ table.append([ 1.3, datetime.now(), False, 'BLUBB'])
237
+ #add the table to the pytrex
238
+ mydata.update({'TABLE': table})
239
+
240
+ # Create TREX
241
+ trex = mydata.to_trex()
242
+
243
+
244
+ # Validation also works the same way for TREX
245
+ trex.print_validation_messages(target=target)
246
+ ```
247
+ ```text
248
+ >> Validation Results
249
+ >> ┌────────────────────────────────────────────────────────────┐
250
+ >> │ ERROR in TREX table column Date │
251
+ >> │ Column header key contains invalid characters: 'e','t','a' │
252
+ >> │ │
253
+ >> │ STOP$T.D:20240505T1306 │
254
+ >> │ +TEMP$KEL:10.15 │
255
+ >> │ +OK$T.B:F │
256
+ >> │ +COMMENT$T.A:FOO │
257
+ >> │ +COMMENT2$T.T:QMDTNXIKU │
258
+ >> │ +TABLE$$DURATION$HUR:Date$T.D:OK$T.B:COMMENT$T.A:: │
259
+ >> │ 1:20250423T170126.335:T:FOO:: │
260
+ >> │ 1.1:20250423T170126.335:T:BAR:: │
261
+ >> │ 1.3:20250423T170126.335:F:BLUBB │
262
+ >> └────────────────────────────────────────────────────────────┘
263
+ ```
264
+ #### Combine PAC-ID and TREX and serialize
265
+
266
+ ```python
267
+ from labfreed.well_known_extensions import TREX_Extension # noqa: E402
268
+ pac.extensions = [TREX_Extension(name='MYTREX', trex=trex)]
269
+ pac_str = pac.to_url()
270
+ print(pac_str)
271
+ ```
272
+ ```text
273
+ >> HTTPS://PAC.METTORIUS.COM/21:1234*MYTREX$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:QMDTNXIKU+TABLE$$DURATION$HUR:Date$T.D:OK$T.B:COMMENT$T.A::1:20250423T170126.335:T:FOO::1.1:20250423T170126.335:T:BAR::1.3:20250423T170126.335:F:BLUBB
274
+ ```
275
+ ## PAC-ID Resolver
276
+
277
+ ```python
278
+ from labfreed.pac_id_resolver import PAC_ID_Resolver, load_cit # noqa: E402
279
+ # Get a CIT
280
+ dir = os.path.join(os.getcwd(), 'examples')
281
+ p = os.path.join(dir, 'cit_mine.yaml')
282
+ cit = load_cit(p)
283
+
284
+ # validate the CIT
285
+ cit.is_valid
286
+ cit.print_validation_messages(target=target)
287
+ ```
288
+ ```python
289
+ # get a second cit
290
+ p = os.path.join(dir, 'coupling-information-table')
291
+ cit2 = load_cit(p)
292
+ cit2.origin = 'MY_COMPANY'
293
+ ```
294
+ ```python
295
+ # resolve a pac id
296
+ pac_str = 'HTTPS://PAC.METTORIUS.COM/-MS/X3511/CAS:7732-18-5'
297
+ service_groups = PAC_ID_Resolver(cits=[cit, cit2]).resolve(pac_str)
298
+ for sg in service_groups:
299
+ sg.update_states()
300
+ sg.print()
301
+
302
+ ```
303
+ ```text
304
+ >> Services from origin 'PERSONAL
305
+ >> ┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
306
+ >> ┃ Service Name ┃ URL ┃ Reachable ┃
307
+ >> ┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
308
+ >> │ CAS Search │ https://pubchem.ncbi.nlm.nih.gov/#query=7732-18-5 │ ACTIVE │
309
+ >> └──────────────┴───────────────────────────────────────────────────┴───────────┘
310
+ >> Services from origin 'MY_COMPANY
311
+ >> ┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
312
+ >> ┃ Service Name ┃ URL ┃ Reachable ┃
313
+ >> ┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
314
+ >> │ Chemical Management │ https://chem-manager.com/METTORIUS.COM/-MS/240:X3511/CAS:7732-18-5 │ INACTIVE │
315
+ >> └─────────────────────┴────────────────────────────────────────────────────────────────────┴───────────┘
316
+ >> Services from origin 'METTORIUS.COM
317
+ >> ┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
318
+ >> ┃ Service Name ┃ URL ┃ Reachable ┃
319
+ >> ┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
320
+ >> │ CoA │ https://mettorius.com/CoA.pdf │ ACTIVE │
321
+ >> │ MSDS │ https://mettorius.com/MSDS.pdf │ ACTIVE │
322
+ >> │ Shop │ https://mettorius.com/shop.html │ ACTIVE │
323
+ >> └──────────────┴─────────────────────────────────┴───────────┘
324
+ ```
325
+ <!-- END EXAMPLES -->
326
+
327
+
328
+
329
+ <!-- BEGIN CHANGELOG -->
330
+ ## Change Log
331
+ ### v0.2.0b2
332
+ - improvements in api consistency and ease of use
333
+ - restructured code for better separation of concerns
334
+ - support for coupling information table v1
335
+
336
+ ### v0.1.1
337
+ - minor internal improvements and bugfixes
338
+
339
+ ### v0.1.0
340
+ - DRAFT Support for PAC-ID Resolver
341
+
342
+ ### v0.0.20
343
+ - bugfix in TREX table to dict conversion
344
+ - markdown compatible validation printing
345
+
346
+ ### v0.0.19
347
+ - supports PAC-ID, PAC-CAT, TREX and DisplayName
348
+ - QR generation
349
+ - ok-ish test coverage
350
+
351
+ # Attributions
352
+ The following tools were used:
353
+ - [pdoc](https://pdoc.dev/) was a great help with generating documentation
354
+ - [Pydantic](https://docs.pydantic.dev/latest/)
355
+ - json with UNECE units from (https://github.com/quadient/unece-units/blob/main/python/src/unece_excel_parser/parsedUneceUnits.json)
356
+ - json with GS1 codes from (https://ref.gs1.org/ai/GS1_Application_Identifiers.jsonld)
357
+ <!-- END CHANGELOG -->