Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-openapi-core for openSUSE:Factory checked in at 2022-12-03 10:03:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-openapi-core (Old) and /work/SRC/openSUSE:Factory/.python-openapi-core.new.1835 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-openapi-core" Sat Dec 3 10:03:42 2022 rev:13 rq:1039660 version:0.16.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-openapi-core/python-openapi-core.changes 2022-10-08 01:24:54.282185576 +0200 +++ /work/SRC/openSUSE:Factory/.python-openapi-core.new.1835/python-openapi-core.changes 2022-12-03 10:03:56.747343407 +0100 @@ -1,0 +2,12 @@ +Fri Dec 2 21:23:01 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com> + +- Update to 0.16.2: + Add NullUnmarshaller #432 + Multi type unmarshaller #433 + Unmarshaller format refactor #434 + +- Update to 0.16.1: + lists as additional properties fix #429 + x-model extension optional #431 + +------------------------------------------------------------------- Old: ---- openapi-core-0.16.0-gh.tar.gz New: ---- openapi-core-0.16.1-gh.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-openapi-core.spec ++++++ --- /var/tmp/diff_new_pack.EUTr05/_old 2022-12-03 10:03:57.351346763 +0100 +++ /var/tmp/diff_new_pack.EUTr05/_new 2022-12-03 10:03:57.363346830 +0100 @@ -17,7 +17,7 @@ Name: python-openapi-core -Version: 0.16.0 +Version: 0.16.1 Release: 0 Summary: Client- and server-side support for the OpenAPI Specification v3 License: BSD-3-Clause ++++++ openapi-core-0.16.0-gh.tar.gz -> openapi-core-0.16.1-gh.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/.bumpversion.cfg new/openapi-core-0.16.1/.bumpversion.cfg --- old/openapi-core-0.16.0/.bumpversion.cfg 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/.bumpversion.cfg 2022-10-10 15:12:21.000000000 +0200 @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.16.0 +current_version = 0.16.1 tag = True tag_name = {new_version} commit = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/.pre-commit-config.yaml new/openapi-core-0.16.1/.pre-commit-config.yaml --- old/openapi-core-0.16.0/.pre-commit-config.yaml 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/.pre-commit-config.yaml 2022-10-10 15:12:21.000000000 +0200 @@ -10,7 +10,7 @@ - id: check-hooks-apply - repo: https://github.com/asottile/pyupgrade - rev: v2.19.0 + rev: v2.38.4 hooks: - id: pyupgrade args: ["--py36-plus"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/docs/extensions.rst new/openapi-core-0.16.1/docs/extensions.rst --- old/openapi-core-0.16.0/docs/extensions.rst 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/docs/extensions.rst 2022-10-10 15:12:21.000000000 +0200 @@ -4,7 +4,7 @@ x-model ------- -By default, objects are unmarshalled to dynamically created dataclasses. You can use your own dataclasses, pydantic models or models generated by third party generators (i.e. `datamodel-code-generator <https://github.com/koxudaxi/datamodel-code-generator>`__) by providing ``x-model`` property inside schema definition with location of your class. +By default, objects are unmarshalled to dictionaries. You can use dynamically created dataclasses. .. code-block:: yaml @@ -12,7 +12,27 @@ components: schemas: Coordinates: - x-model: foo.bar.Coordinates + x-model: Coordinates + type: object + required: + - lat + - lon + properties: + lat: + type: number + lon: + type: number + + +You can use your own dataclasses, pydantic models or models generated by third party generators (i.e. `datamodel-code-generator <https://github.com/koxudaxi/datamodel-code-generator>`__) by providing ``x-model-path`` property inside schema definition with location of your class. + +.. code-block:: yaml + + ... + components: + schemas: + Coordinates: + x-model-path: foo.bar.Coordinates type: object required: - lat diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/openapi_core/__init__.py new/openapi-core-0.16.1/openapi_core/__init__.py --- old/openapi-core-0.16.0/openapi_core/__init__.py 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/openapi_core/__init__.py 2022-10-10 15:12:21.000000000 +0200 @@ -14,7 +14,7 @@ __author__ = "Artur Maciag" __email__ = "maciag.ar...@gmail.com" -__version__ = "0.16.0" +__version__ = "0.16.1" __url__ = "https://github.com/p1c2u/openapi-core" __license__ = "BSD 3-Clause License" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/openapi_core/extensions/models/factories.py new/openapi-core-0.16.1/openapi_core/extensions/models/factories.py --- old/openapi-core-0.16.0/openapi_core/extensions/models/factories.py 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/openapi_core/extensions/models/factories.py 2022-10-10 15:12:21.000000000 +0200 @@ -9,43 +9,40 @@ from typing import Type from openapi_core.extensions.models.types import Field +from openapi_core.spec import Spec class DictFactory: base_class = dict - def create(self, fields: Iterable[Field]) -> Type[Dict[Any, Any]]: + def create( + self, schema: Spec, fields: Iterable[Field] + ) -> Type[Dict[Any, Any]]: return self.base_class -class DataClassFactory(DictFactory): +class ModelFactory(DictFactory): def create( self, + schema: Spec, fields: Iterable[Field], - name: str = "Model", ) -> Type[Any]: + name = schema.getkey("x-model") + if name is None: + return super().create(schema, fields) + return make_dataclass(name, fields, frozen=True) -class ModelClassImporter(DataClassFactory): +class ModelPathFactory(ModelFactory): def create( self, + schema: Spec, fields: Iterable[Field], - name: str = "Model", - model: Optional[str] = None, ) -> Any: - if model is None: - return super().create(fields, name=name) + model_class_path = schema.getkey("x-model-path") + if model_class_path is None: + return super().create(schema, fields) - model_class = self._get_class(model) - if model_class is not None: - return model_class - - return super().create(fields, name=model) - - def _get_class(self, model_class_path: str) -> Optional[object]: - try: - return locate(model_class_path) - except ErrorDuringImport: - return None + return locate(model_class_path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/openapi_core/unmarshalling/schemas/unmarshallers.py new/openapi-core-0.16.1/openapi_core/unmarshalling/schemas/unmarshallers.py --- old/openapi-core-0.16.0/openapi_core/unmarshalling/schemas/unmarshallers.py 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/openapi_core/unmarshalling/schemas/unmarshallers.py 2022-10-10 15:12:21.000000000 +0200 @@ -18,7 +18,7 @@ from openapi_schema_validator._format import oas30_format_checker from openapi_schema_validator._types import is_string -from openapi_core.extensions.models.factories import ModelClassImporter +from openapi_core.extensions.models.factories import ModelPathFactory from openapi_core.schema.schemas import get_all_properties from openapi_core.spec import Spec from openapi_core.unmarshalling.schemas.datatypes import FormattersDict @@ -181,7 +181,9 @@ @property def items_unmarshaller(self) -> "BaseSchemaUnmarshaller": - return self.unmarshallers_factory.create(self.schema / "items") + # sometimes we don't have any schema i.e. free-form objects + items_schema = self.schema.get("items", Spec.from_dict({})) + return self.unmarshallers_factory.create(items_schema) def __call__(self, value: Any) -> Optional[List[Any]]: value = super().__call__(value) @@ -197,15 +199,14 @@ } @property - def object_class_factory(self) -> ModelClassImporter: - return ModelClassImporter() + def object_class_factory(self) -> ModelPathFactory: + return ModelPathFactory() def unmarshal(self, value: Any) -> Any: properties = self.unmarshal_raw(value) - model = self.schema.getkey("x-model") fields: Iterable[str] = properties and properties.keys() or [] - object_class = self.object_class_factory.create(fields, model=model) + object_class = self.object_class_factory.create(self.schema, fields) return object_class(**properties) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/pyproject.toml new/openapi-core-0.16.1/pyproject.toml --- old/openapi-core-0.16.0/pyproject.toml 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/pyproject.toml 2022-10-10 15:12:21.000000000 +0200 @@ -29,7 +29,7 @@ [tool.poetry] name = "openapi-core" -version = "0.16.0" +version = "0.16.1" description = "client-side and server-side support for the OpenAPI Specification v3" authors = ["Artur Maciag <maciag.ar...@gmail.com>"] license = "BSD-3-Clause" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/tests/integration/data/v3.0/petstore.yaml new/openapi-core-0.16.1/tests/integration/data/v3.0/petstore.yaml --- old/openapi-core-0.16.0/tests/integration/data/v3.0/petstore.yaml 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/tests/integration/data/v3.0/petstore.yaml 2022-10-10 15:12:21.000000000 +0200 @@ -233,6 +233,7 @@ components: schemas: Coordinates: + x-model: Coordinates type: object required: - lat @@ -243,6 +244,7 @@ lon: type: number Userdata: + x-model: Userdata type: object required: - name diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/tests/integration/data/v3.0/read_only_write_only.yaml new/openapi-core-0.16.1/tests/integration/data/v3.0/read_only_write_only.yaml --- old/openapi-core-0.16.0/tests/integration/data/v3.0/read_only_write_only.yaml 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/tests/integration/data/v3.0/read_only_write_only.yaml 2022-10-10 15:12:21.000000000 +0200 @@ -23,6 +23,7 @@ components: schemas: User: + x-model: User type: object required: - id diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/tests/integration/validation/test_petstore.py new/openapi-core-0.16.1/tests/integration/validation/test_petstore.py --- old/openapi-core-0.16.0/tests/integration/validation/test_petstore.py 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/tests/integration/validation/test_petstore.py 2022-10-10 15:12:21.000000000 +0200 @@ -644,7 +644,7 @@ assert is_dataclass(result.parameters.query["coordinates"]) assert ( result.parameters.query["coordinates"].__class__.__name__ - == "Model" + == "Coordinates" ) assert result.parameters.query["coordinates"].lat == coordinates["lat"] assert result.parameters.query["coordinates"].lon == coordinates["lon"] @@ -705,7 +705,8 @@ assert is_dataclass(result.parameters.cookie["userdata"]) assert ( - result.parameters.cookie["userdata"].__class__.__name__ == "Model" + result.parameters.cookie["userdata"].__class__.__name__ + == "Userdata" ) assert result.parameters.cookie["userdata"].name == "user1" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/tests/integration/validation/test_read_only_write_only.py new/openapi-core-0.16.1/tests/integration/validation/test_read_only_write_only.py --- old/openapi-core-0.16.0/tests/integration/validation/test_read_only_write_only.py 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/tests/integration/validation/test_read_only_write_only.py 2022-10-10 15:12:21.000000000 +0200 @@ -51,7 +51,7 @@ assert not result.errors assert is_dataclass(result.data) - assert result.data.__class__.__name__ == "Model" + assert result.data.__class__.__name__ == "User" assert result.data.id == 10 assert result.data.name == "Pedro" @@ -73,7 +73,7 @@ assert not result.errors assert is_dataclass(result.body) - assert result.body.__class__.__name__ == "Model" + assert result.body.__class__.__name__ == "User" assert result.body.name == "Pedro" assert result.body.hidden == False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/tests/integration/validation/test_validators.py new/openapi-core-0.16.1/tests/integration/validation/test_validators.py --- old/openapi-core-0.16.0/tests/integration/validation/test_validators.py 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/tests/integration/validation/test_validators.py 2022-10-10 15:12:21.000000000 +0200 @@ -536,6 +536,7 @@ "in": "query", "required": True, "schema": { + "x-model": "paramObj", "type": "object", "properties": { "count": {"type": "integer"}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/tests/unit/extensions/test_factories.py new/openapi-core-0.16.1/tests/unit/extensions/test_factories.py --- old/openapi-core-0.16.0/tests/unit/extensions/test_factories.py 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/tests/unit/extensions/test_factories.py 2022-10-10 15:12:21.000000000 +0200 @@ -6,7 +6,8 @@ import pytest -from openapi_core.extensions.models.factories import ModelClassImporter +from openapi_core.extensions.models.factories import ModelPathFactory +from openapi_core.spec import Spec class TestImportModelCreate: @@ -24,18 +25,20 @@ del modules["foo"] def test_dynamic_model(self): - factory = ModelClassImporter() + factory = ModelPathFactory() - test_model_class = factory.create(["name"], model="TestModel") + schema = Spec.from_dict({"x-model": "TestModel"}) + test_model_class = factory.create(schema, ["name"]) assert is_dataclass(test_model_class) assert test_model_class.__name__ == "TestModel" assert list(test_model_class.__dataclass_fields__.keys()) == ["name"] assert test_model_class.__dataclass_fields__["name"].type == str(Any) - def test_imported_model(self, loaded_model_class): - factory = ModelClassImporter() + def test_model_path(self, loaded_model_class): + factory = ModelPathFactory() - test_model_class = factory.create(["a", "b"], model="foo.BarModel") + schema = Spec.from_dict({"x-model-path": "foo.BarModel"}) + test_model_class = factory.create(schema, ["a", "b"]) assert test_model_class == loaded_model_class diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openapi-core-0.16.0/tests/unit/unmarshalling/test_unmarshal.py new/openapi-core-0.16.1/tests/unit/unmarshalling/test_unmarshal.py --- old/openapi-core-0.16.0/tests/unit/unmarshalling/test_unmarshal.py 2022-10-04 14:57:10.000000000 +0200 +++ new/openapi-core-0.16.1/tests/unit/unmarshalling/test_unmarshal.py 2022-10-10 15:12:21.000000000 +0200 @@ -1,6 +1,5 @@ import datetime import uuid -from dataclasses import is_dataclass import pytest from isodate.tzinfo import UTC @@ -540,8 +539,9 @@ value = {"foo": None} result = unmarshaller_factory(spec)(value) - assert is_dataclass(result) - assert result.foo == None + assert result == { + "foo": None, + } def test_schema_any_one_of(self, unmarshaller_factory): schema = { @@ -596,8 +596,9 @@ spec = Spec.from_dict(schema) result = unmarshaller_factory(spec)({"someint": 1}) - assert is_dataclass(result) - assert result.someint == 1 + assert result == { + "someint": 1, + } def test_schema_object_any_of_invalid(self, unmarshaller_factory): schema = { @@ -728,14 +729,7 @@ result = unmarshaller_factory(spec)(value) - assert is_dataclass(result) - for field, val in value.items(): - result_field = getattr(result, field) - if isinstance(val, dict): - for field2, val2 in val.items(): - assert getattr(result_field, field2) == val2 - else: - assert result_field == val + assert result == value def test_read_only_properties(self, unmarshaller_factory): schema = { @@ -755,8 +749,9 @@ {"id": 10} ) - assert is_dataclass(result) - assert result.id == 10 + assert result == { + "id": 10, + } def test_read_only_properties_invalid(self, unmarshaller_factory): schema = { @@ -795,8 +790,9 @@ {"id": 10} ) - assert is_dataclass(result) - assert result.id == 10 + assert result == { + "id": 10, + } def test_write_only_properties_invalid(self, unmarshaller_factory): schema = { @@ -816,3 +812,15 @@ unmarshaller_factory(spec, context=UnmarshalContext.RESPONSE)( {"id": 10} ) + + def test_additional_properties_list(self, unmarshaller_factory): + schema = {"type": "object"} + spec = Spec.from_dict(schema) + + result = unmarshaller_factory(spec, context=UnmarshalContext.RESPONSE)( + {"user_ids": [1, 2, 3, 4]} + ) + + assert result == { + "user_ids": [1, 2, 3, 4], + }