sdata 0.22.5__tar.gz → 0.23.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 (95) hide show
  1. {sdata-0.22.5/sdata.egg-info → sdata-0.23.0}/PKG-INFO +1 -1
  2. {sdata-0.22.5 → sdata-0.23.0}/sdata/__init__.py +1 -1
  3. {sdata-0.22.5 → sdata-0.23.0}/sdata/data.py +38 -12
  4. {sdata-0.22.5 → sdata-0.23.0}/sdata/image.py +72 -16
  5. {sdata-0.22.5 → sdata-0.23.0}/sdata/metadata.py +48 -11
  6. {sdata-0.22.5 → sdata-0.23.0}/sdata/suuid.py +30 -3
  7. {sdata-0.22.5 → sdata-0.23.0/sdata.egg-info}/PKG-INFO +1 -1
  8. {sdata-0.22.5 → sdata-0.23.0}/LICENSE-MIT +0 -0
  9. {sdata-0.22.5 → sdata-0.23.0}/MANIFEST.in +0 -0
  10. {sdata-0.22.5 → sdata-0.23.0}/README.md +0 -0
  11. {sdata-0.22.5 → sdata-0.23.0}/sdata/blob.py +0 -0
  12. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/__init__.py +0 -0
  13. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/attrdict/__init__.py +0 -0
  14. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/attrdict/default.py +0 -0
  15. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/attrdict/dictionary.py +0 -0
  16. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/attrdict/mapping.py +0 -0
  17. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/attrdict/merge.py +0 -0
  18. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/attrdict/mixins.py +0 -0
  19. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/__init__.py +0 -0
  20. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_common.py +0 -0
  21. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_dump.py +0 -0
  22. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_exceptions.py +0 -0
  23. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_exif.py +0 -0
  24. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_insert.py +0 -0
  25. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_load.py +0 -0
  26. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_remove.py +0 -0
  27. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_transplant.py +0 -0
  28. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/_webp.py +0 -0
  29. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/piexif/helper.py +0 -0
  30. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/ranger/__init__.py +0 -0
  31. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/ranger/collections/__init__.py +0 -0
  32. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/ranger/collections/rangebucketmap.py +0 -0
  33. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/ranger/collections/rangemap.py +0 -0
  34. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/ranger/collections/rangeset.py +0 -0
  35. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/ranger/range/__init__.py +0 -0
  36. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/ranger/range/cut.py +0 -0
  37. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/ranger/range/range.py +0 -0
  38. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/semver.py +0 -0
  39. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/simple_graph_db/LICENSE +0 -0
  40. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/simple_graph_db/__init__.py +0 -0
  41. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/simple_graph_db/database.py +0 -0
  42. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/simple_graph_db/schema.sql +0 -0
  43. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/sobol_seq.py +0 -0
  44. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/sortedcontainers/LICENSE +0 -0
  45. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/sortedcontainers/__init__.py +0 -0
  46. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/sortedcontainers/sorteddict.py +0 -0
  47. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/sortedcontainers/sortedlist.py +0 -0
  48. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/sortedcontainers/sortedset.py +0 -0
  49. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/sqlitedict.py +0 -0
  50. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/timeflake/__init__.py +0 -0
  51. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/timeflake/flake.py +0 -0
  52. {sdata-0.22.5 → sdata-0.23.0}/sdata/contrib/timeflake/utils.py +0 -0
  53. {sdata-0.22.5 → sdata-0.23.0}/sdata/doe.py +0 -0
  54. {sdata-0.22.5 → sdata-0.23.0}/sdata/experiments/__init__.py +0 -0
  55. {sdata-0.22.5 → sdata-0.23.0}/sdata/experiments/ks2.py +0 -0
  56. {sdata-0.22.5 → sdata-0.23.0}/sdata/experiments/lapshear.py +0 -0
  57. {sdata-0.22.5 → sdata-0.23.0}/sdata/experiments/material.py +0 -0
  58. {sdata-0.22.5 → sdata-0.23.0}/sdata/iolib/__init__.py +0 -0
  59. {sdata-0.22.5 → sdata-0.23.0}/sdata/iolib/db.py +0 -0
  60. {sdata-0.22.5 → sdata-0.23.0}/sdata/iolib/hdf.py +0 -0
  61. {sdata-0.22.5 → sdata-0.23.0}/sdata/iolib/isomme.py +0 -0
  62. {sdata-0.22.5 → sdata-0.23.0}/sdata/iolib/pgp.py +0 -0
  63. {sdata-0.22.5 → sdata-0.23.0}/sdata/iolib/pud.py +0 -0
  64. {sdata-0.22.5 → sdata-0.23.0}/sdata/iolib/simple_signature.py +0 -0
  65. {sdata-0.22.5 → sdata-0.23.0}/sdata/iolib/vault.py +0 -0
  66. {sdata-0.22.5 → sdata-0.23.0}/sdata/timestamp.py +0 -0
  67. {sdata-0.22.5 → sdata-0.23.0}/sdata/tools.py +0 -0
  68. {sdata-0.22.5 → sdata-0.23.0}/sdata/workbook.py +0 -0
  69. {sdata-0.22.5 → sdata-0.23.0}/sdata.egg-info/SOURCES.txt +0 -0
  70. {sdata-0.22.5 → sdata-0.23.0}/sdata.egg-info/dependency_links.txt +0 -0
  71. {sdata-0.22.5 → sdata-0.23.0}/sdata.egg-info/requires.txt +0 -0
  72. {sdata-0.22.5 → sdata-0.23.0}/sdata.egg-info/top_level.txt +0 -0
  73. {sdata-0.22.5 → sdata-0.23.0}/setup.cfg +0 -0
  74. {sdata-0.22.5 → sdata-0.23.0}/setup.py +0 -0
  75. {sdata-0.22.5 → sdata-0.23.0}/tests/__init__.py +0 -0
  76. {sdata-0.22.5 → sdata-0.23.0}/tests/iolib/__init__.py +0 -0
  77. {sdata-0.22.5 → sdata-0.23.0}/tests/iolib/pud/__init__.py +0 -0
  78. {sdata-0.22.5 → sdata-0.23.0}/tests/iolib/pud/test_pud.py +0 -0
  79. {sdata-0.22.5 → sdata-0.23.0}/tests/iolib/test_hdf.py +0 -0
  80. {sdata-0.22.5 → sdata-0.23.0}/tests/test_attribute.py +0 -0
  81. {sdata-0.22.5 → sdata-0.23.0}/tests/test_blob.py +0 -0
  82. {sdata-0.22.5 → sdata-0.23.0}/tests/test_data.py +0 -0
  83. {sdata-0.22.5 → sdata-0.23.0}/tests/test_image.py +0 -0
  84. {sdata-0.22.5 → sdata-0.23.0}/tests/test_io.py +0 -0
  85. {sdata-0.22.5 → sdata-0.23.0}/tests/test_ks2.py +0 -0
  86. {sdata-0.22.5 → sdata-0.23.0}/tests/test_metadata.py +0 -0
  87. {sdata-0.22.5 → sdata-0.23.0}/tests/test_sqlite.py +0 -0
  88. {sdata-0.22.5 → sdata-0.23.0}/tests/test_suuid.py +0 -0
  89. {sdata-0.22.5 → sdata-0.23.0}/tests/test_table.py +0 -0
  90. {sdata-0.22.5 → sdata-0.23.0}/tests/test_testprogram.py +0 -0
  91. {sdata-0.22.5 → sdata-0.23.0}/tests/test_timeflake.py +0 -0
  92. {sdata-0.22.5 → sdata-0.23.0}/tests/test_timestamp.py +0 -0
  93. {sdata-0.22.5 → sdata-0.23.0}/tests/test_tools.py +0 -0
  94. {sdata-0.22.5 → sdata-0.23.0}/tests/test_vault.py +0 -0
  95. {sdata-0.22.5 → sdata-0.23.0}/tests/test_workbook.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sdata
