Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/oold/validation/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,17 @@ def embedded_properties(schema: dict[str, Any]) -> list[str]:

Shape is the primary signal; a scoped context is a strong hint but not mandatory, since an
embed can also be mapped by the ambient top-level context.

A scoped term only counts where the schema declares a property of that name. A schema must
reflect every ``$ref`` in its ``@context`` (``OOLD-CMP-b926``), including the ones reached
from ``$defs``, so the context carries terms for properties this schema's instances never
hold; treating those as embeds puts a property into the derived frame that no instance can
match, and framing then returns nothing.
"""
properties = collect_composed_properties(schema)
structural = [name for name, prop in properties.items() if is_embed(prop)]
terms = context_terms(schema.get("@context"))
scoped = [term for term, definition in terms.items() if "@context" in definition]
scoped = [term for term, definition in terms.items() if "@context" in definition and term in properties]
# dict.fromkeys dedupes while preserving order, matching the JS Set spread.
return list(dict.fromkeys([*structural, *scoped]))

Expand Down
22 changes: 22 additions & 0 deletions tests/test_validation/test_jsonld.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,28 @@ def test_embedded_properties_follows_allof_composition():
assert embedded_properties(schema) == ["inherited"]


def test_embedded_properties_ignores_a_scoped_term_that_is_not_a_property_here():
"""A $defs subschema's $ref is reflected in the root @context (OOLD-CMP-b926).

Its term carries a scoped @context, but the root object has no such property, so an instance
can never hold one. Counting it would put an unmatchable property into the derived frame.
"""
schema = {
"properties": {"type": {"type": "array", "items": {"type": "string"}}},
"$defs": {"Component": {"properties": {"amount": {"$ref": "https://oo-ld.test/x/MassFraction.schema.json"}}}},
"@context": {
"type": {"@id": "@type", "@container": "@set"},
"amount": {
"@id": "https://example.org/amount",
"@type": "@id",
"@context": "https://oo-ld.test/x/MassFraction.schema.json",
},
},
}
assert embedded_properties(schema) == []
assert "amount" not in schema_to_frame(schema, "https://oo-ld.test/x/C.schema.json")


# ------------------------------------------------------------------ loader


Expand Down
Loading