dccQuantities 2.0.0.dev1__tar.gz → 2.0.0.dev2__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 (47) hide show
  1. {dccquantities-2.0.0.dev1/src/dccQuantities.egg-info → dccquantities-2.0.0.dev2}/PKG-INFO +1 -1
  2. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/pyproject.toml +1 -1
  3. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/AbstractListType.py +2 -1
  4. dccquantities-2.0.0.dev2/src/AbstractQuantityTypeData.py +4 -0
  5. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/AbstractValueType.py +22 -6
  6. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/DccName.py +1 -1
  7. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/DccNoQuantity.py +9 -3
  8. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/DccQuantityTable.py +5 -5
  9. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/DccQuantityType.py +2 -5
  10. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/DccRichContentType.py +1 -1
  11. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/SiRealList.py +59 -10
  12. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2/src/dccQuantities.egg-info}/PKG-INFO +1 -1
  13. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/helpers.py +44 -33
  14. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/parseUncertainties.py +5 -4
  15. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_dccName.py +2 -2
  16. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_parser.py +65 -52
  17. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_serilizer.py +2 -2
  18. dccquantities-2.0.0.dev1/src/AbstractQuantityTypeData.py +0 -10
  19. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/LICENSE +0 -0
  20. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/MANIFEST.in +0 -0
  21. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/README.md +0 -0
  22. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/setup.cfg +0 -0
  23. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/DccCharsXMLList.py +0 -0
  24. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/DccFormulaType.py +0 -0
  25. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/SiComplexList.py +0 -0
  26. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/SiHybrid.py +0 -0
  27. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/SiList.py +0 -0
  28. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/__init__.py +0 -0
  29. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/dccQuantities.egg-info/SOURCES.txt +0 -0
  30. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/dccQuantities.egg-info/dependency_links.txt +0 -0
  31. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/dccQuantities.egg-info/requires.txt +0 -0
  32. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/dccQuantities.egg-info/top_level.txt +0 -0
  33. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/dccQuantityParser.py +0 -0
  34. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/src/testHelpers.py +0 -0
  35. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_DccCharsXMLList.py +0 -0
  36. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_DccNoQuantity.py +0 -0
  37. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_DccQuantityType.py +0 -0
  38. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_SiList.py +0 -0
  39. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_SiRealList.py +0 -0
  40. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_SiRealList_parseData.py +0 -0
  41. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_SiRealList_toDict.py +0 -0
  42. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_generateExampleTableData.py +0 -0
  43. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_getAndProperties.py +0 -0
  44. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_helpers.py +0 -0
  45. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_quantityTypeCollector.py +0 -0
  46. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_surfaceFlatTableGeneration.py +0 -0
  47. {dccquantities-2.0.0.dev1 → dccquantities-2.0.0.dev2}/tests/test_tables.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dccQuantities
3
- Version: 2.0.0.dev1
3
+ Version: 2.0.0.dev2
4
4
  Summary: Python classes for working with DDC calibration data
5
5
  Author: Vanessa Stehr, Thomas Bruns
6
6
  Author-email: Benedikt Seeger <benedikt.seeger@ptb.de>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dccQuantities"
7
- version = "2.0.0.dev1"
7
+ version = "2.0.0.dev2"
8
8
  description = "Python classes for working with DDC calibration data"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -10,7 +10,7 @@ class AbstractListType(AbstractQuantityTypeData):
10
10
  def __init__(self, children: list[Union[AbstractListType,AbstractValueType]]) -> None:
11
11
  super().__init__()
12
12
  self.children = children
13
-
13
+
14
14
  def toJsonDict(self):
15
15
  result = defaultdict(list)
16
16
  for child in self.children:
@@ -19,6 +19,7 @@ class AbstractListType(AbstractQuantityTypeData):
19
19
  result[key].append(value)
20
20
  return dict(result)
21
21
 
22
+
22
23
  def flatten(self):
23
24
  pass
24
25
 