3
- Version: 0.22.5
3
+ Version: 0.23.0
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.5'
4
+ __version__ = '0.23.0'
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"
@@ -59,9 +60,10 @@ class Data(object):
59
60
  SDATA_PARENT = "!sdata_parent"
60
61
  SDATA_CLASS = "!sdata_class"
61
62
  SDATA_PROJECT = "!sdata_project"
63
+ SDATA_URL = "!sdata_url"
62
64
 
63
65
  SDATA_ATTRIBUTES = [SDATA_VERSION, SDATA_NAME, SDATA_UUID, SDATA_SUUID, SDATA_CLASS, SDATA_PARENT, SDATA_PROJECT,
64
- SDATA_CTIME, SDATA_MTIME]
66
+ SDATA_CTIME, SDATA_MTIME, SDATA_URL]
65
67
 
66
68
  def __init__(self, **kwargs):
67
69
  """create Data object
@@ -94,12 +96,14 @@ class Data(object):
94
96
  # set default sdata attributes
95
97
  self.metadata.add(self.SDATA_VERSION, __version__, dtype="str", description="sdata package version")
96
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")
97
100
  self.metadata.add(self.SDATA_UUID, "", dtype="str", description="Universally Unique Identifier")
98
101
  self.metadata.add(self.SDATA_SUUID, "", dtype="str", description="Super Universally Unique Identifier")
99
102
  self.metadata.add(self.SDATA_PARENT, "", dtype="str", description="uuid of the parent sdata object")
100
103
  self.metadata.add(self.SDATA_CLASS, self.__class__.__name__, dtype="str", description="sdata class")
101
104
  self.metadata.add(self.SDATA_CTIME, now_utc_str(), dtype="str", description="creation date")
102
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")
103
107
 
104
108
  metadata = kwargs.get("metadata")
105
109
  if metadata is not None:
@@ -150,10 +154,19 @@ class Data(object):
150
154
  # logger.info("uuid new")
151
155
  self._set_uuid(uuid.uuid4())
152
156
 
153
- 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")
154
166
 
155
167
  def gen_suuid(self):
156
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
157
170
 
158
171
  def gen_uuid_from_state(self):
159
172
  """generate the same uuid for the same data
