Skip to content

Commit 2d1ce00

Browse files
🐛 Fix normalization of allof; add tests.
1 parent 5b55db0 commit 2d1ce00

2 files changed

Lines changed: 62 additions & 3 deletions

File tree

src/lapidary_render/model/metamodel.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def normalize_model(self) -> MetaModel | None:
133133
for schema in self.all_of or ():
134134
if model is None:
135135
return None
136-
model &= schema
136+
model &= schema.normalize_model()
137137

138138
assert model is not None
139139
model.all_of = None
@@ -197,7 +197,6 @@ def intersect(self, other: MetaModel | bool, stack: Stack) -> MetaModel | None:
197197
model = dc.replace(self, stack=stack)
198198

199199
model.type_ = not_none_or(self.type_, other.type_, operator.and_)
200-
201200
model.enum = not_none_or(self.enum, other.enum, operator.and_)
202201
model.gt = not_none_or(self.gt, other.gt, max)
203202
model.ge = not_none_or(self.ge, other.ge, max)
@@ -236,7 +235,7 @@ def intersect(self, other: MetaModel | bool, stack: Stack) -> MetaModel | None:
236235
model.items = not_none_or(self.items, other.items, operator.and_)
237236

238237
for field in ('all_of', 'any_of', 'one_of'):
239-
merge(model, other, field, operator.and_)
238+
merge(model, other, field, operator.add)
240239

241240
# not_: MetaModel | None = None
242241

tests/process/test_normalize.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,66 @@
44
from lapidary_render.model.stack import Stack
55

66

7+
def test_normalize_allof_type_intersection():
8+
# docs/json-schema.md#allof-and-type — allOf applies set intersection to type
9+
schema = MetaModel(
10+
stack=Stack.from_str('#/components/schemas/obj'),
11+
all_of=[
12+
MetaModel(
13+
stack=Stack.from_str('#/components/schemas/obj/allOf/0'),
14+
type_={DataType.INTEGER, DataType.STRING},
15+
),
16+
MetaModel(
17+
stack=Stack.from_str('#/components/schemas/obj/allOf/1'),
18+
type_={DataType.INTEGER, DataType.BOOLEAN},
19+
),
20+
],
21+
)
22+
23+
result = schema.normalize_model()
24+
25+
assert result == MetaModel(
26+
stack=Stack.from_str('#/components/schemas/obj'),
27+
type_={DataType.INTEGER},
28+
)
29+
30+
31+
def test_normalize_nested_allof():
32+
# docs/json-schema.md#nested-allof — nested allOf is flattened into a single allOf
33+
root = Stack.from_str('#/components/schemas/obj')
34+
schema = MetaModel(
35+
stack=root,
36+
all_of=[
37+
MetaModel(
38+
stack=root.push('allOf/0'),
39+
all_of=[
40+
MetaModel(
41+
stack=root.push('allOf/0'),
42+
type_={DataType.INTEGER},
43+
),
44+
MetaModel(
45+
stack=root.push('allOf/1'),
46+
ge=10.0,
47+
),
48+
],
49+
),
50+
MetaModel(
51+
stack=root.push('allOf/1'),
52+
multiple_of=2,
53+
),
54+
],
55+
)
56+
57+
result = schema.normalize_model()
58+
59+
assert result == MetaModel(
60+
stack=Stack.from_str('#/components/schemas/obj'),
61+
type_={DataType.INTEGER},
62+
ge=10.0,
63+
multiple_of=2,
64+
)
65+
66+
767
def test_normalize_allof_scalar_constraints():
868
# docs/json-schema.md#allof-and-scalar-constraints — most restrictive value wins: max for ge/gt, min for le/lt
969
schema = MetaModel(

0 commit comments

Comments
 (0)