File size: 3,901 Bytes
f8dbde1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import pytest
from deg.normalize import count_leaves, normalize_schema
from deg.schema import compile_schema
def test_refs_inlined_annotations_dropped_and_compiles():
raw = {
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {"addr": {"type": "object", "properties": {
"city": {"type": "string", "examples": ["Paris"]},
"zip": {"type": "string", "format": "postal-code"}}}},
"type": "object",
"properties": {
"home": {"$ref": "#/definitions/addr"},
"when": {"type": "string", "format": "date", "evaluation_config": "exact"},
"kind": {"oneOf": [{"const": "a", "description": "A"}, {"const": "b"}]},
"fixed": {"const": 3},
"map": {"type": "object", "additionalProperties": {"type": "string"}},
"maybe": {"anyOf": [{"type": "integer"}, {"type": "null"}]},
"tags": {"type": "array", "items": {"type": "string"}, "contains": {}},
},
"required": ["home", "fixed"],
"minProperties": 1,
}
out, why = normalize_schema(raw)
assert why == "ok"
compile_schema(out)
props = out["properties"]
assert set(props) == {"home", "when", "kind", "maybe", "tags"}
assert props["home"]["properties"]["zip"] == {"type": "string"} # unknown format dropped
assert "examples" not in props["home"]["properties"]["city"]
assert props["kind"]["enum"] == ["a", "b"]
assert props["maybe"]["type"] == ["integer", "null"]
assert out["required"] == ["home"] and out["additionalProperties"] is False
assert "contains" not in props["tags"]
def test_leaf_cap_depth_and_skips():
wide = {"type": "object", "properties": {f"f{i}": {"type": "string"} for i in range(50)}}
out, _ = normalize_schema(wide, max_leaves=30)
assert count_leaves(out) == 30 and list(out["properties"])[-1] == "f29"
assert normalize_schema({"type": "array", "items": {"type": "string"}})[1] == \
"root_not_object"
rec = {"type": "object", "properties": {"n": {"$ref": "#"}, "a": {"type": "string"},
"b": {"type": "number"}}}
out, why = normalize_schema(rec)
assert why == "ok" and set(out["properties"]) == {"a", "b"}
assert normalize_schema({"type": "object", "properties": {"x": {"const": 1}}})[0] is None
@pytest.mark.parametrize("bad", [
{"type": "object", "properties": {"a": {"type": "integer", "minimum": 1, "maximum": 1},
"b": {"type": "string"}, "c": {"type": "boolean"}}},
{"type": "object", "properties": {"a": {"enum": ["x", "y"], "maxLength": 3},
"b": {"type": "string"}}},
])
def test_compiler_errors_drop_only_the_bad_field(bad):
out, why = normalize_schema(bad)
assert why == "ok"
compile_schema(out)
assert "b" in out["properties"]
def test_string_or_number_union_becomes_span():
raw = {"type": "object", "properties": {
"year": {"anyOf": [{"type": "string", "vendor": 1}, {"type": "integer"},
{"type": "null"}]},
"rank": {"anyOf": [{"type": "integer"}, {"type": "string"}]},
"mixed": {"anyOf": [{"type": "integer", "minimum": 3}, {"type": "string"}]}}}
out, why = normalize_schema(raw)
assert why == "ok"
assert out["properties"]["year"]["type"] == ["string", "null"]
assert out["properties"]["rank"]["type"] == "string"
assert "mixed" not in out["properties"] # a constrained branch is not merged away
def test_union_with_list_typed_branch_does_not_crash():
raw = {"type": "object", "properties": {
"a": {"anyOf": [{"type": ["string", "integer"]}, {"type": "string"}]},
"b": {"type": "string"}, "c": {"type": "number"}}}
out, why = normalize_schema(raw)
assert why == "ok" and set(out["properties"]) == {"b", "c"}
|