sdata 0.23.0__tar.gz → 0.23.2__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.
- {sdata-0.23.0/sdata.egg-info → sdata-0.23.2}/PKG-INFO +1 -1
- {sdata-0.23.0 → sdata-0.23.2}/sdata/__init__.py +1 -1
- {sdata-0.23.0 → sdata-0.23.2}/sdata/data.py +9 -1
- {sdata-0.23.0 → sdata-0.23.2}/sdata/experiments/__init__.py +43 -7
- {sdata-0.23.0 → sdata-0.23.2}/sdata/image.py +80 -3
- {sdata-0.23.0 → sdata-0.23.2/sdata.egg-info}/PKG-INFO +1 -1
- {sdata-0.23.0 → sdata-0.23.2}/LICENSE-MIT +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/MANIFEST.in +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/README.md +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/blob.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/attrdict/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/attrdict/default.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/attrdict/dictionary.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/attrdict/mapping.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/attrdict/merge.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/attrdict/mixins.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_common.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_dump.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_exceptions.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_exif.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_insert.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_load.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_remove.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_transplant.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/_webp.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/piexif/helper.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/ranger/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/ranger/collections/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/ranger/collections/rangebucketmap.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/ranger/collections/rangemap.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/ranger/collections/rangeset.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/ranger/range/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/ranger/range/cut.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/ranger/range/range.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/semver.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/simple_graph_db/LICENSE +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/simple_graph_db/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/simple_graph_db/database.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/simple_graph_db/schema.sql +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/sobol_seq.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/sortedcontainers/LICENSE +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/sortedcontainers/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/sortedcontainers/sorteddict.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/sortedcontainers/sortedlist.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/sortedcontainers/sortedset.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/sqlitedict.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/timeflake/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/timeflake/flake.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/contrib/timeflake/utils.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/doe.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/experiments/ks2.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/experiments/lapshear.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/experiments/material.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/iolib/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/iolib/db.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/iolib/hdf.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/iolib/isomme.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/iolib/pgp.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/iolib/pud.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/iolib/simple_signature.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/iolib/vault.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/metadata.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/suuid.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/timestamp.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/tools.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata/workbook.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata.egg-info/SOURCES.txt +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata.egg-info/dependency_links.txt +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata.egg-info/requires.txt +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/sdata.egg-info/top_level.txt +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/setup.cfg +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/setup.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/iolib/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/iolib/pud/__init__.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/iolib/pud/test_pud.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/iolib/test_hdf.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_attribute.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_blob.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_data.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_image.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_io.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_ks2.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_metadata.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_sqlite.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_suuid.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_table.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_testprogram.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_timeflake.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_timestamp.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_tools.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_vault.py +0 -0
- {sdata-0.23.0 → sdata-0.23.2}/tests/test_workbook.py +0 -0
|
@@ -189,7 +189,7 @@ class Data(object):
|
|
|
189
189
|
def __eq__(self, other):
|
|
190
190
|
"""compare Data checksum
|
|
191
191
|
|
|
192
|
-
:param other: sdata.Data
|
|
192
|
+
:param other: sdata.Data object
|
|
193
193
|
:return: True or False
|
|
194
194
|
"""
|
|
195
195
|
if not isinstance(other, self.__class__):
|
|
@@ -656,6 +656,14 @@ class Data(object):
|
|
|
656
656
|
def mdf(self):
|
|
657
657
|
return self.metadata.df
|
|
658
658
|
|
|
659
|
+
@property
|
|
660
|
+
def udf(self):
|
|
661
|
+
return self.metadata.udf
|
|
662
|
+
|
|
663
|
+
@property
|
|
664
|
+
def sdf(self):
|
|
665
|
+
return self.metadata.sdf
|
|
666
|
+
|
|
659
667
|
@property
|
|
660
668
|
def md(self):
|
|
661
669
|
return self.metadata
|
|
@@ -21,6 +21,21 @@ class TestProgram(Data):
|
|
|
21
21
|
"""A sdata Testprogram
|
|
22
22
|
|
|
23
23
|
"""
|
|
24
|
+
ATTRIBUTES = [
|
|
25
|
+
['material_name', '', 'str', '-', 'Der Name des Materials.', '', False],
|
|
26
|
+
['material_norm_name', '', 'str', '-', 'Der normative Name des Materials.', '', False],
|
|
27
|
+
['material_number_norm', '', 'str', '-', 'Die normative Nummer des Materials.', '', False],
|
|
28
|
+
['material_manifacturer', '', 'str', '-', 'Die Hersteller des Materials.', '', False],
|
|
29
|
+
['material_grade', '', 'str', '-', 'Der Zustand des Materials.', '', False],
|
|
30
|
+
['material_coating', '', 'str', '-', 'Die Beschichtung des Materials.', '', False],
|
|
31
|
+
['material_density', '', 'float', 'g/cm^3', 'Die Dichte des Materials.', '', False],
|
|
32
|
+
['material_production_date', '', 'str', '-', 'Das Produktionsdatum des Materials.', '', False],
|
|
33
|
+
['responsible_person', '', 'str', '-', 'Verantwortlicher des Testprogramms.', '', False],
|
|
34
|
+
['responsible_person_phone', '', 'str', '-', 'Telefonnummer des Verantwortlichen vom Testprogramms.', '', False],
|
|
35
|
+
['responsible_person_email', '', 'str', '-', 'Emailadressen des Verantwortlichen vom Testprogramms.', '', False],
|
|
36
|
+
['responsible_person_organisation', '', 'str', '-', 'Organisation des Verantwortlichen vom Testprogramms.', '', False],
|
|
37
|
+
['notes', '', 'str', '-', 'Notizen zum Testprogramm.', '', False],
|
|
38
|
+
]
|
|
24
39
|
|
|
25
40
|
def __init__(self, **kwargs):
|
|
26
41
|
"""
|
|
@@ -48,13 +63,26 @@ class TestProgram(Data):
|
|
|
48
63
|
if kwargs.get("uuid_testprogram") is not None:
|
|
49
64
|
self._set_uuid(kwargs.get("uuid_testprogram"))
|
|
50
65
|
|
|
66
|
+
for attrlist in self.ATTRIBUTES:
|
|
67
|
+
self.metadata.set_attr(attrlist[0], attrlist[1],
|
|
68
|
+
dtype=attrlist[2],
|
|
69
|
+
unit=attrlist[3],
|
|
70
|
+
description=attrlist[4],
|
|
71
|
+
label=attrlist[5],
|
|
72
|
+
required=attrlist[6])
|
|
73
|
+
|
|
74
|
+
|
|
51
75
|
def gen_testseries(self, **kwargs):
|
|
52
76
|
"""generate TestSeries instance
|
|
53
77
|
|
|
54
78
|
:param kwargs:
|
|
55
79
|
:return: TestSeries()
|
|
56
80
|
"""
|
|
57
|
-
|
|
81
|
+
class_name = kwargs.get("class_name", TestSeries)
|
|
82
|
+
if "class_name" in kwargs:
|
|
83
|
+
kwargs.pop("class_name")
|
|
84
|
+
|
|
85
|
+
ts = class_name(**kwargs)
|
|
58
86
|
ts.project = self.project
|
|
59
87
|
ts.name_testprogram = self.name_testprogram
|
|
60
88
|
ts.uuid_testprogram = self.uuid_testprogram
|
|
@@ -63,7 +91,7 @@ class TestProgram(Data):
|
|
|
63
91
|
|
|
64
92
|
@property
|
|
65
93
|
def longname(self):
|
|
66
|
-
return "
|
|
94
|
+
return "|".join([self.name_testprogram])
|
|
67
95
|
|
|
68
96
|
class TestSeries(TestProgram):
|
|
69
97
|
"""A sdata TestSeries
|
|
@@ -75,6 +103,8 @@ class TestSeries(TestProgram):
|
|
|
75
103
|
|
|
76
104
|
SDATA_TESTTYPE = "!sdata_testtype"
|
|
77
105
|
|
|
106
|
+
|
|
107
|
+
|
|
78
108
|
def __init__(self, **kwargs):
|
|
79
109
|
"""Test Series
|
|
80
110
|
|
|
@@ -185,7 +215,11 @@ class TestSeries(TestProgram):
|
|
|
185
215
|
:param kwargs:
|
|
186
216
|
:return: Test()
|
|
187
217
|
"""
|
|
188
|
-
|
|
218
|
+
class_name = kwargs.get("class_name", Test)
|
|
219
|
+
if "class_name" in kwargs:
|
|
220
|
+
kwargs.pop("class_name")
|
|
221
|
+
|
|
222
|
+
t = class_name(**kwargs)
|
|
189
223
|
t.name_testprogram = self.name_testprogram
|
|
190
224
|
t.uuid_testprogram = self.uuid_testprogram
|
|
191
225
|
t.name_testseries = self.name_testseries
|
|
@@ -198,7 +232,7 @@ class TestSeries(TestProgram):
|
|
|
198
232
|
|
|
199
233
|
@property
|
|
200
234
|
def longname(self):
|
|
201
|
-
return "
|
|
235
|
+
return "|".join([self.name_testprogram, self.name])
|
|
202
236
|
|
|
203
237
|
|
|
204
238
|
class Test(TestSeries):
|
|
@@ -209,14 +243,15 @@ class Test(TestSeries):
|
|
|
209
243
|
SDATA_TESTSERIES_NAME = "!sdata_testseries_name"
|
|
210
244
|
SDATA_TESTSERIES_UUID = "!sdata_testseries_uuid"
|
|
211
245
|
|
|
246
|
+
|
|
212
247
|
def __init__(self, **kwargs):
|
|
213
248
|
"""Test
|
|
214
249
|
|
|
215
250
|
:param kwargs:
|
|
216
251
|
"""
|
|
217
252
|
TestSeries.__init__(self, **kwargs)
|
|
218
|
-
self.metadata.add(name=self.SDATA_TESTSERIES_NAME, value="N.N.", dtype="str")
|
|
219
|
-
self.metadata.add(name=self.SDATA_TESTSERIES_UUID, value="", dtype="str")
|
|
253
|
+
self.metadata.add(name=self.SDATA_TESTSERIES_NAME, value="N.N.", dtype="str", description="name of the testseries")
|
|
254
|
+
self.metadata.add(name=self.SDATA_TESTSERIES_UUID, value="", dtype="str", description="uuid of the testseries")
|
|
220
255
|
|
|
221
256
|
if kwargs.get("name") is not None:
|
|
222
257
|
self._set_name(kwargs.get("name"))
|
|
@@ -235,6 +270,7 @@ class Test(TestSeries):
|
|
|
235
270
|
# print("uuid_testprogram", kwargs.get("uuid_testprogram"), self._set_uuid_testprogram)
|
|
236
271
|
self._set_uuid_testprogram(kwargs.get("uuid_testprogram"))
|
|
237
272
|
|
|
273
|
+
|
|
238
274
|
def _get_uuid_testseries(self):
|
|
239
275
|
return self.metadata.get(self.SDATA_TESTSERIES_UUID).value
|
|
240
276
|
|
|
@@ -284,7 +320,7 @@ class Test(TestSeries):
|
|
|
284
320
|
|
|
285
321
|
@property
|
|
286
322
|
def longname(self):
|
|
287
|
-
return "
|
|
323
|
+
return "|".join([self.name_testprogram, self.name_testseries, self.name])
|
|
288
324
|
|
|
289
325
|
|
|
290
326
|
|
|
@@ -12,6 +12,8 @@ import sdata.contrib.piexif
|
|
|
12
12
|
import sdata.contrib.piexif.helper
|
|
13
13
|
import json
|
|
14
14
|
import os
|
|
15
|
+
from io import BytesIO
|
|
16
|
+
import base64
|
|
15
17
|
import hashlib
|
|
16
18
|
try:
|
|
17
19
|
import PIL
|
|
@@ -47,15 +49,68 @@ class Image(Data):
|
|
|
47
49
|
def _from_filepath(cls, filepath, **kwargs):
|
|
48
50
|
"""read image from file
|
|
49
51
|
|
|
52
|
+
:param fielpath: image file path
|
|
53
|
+
:return: sdata.Image
|
|
50
54
|
"""
|
|
51
55
|
project = kwargs.get("project")
|
|
52
56
|
suuid = SUUID.from_file(cls.__class__.__name__, filepath, ns_name=project)
|
|
53
57
|
kwargs["uuid"] = suuid.huuid
|
|
54
58
|
kwargs["url"] = filepath
|
|
55
|
-
|
|
56
59
|
data = cls(name=os.path.basename(filepath), **kwargs)
|
|
57
60
|
return data
|
|
58
61
|
|
|
62
|
+
@classmethod
|
|
63
|
+
def from_image(cls, name, img, **kwargs):
|
|
64
|
+
"""read image from PIL.Image
|
|
65
|
+
|
|
66
|
+
"""
|
|
67
|
+
project = kwargs.get("project", "")
|
|
68
|
+
parent = kwargs.get("parent", "")
|
|
69
|
+
class_name = "Image" #cls.__class__.__name__
|
|
70
|
+
|
|
71
|
+
sh = hashlib.sha3_256()
|
|
72
|
+
sh.update(img.tobytes())
|
|
73
|
+
suuid = SUUID.from_name(class_name=class_name, name=sh.hexdigest(), ns_name=project)
|
|
74
|
+
suuid.project = project
|
|
75
|
+
kwargs["parent"] = parent
|
|
76
|
+
kwargs["project"] = suuid.project
|
|
77
|
+
kwargs["sname"] = suuid.sname
|
|
78
|
+
kwargs["uuid"] = suuid.huuid
|
|
79
|
+
kwargs["suuid"] = suuid.idstr
|
|
80
|
+
kwargs["url"] = sdata.osname(name)
|
|
81
|
+
# name = os.path.basename(filepath)
|
|
82
|
+
data = cls(name=name, **kwargs)
|
|
83
|
+
data.img = img
|
|
84
|
+
return data
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def from_bytes(cls, name, image_data, **kwargs):
|
|
89
|
+
"""read image from file
|
|
90
|
+
|
|
91
|
+
"""
|
|
92
|
+
project = kwargs.get("project")
|
|
93
|
+
class_name = "Image" #cls.__class__.__name__
|
|
94
|
+
suuid = SUUID.from_str(class_name, name, ns_name=project)
|
|
95
|
+
kwargs["sname"] = suuid.sname
|
|
96
|
+
kwargs["uuid"] = suuid.huuid
|
|
97
|
+
kwargs["suuid"] = suuid.idstr
|
|
98
|
+
kwargs["url"] = name
|
|
99
|
+
data = cls(name=name, **kwargs)
|
|
100
|
+
data.img = PIL.Image.open(BytesIO(image_data))
|
|
101
|
+
try:
|
|
102
|
+
d = None
|
|
103
|
+
if name.lower().endswith(".png"):
|
|
104
|
+
d = cls._get_png_metadata(image_data)
|
|
105
|
+
elif name.lower().endswith(("jpg", "jpeg")):
|
|
106
|
+
d = cls._get_jpg_metadata(image_data)
|
|
107
|
+
if d is not None:
|
|
108
|
+
data.metadata = data.metadata.from_json(d)
|
|
109
|
+
except:
|
|
110
|
+
pass
|
|
111
|
+
return data
|
|
112
|
+
|
|
113
|
+
|
|
59
114
|
@classmethod
|
|
60
115
|
def from_file(cls, filepath, **kwargs):
|
|
61
116
|
"""read image from file
|
|
@@ -73,7 +128,7 @@ class Image(Data):
|
|
|
73
128
|
|
|
74
129
|
if filepath.lower().endswith(".png"):
|
|
75
130
|
data = cls.from_png(filepath, **kwargs)
|
|
76
|
-
elif filepath.lower().endswith("
|
|
131
|
+
elif filepath.lower().endswith(("jpg", "jpeg")):
|
|
77
132
|
data = cls.from_jpg(filepath, **kwargs)
|
|
78
133
|
else:
|
|
79
134
|
data = cls(name=name, **kwargs)
|
|
@@ -228,4 +283,26 @@ class Image(Data):
|
|
|
228
283
|
json_string = json.dumps(self.metadata.to_json())
|
|
229
284
|
exif_dict = {"Exif": {sdata.contrib.piexif.ExifIFD.UserComment: sdata.contrib.piexif.helper.UserComment.dump(json_string)}}
|
|
230
285
|
exif_bytes = sdata.contrib.piexif.dump(exif_dict)
|
|
231
|
-
self.img.save(filepath, "jpeg", exif=exif_bytes)
|
|
286
|
+
self.img.save(filepath, "jpeg", exif=exif_bytes)
|
|
287
|
+
|
|
288
|
+
def get_image_download_link(self, img, filename, text):
|
|
289
|
+
|
|
290
|
+
json_string = json.dumps(self.metadata.to_json())
|
|
291
|
+
buffered = BytesIO()
|
|
292
|
+
|
|
293
|
+
if filename.endswith(".png"):
|
|
294
|
+
metadaten = PIL.PngImagePlugin.PngInfo()
|
|
295
|
+
metadaten.add_text("sdata", json_string)
|
|
296
|
+
img.save(buffered, "PNG", pnginfo=metadaten)
|
|
297
|
+
elif filename.lower().endswith(".jpg"):
|
|
298
|
+
exif_dict = {"Exif": {
|
|
299
|
+
sdata.contrib.piexif.ExifIFD.UserComment: sdata.contrib.piexif.helper.UserComment.dump(json_string)}}
|
|
300
|
+
exif_bytes = sdata.contrib.piexif.dump(exif_dict)
|
|
301
|
+
img.save(buffered, format="JPEG", exif=exif_bytes)
|
|
302
|
+
else:
|
|
303
|
+
logging.warning(f"metadata not supported for {filepath}")
|
|
304
|
+
img.save(buffered)
|
|
305
|
+
|
|
306
|
+
img_str = base64.b64encode(buffered.getvalue()).decode()
|
|
307
|
+
href = f'<a href="data:file/txt;base64,{img_str}" download="{filename}">{text}</a>'
|
|
308
|
+
return href
|
|
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
|
|
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
|
|
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
|