Skip to content

Commit 95bd561

Browse files
committed
test: cover def pruning and the v1 requiredness spelling
1 parent 77f7d85 commit 95bd561

2 files changed

Lines changed: 48 additions & 2 deletions

File tree

‎src/oold/static.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -938,13 +938,13 @@ def _prune_unreferenced_defs(schema: dict) -> None:
938938
if not isinstance(defs, dict):
939939
return
940940

941-
def referenced(node: Any, skip: str | None = None) -> set:
941+
def referenced(node: Any) -> set:
942942
out: set = set()
943943
if isinstance(node, dict):
944944
for key, value in node.items():
945945
if key == "$ref" and isinstance(value, str) and value.startswith("#/$defs/"):
946946
out.add(value.split("/")[-1])
947-
elif not (skip and key == "$defs"):
947+
else:
948948
out |= referenced(value)
949949
elif isinstance(node, list):
950950
for item in node:

‎tests/test_validation/test_schema_levels.py‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,49 @@ def test_both_levels_validate(tmp_path):
123123
(tmp_path / f"{name}.json").write_text(json.dumps(schema, indent=2), encoding="utf-8")
124124
report = validate_schema(tmp_path / "Person.schema.json")
125125
assert report.passed, failure_reasons(report)
126+
127+
128+
def test_a_definition_reached_only_through_another_is_kept():
129+
"""Reachability is transitive: `$defs.Outer` is referenced from the body and
130+
itself references `$defs.Inner`, so neither is dead. Pruning only what the
131+
body points at directly would delete Inner and break the schema."""
132+
from oold.static import _prune_unreferenced_defs
133+
134+
schema = {
135+
"properties": {"a": {"$ref": "#/$defs/Outer"}},
136+
"$defs": {
137+
"Outer": {"properties": {"b": {"$ref": "#/$defs/Inner"}}},
138+
"Inner": {"type": "string"},
139+
"Orphan": {"type": "string"},
140+
},
141+
}
142+
_prune_unreferenced_defs(schema)
143+
assert sorted(schema["$defs"]) == ["Inner", "Outer"]
144+
145+
146+
def test_defs_disappears_when_nothing_survives():
147+
from oold.static import _prune_unreferenced_defs
148+
149+
schema = {"properties": {}, "$defs": {"Orphan": {"type": "string"}}}
150+
_prune_unreferenced_defs(schema)
151+
assert "$defs" not in schema
152+
153+
154+
def test_the_v1_underscore_spelling_is_normalised_too():
155+
"""pydantic v1 cannot pass a hyphenated keyword to Field(), so downstream
156+
spells it with underscores. Both reach `required` and neither survives."""
157+
from oold.static import _state_requiredness_in_the_required_array
158+
159+
schema = {
160+
"properties": {
161+
"a": {"type": "string", "x_oold_required_iri": True, "default": None},
162+
"b": {"type": "string", "x-oold-required-iri": True},
163+
"c": {"type": "string", "default": None},
164+
}
165+
}
166+
_state_requiredness_in_the_required_array(schema)
167+
assert sorted(schema["required"]) == ["a", "b"]
168+
assert "default" not in schema["properties"]["a"]
169+
assert not any(k.startswith(("x-oold-required", "x_oold_required")) for k in schema["properties"]["a"])
170+
# an optional property keeps its default and stays out of `required`
171+
assert schema["properties"]["c"]["default"] is None

0 commit comments

Comments
 (0)