labfreed 0.1.1__tar.gz → 0.2.0b0__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.

Potentially problematic release.


This version of labfreed might be problematic. Click here for more details.

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