sdata 0.22.7__tar.gz → 0.23.1__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 (95) hide show
  1. {sdata-0.22.7/sdata.egg-info → sdata-0.23.1}/PKG-INFO +1 -1
  2. {sdata-0.22.7 → sdata-0.23.1}/sdata/__init__.py +1 -1
  3. {sdata-0.22.7 → sdata-0.23.1}/sdata/data.py +23 -2
  4. {sdata-0.22.7 → sdata-0.23.1}/sdata/image.py +108 -8
  5. {sdata-0.22.7 → sdata-0.23.1}/sdata/metadata.py +40 -6
  6. {sdata-0.22.7 → sdata-0.23.1}/sdata/suuid.py +30 -3
  7. {sdata-0.22.7 → sdata-0.23.1/sdata.egg-info}/PKG-INFO +1 -1
  8. {sdata-0.22.7 → sdata-0.23.1}/LICENSE-MIT +0 -0
  9. {sdata-0.22.7 → sdata-0.23.1}/MANIFEST.in +0 -0
  10. {sdata-0.22.7 → sdata-0.23.1}/README.md +0 -0
  11. {sdata-0.22.7 → sdata-0.23.1}/sdata/blob.py +0 -0
  12. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/__init__.py +0 -0
  13. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/attrdict/__init__.py +0 -0
  14. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/attrdict/default.py +0 -0
  15. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/attrdict/dictionary.py +0 -0
  16. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/attrdict/mapping.py +0 -0
  17. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/attrdict/merge.py +0 -0
  18. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/attrdict/mixins.py +0 -0
  19. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/__init__.py +0 -0
  20. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_common.py +0 -0
  21. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_dump.py +0 -0
  22. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_exceptions.py +0 -0
  23. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_exif.py +0 -0
  24. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_insert.py +0 -0
  25. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_load.py +0 -0
  26. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_remove.py +0 -0
  27. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_transplant.py +0 -0
  28. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/_webp.py +0 -0
  29. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/piexif/helper.py +0 -0
  30. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/ranger/__init__.py +0 -0
  31. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/ranger/collections/__init__.py +0 -0
  32. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/ranger/collections/rangebucketmap.py +0 -0
  33. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/ranger/collections/rangemap.py +0 -0
  34. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/ranger/collections/rangeset.py +0 -0
  35. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/ranger/range/__init__.py +0 -0
  36. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/ranger/range/cut.py +0 -0
  37. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/ranger/range/range.py +0 -0
  38. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/semver.py +0 -0
  39. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/simple_graph_db/LICENSE +0 -0
  40. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/simple_graph_db/__init__.py +0 -0
  41. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/simple_graph_db/database.py +0 -0
  42. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/simple_graph_db/schema.sql +0 -0
  43. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/sobol_seq.py +0 -0
  44. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/sortedcontainers/LICENSE +0 -0
  45. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/sortedcontainers/__init__.py +0 -0
  46. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/sortedcontainers/sorteddict.py +0 -0
  47. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/sortedcontainers/sortedlist.py +0 -0
  48. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/sortedcontainers/sortedset.py +0 -0
  49. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/sqlitedict.py +0 -0
  50. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/timeflake/__init__.py +0 -0
  51. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/timeflake/flake.py +0 -0
  52. {sdata-0.22.7 → sdata-0.23.1}/sdata/contrib/timeflake/utils.py +0 -0
  53. {sdata-0.22.7 → sdata-0.23.1}/sdata/doe.py +0 -0
  54. {sdata-0.22.7 → sdata-0.23.1}/sdata/experiments/__init__.py +0 -0
  55. {sdata-0.22.7 → sdata-0.23.1}/sdata/experiments/ks2.py +0 -0
  56. {sdata-0.22.7 → sdata-0.23.1}/sdata/experiments/lapshear.py +0 -0
  57. {sdata-0.22.7 → sdata-0.23.1}/sdata/experiments/material.py +0 -0
  58. {sdata-0.22.7 → sdata-0.23.1}/sdata/iolib/__init__.py +0 -0
  59. {sdata-0.22.7 → sdata-0.23.1}/sdata/iolib/db.py +0 -0
  60. {sdata-0.22.7 → sdata-0.23.1}/sdata/iolib/hdf.py +0 -0
  61. {sdata-0.22.7 → sdata-0.23.1}/sdata/iolib/isomme.py +0 -0
  62. {sdata-0.22.7 → sdata-0.23.1}/sdata/iolib/pgp.py +0 -0
  63. {sdata-0.22.7 → sdata-0.23.1}/sdata/iolib/pud.py +0 -0
  64. {sdata-0.22.7 → sdata-0.23.1}/sdata/iolib/simple_signature.py +0 -0
  65. {sdata-0.22.7 → sdata-0.23.1}/sdata/iolib/vault.py +0 -0
  66. {sdata-0.22.7 → sdata-0.23.1}/sdata/timestamp.py +0 -0
  67. {sdata-0.22.7 → sdata-0.23.1}/sdata/tools.py +0 -0
  68. {sdata-0.22.7 → sdata-0.23.1}/sdata/workbook.py +0 -0
  69. {sdata-0.22.7 → sdata-0.23.1}/sdata.egg-info/SOURCES.txt +0 -0
  70. {sdata-0.22.7 → sdata-0.23.1}/sdata.egg-info/dependency_links.txt +0 -0
  71. {sdata-0.22.7 → sdata-0.23.1}/sdata.egg-info/requires.txt +0 -0
  72. {sdata-0.22.7 → sdata-0.23.1}/sdata.egg-info/top_level.txt +0 -0
  73. {sdata-0.22.7 → sdata-0.23.1}/setup.cfg +0 -0
  74. {sdata-0.22.7 → sdata-0.23.1}/setup.py +0 -0
  75. {sdata-0.22.7 → sdata-0.23.1}/tests/__init__.py +0 -0
  76. {sdata-0.22.7 → sdata-0.23.1}/tests/iolib/__init__.py +0 -0
  77. {sdata-0.22.7 → sdata-0.23.1}/tests/iolib/pud/__init__.py +0 -0
  78. {sdata-0.22.7 → sdata-0.23.1}/tests/iolib/pud/test_pud.py +0 -0
  79. {sdata-0.22.7 → sdata-0.23.1}/tests/iolib/test_hdf.py +0 -0
  80. {sdata-0.22.7 → sdata-0.23.1}/tests/test_attribute.py +0 -0
  81. {sdata-0.22.7 → sdata-0.23.1}/tests/test_blob.py +0 -0
  82. {sdata-0.22.7 → sdata-0.23.1}/tests/test_data.py +0 -0
  83. {sdata-0.22.7 → sdata-0.23.1}/tests/test_image.py +0 -0
  84. {sdata-0.22.7 → sdata-0.23.1}/tests/test_io.py +0 -0
  85. {sdata-0.22.7 → sdata-0.23.1}/tests/test_ks2.py +0 -0
  86. {sdata-0.22.7 → sdata-0.23.1}/tests/test_metadata.py +0 -0
  87. {sdata-0.22.7 → sdata-0.23.1}/tests/test_sqlite.py +0 -0
  88. {sdata-0.22.7 → sdata-0.23.1}/tests/test_suuid.py +0 -0
  89. {sdata-0.22.7 → sdata-0.23.1}/tests/test_table.py +0 -0
  90. {sdata-0.22.7 → sdata-0.23.1}/tests/test_testprogram.py +0 -0
  91. {sdata-0.22.7 → sdata-0.23.1}/tests/test_timeflake.py +0 -0
  92. {sdata-0.22.7 → sdata-0.23.1}/tests/test_timestamp.py +0 -0
  93. {sdata-0.22.7 → sdata-0.23.1}/tests/test_tools.py +0 -0
  94. {sdata-0.22.7 → sdata-0.23.1}/tests/test_vault.py +0 -0
  95. {sdata-0.22.7 → sdata-0.23.1}/tests/test_workbook.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sdata