@@ -0,0 +1,4 @@
1
+ class AbstractQuantityTypeData:
2
+ def __init__(self) -> None:
3
+ self._sorted=None
4
+ pass
@@ -1,5 +1,6 @@
1
1
  from datetime import datetime
2
2
  from dsiUnits import dsiUnit
3
+ from numpy.core.defchararray import endswith
3
4
 
4
5
  from AbstractQuantityTypeData import AbstractQuantityTypeData
5
6
  from typing import Union #for python 3.8/3.9 compatibility
@@ -59,7 +60,7 @@ class AbstractValueType(AbstractQuantityTypeData):
59
60
  flattValues = vec_values(flattarray)[0]
60
61
  flattUncs = vec_uncs(flattarray)[0]
61
62
  # okay now we can create the json
62
- suffix = "" if length ==1 else "XMLList"
63
+ suffix = "" if length ==1 and not self._originType.endswith('XMLList') else "XMLList"
63
64
  resultjson = {"si:value"+suffix: flattValues,}
64
65
  if flattUncs and self._uncInfo != None:
65
66
  kfactor=self._uncInfo['coverageFactor']
@@ -72,18 +73,33 @@ class AbstractValueType(AbstractQuantityTypeData):
72
73
  distribution=distribution[0]
73
74
  if not np.all(kfactor==1.0):
74
75
  # we should create expanded uncs now
76
+
77
+ if not "originalUnc" in self._uncInfo:
78
+ # we had no original uncer so wie calculate expanded unc
79
+ uncValues=(np.array(flattUncs) * kfactor).tolist()
80
+ if suffix=='':
81
+ try:
82
+ uncValues=uncValues[0]
83
+ except TypeError:
84
+ # if we cant suscribe it it must be int or float
85
+ pass
86
+ else:
87
+ uncValues=self._uncInfo["originalUnc"]
88
+ if suffix=='':
89
+ try:
90
+ uncValues=uncValues[0]
91
+ except TypeError:
92
+ # if we cant suscribe it it must be int or float
93
+ pass
94
+
75
95
  resultjson["si:measurementUncertaintyUnivariate"+suffix] = {
76
96
  "si:expandedMU"+suffix:{
97
+ "si:valueExpandedMU" + suffix:uncValues,
77
98
  "si:coverageFactor"+suffix:kfactor,
78
99
  "si:coverageProbability"+suffix:covP,
79
100
  "si:distribution"+suffix:distribution
80
101
  }
81
102
  }
82
- if not "originalUnc" in self._uncInfo:
83
- # we had no original uncer so wie calculate expanded unc
84
- resultjson["si:measurementUncertaintyUnivariate"+suffix]["si:valueExpandedMU" + suffix]= (np.array(flattUncs) * kfactor).tolist()
85
- else:
86
- resultjson["si:measurementUncertaintyUnivariate" + suffix]["si:valueExpandedMU" + suffix]=self._uncInfo["originalUnc"]
87
103
  else:
88
104
  resultjson["si:measurementUncertaintyUnivariate"+suffix] = {
89
105
  "si:standardMU"+suffix:{
@@ -67,7 +67,7 @@ class DccName(dict):
67
67
  else:
68
68
  raise TypeError(f"Unsupported type {type(other)} for matching")
69
69
 
70
- def toJsonDict(self):
70
+ def to_json_dict(self):
71
71
  return {'dcc:name':{'dcc:content': [{'@lang': key, '$': value} for key, value in dict(self).items()]}}
72
72
 
73
73
  def merge_names(self, insertion: str, other: Union['DccName', str, float, int, None]):
@@ -11,7 +11,6 @@ from DccRichContentType import (
11
11
  )
12
12
  from DccName import DccName
13
13
 
14
-
15
14
  class DccNoQuantity(AbstractQuantityTypeData):
16
15
  def __init__(
17
16
  self,
@@ -48,8 +47,9 @@ class DccNoQuantity(AbstractQuantityTypeData):
48
47
  if len(paramStr) > 0:
49
48
  paramStr = " (" + paramStr + ")"
50
49
  return f"{str(self.data)}{paramStr}"
51
-
50
+
52
51
  def toJsonDict(self) -> dict:
52
+ privateKeys=['_sorted']
53
53
  keyMapping = {
54
54
  'id': '@id',
55
55
  'refId': '@refId',
@@ -68,9 +68,15 @@ class DccNoQuantity(AbstractQuantityTypeData):
68
68
  elif key == 'data':
69
69
  for key, value in self.data.items():
70
70
  if value is not None:
71
- result[dataKeyMapping[key]] = value
71
+ if isinstance(value,list):
72
+ if len(value) >0: #skip empty lists
73
+ result[dataKeyMapping[key]] = []
74
+ for item in value:
75
+ result[dataKeyMapping[key]].append(item.toJSONDict())
72
76
  if set(self.data.keys()) - set(dataKeyMapping.keys()):
73
77
  pass # TODO: This should not happen, maybe add a warning?
78
+ elif key in privateKeys:
79
+ pass
74
80
  else:
75
81
  # Use the fallback handler for unexpected keys.
76
82
  unexpected_key_serialization_handler(result, key, value, self.__class__.__name__)
@@ -459,7 +459,7 @@ class DccLongTable(DccQuantityTable):
459
459
  FieldSpec(
460
460
  name=None,
461
461
  tag="dcc:name",
462
- serializer=lambda s: s.name.toJsonDict()["dcc:name"] if s.name else None
462
+ serializer=lambda s: s.name.to_json_dict()["dcc:name"] if s.name else None
463
463
  ),
464
464
 
465
465
  # 2. description
@@ -606,7 +606,7 @@ class DccLongTable(DccQuantityTable):
606
606
  all_quants = idxs + vals
607
607
 
608
608
  return [
609
- q.toJsonDict()["dcc:quantity"]
609
+ q.to_json_dict()
610
610
  for q in all_quants
611
611
  ]
612
612
 
@@ -637,7 +637,7 @@ class DccFlatTable(DccQuantityTable):
637
637
  FieldSpec(
638
638
  name=None,
639
639
  tag="dcc:name",
640
- serializer=lambda s: s.name.toJsonDict()["dcc:name"] if s.name else None
640
+ serializer=lambda s: s.name.to_json_dict()["dcc:name"] if s.name else None
641
641
  ),
642
642
 
643
643
  # 2. description
@@ -745,12 +745,12 @@ class DccFlatTable(DccQuantityTable):
745
745
  """
746
746
  # helper to build one wrapper
747
747
  def make_wrapper(title: dict, ref_type: list[str], quants: list):
748
- wrapper = DccName(title).toJsonDict() # yields {'dcc:name': ...}
748
+ wrapper = DccName(title).to_json_dict() # yields {'dcc:name': ...}
749
749
  wrapper["@refType"] = ref_type
750
750
  # each quant.toJsonDict() returns {'dcc:quantity': {...}}
751
751
  # we pull out that inner dict
752
752
  wrapper["dcc:quantity"] = [
753
- q.toJsonDict()["dcc:quantity"] for q in quants
753
+ q.to_json_dict() for q in quants
754
754
  ]
755
755
  return wrapper
756
756
 
@@ -28,7 +28,7 @@ class DccQuantityType(ExplicitSerializerMixin):
28
28
  FieldSpec(
29
29
  name=None,
30
30
  tag="dcc:name",
31
- serializer=lambda s: s.name.toJsonDict()["dcc:name"]
31
+ serializer=lambda s: s.name.to_json_dict()["dcc:name"]
32
32
  ),
33
33
 
34
34
  # 2. description (raw dict under 'dcc:description')
@@ -223,7 +223,4 @@ class DccQuantityType(ExplicitSerializerMixin):
223
223
  """
224
224
  Wrap the ordered fields under the <dcc:quantity> root.
225
225
  """
226
- return {"dcc:quantity": self.to_dict()}
227
-
228
- # keep backwards‐compatibility if code calls toJsonDict()
229
- toJsonDict = to_json_dict
226
+ return self.to_dict()
@@ -36,7 +36,7 @@ class DccContent:
36
36
  # Use the fallback handler for unexpected keys.
37
37
  unexpected_key_serialization_handler(result, key, value, self.__class__.__name__)
38
38
 
39
- return {'dcc:content': result}
39
+ return result
40
40
 
41
41
 
42
42
  def parseDccContent(jsonDict):
@@ -14,28 +14,47 @@ from parseUncertainties import parseUncertainties, uncertaintyKeys
14
14
  import numpy as np
15
15
  from helpers import FieldSpec,ExplicitSerializerMixin
16
16
 
17
-
18
17
  class SiRealList(ExplicitSerializerMixin,AbstractValueType):
19
- # 1) FieldSpec list for singlevalue serialization
18
+ # 1) Specs for the singlevalue form
20
19
  __single_specs__ = [
21
- # (attr_name, output_tag, serializer, merge)
20
+ # optional label first
22
21
  FieldSpec("label", "si:label",
23
22
  lambda s: s.label[0] if isinstance(s.label, list) else s.label),
24
- # merge in whatever serilizeDataToJSON() returns (expects {'si:value':…, …})
25
- FieldSpec(None, None, "serilizeDataToJSON", merge=True),
23
+
24
+ # raw value
25
+ FieldSpec(None, "si:value", "serialize_value", merge=False),
26
+
27
+ # unit
26
28
  FieldSpec("unit", "si:unit",
27
29
  lambda s: str(s.unit[0])),
30
+
31
+ # timestamp
28
32
  FieldSpec("dateTime", "si:dateTime",
29
33
  lambda s: s.dateTime[0] if isinstance(s.dateTime, list) else s.dateTime),
34
+
35
+ # then any measurementUncertainty…
36
+ FieldSpec(None, "si:measurementUncertaintyUnivariate",
37
+ "serialize_unc", merge=True),
30
38
  ]
39
+ # For unkown reason the order of sireal and sireallist ist not consitent, WTF!
31
40
 
32
- # 2) FieldSpec list for list serialization
41
+ # 2) Specs for the list‐value form
33
42
  __list_specs__ = [
34
- FieldSpec("label", "si:labelXMLList", lambda s: s.label),
35
- FieldSpec("dateTime", "si:dateTimeXMLList",lambda s: s.dateTime),
36
- FieldSpec(None, None, "serilizeDataToJSON", merge=True), # merge in data dict (expects {'si:valueXMLList':…, …})
37
- FieldSpec("unit", "si:unitXMLList", lambda s: [str(u) for u in s.unit]),
43
+ # optional label list
44
+ FieldSpec("label", "si:labelXMLList", lambda s: s.label),
45
+
46
+ # array of values
47
+ FieldSpec(None, "si:valueXMLList", "serialize_value", merge=False),
48
+
49
+ # list‐unit
50
+ FieldSpec("unit", "si:unitXMLList", lambda s: [str(u) for u in s.unit]),
38
51
 
52
+ # optional timestamp list
53
+ FieldSpec("dateTime", "si:dateTimeXMLList", lambda s: s.dateTime),
54
+
55
+ # then any list‐uncertainty
56
+ FieldSpec(None, "si:measurementUncertaintyUnivariateXMLList",
57
+ "serialize_unc", merge=True),
39
58
  ]
40
59
 
41
60
  def __init__(
@@ -173,6 +192,36 @@ class SiRealList(ExplicitSerializerMixin,AbstractValueType):
173
192
  # 3) Wrap under the correct root element
174
193
  return {root: ordered}
175
194
 
195
+ # ————— helper methods for those specs —————
196
+
197
+ def serialize_value(self):
198
+ """
199
+ Return just the flattened 'si:value' or 'si:valueXMLList' entry
200
+ from serilizeDataToJSON().
201
+ """
202
+ if not hasattr(self,'_data'):
203
+ self._data = self.serilizeDataToJSON()
204
+ for key, val in self._data.items():
205
+ if key.startswith("si:value"):
206
+ return val
207
+ return None
208
+
209
+ def serialize_unc(self):
210
+ """
211
+ Return only the uncertainty sub-dict (everything *except* the 'si:value…'
212
+ keys) from serilizeDataToJSON(), so it merges in the correct position.
213
+ """
214
+ # we dont need to copy since unc will allways call after the values ...
215
+ if not hasattr(self, '_data'):
216
+ self._data = self.serilizeDataToJSON()
217
+ for key in list(self._data.keys()):
218
+ if key.startswith("si:value"):
219
+ self._data.pop(key)
220
+ out=deepcopy(self._data)
221
+ del self._data
222
+ #we will delete '_data' since we don't need it anymore ... if we serialize again, we will create it again completely to prevent race conditions ...
223
+ return out
224
+
176
225
  def __neg__(self):
177
226
  new_data = [-item for item in self.data]
178
227
  return SiRealList(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dccQuantities
3
- Version: 2.0.0.dev1
3
+ Version: 2.0.0.dev2
4
4
  Summary: Python classes for working with DDC calibration data
5
5
  Author: Vanessa Stehr, Thomas Bruns
6
6
  Author-email: Benedikt Seeger <benedikt.seeger@ptb.de>
@@ -33,10 +33,15 @@ _REGEX_TYPE = type(re.compile(''))
33
33
  class DCCJSONEncoder(json.JSONEncoder):
34
34
  def default(self, obj):
35
35
  # If the object has a callable toJSON method, use it.
36
+ if hasattr(obj, 'to_json_dict') and callable(obj.to_json_dict):
37
+ return obj.to_json_dict()
38
+
36
39
  if hasattr(obj, 'toJSONDict') and callable(obj.toJSONDict):
37
40
  return obj.toJSONDict()
41
+
38
42
  elif hasattr(obj, 'toJSON') and callable(obj.toJSON):
39
43
  return obj.toJSON()
44
+
40
45
  elif isinstance(obj, dsiUnit):
41
46
  return str(obj)
42
47
  # 3a) explicit DateTime10
@@ -79,42 +84,48 @@ class ExplicitSerializerMixin:
79
84
  """
80
85
  out = OrderedDict()
81
86
  for spec in self.__serialize_fields__:
82
- # Determine raw value
83
- if spec.serializer is None:
84
- val = getattr(self, spec.name)
85
- elif isinstance(spec.serializer, tuple):
86
- method, key = spec.serializer
87
- temp = getattr(self, method)() if isinstance(method, str) else method(self)
88
- val = temp[key]
89
- elif isinstance(spec.serializer, str):
90
- val = getattr(self, spec.serializer)()
91
- else:
92
- val = spec.serializer(self)
87
+ try:
88
+ # Determine raw value
89
+ if spec.serializer is None:
90
+ val = getattr(self, spec.name, None)
91
+ elif isinstance(spec.serializer, tuple):
92
+ method, key = spec.serializer
93
+ temp = getattr(self, method)() if isinstance(method, str) else method(self)
94
+ val = temp.get(key) if isinstance(temp, dict) else None
95
+ elif isinstance(spec.serializer, str):
96
+ val = getattr(self, spec.serializer)()
97
+ else:
98
+ val = spec.serializer(self)
99
+
100
+ # Skip None or empty collections/arrays
101
+ if val is None:
102
+ continue
103
+ if isinstance(val, (list, tuple, dict, set)) and len(val) == 0:
104
+ continue
105
+ if isinstance(val, np.ndarray) and val.size == 0:
106
+ continue
107
+
108
+ # Merge dict or assign directly
109
+ if spec.merge:
110
+ if not isinstance(val, dict):
111
+ raise ValueError(f"Field {spec.name} expected to merge a dict, got {type(val)}")
112
+ for k, v in val.items():
113
+ if v in [None, [], {}, (), set()] or (isinstance(v, np.ndarray) and v.size == 0):
114
+ continue
115
+ out[k] = v
116
+ else:
117
+ out[spec.tag or spec.name] = val
93
118
 
94
- # Skip None or empty collections/arrays
95
- if val is None:
96
- continue
97
- if isinstance(val, (list, tuple, dict, set)) and len(val) == 0:
98
- continue
99
- if isinstance(val, np.ndarray) and val.size == 0:
119
+ except Exception as e:
120
+ # Silently skip common NoneType attribute access errors (e.g., s.name.to_json_dict())
121
+ if isinstance(e, AttributeError) and "'NoneType'" in str(e):
122
+ continue
123
+ warnings.warn(
124
+ f"Serialization of field {spec.name or spec.tag} failed in {self.__class__.__name__}: {e}",
125
+ RuntimeWarning
126
+ )
100
127
  continue
101
128
 
102
- # Merge dict or assign directly
103
- if spec.merge:
104
- if not isinstance(val, dict):
105
- raise ValueError(f"Field {spec.name} expected to merge a dict, got {type(val)}")
106
- for k, v in val.items():
107
- # Also treat any empty collections in merged dict as skip
108
- if v is None:
109
- continue
110
- if isinstance(v, (list, tuple, dict, set)) and len(v) == 0:
111
- continue
112
- if isinstance(v, np.ndarray) and v.size == 0:
113
- continue
114
- out[k] = v
115
- else:
116
- out[spec.tag or spec.name] = val
117
-
118
129
  return out
119
130
 
120
131
  def to_json_dict(self) -> dict:
@@ -51,6 +51,7 @@ def parseUncertainties(jsonDict: dict, data: list, relativeUncertainty: dict = N
51
51
 
52
52
  def parseExpandedUnc(jsonDict: dict, data: list, relativeUncertainty: dict = None):
53
53
  uncData = {}
54
+ #TODO we will lose keys if one of the predescending wasn't defined NEDS TO BE CHANGED ASAP
54
55
  if "si:expandedUnc" in jsonDict.keys():
55
56
  uncJsonData = jsonDict["si:expandedUnc"]
56
57
  uncData["uncertainty"] = uncJsonData["si:uncertainty"]
@@ -73,13 +74,13 @@ def parseExpandedUnc(jsonDict: dict, data: list, relativeUncertainty: dict = Non
73
74
  )
74
75
  elif "si:measurementUncertaintyUnivariate" in jsonDict.keys():
75
76
  try:
76
- uncJsonData = jsonDict["si:measurementUncertaintyUnivariate"]
77
- uncData["uncertainty"] = uncJsonData["si:measurementUncertaintyUnivariate"]
77
+ uncJsonData = jsonDict["si:measurementUncertaintyUnivariate"]['si:expandedMU']
78
+ uncData["uncertainty"] = uncJsonData['si:valueExpandedMU']
78
79
  uncData["coverageFactor"] = uncJsonData["si:coverageFactor"]
79
80
  uncData["coverageProbability"] = uncJsonData["si:coverageProbability"]
80
81
  uncData["distribution"] = (
81
- uncJsonData["si:distributionXMLList"]
82
- if "si:distributionXMLList" in uncJsonData.keys()
82
+ uncJsonData["si:distribution"]
83
+ if "si:distribution" in uncJsonData.keys()
83
84
  else ["normal"]
84
85
  )
85
86
  except Exception as e:
@@ -1,11 +1,11 @@
1
1
  import pytest
2
2
  from DccName import DccName
3
3
 
4
- def test_toJsonDict():
4
+ def test_to_json_dict():
5
5
  jsonDict = {'dcc:name':{'dcc:content': [{'@lang': 'en', '$': 'Room temperature during calibration'}, {'@lang': 'de', '$': 'Raumtemperatur währenden der Kalibration'}]}}
6
6
  parsedDict = {'en': 'Room temperature during calibration', 'de': 'Raumtemperatur währenden der Kalibration'}
7
7
  nameInstance = DccName(parsedDict)
8
- generatedJsonDict = nameInstance.toJsonDict()
8
+ generatedJsonDict = nameInstance.to_json_dict()
9
9
  assert jsonDict == generatedJsonDict
10
10
 
11
11
  def test_matches_with_subset_dict():
@@ -13,6 +13,71 @@ from helpers import replaceQuantitiesInDict,DCCJSONEncoder
13
13
  from dccXMLJSONConv.dccConv import XMLToDict,DictToXML
14
14
  from dccQuantityParser import parseItemFromJsonDict
15
15
  from xmlschema import XMLSchemaValidationError
16
+ import copy
17
+
18
+ @pytest.mark.filterwarnings("ignore:Parsing a correctly marked non D-SI unit")
19
+ @pytest.mark.filterwarnings("ignore:The identifier .* does not match any D-SI units!")
20
+ def test_allFilesBackAndForthSer():
21
+ # load our list of known-invalid files
22
+ filePath = get_test_file(
23
+ "tests", "data", "private", "1_7calibrationanddccsampledata",
24
+ "AndereScheine", "grabbedFiles", "validation_results.json"
25
+ )
26
+ dirPath = get_test_file(
27
+ "tests", "data", "private", "1_7calibrationanddccsampledata",
28
+ "AndereScheine", "grabbedFiles")
29
+ with open(filePath, "r") as validationFile:
30
+ validationDict = json.load(validationFile)
31
+ invalidFileNames = [
32
+ "dcc-2019-75056_mod.xml",
33
+ "DCCTableXMLStub.xml",
34
+ "test_xmlDumpingSingleQuantNoUncer.xml",
35
+ "test_dccQuantTabXMLDumping.xml",
36
+ "CalSchein_20220708_8305_SN1842876.xml",
37
+ "dcc-vacuumlab-CDG.xml",
38
+ "acoustics_refTypeDefinition.xml"
39
+ ]
40
+ # add any others flagged in the validation results
41
+ invalidFileNames += [
42
+ entry["Invalid File"] for entry in validationDict.values()
43
+ ]
44
+ allowed_reason = "value doesn't match any pattern of ['3\\\\.3\\\\.0']"
45
+ # iterate every XML that isn't already known-bad
46
+ #TODO test all files and fix things like quants WO a name
47
+ for fileCount,xmlFile in enumerate(dirPath.rglob("*.xml")):
48
+ #for xmlFile in [get_test_file( "tests", "data", "private", "1_7calibrationanddccsampledata","sinCal","sin_acceleration_example_dcc","sin_acceleration_example_dcc_WithExampleConformatyStatment.xml")]:
49
+ if xmlFile.name in invalidFileNames:
50
+ continue
51
+ with open(xmlFile, "r") as f:
52
+ xml_text = f.read()
53
+ xmlDict, errors = XMLToDict(xml_text)
54
+ # update schema Version brutaly to 3.3.0
55
+ xmlDict['@xsi:schemaLocation']=r'https://ptb.de/dcc https://ptb.de/dcc/v3.3.0/dcc.xsd'
56
+ xmlDict['@schemaVersion'] = '3.3.0'
57
+
58
+ xmlDictcopy=copy.deepcopy(xmlDict)
59
+
60
+ serDict, quantList = replaceQuantitiesInDict(xmlDictcopy, parser=parseItemFromJsonDict,returnQuantityList=True)
61
+ assert len(quantList) > 0
62
+ json_text = json.dumps(serDict, cls=DCCJSONEncoder)
63
+ dictForConversion=json.loads(json_text)
64
+ xml_out, root_elem, errors = DictToXML(dictForConversion)
65
+ assert xml_out, f"No XML produced for {xmlFile.name}"
66
+ # Filter out the one allowed schema‐validation complaint
67
+ remaining = [
68
+ err for err in errors
69
+ if not (
70
+ isinstance(err, XMLSchemaValidationError)
71
+ and err.reason.startswith("value doesn't match any pattern of ")
72
+ )
73
+ ]
74
+ # If anything unexpected remains, fail
75
+ assert not remaining, (
76
+ f"Unexpected validation errors in {xmlFile.name}:\n"
77
+ + "\n".join(f" • {type(err).__name__}: {getattr(err, 'reason', err)}"
78
+ for err in remaining)
79
+ )
80
+
16
81
 
17
82
  def test_parsedQuantValuesAndFunctions(): # Use the correct relative paths
18
83
  try:
@@ -152,55 +217,3 @@ def test_allFiles():
152
217
  except Exception as e:
153
218
  raise e
154
219
 
155
- @pytest.mark.filterwarnings("ignore:Parsing a correctly marked non D-SI unit")
156
- @pytest.mark.filterwarnings("ignore:The identifier .* does not match any D-SI units!")
157
- def test_allFilesBackAndForthSer():
158
- # load our list of known-invalid files
159
- filePath = get_test_file(
160
- "tests", "data", "private", "1_7calibrationanddccsampledata",
161
- "AndereScheine", "grabbedFiles", "validation_results.json"
162
- )
163
- dirPath = get_test_file(
164
- "tests", "data", "private", "1_7calibrationanddccsampledata",
165
- "AndereScheine", "grabbedFiles")
166
- with open(filePath, "r") as validationFile:
167
- validationDict = json.load(validationFile)
168
- invalidFileNames = [
169
- "dcc-2019-75056_mod.xml",
170
- "DCCTableXMLStub.xml",
171
- "test_xmlDumpingSingleQuantNoUncer.xml",
172
- "test_dccQuantTabXMLDumping.xml",
173
- "CalSchein_20220708_8305_SN1842876.xml",
174
- "dcc-vacuumlab-CDG.xml",
175
- "acoustics_refTypeDefinition.xml"
176
- ]
177
- # add any others flagged in the validation results
178
- invalidFileNames += [
179
- entry["Invalid File"] for entry in validationDict.values()
180
- ]
181
- allowed_reason = "value doesn't match any pattern of ['3\\\\.3\\\\.0']"
182
- # iterate every XML that isn't already known-bad
183
- for xmlFile in dirPath.rglob("*.xml"):
184
- if xmlFile.name in invalidFileNames:
185
- continue
186
- with open(xmlFile, "r") as f:
187
- xml_text = f.read()
188
- xmlDict = XMLToDict(xml_text)
189
- serDict, errors = replaceQuantitiesInDict(xmlDict, parser=parseItemFromJsonDict)
190
- json_text = json.dumps(serDict, cls=DCCJSONEncoder)
191
- xml_out, root_elem, errors = DictToXML(json.loads(json_text))
192
- assert xml_out, f"No XML produced for {xmlFile.name}"
193
- # Filter out the one allowed schema‐validation complaint
194
- remaining = [
195
- err for err in errors
196
- if not (
197
- isinstance(err, XMLSchemaValidationError)
198
- and err.reason.startswith("value doesn't match any pattern of ")
199
- )
200
- ]
201
- # If anything unexpected remains, fail
202
- assert not remaining, (
203
- f"Unexpected validation errors in {xmlFile.name}:\n"
204
- + "\n".join(f" • {type(err).__name__}: {getattr(err, 'reason', err)}"
205
- for err in remaining)
206
- )
@@ -38,12 +38,12 @@ def test_basic():
38
38
  warnings.warn(str(e))
39
39
  serilizedData=[]
40
40
  for q in dccQunats:
41
- serilizedData.append(q.toJsonDict())
41
+ serilizedData.append(q.to_json_dict())
42
42
  # check if the first key is 'dcc:qunatity'
43
43
  for i,serilized in enumerate(serilizedData):
44
44
  try:
45
45
  jsonSTR=json.dumps(serilized, cls=DCCJSONEncoder)
46
46
  except TypeError as te:
47
47
  raise te # to catch unimplemented cases
48
- simplejsonDict=loads(jsonSTR)['dcc:quantity']
48
+ simplejsonDict=loads(jsonSTR)
49
49
  inputJSONDict=quantityDict[i][1]
@@ -1,10 +0,0 @@
1
- class AbstractQuantityTypeData:
2
- def __init__(self) -> None:
3
- self._sorted=None
4
- pass
5
-
6
- def __len__(self):
7
- return NotImplemented
8
-
9
- def toJsonDict(self):
10
- return NotImplemented