@@ -330,6 +343,15 @@ class Data(object):
330
343
 
331
344
  suuid = property(fget=_get_suuid, fset=_set_suuid, doc="suuid of the object")
332
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
+
333
355
  def _get_uuid(self):
334
356
  return self.metadata.get(self.SDATA_UUID).value
335
357
  # return self._uuid
@@ -969,7 +991,6 @@ class Data(object):
969
991
  exportlines.append(self.metadata.to_csv_header(prefix="#;", sep=";", filepath=None))
970
992
  if self.df is not None:
971
993
  exportlines.append(self.df.to_csv(sep=";"))
972
-
973
994
  exportstr = "".join(exportlines)
974
995
 
975
996
  if filepath is None:
@@ -988,16 +1009,21 @@ class Data(object):
988
1009
  :return: sdata.Data
989
1010
  """
990
1011
  data = cls()
991
- if filepath:
992
- df = pd.read_csv(filepath, sep=";", comment="#", index_col=0)
993
- sio = open(filepath, "r")
994
- elif s is not None:
995
- sio = StringIO(s)
996
- pd.read_csv(sio, sep=";", comment="#")
997
- sio.seek(0)
998
- else:
999
- logger.error("data.from_csv: no csv data available")
1012
+ df = None
1013
+ try:
1014
+ if filepath:
1015
+ df = pd.read_csv(filepath, sep=";", comment="#", index_col=0)
1016
+ sio = open(filepath, "r")
1017
+ elif s is not None:
1018
+ sio = StringIO(s)
1019
+ pd.read_csv(sio, sep=";", comment="#")
1020
+ sio.seek(0)
1021
+ else:
1022
+ logger.error("data.from_csv: no csv data available")
1023
+ except Exception as exp:
1024
+ logging.error(f"{exp}")
1000
1025
  raise
1026
+ return
1001
1027
 
1002
1028
  attritute_list = []
1003
1029
  for line in sio:
@@ -7,6 +7,7 @@ from sdata.timestamp import TimeStamp
7
7
  from sdata.data import Data
8
8
  from sdata.suuid import SUUID
9
9
  from sdata.metadata import Metadata, Attribute
10
+ import sdata.contrib
10
11
  import sdata.contrib.piexif
11
12
  import sdata.contrib.piexif.helper
12
13
  import json
@@ -25,11 +26,22 @@ class Image(Data):
25
26
  highly experimental"""
