Repository navigation
Mapping-set selection and rc.2 x-oold-context transform - #154
simontaurus wants to merge 10 commits into
Conversation
Release previewMerging this PR would release v2.4.0 (current: Changelog preview (truncated)## v2.4.0 (2026-11-15)
### Bug Fixes
- **mappings**: Keep a promoted term's scoped @context
([`e87f580`](https://github.com/OO-LD/oold-python/commit/e87f580df7256a014bde51e60047e9d6afc63664))
### Features
- **generate**: Build an instance from authored examples and defaults
([`e23d4d3`](https://github.com/OO-LD/oold-python/commit/e23d4d31eed58dbad0ed43b48652a5ade1e047cc))
- **labels**: Harvest labels from pinned ontology snapshots
([`f1a7b67`](https://github.com/OO-LD/oold-python/commit/f1a7b67086e8a18aa52ced1dfc5871df6ff6558c))
- **locator**: Resolve a published IRI in the working tree
([`e085814`](https://github.com/OO-LD/oold-python/commit/e085814b68c0021b2b7e3fae4f3ab3fd9cf9adde))
- **mappings**: Inline a scoped @context under the selected set
([`bc6a90d`](https://github.com/OO-LD/oold-python/commit/bc6a90d96221c107739020381a0c8faf549aed9b))
- **readings**: Render an instance as RDF per mapping set
([`d6009ab`](https://github.com/OO-LD/oold-python/commit/d6009ab4013feff9151ae3ae14954946a5c08cf1))
- **sssom**: Derive mapping sets from the schemas that carry them
([`73e88db`](https://github.com/OO-LD/oold-python/commit/73e88db9e6cf96d04f1da8ca4211fae8b9fe6a03))
- **utils**: Mapping-set selection and rc.2 x-oold-context transform
([`dfeb43f`](https://github.com/OO-LD/oold-python/commit/dfeb43febec2377b7dc3be65115fdebab023b80d))
- **utils**: Rewrite synonyms in JSON-LD rather than in RDF
([`5b1f25d`](https://github.com/OO-LD/oold-python/commit/5b1f25d0c2020d948e16b759e816bc0331fffc90))
- **validation**: Round-trip an instance under every mapping set
([`cd3f8a5`](https://github.com/OO-LD/oold-python/commit/cd3f8a551e450620a3e7d991da0508c90dc39c09))
Preview via python-semantic-release and conventional commits. |
📊 Benchmark ResultsClick to see benchmark comparisonThreshold: 1.3x (30% slower triggers a regression warning) Note: Benchmarks are informational only and won't fail the build. 💡 Tip: Download the |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
Reviewed at 156b9b0 merged with current Blocking: silent, total data loss. schema = {"@context": CTX, "x-oold-instance-rdf-type": ["ex:Person"], "properties": {...}}
inst = {"id": "https://ex.org/p1", "name": "Jane", "address": {...}}
transform(inst, [schema], [schema])
# -> {'@context': {...}} every triple gone, no error
The RDF detour is not needed, and the reason is not cost. Measured over the schemas.oo-ld.org cases and synthetic graphs, all three candidates agree on every corpus case and separate only on constructed input: So rewriting the dataset dict is the faster of the two viable options, and it still cannot be made correct. An RDF dataset carries no term definitions, so nothing in it separates a Separately, Correctness
Process
|
📊 Benchmark ResultsClick to see benchmark comparisonThreshold: 1.3x (30% slower triggers a regression warning) Note: Benchmarks are informational only and won't fail the build. 💡 Tip: Download the |
- add oold.utils.mappings: promote, mapping_sets, chain, context_of, synonym_entries; the selection OOLD-EXT-4966 describes, complementing validation's promoted_terms which deliberately never chooses - replace the name* alias notation in oold.utils.transform with to_rdf/from_rdf/transform over x-oold-context: exactMatch rewriting, @reverse inversion, @graph framing, @nest shape bridging under a named set (OO-LD/oold-schema#135) - re-encode the alias-notation test cases as x-oold-context, same inputs and expected outputs
- bridge terms carry the rewrite: compact under a context where the term means the synonym IRI, redefine it to the primary IRI, flatten, recompact - a dataset carries no term definitions, so rewriting RDF cannot tell a @vocab-coerced value from a reference to a node - from_rdf reads a JSON-LD document as it stands instead of sending it through RDF and back, keeping @index and @direction - keep jsonld_to_jsonld and json_to_json, deprecated, with their tests - Dataset.default_union, else triples() drops every quad in a named graph
- what a term scopes is a property of the shape, not of the vocabulary - a @reverse synonym lost it, so an embedded object fell back to the consensus terms under a selected set
- inline_scoped resolves a term's scoped @context reference and promotes it with the same mapping set, so an embedded object speaks the vocabulary of the tree it hangs in - ScopeSource states the resolution step as a protocol, keeping the module free of any directory layout - a cyclic reference drops the scoping instead of recursing
- MirrorRule states the IRI-to-path layout as data, so a different tree is a rule rather than a patch - term_chain walks allOf, @context and $ref, which is what a reading needs and wider than the inheritance chain - loader() feeds mappings.chain; a reference the tree cannot reach is skipped, and a cycle terminates
- effective_views promotes each declared set in turn and reports lossless or lossy per reading, which the declared-context checks cannot see - a reading that only changes the document shape is compared as a graph (URDNA2015) rather than as a tree - view_checks reports them as roundtrip.mapping_set records
- readings() returns Turtle plus a Mermaid diagram for the consensus reading and every declared set, and reports a mapping a processor rejects instead of failing the run - blank nodes are skolemised from their URDNA2015 labels, so the same input serialises to the same bytes on every run - named_namespaces names what a serializer would call ns1, ns2
- synth_instance fills a schema from its own examples, defaults and enums only, so a schema with no committed instance still has one to show without inventing a value - a schema whose required properties cannot be filled yields nothing - the inheritance walk it needs is mappings.chain over a Locator
- collect() groups the inline mappings by set, with the consensus ones emitted as a set of their own - crosswalk() chains two sets through the terms they share, and only where one side is an exactMatch - render_set() writes the SSSOM preamble and rows, sorted, so the same mappings give the same file
- a term is labelled by the ontology that owns it, not by one that merely imports it, decided on the local name prefix where there is one - only the IRIs the schemas map are kept, read from the schemas rather than listed - the network lookup is a separate opt-in step, since it is the one part that is neither offline nor reproducible
d57172b to
f1a7b67
Compare
📊 Benchmark ResultsClick to see benchmark comparisonThreshold: 1.3x (30% slower triggers a regression warning) Note: Benchmarks are informational only and won't fail the build. 💡 Tip: Download the |
Changes
oold.utils.mappings(new):promote,mapping_sets,chain,context_of,synonym_entries,inline_scoped. This is the profile-based selectionOOLD-EXT-4966describes; it complementsvalidation.context_resolution.promoted_terms, which deliberately never chooses a synonym (OOLD-EXT-8f62). Ported fromoold-reference-schemas/scripts/{_shared,build_docs}.pyand verified equivalent against that implementation on every module, all schemas, all three mapping sets plus consensus. Two deliberate extensions over the port:mapping_set_idmay be a list (the spec allows it), and a@reversesynonym promotes to@reverserather than an invalid@id+@reversepair.oold.utils.transform(replaced):to_rdf/from_rdf/transformoverx-oold-context. Export promotes a named set; import rewrites everyexactMatchsynonym onto the primary IRI (no set needed), inverts@reverserelations, frames@graphinput viavalidation.frame.schema_to_frame, and bridges document shapes when a promoted fragment carries@nestand a set is named. Readings A/B/C/E of Mapping-set selection can bridge document shapes via @nest, and the spec should say so oold-schema#135 are reproduced exactly and pinned as regression tests, including the boundary that vocabulary is bridged without a selection and shape is not.tests/test_transform.pyrewritten: thename*alias cases are re-encoded asx-oold-contextwith the same inputs and expected outputs, so the change of notation provably does not change what the transformation produces.promotekept a term's scoped@context. A@reversesynonym dropped it, so an embedded object fell back to the consensus terms under a selected set. Direction does not change which terms the object at the end of an edge may use.Notation
x-oold-contextreplaces thename*alias notation as whattransformreads.That notation predates the specification and was never part of it. Nothing in the spec surface changes. The commit stays
feat:.jsonld_to_jsonldandjson_to_jsonare kept, deprecated, with their tests. They are the only readers of the old notation left.Generic tools ported from oold-reference-schemas
Nothing ported assumes a directory layout, a module name or a docs pipeline.
mappings.inline_scopedand theScopeSourceprotocol: resolves a term's scoped@contextfrom the tree and promotes it with the same mapping set. Identical tobuild_docs.inline_scopedon 58 schema and mapping-set combinations.oold.utils.locator:LocatorplusMirrorRule, which states the published-IRI-to-path layout as data.term_chainmatches_shared.chainon every schema. The cycle guard is new, the source recurses forever on one.oold.validation.effective_views: the round trip per mapping set, with the URDNA2015 fallback for a reading that legitimately changes the document shape. Same verdict and triple count asscripts/effective_views.pyon 26 readings.validation/compliance.pyonly ever exercises the declared context, so a defect confined to one set was invisible until now.oold.utils.readings: Turtle and Mermaid per mapping set, returned rather than written. 54 readings byte-identical tobuild_docs.write_rdf.validation.generate.synth_instance: an instance built from a schema's own examples and defaults. Identical on all 15 schemas and to the committed generated instances.inheritedneeded no port,mappings.chainover aLocatorreproduces it exactly.oold.utils.sssom: SSSOM sets and the crosswalk between them. 10 sets identical tobuild_mappings.py, except 51 rows where the source holds a literal0x01byte in place of a back-reference (build_mappings.pyline 209) and emits a relative subject. The port writes what the comment beside it says.oold.utils.labels: label harvest from pinned ontology snapshots.mapped_irisidentical at 121 IRIs, and the harvest over the 16 pinned snapshots reproducesgenerated/labels.jsonbyte for byte.Left out:
scripts/level.py, because OO-LD/oold-reference-schemas#19 changessurface()andcompare(), the two functions a port would consist of.Verification
main, against 804, 10, 1 onmainitself.make checkgreen.mainafter fix(frame): reverse IRI grouping, $ref embeds and default type anchors #179. The tests pass against the newschema_to_frameoutput rather than around it.schema-playgroundin https://github.com/OO-LD/oold-playgrounds/tree/feat/schema-playground vendors exactly these modules pending this PR; once released they can be deleted there.Closes the mappings/transform part of the migration listed in https://github.com/OO-LD/oold-playgrounds/blob/feat/schema-playground/schema-playground/README.md#pending-upstream-migration