|
| 1 | +""" |
| 2 | +Validating highly nested schemas shouldn't cause exponential time blowups. |
| 3 | +
|
| 4 | +See https://github.com/python-jsonschema/jsonschema/issues/1097. |
| 5 | +""" |
| 6 | +from itertools import cycle |
| 7 | + |
| 8 | +from jsonschema.validators import validator_for |
| 9 | + |
| 10 | +metaschemaish = { |
| 11 | + "$id": "https://example.com/draft/2020-12/schema/strict", |
| 12 | + "$schema": "https://json-schema.org/draft/2020-12/schema", |
| 13 | + |
| 14 | + "$vocabulary": { |
| 15 | + "https://json-schema.org/draft/2020-12/vocab/core": True, |
| 16 | + "https://json-schema.org/draft/2020-12/vocab/applicator": True, |
| 17 | + "https://json-schema.org/draft/2020-12/vocab/unevaluated": True, |
| 18 | + "https://json-schema.org/draft/2020-12/vocab/validation": True, |
| 19 | + "https://json-schema.org/draft/2020-12/vocab/meta-data": True, |
| 20 | + "https://json-schema.org/draft/2020-12/vocab/format-annotation": True, |
| 21 | + "https://json-schema.org/draft/2020-12/vocab/content": True |
| 22 | + }, |
| 23 | + "$dynamicAnchor": "meta", |
| 24 | + |
| 25 | + "$ref": "https://json-schema.org/draft/2020-12/schema", |
| 26 | + "unevaluatedProperties": False, |
| 27 | +} |
| 28 | + |
| 29 | + |
| 30 | +def nested_schema(levels): |
| 31 | + """ |
| 32 | + Produce a schema which validates deeply nested objects and arrays. |
| 33 | + """ |
| 34 | + |
| 35 | + names = cycle(["foo", "bar", "baz", "quux", "spam", "eggs"]) |
| 36 | + schema = {"type": "object", "properties": {"ham": {"type": "string"}}} |
| 37 | + for _, name in zip(range(levels - 1), names): |
| 38 | + schema = {"type": "object", "properties": {name: schema}} |
| 39 | + return schema |
| 40 | + |
| 41 | + |
| 42 | +validator = validator_for(metaschemaish)(metaschemaish) |
| 43 | + |
| 44 | +if __name__ == "__main__": |
| 45 | + from pyperf import Runner |
| 46 | + runner = Runner() |
| 47 | + |
| 48 | + not_nested = nested_schema(levels=1) |
| 49 | + runner.bench_func("not nested", lambda: validator.is_valid(not_nested)) |
| 50 | + |
| 51 | + for levels in range(1, 11, 3): |
| 52 | + schema = nested_schema(levels=levels) |
| 53 | + runner.bench_func( |
| 54 | + f"nested * {levels}", |
| 55 | + lambda schema=schema: validator.is_valid(schema), |
| 56 | + ) |
0 commit comments