26
27
 
27
28
 
28
- def __init__(self, **kwargs):
29
+ def __init__(self, url, **kwargs):
29
30
  """Image Object"""
31
+
32
+ # url = kwargs.get("url", "")
33
+ load = kwargs.get("load", False)
34
+ try:
35
+ name = os.path.basename(url)
36
+ except Exception as exp:
37
+ name = None
38
+ if "name" not in kwargs:
39
+ kwargs["name"] = name
30
40
  Data.__init__(self, **kwargs)
31
- self.url = kwargs.get("url", "")
41
+ self.url = url
32
42
  self.img = None
43
+ if load is True:
44
+ self.load()
33
45
 
34
46
  @classmethod
35
47
  def _from_filepath(cls, filepath, **kwargs):
@@ -38,7 +50,10 @@ class Image(Data):
38
50
  """
39
51
  project = kwargs.get("project")
40
52
  suuid = SUUID.from_file(cls.__class__.__name__, filepath, ns_name=project)
41
- data = cls(name=os.path.basename(filepath), uuid=suuid.huuid, url=filepath, **kwargs)
53
+ kwargs["uuid"] = suuid.huuid
54
+ kwargs["url"] = filepath
55
+
56
+ data = cls(name=os.path.basename(filepath), **kwargs)
42
57
  return data
43
58
 
44
59
  @classmethod
@@ -47,13 +62,21 @@ class Image(Data):
47
62
 
48
63
  """
49
64
  project = kwargs.get("project")
50
- suuid = SUUID.from_file(cls.__class__.__name__, filepath, ns_name=project)
65
+ class_name = "Image" #cls.__class__.__name__
66
+ suuid = SUUID.from_file(class_name, filepath, ns_name=project)
67
+ kwargs["sname"] = suuid.sname
68
+ kwargs["uuid"] = suuid.huuid
69
+ kwargs["suuid"] = suuid.idstr
70
+ kwargs["url"] = filepath
71
+ name = os.path.basename(filepath)
72
+
73
+
51
74
  if filepath.lower().endswith(".png"):
52
75
  data = cls.from_png(filepath, **kwargs)
53
76
  elif filepath.lower().endswith(".jpg"):
54
77
  data = cls.from_jpg(filepath, **kwargs)
55
78
  else:
56
- data = cls(name=os.path.basename(filepath), uuid=suuid.huuid, url=filepath, **kwargs)
79
+ data = cls(name=name, **kwargs)
57
80
  return data
58
81
 
59
82
  def get_sha3_256(self, filepath):
@@ -78,6 +101,15 @@ class Image(Data):
78
101
  self.img = PIL.Image.open(self.url)
79
102
  return self.img
80
103
 
104
+ def to_numpy(self):
105
+ """returns a NumPy array created from the color channels of the given Image object
106
+
107
+ array([[[192, 190, 187],
108
+ [193, 190, 187],
109
+ [193, 190, 185],
110
+ """
111
+ return np.array(self.img)
112
+
81
113
  @classmethod
82
114
  def from_png(cls, filepath, **kwargs):