3
- Version: 0.22.7
3
+ Version: 0.23.1
4
4
  Summary: a structured data format
5
5
  Home-page: https://github.com/lepy/sdata
6
6
  Author: Lepy
@@ -1,7 +1,7 @@
1
1
  # -*-coding: utf-8-*-
2
2
  from __future__ import division
3
3
 
4
- __version__ = '0.22.7'
4
+ __version__ = '0.23.1'
5
5
  __revision__ = None
6
6
  __version_info__ = tuple([int(num) for num in __version__.split('.')])
7
7
 
@@ -52,6 +52,7 @@ class Data(object):
52
52
 
53
53
  SDATA_VERSION = "!sdata_version"
54
54
  SDATA_NAME = "!sdata_name"
55
+ SDATA_SNAME = "!sdata_sname"
55
56
  SDATA_UUID = "!sdata_uuid"
56
57
  SDATA_SUUID = "!sdata_suuid"
57
58
  SDATA_CTIME = "!sdata_ctime"
@@ -95,12 +96,14 @@ class Data(object):
95
96
  # set default sdata attributes
96
97
  self.metadata.add(self.SDATA_VERSION, __version__, dtype="str", description="sdata package version")
97
98
  self.metadata.add(self.SDATA_NAME, "N.N.", dtype="str", description="name of the data object")
