feat(context): add --xsd-anyuri-as-iri flag for IRI type coercion#3
feat(context): add --xsd-anyuri-as-iri flag for IRI type coercion#3
Conversation
5e372a8 to
d279be0
Compare
🔍 Adversarial Review — PR #3SummaryWell-structured feature with clean opt-in design. The JSON-LD context generator changes are solid and well-tested. However, the OWL generator changes introduce a cross-generator inconsistency for 🐛 Bugs & Issues1. Cross-generator inconsistency for The OWL generator uses
All three generators disagree on Fix: Either (a) use a URI-check consistent with the JSON-LD context generator (checking the resolved 2. When the flag is set and range is URI-like, no this_expr = self._intersection_of(owl_exprs=[], owl_types={OWL.Thing})
This is technically valid OWL but: (a) the
|
| Missing Test | Risk | Priority |
|---|---|---|
uriorcurie range with flag |
uriorcurie also maps to xsd:anyURI — should verify same behavior as uri |
High |
curie range with flag |
Exposes the cross-generator inconsistency bug above | High |
| SHACL consistency test | Verify SHACL still emits sh:IRI and doesn't conflict with OWL output |
Medium |
| CLI integration test | Verify --xsd-anyuri-as-iri flag is wired correctly through Click |
Medium |
_range_is_datatype unit test |
Verify False return for URI ranges doesn't break downstream | Medium |
OWL output for any_of with URI + class |
JSON-LD has test_xsd_anyuri_as_iri_with_any_of but OWL doesn't |
Medium |
| Inherited/custom URI types | is_uri_range checks ancestors — verify a custom type inheriting from uri works |
Low |
type_objects=True interaction |
OWL generator with both type_objects=True and xsd_anyuri_as_iri=True |
Low |
📋 Fix Plan
- [Bug Fix] Align OWL generator's URI-range check with JSON-LD context generator — either check the resolved
type_uriagainstXSD.anyURIinstead of callingis_uri_range(), or guardis_uri_range()with an additionaltype_uricheck to excludecurie(which maps toxsd:string) - [Bug Fix] Handle the
Nonereturn from_intersection_ofwhenowl_exprsis empty — consider returning early fromtransform_class_slot_expressionwith a sentinel instead of lettingNonepollutenode_owltypes - [Test] Add
uriorcurierange test for both JSON-LD and OWL generators - [Test] Add
curierange test that documents the expected cross-generator behavior - [Test] Add SHACL consistency assertion (e.g., verify
sh:nodeKind sh:IRIis emitted forurirange regardless of flag) - [Docs] Update PR title scope to reflect OWL changes
✅ What's Good
- Clean opt-in design — defaults to
False, zero behavioral change for existing users - Excellent docstrings with W3C spec references and cross-generator alignment notes
_literal_coercion_for_rangeschange is surgical — correctly handlesany_ofmixed branchesis_uri_rangereuse fromcommon/subproperty— shares the SHACL generator's type-ancestry logic instead of reimplementing- Test for
any_ofmixed branches — this is a non-obvious edge case and the test catches it well - Both generators get CLI flags — consistent UX across
gen-jsonld-contextandgen-owl
06037d3 to
9e4b11f
Compare
… consistency JSON-LD processors treat xsd:anyURI as an opaque string literal, so range:uri/uriorcurie slots get xsd:anyURI coercion instead of proper IRI node semantics (@type:@id, owl:ObjectProperty, sh:IRI). Add an opt-in --xsd-anyuri-as-iri flag that promotes xsd:anyURI ranges to IRI semantics across all three generators: - JSON-LD context: @type: xsd:anyURI → @type: @id - OWL: DatatypeProperty → ObjectProperty (no rdfs:range restriction) - SHACL: sh:datatype xsd:anyURI → sh:nodeKind sh:IRI The flag only affects types whose XSD mapping is xsd:anyURI (uri and uriorcurie). The curie type (xsd:string) is correctly excluded via is_xsd_anyuri_range() to maintain cross-generator consistency. Standards basis: - OWL 2 §5.3-5.4 (ObjectProperty vs DatatypeProperty) - SHACL §4.8.1 (sh:nodeKind sh:IRI) - JSON-LD 1.1 §4.2.2 (type coercion with @id) - RDF 1.1 §3.2-3.3 (IRIs as first-class nodes, not string literals) Signed-off-by: jdsika <carlo.van-driesten@bmw.de>
9e4b11f to
acc2df3
Compare
Summary
Add an
--xsd-anyuri-as-iriflag to the JSON-LD context generator that emits"@type": "@id"forxsd:anyURIslots instead of the default"@type": "xsd:anyURI".Problem
JSON-LD processors treat
xsd:anyURIvalues as plain strings. When a LinkML slot has rangeuri(mapped toxsd:anyURI), the generated context marks it as a string type. Downstream RDF consumers then cannot distinguish IRIs from string literals.Solution
When
--xsd-anyuri-as-iriis set, the context generator checks whether a slot's range resolves toxsd:anyURIand, if so, emits"@type": "@id"to ensure the value is interpreted as an IRI reference during JSON-LD expansion.Testing
Existing tests pass. The flag defaults to
False, preserving current behaviour.