83
115
  """load png image and metadata
@@ -93,12 +125,28 @@ class Image(Data):
93
125
  data.metadata = data.metadata.from_json(d)
94
126
  return data
95
127
 
128
+ @staticmethod
129
+ def _get_metadata(filepath, **kwargs):
130
+ """
131
+
132
+ """
133
+ if filepath.lower().endswith(".png"):
134
+ d = Image._get_png_metadata(filepath, **kwargs)
135
+ elif filepath.lower().endswith(".jpg"):
136
+ d = Image._get_png_metadata(filepath, **kwargs)
137
+ else:
138
+ d = {}
139
+ return d
140
+
96
141
  @staticmethod
97
142
  def _get_png_metadata(filepath, **kwargs):
98
143
  """load metadata json dict from img.info
99
144
  """
100
145
  img = PIL.Image.open(filepath)
101
- d = json.loads(img.info.get("sdata"))
146
+ try:
147
+ d = json.loads(img.info.get("sdata"))
148
+ except Exception as exp:
149
+ d = {}
102
150
  return d
103
151
 
104
152
  @classmethod
@@ -111,9 +159,12 @@ class Image(Data):
111
159
  return
112
160
  data = cls._from_filepath(filepath, **kwargs)
113
161
  # data.load()
114
- d = cls._get_jpg_metadata(filepath)
115
- if d is not None:
116
- data.metadata = data.metadata.from_json(d)
162
+ try:
163
+ d = cls._get_jpg_metadata(filepath)
164
+ if d is not None:
165
+ data.metadata = data.metadata.from_json(d)
166
+ except Exception as exp:
167
+ logging.debug(exp)
117
168
  return data
118
169
 
119
170
  @staticmethod
@@ -130,7 +181,7 @@ class Image(Data):
130
181
  d = json.loads(json_string)
131
182
  return d
132
183
 
133
- def save(self, filepath, rename=True, random=True, **kwargs):
184
+ def saveas(self, filepath, rename=True, random=True, **kwargs):
134
185
  """save image
135
186
 
136
187
  """
@@ -138,17 +189,22 @@ class Image(Data):
138
189
  if rename is True:
139
190
  basename = os.path.basename(filepath)
140
191
  other.rename(basename, random=random)
192
+ other.update_mtime()
193
+ other.save(filepath)
194
+ return other
141
195
 
142
- if other.img is None:
143
- other.load()
196
+ def save(self, filepath, **kwargs):
144
197
 
145
- if filepath.lower().endswith(".png"):
146
- other._save_png(filepath)
198
+ if self.img is None:
199
+ self.load()
200
+
201
+ if filepath.endswith(".png"):
202
+ self._save_png(filepath)
147
203
  elif filepath.lower().endswith(".jpg"):
148
- other._save_jpg(filepath)
204
+ self._save_jpg(filepath)
149
205
  else:
150
206
  logging.warning(f"metadata not supported for {filepath}")
151
- other.img.save(filepath)
207
+ self.img.save(filepath)
152
208
 
153
209
  def _save_png(self, filepath):
154
210
  """save png with metadata
@@ -56,6 +56,7 @@ class Attribute(object):
56
56
  """Attribute class"""
57
57
 
58
58
  DTYPES = {'float': float, 'int': int, 'str': str, 'timestamp': TimeStamp, "bool": bool}
59
+ DTYPES_INV = {v: k for k, v in DTYPES.items()}
59
60
 
60
61
  def __init__(self, name, value, **kwargs):
61
62
  """Attribute
@@ -158,6 +159,8 @@ s
158
159
  """
159
160
  if value is None:
160
161
  return None
162
+ if value in self.DTYPES_INV.keys():
163
+ value = self.DTYPES_INV.get(value, "str")
161
164
  elif "float" in value:
162
165
  value = "float"
163
166
  elif "int" in value:
@@ -259,7 +262,7 @@ class Metadata(object):
259
262
  * type (int, str, float, bool, timestamp)
