sdcreader 4.3.0__tar.gz → 4.3.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 (22) hide show
  1. {sdcreader-4.3.0/src/sdcreader.egg-info → sdcreader-4.3.1}/PKG-INFO +1 -1
  2. {sdcreader-4.3.0 → sdcreader-4.3.1}/pyproject.toml +1 -1
  3. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader/__init__.py +3 -3
  4. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader/record.py +18 -2
  5. {sdcreader-4.3.0 → sdcreader-4.3.1/src/sdcreader.egg-info}/PKG-INFO +1 -1
  6. {sdcreader-4.3.0 → sdcreader-4.3.1}/tests/test_record.py +17 -0
  7. {sdcreader-4.3.0 → sdcreader-4.3.1}/LICENSE +0 -0
  8. {sdcreader-4.3.0 → sdcreader-4.3.1}/NOTICE +0 -0
  9. {sdcreader-4.3.0 → sdcreader-4.3.1}/README.md +0 -0
  10. {sdcreader-4.3.0 → sdcreader-4.3.1}/setup.cfg +0 -0
  11. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader/mcp.py +0 -0
  12. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader/mcp_server.py +0 -0
  13. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader/model.py +0 -0
  14. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader/package.py +0 -0
  15. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader.egg-info/SOURCES.txt +0 -0
  16. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader.egg-info/dependency_links.txt +0 -0
  17. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader.egg-info/entry_points.txt +0 -0
  18. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader.egg-info/requires.txt +0 -0
  19. {sdcreader-4.3.0 → sdcreader-4.3.1}/src/sdcreader.egg-info/top_level.txt +0 -0
  20. {sdcreader-4.3.0 → sdcreader-4.3.1}/tests/test_mcp_scaffold.py +0 -0
  21. {sdcreader-4.3.0 → sdcreader-4.3.1}/tests/test_mcp_server.py +0 -0
  22. {sdcreader-4.3.0 → sdcreader-4.3.1}/tests/test_reader.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdcreader
3
- Version: 4.3.0
3
+ Version: 4.3.1
4
4
  Summary: Read a published Semantic Data Charter model's package for projection into other standards (CDIF, DCAT-US, DCAT-AP, HealthDCAT-AP); MCP server included.
5
5
  Author: Axius SDC, Inc.
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sdcreader"
7
- version = "4.3.0"
7
+ version = "4.3.1"
8
8
  description = "Read a published Semantic Data Charter model's package for projection into other standards (CDIF, DCAT-US, DCAT-AP, HealthDCAT-AP); MCP server included."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -14,10 +14,10 @@ to the component that defines it, Exceptional Values included, for record-level
14
14
  from .model import (CLOSE, DC_DEFAULTS, EXACT, HAS_UNIT, IDENTIFIER, LEAF_TYPES, NUMERIC_TYPES, PUBLISHER, QUANTIFIED_TYPES, SEE_ALSO,
15
15
  SOURCE, Code, Component, Leaf, Model, enumeration_iri, read_header, read_model)
16
16
  from .package import DEFAULT_HOST, ModelPackage, PackageError, fetch_package, load_package
17
- from .record import CONTEXT_ELEMENTS, EXCEPTIONAL_VALUES, RECORD_ATTRIBUTES, ExceptionalValue, Record, RecordError, RecordValue, read_record
17
+ from .record import CONTEXT_ELEMENTS, EXCEPTIONAL_VALUES, RECORD_ATTRIBUTES, VALUE_ELEMENTS, ExceptionalValue, Record, RecordError, RecordValue, read_record
18
18
 