99
+ self.metadata.add(self.SDATA_SNAME, "", dtype="str", description="sname of the data object")
98
100
  self.metadata.add(self.SDATA_UUID, "", dtype="str", description="Universally Unique Identifier")
99
101
  self.metadata.add(self.SDATA_SUUID, "", dtype="str", description="Super Universally Unique Identifier")
100
102
  self.metadata.add(self.SDATA_PARENT, "", dtype="str", description="uuid of the parent sdata object")
101
103
  self.metadata.add(self.SDATA_CLASS, self.__class__.__name__, dtype="str", description="sdata class")
102
104
  self.metadata.add(self.SDATA_CTIME, now_utc_str(), dtype="str", description="creation date")
103
105
  self.metadata.add(self.SDATA_MTIME, now_utc_str(), dtype="str", description="modification date")
106
+ self.metadata.add(self.SDATA_URL, "", dtype="str", description="url of the data object")
104
107
 
105
108
  metadata = kwargs.get("metadata")
106
109
  if metadata is not None:
@@ -151,10 +154,19 @@ class Data(object):
151
154
  # logger.info("uuid new")
152
155
  self._set_uuid(uuid.uuid4())
153
156
 
154
- self.gen_suuid()
157
+ if "suuid" not in kwargs:
158
+ self.gen_suuid()
159
+ else:
160
+ suuid = sdata.SUUID.from_suuid_str(kwargs.get("suuid"))
161
+ self.suuid = kwargs.get("suuid")
162
+ self.sname = suuid.sname
163
+
164
+ if "sname" in kwargs:
165
+ self.sname = kwargs.get("sname")
155
166
 
156
167
  def gen_suuid(self):
157
168
  self.suuid = sdata.SUUID(self.__class__.__name__, self.name, huuid=self.uuid).idstr
169
+ self.sname = sdata.SUUID(self.__class__.__name__, self.name, huuid=self.uuid).sname
158
170
 
159
171
  def gen_uuid_from_state(self):
160
172
  """generate the same uuid for the same data
@@ -177,7 +189,7 @@ class Data(object):
177
189
  def __eq__(self, other):
178
190
  """compare Data checksum
179
191
 
180
- :param other: sdata.Data objecet
192
+ :param other: sdata.Data object
181
193
  :return: True or False