260
263
  """
261
264
 
262
- ATTRIBUTEKEYS = ["name", "value", "dtype", "unit", "description", "label", "required"]
265
+ ATTRIBUTEKEYS = ["name", "value", "unit", "dtype", "description", "label", "required"]
263
266
 
264
267
  def __init__(self, **kwargs):
265
268
  """Metadata class
@@ -307,7 +310,7 @@ class Metadata(object):
307
310
  attr = name # name is the Attribute!
308
311
  else:
309
312
  attr = self.get_attr(prefix + name) or Attribute(name, value, **kwargs)
310
- for key in ["dtype", "unit", "description", "label", "required"]:
313
+ for key in ["unit", "dtype", "description", "label", "required"]:
311
314
  if key in kwargs:
312
315
  if key in kwargs:
313
316
  # print("!!!", attr, key, kwargs.get(key))
@@ -355,16 +358,21 @@ class Metadata(object):
355
358
  pass
356
359
  return str(value), "str"
357
360
 
358
- def update_from_dict(self, d):
361
+ def update_from_dict(self, d, guess_dtype=True):
359
362
  """set attributes from dict
360
363
 
361
364
  :param d: dict
362
365
  :return:
363
366
  """
364
367
  for k, v in d.items():
365
- 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)
366
373
  if dtype in ["float", "int", "bool"]:
367
- 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}
368
376
  elif isinstance(v, (str,)):
369
377
  v = {"name":k, "value":v, "dtype":"str", "unit":"", "description":"", "label":"", "required":False}
370
378
  elif hasattr(v, "keys"):
@@ -375,7 +383,8 @@ class Metadata(object):
375
383
  "label":v.get("label", ""), "required":v.get("required", False)}
376
384
  else:
377
385
  v, dtype = self.guess_dtype_from_value(v)
378
- 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}
379
388
  self.set_attr(**v)
380
389
 
381
390
  @classmethod
@@ -449,6 +458,9 @@ class Metadata(object):
449
458
  @classmethod
450
459
  def from_dataframe(cls, df):
451
460
  """create metadata from dataframe"""
461
+ df.unit.fillna("", inplace=True)
462
+ df.label.fillna("", inplace=True)
463
+ df.description.fillna("", inplace=True)
452
464
  d = df.to_dict(orient='index')
453
465
  metadata = cls.from_dict(d)
454
466
  return metadata
@@ -533,17 +545,17 @@ class Metadata(object):
533
545
  def from_list(cls, mlist):
534
546
  """create metadata from a list of Attribute values
535
547
 
536
- [['force_x', 1.2, 'float', 'kN', 'force in x-direction'],
537
- ['force_y', 3.1, 'float', 'N', 'force in y-direction', 'label', True]]
548
+ [['force_x', 1.2, 'kN', 'float', 'force in x-direction'],
549
+ ['force_y', 3.1, 'N', 'float', 'force in y-direction', 'label', True]]
538
550
  """
539
551
  metadata = cls()
540
552
  for alist in mlist:
541
553
  if len(alist) < 2:
542
554
  logger.error("Metadata.from_list skip {}".format(alist))
543
555
  else:
544
- alist.extend(["", "", "", ""])
545
- #["name", "value", "dtype", "unit", "description"]
546
- metadata.add(alist[0], alist[1], dtype=alist[2], unit=alist[3], description=alist[4],
556
+ alist.extend(["", "", "", "", ""])
557
+ #["name", "value", "unit", "dtype", "description", "label", "required"]
558
+ metadata.add(alist[0], alist[1], unit=alist[2], dtype=alist[3], description=alist[4],
547
559
  label=alist[5], required=alist[6])
548
560
  return metadata
549
561
 
@@ -618,6 +630,31 @@ class Metadata(object):
618
630
  def __getitem__(self, name):
619
631
  return self.get(name)
620
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
+
621
658
  @property
622
659
  def sha3_256(self):
623
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.5
3
+ Version: 0.23.0
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