19
- __version__ = "4.3.0"
19
+ __version__ = "4.3.1"
20
20
  __all__ = ["ModelPackage", "PackageError", "DEFAULT_HOST", "load_package", "fetch_package", "read_model", "read_header", "enumeration_iri",
21
21
  "Model", "Component", "Leaf", "Code", "LEAF_TYPES", "NUMERIC_TYPES", "QUANTIFIED_TYPES", "DC_DEFAULTS", "IDENTIFIER", "SOURCE",
22
22
  "PUBLISHER", "EXACT", "CLOSE", "SEE_ALSO", "HAS_UNIT", "read_record", "Record", "RecordValue", "RecordError", "ExceptionalValue",
23
- "EXCEPTIONAL_VALUES", "RECORD_ATTRIBUTES", "CONTEXT_ELEMENTS", "__version__"]
23
+ "EXCEPTIONAL_VALUES", "RECORD_ATTRIBUTES", "CONTEXT_ELEMENTS", "VALUE_ELEMENTS", "__version__"]
@@ -39,6 +39,18 @@ RECORD_ATTRIBUTES = ("dm-label", "dm-language", "dm-encoding", "creation_timesta
39
39
  #: Per-value context elements: what the record says about a value rather than the value itself.
40
40
  CONTEXT_ELEMENTS = ("act", "vtb", "vte", "tr", "modified", "latitude", "longitude")
41
41
 
42
+ #: The elements that hold a value, by the SDC4 reference model (sdc4.xsd), for every value type. A recovery Exceptional
43
+ #: Value stands beside one of these; one written at the source stands in place of them. Units, language, magnitude
44
+ #: status, accuracy, reference ranges and a link's relation describe a value and are not in this set.
45
+ VALUE_ELEMENTS = frozenset({
46
+ "xdstring-value", "xdtoken-value", "true-value", "false-value",
47
+ "xdcount-value", "xdquantity-value", "xdfloat-value", "xddouble-value",
48
+ "xdtemporal-date", "xdtemporal-time", "xdtemporal-datetime", "xdtemporal-duration", "xdtemporal-year",
49
+ "xdtemporal-year-month", "xdtemporal-month", "xdtemporal-month-day", "xdtemporal-day",
50
+ "ordinal", "symbol", "link", "uri", "media-content", "lower", "upper",
51
+ "xdstringlist-value", "xdtokenlist-value", "xddecimallist-value", "xdintegerlist-value",
52
+ })
53
+
42
54
 
43
55
  class RecordError(Exception):
44
56
  pass
@@ -48,7 +60,11 @@ class RecordError(Exception):
48
60
  class ExceptionalValue:
49
61
  code: str # "ASKR"
50
62
  name: str # "Asked and Refused"
51
- origin: str # "source": in place of the value; "recovery": beside a value that failed its constraint
63
+ origin: str # "source": in place of the value; "recovery": beside a value that failed its constraint.
64
+ # Inferred from the record's shape, so a best guess: a published model may require the
65
+ # value element (SDCStudio's generated schemas do, though the reference model leaves it
66
+ # optional), and then a source Exceptional Value sits beside a value too. Whoever inserted
67
+ # Exceptional Values (a validator's recovery) knows the origin for certain.
52
68
 
53
69
 
54
70
  @dataclass
@@ -173,7 +189,7 @@ def _value(el, comp: Component, path: list[Component], occurrence: int, position
173
189
  elements[n] = _nested(c)
174
190
  exceptional = None
175
191
  if ev_code:
176
- value_present = any(k.endswith("-value") or k.startswith("xdtemporal-") for k in elements)
192
+ value_present = any(k in VALUE_ELEMENTS for k in elements)
177
193
  exceptional = ExceptionalValue(code=ev_code, name=EXCEPTIONAL_VALUES[ev_code],
178
194
  origin="recovery" if value_present else "source")
179
195
  return RecordValue(component=comp, path=path, occurrence=occurrence, position=position, elements=elements,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdcreader
3
- Version: 4.3.0
3
+ Version: 4.3.1
4
4
  Summary: Read a published Semantic Data Charter model's package for projection into other standards (CDIF, DCAT-US, DCAT-AP, HealthDCAT-AP); MCP server included.
5
5
  Author: Axius SDC, Inc.
6
6
  License: Apache-2.0
@@ -128,3 +128,20 @@ def test_context_elements_are_kept_apart_from_the_value(model):
128
128
  r = read_record(etree.tostring(tree), model)
129
129
  v = next(v for v in r.values if v.context)
130
130
  assert v.context == {"vtb": "2026-01-01T00:00:00"} and "vtb" not in v.elements
131
+
132
+
133
+ @pytest.mark.parametrize("sdc_type, value_el", [("XdOrdinal", "ordinal"), ("XdLink", "link"), ("XdFile", "uri"),
134
+ ("XdInterval", "lower"), ("XdBoolean", "true-value")])
135
+ def test_recovery_is_recognized_for_every_value_element(model, sdc_type, value_el):
136
+ """4.3.1: a recovery Exceptional Value beside a value whose element does not end in -value (an ordinal, a link,
137
+ a file, an interval) was read as written at the source, and its rejected value was lost."""
138
+ from sdcreader.record import VALUE_ELEMENTS, _value
139
+ from sdcreader.model import Component
140
+ assert value_el in VALUE_ELEMENTS
141
+ el = etree.Element(f"{{{SDC4}}}ms-x")
142
+ etree.SubElement(el, "label").text = "L"
143
+ etree.SubElement(el, f"{{{SDC4}}}INV").append(etree.Element("ev-name"))
144
+ etree.SubElement(el, value_el).text = "bad"
145
+ comp = Component(ct_id="x", sdc_type=sdc_type, label="L", description="", data_type="", constraints={}, links={})
146
+ v = _value(el, comp, [], 0, 0)
147
+ assert v.exceptional.origin == "recovery" and v.rejected == {value_el: "bad"}
File without changes
File without changes
File without changes
File without changes