182
194
  """
183
195
  if not isinstance(other, self.__class__):
@@ -331,6 +343,15 @@ class Data(object):
331
343
 
332
344
  suuid = property(fget=_get_suuid, fset=_set_suuid, doc="suuid of the object")
333
345
 
346
+
347
+ def _get_sname(self):
348
+ return self.metadata.get(self.SDATA_SNAME).value
349
+
350
+ def _set_sname(self, value):
351
+ self.metadata.set_attr(self.SDATA_SNAME, value)
352
+
353
+ sname = property(fget=_get_sname, fset=_set_sname, doc="sname of the object")
354
+
334
355
  def _get_uuid(self):
335
356
  return self.metadata.get(self.SDATA_UUID).value
336
357
  # return self._uuid
@@ -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,25 +49,89 @@ 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
- data = cls(name=os.path.basename(filepath), uuid=suuid.huuid, url=filepath, **kwargs)
57
+ kwargs["uuid"] = suuid.huuid
58
+ kwargs["url"] = filepath
59
+ data = cls(name=os.path.basename(filepath), **kwargs)
54
60
  return data
55
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
+
56
114
  @classmethod
57
115
  def from_file(cls, filepath, **kwargs):
58
116
  """read image from file
59
117
 
60
118
  """
61
119
  project = kwargs.get("project")
62
- suuid = SUUID.from_file(cls.__class__.__name__, filepath, ns_name=project)
120
+ class_name = "Image" #cls.__class__.__name__
121
+ suuid = SUUID.from_file(class_name, filepath, ns_name=project)
122
+ kwargs["sname"] = suuid.sname
123
+ kwargs["uuid"] = suuid.huuid
124
+ kwargs["suuid"] = suuid.idstr
125
+ kwargs["url"] = filepath
126
+ name = os.path.basename(filepath)
127
+
128
+
63
129
  if filepath.lower().endswith(".png"):
64
130
  data = cls.from_png(filepath, **kwargs)
65
- elif filepath.lower().endswith(".jpg"):
131
+ elif filepath.lower().endswith(("jpg", "jpeg")):
66
132
  data = cls.from_jpg(filepath, **kwargs)
67
133
  else:
68
- data = cls(name=os.path.basename(filepath), uuid=suuid.huuid, url=filepath, **kwargs)
134
+ data = cls(name=name, **kwargs)
69
135
  return data
70
136
 
71
137
  def get_sha3_256(self, filepath):
@@ -90,6 +156,15 @@ class Image(Data):
90
156
  self.img = PIL.Image.open(self.url)
91
157
  return self.img
92
158
 
159
+ def to_numpy(self):
160
+ """returns a NumPy array created from the color channels of the given Image object
161
+
162
+ array([[[192, 190, 187],
163
+ [193, 190, 187],
164
+ [193, 190, 185],
165
+ """
166
+ return np.array(self.img)
167
+
93
168
  @classmethod
94
169
  def from_png(cls, filepath, **kwargs):
95
170
  """load png image and metadata
@@ -139,9 +214,12 @@ class Image(Data):
139
214
  return
140
215
  data = cls._from_filepath(filepath, **kwargs)
141
216
  # data.load()
142
- d = cls._get_jpg_metadata(filepath)
143
- if d is not None:
144
- data.metadata = data.metadata.from_json(d)
217
+ try:
218
+ d = cls._get_jpg_metadata(filepath)
219
+ if d is not None:
220
+ data.metadata = data.metadata.from_json(d)
221
+ except Exception as exp:
222
+ logging.debug(exp)
145
223
  return data
146
224
 
147
225
  @staticmethod
@@ -205,4 +283,26 @@ class Image(Data):
205
283
  json_string = json.dumps(self.metadata.to_json())
206
284
  exif_dict = {"Exif": {sdata.contrib.piexif.ExifIFD.UserComment: sdata.contrib.piexif.helper.UserComment.dump(json_string)}}
207
285
  exif_bytes = sdata.contrib.piexif.dump(exif_dict)
208
- 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
@@ -262,7 +262,7 @@ class Metadata(object):
262
262
  * type (int, str, float, bool, timestamp)
263
263
  """
264
264
 
265
- ATTRIBUTEKEYS = ["name", "value", "dtype", "unit", "description", "label", "required"]
265
+ ATTRIBUTEKEYS = ["name", "value", "unit", "dtype", "description", "label", "required"]
266
266
 
267
267
  def __init__(self, **kwargs):
268
268
  """Metadata class
@@ -310,7 +310,7 @@ class Metadata(object):
310
310
  attr = name # name is the Attribute!
311
311
  else:
312
312
  attr = self.get_attr(prefix + name) or Attribute(name, value, **kwargs)
313
- for key in ["dtype", "unit", "description", "label", "required"]:
313
+ for key in ["unit", "dtype", "description", "label", "required"]:
314
314
  if key in kwargs:
315
315
  if key in kwargs:
316
316
  # print("!!!", attr, key, kwargs.get(key))
@@ -358,16 +358,21 @@ class Metadata(object):
358
358
  pass
359
359
  return str(value), "str"
360
360
 
361
- def update_from_dict(self, d):
361
+ def update_from_dict(self, d, guess_dtype=True):
362
362
  """set attributes from dict
363
363
 
364
364
  :param d: dict
365
365
  :return:
366
366
  """
367
367
  for k, v in d.items():
368
- value, dtype = self.guess_dtype_from_value(v)
368
+ if guess_dtype is False:
369
+ value = v
370
+ dtype = None
371
+ else:
372
+ value, dtype = self.guess_dtype_from_value(v)
369
373
  if dtype in ["float", "int", "bool"]:
370
- v = {"name":k, "value":value, "dtype":dtype, "unit":"", "description":"", "label":"", "required":False}
374
+ v = {"name":k, "value":value}
375
+ # v = {"name":k, "value":value, "dtype":dtype, "unit":"", "description":"", "label":"", "required":False}
371
376
  elif isinstance(v, (str,)):
372
377
  v = {"name":k, "value":v, "dtype":"str", "unit":"", "description":"", "label":"", "required":False}
373
378
  elif hasattr(v, "keys"):
@@ -378,7 +383,8 @@ class Metadata(object):
378
383
  "label":v.get("label", ""), "required":v.get("required", False)}
379
384
  else:
380
385
  v, dtype = self.guess_dtype_from_value(v)
381
- v = {"name":k, "value":v, "dtype":dtype, "unit":"", "description":"", "label":"", "required":False}
386
+ # v = {"name":k, "value":v, "dtype":dtype, "unit":"", "description":"", "label":"", "required":False}
387
+ v = {"name":k, "value":v, "dtype":dtype}
382
388
  self.set_attr(**v)
383
389
 
384
390
  @classmethod
@@ -452,6 +458,9 @@ class Metadata(object):
452
458
  @classmethod
453
459
  def from_dataframe(cls, df):
454
460
  """create metadata from dataframe"""
461
+ df.unit.fillna("", inplace=True)
462
+ df.label.fillna("", inplace=True)
463
+ df.description.fillna("", inplace=True)
455
464
  d = df.to_dict(orient='index')
456
465
  metadata = cls.from_dict(d)
457
466
  return metadata
@@ -621,6 +630,31 @@ class Metadata(object):
621
630
  def __getitem__(self, name):
622
631
  return self.get(name)
623
632
 
633
+ def __setitem__(self, name, value):
634
+ """update value in Attribute or create new Attribute"""
635
+ attr = self.get(name)
636
+
637
+ if attr is None:
638
+ attr = Attribute(name=name, value=value, dtype=type(value).__name__)
639
+ self._attributes[attr.name] = attr
640
+ else:
641
+ dtype = attr.guess_dtype(value)
642
+ attr.dtype = dtype
643
+ attr.value = dtype(value)
644
+
645
+ def __contains__(self, item):
646
+ return item in self.attributes.keys()
647
+
648
+ def pop(self, item):
649
+ try:
650
+ return self._attributes.pop(item)
651
+ except KeyError as exp:
652
+ return None
653
+
654
+ def __iter__(self):
655
+ for x in self.attributes.items():
656
+ yield x
657
+
624
658
  @property
625
659
  def sha3_256(self):
626
660
  """Return a new SHA3 hash object with a hashbit length of 32 bytes.
@@ -1,6 +1,7 @@
1
1
  import uuid
2
2
  import base64
3
3
  import hashlib
4
+ import os
4
5
 
5
6
  """
6
7
  SUUID
@@ -54,7 +55,14 @@ class SUUID:
54
55
  if name is None:
55
56
  name = ""
56
57
 
57
- self.name = name
58
+ self.name = self._clean_name(name)
59
+
60
+ @staticmethod
61
+ def _clean_name(name):
62
+ rs = ["|", ";"]
63
+ for r in rs:
64
+ name = name.replace(r, "")
65
+ return name
58
66
 
59
67
  def __str__(self):
60
68
  return f"({self.class_name}|{self.name}|{self.huuid})"
@@ -88,6 +96,11 @@ class SUUID:
88
96
  s = "".join([self.huuid, self.class_name + "|" + self.name])
89
97
  return base64.b64encode(s.encode())
90
98
 
99
+ @property
100
+ def sname(self):
101
+ s = "|".join([self.class_name, self.name, self.huuid])
102
+ return s
103
+
91
104
  @property
92
105
  def suuid(self):
93
106
  s = "".join([self.huuid, self.class_name + "|" + self.name])
@@ -149,6 +162,7 @@ class SUUID:
149
162
  :param ns_string: e.g. projectname "MyProject"
150
163
  :return: suuid
151
164
  """
165
+ name = cls._clean_name(name)
152
166
  uid = cls.get_uuid_from_name(name=name, ns_name=ns_name)
153
167
  suuid = cls(class_name=class_name, name=name, huuid=uid.hex)
154
168
  return suuid
@@ -167,6 +181,7 @@ class SUUID:
167
181
  :param ns_string: e.g. projectname "MyProject"
168
182
  :return: suuid
169
183
  """
184
+ name = cls._clean_name(name)
170
185
  suuid = cls.from_name(class_name, name=name, ns_name=ns_name)
171
186
  return suuid.id
172
187
 
@@ -188,7 +203,9 @@ class SUUID:
188
203
  sh = hashlib.sha3_256()
189
204
  with open(filepath, "rb") as fh:
190
205
  sh.update(fh.read())
206
+ basename = os.path.basename(filepath)
191
207
  suuid = cls.from_name(class_name=class_name, name=sh.hexdigest(), ns_name=ns_name)
208
+ suuid.name = basename
192
209
  return suuid
193
210
 
194
211
  @classmethod
@@ -210,7 +227,7 @@ class SUUID:
210
227
  @classmethod
211
228
  def from_suuid_bytes(cls, bytestring):
212
229
  """
213
- :param bytestring: b'NTcxYzNlY2E1NGYwNWNlY2E4MzFlOGNkNjYxNjMwOWFDTE5fQ1M=\n'
230
+ :param bytestring: 'MTNhNjMxMWNjZDFlNDFiOGI2MzJhNGY0ZTIzMjdiNTFQYXJ0fG15dGVzdG5hbWUwMQ=='
214
231
  """
215
232
  id_string = base64.b64decode(bytestring).decode()
216
233
  return cls.from_idstr(id_string)
@@ -218,13 +235,23 @@ class SUUID:
218
235
  @classmethod
219
236
  def from_suuid_str(cls, string):
220
237
  """
221
- :param string: 'NTcxYzNlY2E1NGYwNWNlY2E4MzFlOGNkNjYxNjMwOWFDTE5fQ1M=\n'
238
+ :param string: 'MTNhNjMxMWNjZDFlNDFiOGI2MzJhNGY0ZTIzMjdiNTFQYXJ0fG15dGVzdG5hbWUwMQ=='
222
239
 
223
240
  """
224
241
 
225
242
  id_string = base64.b64decode(string.encode()).decode()
226
243
  return cls.from_idstr(id_string)
227
244
 
245
+
246
+ @classmethod
247
+ def from_suuid_sname(cls, s):
248
+ """
249
+ :param string: 'Part|mytestname01|22a476e75a68486a92764eb830395923'
250
+
251
+ """
252
+ class_name, name, huuid = s.split("|")
253
+ return cls(class_name=class_name, name=name, huuid=huuid)
254
+
228
255
  @classmethod
229
256
  def from_idstr(cls, id_string):
230
257
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sdata
3
- Version: 0.22.7
3
+ Version: 0.23.1
4
4
  Summary: a structured data format
5
5
  Home-page: https://github.com/lepy/sdata
6
6
  Author: Lepy
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