Repository navigation
test_json_schema - #452
test_json_schema#452Niccolum wants to merge 6 commits into
Conversation
|
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||||||||
| def _append_with_patcher(self: S, patcher: Callable[[JSONSchema], JSONSchema]) -> S: | ||
| self_copy = copy(self) | ||
| self_copy._patchers.append(patcher) | ||
| self_copy._patchers = [*self._patchers, patcher] |
There was a problem hiding this comment.
What was this change necessary for?
There was a problem hiding this comment.
It fixes a shared-state bug in JSONSchemaPatch. copy(self) is a shallow copy, so self_copy._patchers and self._patchers pointed to the same list. The old .append(patcher) therefore also added the patcher to the original object, and to every other copy made from it.
Example of the bug:
base = JSONSchemaPatch()
a = base.mutate_copy(...) # base._patchers now contains a's patcher too
b = base.mutate_copy(...) # b gets a's patcher as well
The patch methods are meant to be immutable and return a new object. With the old code, using a patch as a base for several variants produced wrong schemas. Building a new list for the copy fixes this, and the original is never mutated.
| from adaptix import Retort, name_mapping | ||
| from adaptix._internal.definitions import Direction | ||
| from adaptix._internal.morphing.facade.func import ( | ||
| DIALECT_2020_12 as DIALECT_URI, |
There was a problem hiding this comment.
What was this renaming needed for?
| /docs/build | ||
|
|
||
| .venv/ | ||
| uv.lock No newline at end of file |
There was a problem hiding this comment.
really. Maybe i forgot remove it when testing
| def test_load_json_schema_strict_unknown_field_raises(): | ||
| with pytest.raises(AggregateLoadError): | ||
| load_json_schema({"type": "string", "x-custom": "value"}, error_on_extra=True) |
There was a problem hiding this comment.
There are raises_exc helper function that can compare exceptions by its fields
| assert_morphing( | ||
| retort=Retort(), | ||
| tp=SimpleModel, | ||
| data={"name": "foo", "value": 1}, | ||
| loaded=SimpleModel(name="foo", value=1), | ||
| json_schema=JSONSchemaFork( | ||
| input=_make({"additionalProperties": True}), | ||
| output=_make({}), | ||
| ), | ||
| ) |
There was a problem hiding this comment.
You can use "additionalProperties": JSONSchemaOptItem(input=True), for these forked tests. Other tests already use it
| def test_generate_json_schema_custom_resolver(): | ||
| schema = generate_json_schema( | ||
| Retort(), SimpleModel, Direction.INPUT, | ||
| resolver=BuiltinJSONSchemaResolver(BuiltinRefGenerator(), IndexRefMangler()), | ||
| ) | ||
|
|
||
| assert "SimpleModel" in schema["$defs"] |
There was a problem hiding this comment.
This test does not assert that custom resolver is used
There was a problem hiding this comment.
hm, really. add parametrized test for that case
| def test_generate_json_schema_optional_field_not_required_on_input(): | ||
| def _make(required: list, extra: dict) -> dict: | ||
| return { | ||
| "$ref": "#/$defs/ModelWithOptional", | ||
| "$schema": DIALECT_URI, | ||
| "$defs": { | ||
| "ModelWithOptional": { | ||
| "title": "ModelWithOptional", | ||
| "type": "object", | ||
| "required": required, | ||
| "properties": { | ||
| "required_field": {"type": "string"}, | ||
| "optional_field": { | ||
| "default": None, | ||
| "anyOf": [{"type": "string"}, {"type": "null"}], | ||
| }, | ||
| }, | ||
| **extra, | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| assert_morphing( | ||
| retort=Retort(), | ||
| tp=ModelWithOptional, | ||
| data={"required_field": "x"}, | ||
| loaded=ModelWithOptional(required_field="x"), | ||
| dumped={"required_field": "x", "optional_field": None}, | ||
| json_schema=JSONSchemaFork( | ||
| # Input schema: only required_field is required (optional_field has a default) | ||
| input=_make(["required_field"], {"additionalProperties": True}), | ||
| # Output schema: both fields are required (dumping doesn't care about defaults) | ||
| output=_make(["required_field", "optional_field"], {}), | ||
| ), | ||
| ) |
There was a problem hiding this comment.
There is JSONSchemaOptItem(input=True) for such tests
There was a problem hiding this comment.
I do not think that such unit tests can be useful. I would advise to test actual system behaviour
There was a problem hiding this comment.
delete because test tests/integration/morphing/test_examples.py::test_readme already check this
| @pytest.mark.parametrize( | ||
| "resolver", | ||
| [ | ||
| pytest.param(None, id="default"), | ||
| pytest.param( | ||
| BuiltinJSONSchemaResolver(BuiltinRefGenerator(), IndexRefMangler()), | ||
| id="custom_resolver", | ||
| ), | ||
| ], | ||
| ) | ||
| def test_generate_schemas_namespace_deduplicates_shared_types(resolver): | ||
| query = _namespace_query() | ||
| kwargs = {"resolver": resolver} if resolver else {} | ||
|
|
||
| defs, schemas = generate_json_schemas_namespace(query, **kwargs) | ||
|
|
||
| assert len(schemas) == 2 | ||
| assert defs.keys() == {"Article", "Post", "Tag"} | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "with_dialect_uri", | ||
| [ | ||
| pytest.param(True, id="with_uri"), | ||
| pytest.param(False, id="without_uri"), | ||
| ], | ||
| ) | ||
| def test_generate_schemas_namespace_dialect_uri(with_dialect_uri: bool): # noqa: FBT001 | ||
| query = _namespace_query() | ||
| _, schemas = generate_json_schemas_namespace(query, with_dialect_uri=with_dialect_uri) | ||
|
|
||
| for schema in schemas: | ||
| assert ("$schema" in schema) == with_dialect_uri | ||
| assert "$ref" in schema | ||
|
|
||
|
|
||
| def test_generate_schemas_namespace_custom_ref_prefix(): | ||
| query = _namespace_query() | ||
| _, schemas = generate_json_schemas_namespace( | ||
| query, local_ref_prefix="#/components/schemas/", | ||
| ) | ||
|
|
||
| assert [schema["$ref"] for schema in schemas] == [ | ||
| "#/components/schemas/Article", | ||
| "#/components/schemas/Post", | ||
| ] |
There was a problem hiding this comment.
These tests duplicate previous tests, but they only use another facade
There was a problem hiding this comment.
removed test_generate_schemas_namespace_dialect_uri and test_generate_schemas_namespace_custom_ref_prefix. Kept test_generate_schemas_namespace_deduplicates_shared_types, because nothing else covers it. Every other test uses a single query, and only this one checks that a type shared between several queries (Tag) lands in $defs once.
| def _product_schema(name_prop: dict, price_prop: dict) -> JSONSchemaFork: | ||
| def _make(product_extra: dict = {}) -> dict: # noqa: B006 | ||
| return { | ||
| "$ref": "#/$defs/Product", | ||
| "$schema": DIALECT_2020_12, | ||
| "$defs": { | ||
| "Product": { | ||
| "title": "Product", | ||
| "type": "object", | ||
| "required": ["name", "price"], | ||
| "properties": { | ||
| "name": name_prop, | ||
| "price": price_prop, | ||
| }, | ||
| **product_extra, | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| return JSONSchemaFork( | ||
| input=_make({"additionalProperties": True}), | ||
| output=_make(), | ||
| ) |
|



No description provided.