labfreed 0.0.17__py2.py3-none-any.whl → 0.0.19__py2.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.
- labfreed/IO/generate_label.py +81 -0
- labfreed/{QR_Generator → IO}/generate_qr.py +12 -37
- labfreed/{parse_pac.py → IO/parse_pac.py} +2 -2
- labfreed/PAC_ID/extensions.py +0 -3
- labfreed/__init__.py +1 -1
- labfreed/utilities/utility_types.py +1 -31
- {labfreed-0.0.17.dist-info → labfreed-0.0.19.dist-info}/METADATA +46 -16
- {labfreed-0.0.17.dist-info → labfreed-0.0.19.dist-info}/RECORD +10 -10
- labfreed/utilities/extension_intertpreters.py +0 -4
- {labfreed-0.0.17.dist-info → labfreed-0.0.19.dist-info}/WHEEL +0 -0
- {labfreed-0.0.17.dist-info → labfreed-0.0.19.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from .generate_qr import generate_qr_with_markers_svg
|
|
4
|
+
|
|
5
|
+
from labfreed.PAC_ID.data_model import PACID
|
|
6
|
+
from labfreed.DisplayNameExtension.DisplayNameExtension import DisplayNames
|
|
7
|
+
from labfreed.IO.parse_pac import PACID_With_Extensions
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def generate_label_200_100(pac_url, pac:PACID_With_Extensions):
|
|
14
|
+
title, infos = get_label_fields(pac)
|
|
15
|
+
pac_svg = generate_qr_with_markers_svg(pac_url, height=60, width=100, border=0)
|
|
16
|
+
label = _generate_label(pac_svg, 200, 100, title, infos)
|
|
17
|
+
return label
|
|
18
|
+
|
|
19
|
+
def generate_label_credit_card_size(pac_url, pac:PACID_With_Extensions):
|
|
20
|
+
title, infos = get_label_fields(pac)
|
|
21
|
+
pac_svg = generate_qr_with_markers_svg(pac_url, height=100, width=200, border=0)
|
|
22
|
+
label = _generate_label(pac_svg, 240, 150, title, infos)
|
|
23
|
+
return label
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _generate_label(qr_svg, width, height, title=None, infos=[]):
|
|
27
|
+
if not qr_svg:
|
|
28
|
+
raise ValueError("no valid qr given")
|
|
29
|
+
env = Environment(
|
|
30
|
+
loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), "templates")),
|
|
31
|
+
autoescape=select_autoescape()
|
|
32
|
+
)
|
|
33
|
+
template = env.get_template("pac_label.jinja.svg")
|
|
34
|
+
svg = template.render(width=width, height= height, pac_qr=qr_svg, title=title, info1=infos[0], info2=infos[1], info3=infos[2])
|
|
35
|
+
|
|
36
|
+
return svg
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_label_fields(pac:PACID_With_Extensions) -> tuple[str, list[tuple[str, str]]]:
|
|
41
|
+
'''
|
|
42
|
+
returns a list of exactly length 3. Containing either info tuples (key value) or None
|
|
43
|
+
'''
|
|
44
|
+
if dn_extension := next((e for e in pac.extensions if isinstance(e, DisplayNames)), None): #find extension of type DisplayName
|
|
45
|
+
title = dn_extension.display_names[0]
|
|
46
|
+
else:
|
|
47
|
+
title = ""
|
|
48
|
+
|
|
49
|
+
infos = []
|
|
50
|
+
cat = pac.pac_id.identifier.categories[0]
|
|
51
|
+
for s in cat.segments:
|
|
52
|
+
lbl = pretty_print_segment_label(cat.key, s.key)
|
|
53
|
+
infos.append((lbl, s.value))
|
|
54
|
+
|
|
55
|
+
while len(infos) < 3:
|
|
56
|
+
infos.append(None)
|
|
57
|
+
|
|
58
|
+
if len(infos) > 3:
|
|
59
|
+
infos = infos[0:3]
|
|
60
|
+
|
|
61
|
+
return title,infos
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def pretty_print_segment_label(category:str, segment_key:str):
|
|
65
|
+
if not segment_key:
|
|
66
|
+
return 'no key'
|
|
67
|
+
|
|
68
|
+
cat = CAT_from_category_key(category)
|
|
69
|
+
if cat:
|
|
70
|
+
alias_to_field = {v.alias: k for k, v in cat.model_fields.items() if v.alias}
|
|
71
|
+
segment_label = alias_to_field.get(segment_key, segment_key)
|
|
72
|
+
segment_label = segment_label.replace('_', ' ').title()
|
|
73
|
+
|
|
74
|
+
segment_label = segment_label.replace('Id', 'ID')
|
|
75
|
+
|
|
76
|
+
else:
|
|
77
|
+
segment_label = segment_key
|
|
78
|
+
|
|
79
|
+
return segment_label
|
|
80
|
+
|
|
81
|
+
|
|
@@ -364,16 +364,16 @@ class VisualMarker:
|
|
|
364
364
|
app = typer.Typer()
|
|
365
365
|
|
|
366
366
|
|
|
367
|
-
def
|
|
367
|
+
def _generate_qr_with_markers(qr_str, text, title, direction):
|
|
368
368
|
if title:
|
|
369
369
|
#try to use standard size 10. Go bigger if 10 does not fit the data
|
|
370
370
|
try:
|
|
371
|
-
qr = segno.make_qr(
|
|
371
|
+
qr = segno.make_qr(qr_str, error="L", version=10)
|
|
372
372
|
except DataOverflowError as e:
|
|
373
|
-
qr = segno.make_qr(
|
|
373
|
+
qr = segno.make_qr(qr_str, error="L")
|
|
374
374
|
v = qr.version
|
|
375
375
|
else:
|
|
376
|
-
qr = segno.make_qr(
|
|
376
|
+
qr = segno.make_qr(qr_str, error="L")
|
|
377
377
|
v = qr.version
|
|
378
378
|
|
|
379
379
|
if(qr.mode != "alphanumeric"):
|
|
@@ -396,42 +396,18 @@ def generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.
|
|
|
396
396
|
combined_matrix = np.concatenate((title_marker, padding, qr_matrix, padding, visual_marker), axis=append_axis)
|
|
397
397
|
else:
|
|
398
398
|
combined_matrix = np.concatenate((qr_matrix, padding, visual_marker), axis=append_axis)
|
|
399
|
-
|
|
399
|
+
|
|
400
400
|
return combined_matrix
|
|
401
|
-
|
|
402
|
-
def generate_qr_with_markers_file(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, fmt='svg', path=str):
|
|
403
|
-
combined_matrix = generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
404
|
-
outfile = f'{path}.{fmt}'
|
|
405
|
-
match fmt:
|
|
406
|
-
case 'png':
|
|
407
|
-
segno.writers.write_png(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
408
|
-
case 'svg':
|
|
409
|
-
segno.writers.write_svg(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
410
401
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
402
|
+
def save_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, fmt='png', path='qr'):
|
|
403
|
+
combined_matrix = _generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
404
|
+
outfile = f'{path}.{fmt}'
|
|
414
405
|
match fmt:
|
|
415
406
|
case 'png':
|
|
416
|
-
|
|
407
|
+
writers.write_png(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
417
408
|
case 'svg':
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
def generate_qr_with_markers_svg(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, width=None, height=None, border=9, svg_omitsize=False):
|
|
422
|
-
combined_matrix = generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
423
|
-
with io.BytesIO() as out:
|
|
424
|
-
version = combined_matrix.shape[::-1]
|
|
425
|
-
scalex = width / (version[0] + 2*border) if width else 1
|
|
426
|
-
scaley = height / (version[1] + 2*border) if height else 1
|
|
427
|
-
scale = min(scalex, scaley)
|
|
428
|
-
segno.writers.write_svg(combined_matrix, version, out, border=border,
|
|
429
|
-
xmldecl=False, svgns=True, scale=scale, omitsize=svg_omitsize
|
|
430
|
-
)
|
|
431
|
-
s = out.getvalue().decode()
|
|
432
|
-
return s
|
|
433
|
-
|
|
434
|
-
|
|
409
|
+
writers.write_svg(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
410
|
+
|
|
435
411
|
|
|
436
412
|
|
|
437
413
|
|
|
@@ -440,8 +416,7 @@ def main(url: Annotated[str, typer.Argument(help="The PAC-ID to be rendered as Q
|
|
|
440
416
|
text: Annotated[str, typer.Option(help="The text of the PAC decoration.")] = "PAC",
|
|
441
417
|
direction: Annotated[Direction, typer.Option(help="The position/direction of the PAC decoration.")] = Direction.TOP_TO_BOTTOM):
|
|
442
418
|
|
|
443
|
-
|
|
444
|
-
img.save('generated_codes', f"{outfile}.svg", format='svg')
|
|
419
|
+
save_qr_with_markers(url, text=text, direction=direction, path=outfile)
|
|
445
420
|
|
|
446
421
|
|
|
447
422
|
|
|
@@ -9,9 +9,9 @@ from labfreed.PAC_ID.extensions import Extension, UnknownExtension
|
|
|
9
9
|
from labfreed.TREX.data_model import TREX
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
from
|
|
12
|
+
from ..PAC_ID.data_model import *
|
|
13
13
|
|
|
14
|
-
from
|
|
14
|
+
from ..validation import ValidationMessage, LabFREEDValidationError
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
labfreed/PAC_ID/extensions.py
CHANGED
labfreed/__init__.py
CHANGED
|
@@ -1,37 +1,7 @@
|
|
|
1
|
-
from
|
|
2
|
-
import json
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from rich import print
|
|
6
|
-
|
|
7
|
-
from typing import Any, Tuple
|
|
8
|
-
from typing_extensions import Annotated
|
|
9
|
-
from pydantic import BaseModel, AfterValidator
|
|
10
|
-
import quantities as pq
|
|
11
|
-
from quantities import units
|
|
1
|
+
from pydantic import BaseModel
|
|
12
2
|
|
|
13
3
|
from labfreed.TREX.unece_units import unece_units
|
|
14
4
|
|
|
15
|
-
def validate_unit(unit_name:str) -> str :
|
|
16
|
-
"""
|
|
17
|
-
Pydantic validator function for the unit.
|
|
18
|
-
Checks if the unit is a valid unit.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
unit (str): unit symbol, e.g. 'kg'
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
str: the input unit.
|
|
26
|
-
|
|
27
|
-
Errors:
|
|
28
|
-
raises an AssertionError if validation fails
|
|
29
|
-
"""
|
|
30
|
-
if hasattr(pq, unit_name):
|
|
31
|
-
return unit_name
|
|
32
|
-
else:
|
|
33
|
-
assert False
|
|
34
|
-
|
|
35
5
|
|
|
36
6
|
class Unit(BaseModel):
|
|
37
7
|
name: str
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: labfreed
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.19
|
|
4
4
|
Summary: Python implementation of LabFREED building blocks
|
|
5
5
|
Author-email: Reto Thürer <thuerer.r@buchi.com>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -41,7 +41,7 @@ pip install labfreed
|
|
|
41
41
|
### Parse a simple PAC-ID
|
|
42
42
|
|
|
43
43
|
```python
|
|
44
|
-
from labfreed.parse_pac import PAC_Parser
|
|
44
|
+
from labfreed.IO.parse_pac import PAC_Parser
|
|
45
45
|
|
|
46
46
|
# Parse the PAC-ID
|
|
47
47
|
pac_str = 'HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234'
|
|
@@ -53,7 +53,7 @@ is_valid = pac_id.is_valid()
|
|
|
53
53
|
print(f'PAC-ID is valid: {is_valid}')
|
|
54
54
|
```
|
|
55
55
|
```text
|
|
56
|
-
>>
|
|
56
|
+
>> PAC-ID is valid: True
|
|
57
57
|
```
|
|
58
58
|
### Show recommendations:
|
|
59
59
|
Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
|
|
@@ -63,7 +63,34 @@ There is a nice function to highlight problems
|
|
|
63
63
|
pac_id.print_validation_messages()
|
|
64
64
|
```
|
|
65
65
|
```text
|
|
66
|
-
>>
|
|
66
|
+
>> =======================================
|
|
67
|
+
>> Validation Results
|
|
68
|
+
>> ---------------------------------------
|
|
69
|
+
>>
|
|
70
|
+
>> Recommendation in id segment value bal500
|
|
71
|
+
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
72
|
+
>> Characters l a b should not be used.
|
|
73
|
+
>>
|
|
74
|
+
>> Recommendation in id segment value @1234
|
|
75
|
+
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
76
|
+
>> Characters @ should not be used.
|
|
77
|
+
>>
|
|
78
|
+
>> Warning in Category -MD
|
|
79
|
+
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
80
|
+
>> Category key -MD is not a well known key. It is recommended to use well known keys only
|
|
81
|
+
```
|
|
82
|
+
### Save as QR Code
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from labfreed.IO.generate_qr import save_qr_with_markers
|
|
86
|
+
|
|
87
|
+
save_qr_with_markers(pac_str, fmt='png')
|
|
88
|
+
```
|
|
89
|
+
```text
|
|
90
|
+
>> Large QR: Provided URL is not alphanumeric!
|
|
91
|
+
>> Size: 29
|
|
92
|
+
>> Version: 3
|
|
93
|
+
>> Error Level: M
|
|
67
94
|
```
|
|
68
95
|
### PAC-CAT
|
|
69
96
|
|
|
@@ -75,7 +102,15 @@ if isinstance(pac_id, PAC_CAT):
|
|
|
75
102
|
pac_id.print_categories()
|
|
76
103
|
```
|
|
77
104
|
```text
|
|
78
|
-
>>
|
|
105
|
+
>> Main Category
|
|
106
|
+
>> ----------
|
|
107
|
+
>> key (): -DR
|
|
108
|
+
>> id (21): XQ908756
|
|
109
|
+
>> Category
|
|
110
|
+
>> ------
|
|
111
|
+
>> key (): -MD
|
|
112
|
+
>> model_number (240): bal500
|
|
113
|
+
>> serial_number (21): @1234
|
|
79
114
|
```
|
|
80
115
|
### Parse a PAC-ID with extensions
|
|
81
116
|
PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
|
|
@@ -89,7 +124,7 @@ display_names = pac_id.get_extension('N') # display name has name 'N'
|
|
|
89
124
|
print(display_names)
|
|
90
125
|
```
|
|
91
126
|
```text
|
|
92
|
-
>>
|
|
127
|
+
>> Display names: My Balance ❤️
|
|
93
128
|
```
|
|
94
129
|
```python
|
|
95
130
|
# TREX
|
|
@@ -99,7 +134,7 @@ v = trex.get_segment('WEIGHT').to_python_type()
|
|
|
99
134
|
print(f'WEIGHT = {v}')
|
|
100
135
|
```
|
|
101
136
|
```text
|
|
102
|
-
>>
|
|
137
|
+
>> WEIGHT = 67.89 g
|
|
103
138
|
```
|
|
104
139
|
### Create a PAC-ID with Extensions
|
|
105
140
|
|
|
@@ -153,20 +188,17 @@ if trex.get_nested_validation_messages():
|
|
|
153
188
|
# Side Note: The TREX can be turned back into a dict
|
|
154
189
|
d = trex.dict()
|
|
155
190
|
```
|
|
156
|
-
```text
|
|
157
|
-
>> [Error during execution: No module named 'quantities']
|
|
158
|
-
```
|
|
159
191
|
#### Combine PAC-ID and TREX and serialize
|
|
160
192
|
|
|
161
193
|
```python
|
|
162
|
-
from labfreed.parse_pac import PACID_With_Extensions
|
|
194
|
+
from labfreed.IO.parse_pac import PACID_With_Extensions
|
|
163
195
|
|
|
164
196
|
pac_with_trex = PACID_With_Extensions(pac_id=pac_id, extensions=[trex])
|
|
165
197
|
pac_str = pac_with_trex.serialize()
|
|
166
198
|
print(pac_str)
|
|
167
199
|
```
|
|
168
200
|
```text
|
|
169
|
-
>>
|
|
201
|
+
>> HTTPS://PAC.METTORIUS:COM/21:1234*DEMO$TREX/STOP$T.D:20240505T1306+TEMP$KEL:10.15+OK$T.B:F+COMMENT$T.A:FOO+COMMENT2$T.T:12G3+TABLE$$DURATION$HUR:DATE$T.D:OK$T.B:COMMENT$T.A::1:20250409T082814.766:T:FOO::1.1:20250409T082814.766:T:BAR::1.3:20250409T082814.766:F:BLUBB
|
|
170
202
|
```
|
|
171
203
|
<!-- END EXAMPLES -->
|
|
172
204
|
|
|
@@ -174,9 +206,7 @@ print(pac_str)
|
|
|
174
206
|
|
|
175
207
|
## Change Log
|
|
176
208
|
|
|
177
|
-
### v0.0.
|
|
178
|
-
- dependencies are installed automatically
|
|
179
|
-
|
|
180
|
-
### v0.0.16
|
|
209
|
+
### v0.0.19
|
|
181
210
|
- supports PAC-ID, PAC-CAT, TREX and DisplayName
|
|
211
|
+
- QR generation
|
|
182
212
|
- ok-ish test coverage
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
labfreed/__init__.py,sha256=
|
|
2
|
-
labfreed/parse_pac.py,sha256=7y65HO1A3OEr5zftiEtrCaiLLI_8LoRPtQpPcKUNVik,6251
|
|
1
|
+
labfreed/__init__.py,sha256=6YWGHiMitcGiwwX9TPLO5MUlsimAgua8aP-e6yoW8-k,88
|
|
3
2
|
labfreed/validation.py,sha256=QwkZWJhAjWbPUZtJJwjVYsw9TxeFhdbZaKjrPPIpuAA,5937
|
|
4
3
|
labfreed/DisplayNameExtension/DisplayNameExtension.py,sha256=l9JZY2eRS0V-H5h3-WXIHiiBJuljns-_e_t9Bp84_CU,1155
|
|
4
|
+
labfreed/IO/generate_label.py,sha256=9ydpD68E7ztecEPXydw40eT7KV4FhAHvzmLidvYxHWI,2661
|
|
5
|
+
labfreed/IO/generate_qr.py,sha256=wdZSf51Id03xSY8liK2RfB7WyGAw9O4s0VhZzrkAa-g,16680
|
|
6
|
+
labfreed/IO/parse_pac.py,sha256=2c-HXkiQdUrGTL8zGb5CmO9l6ZrCb07rrTMMKdMi3_o,6253
|
|
5
7
|
labfreed/PAC_CAT/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
6
8
|
labfreed/PAC_CAT/data_model.py,sha256=dGwcQGLy1Dk6SFbs9utxKQKm_4ROZrXdv618APlQg7M,14308
|
|
7
9
|
labfreed/PAC_ID/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
10
|
labfreed/PAC_ID/data_model.py,sha256=g09qgC-TV6fjJw9VyDF6mTJ6co2i2RKZc0Z-BmiiUIQ,7483
|
|
9
|
-
labfreed/PAC_ID/extensions.py,sha256=
|
|
10
|
-
labfreed/QR_Generator/generate_qr.py,sha256=A4Bw_UESaB_igTDV2Y7a5T7vdz2Sb3yZCfHM0qKnu0M,18091
|
|
11
|
+
labfreed/PAC_ID/extensions.py,sha256=YKIE-aFf1jdL4sqCqUe3txjnP8-dA2zCJrT5lBSjvuE,1092
|
|
11
12
|
labfreed/TREX/UneceUnits.json,sha256=kwfQSp_nTuWbADfBBgqTWrvPl6XtM5SedEVLbMJrM7M,898953
|
|
12
13
|
labfreed/TREX/data_model.py,sha256=neKYBc5_S4t-v86DSaWLq81VJF4oS6eFUch3ChPTYJA,29705
|
|
13
14
|
labfreed/TREX/parse.py,sha256=86962VEJpkrTcT436iFIB5dNed5WHABzpjxRjkA3PXo,2043
|
|
14
15
|
labfreed/TREX/unece_units.py,sha256=scPKdsPzY1neAdFOhA08_tRZaR-yplM8mBhIzzDqZBk,3006
|
|
15
16
|
labfreed/utilities/base36.py,sha256=_yX8aQ1OwrK5tnJU1NUEzQSFGr9xAVnNvPObpNzCPYs,2895
|
|
16
|
-
labfreed/utilities/
|
|
17
|
-
labfreed/utilities/utility_types.py,sha256=Zhk8Mu4hHjkn1gs8oh7vOxxaT7L7wLMVG40ZOWCKGK4,2865
|
|
17
|
+
labfreed/utilities/utility_types.py,sha256=dM0qZgshF3cHJThVzia7UIAOdkNLKukAaaduLqKSaMY,2195
|
|
18
18
|
labfreed/utilities/well_known_keys.py,sha256=nqk66kHdSwJTJfMKlP-xQbBglS8F_NoWsGkfOVITFN0,331
|
|
19
|
-
labfreed-0.0.
|
|
20
|
-
labfreed-0.0.
|
|
21
|
-
labfreed-0.0.
|
|
22
|
-
labfreed-0.0.
|
|
19
|
+
labfreed-0.0.19.dist-info/licenses/LICENSE,sha256=gHFOv9FRKHxO8cInP3YXyPoJnuNeqrvcHjaE_wPSsQ8,1100
|
|
20
|
+
labfreed-0.0.19.dist-info/WHEEL,sha256=Dyt6SBfaasWElUrURkknVFAZDHSTwxg3PaTza7RSbkY,100
|
|
21
|
+
labfreed-0.0.19.dist-info/METADATA,sha256=hxfeVBwFlFMSA9-tGCnva---qoMx6KQvgmf6z9tyjP4,6255
|
|
22
|
+
labfreed-0.0.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|