def test_records_bad_uris_and_keeps_going(self, mocker):
        from openapi_python_client.parser.properties import Schemas, build_schemas
        from openapi_python_client.schema import Schema

        components = {
            "first": Schema.construct(),
            "second": Schema.construct()
        }
        update_schemas_with_data = mocker.patch(
            f"{MODULE_NAME}.update_schemas_with_data")
        parse_reference_path = mocker.patch(
            f"{MODULE_NAME}.parse_reference_path",
            side_effect=[PropertyError(detail="some details"), "a_path"])
        config = Config()

        result = build_schemas(components=components,
                               schemas=Schemas(),
                               config=config)
        parse_reference_path.assert_has_calls([
            call("#/components/schemas/first"),
            call("#/components/schemas/second"),
        ])
        update_schemas_with_data.assert_called_once_with(
            ref_path="a_path",
            config=config,
            data=components["second"],
            schemas=Schemas(errors=[
                PropertyError(detail="some details", data=components["first"])
            ]),
        )
        assert result == update_schemas_with_data.return_value
    def test_retries_failing_properties_while_making_progress(self, mocker):
        from openapi_python_client.parser.properties import Schemas, build_schemas
        from openapi_python_client.schema import Schema

        components = {
            "first": Schema.construct(),
            "second": Schema.construct()
        }
        update_schemas_with_data = mocker.patch(
            f"{MODULE_NAME}.update_schemas_with_data",
            side_effect=[PropertyError(),
                         Schemas(),
                         PropertyError()])
        parse_reference_path = mocker.patch(
            f"{MODULE_NAME}.parse_reference_path")
        config = Config()

        result = build_schemas(components=components,
                               schemas=Schemas(),
                               config=config)
        parse_reference_path.assert_has_calls([
            call("#/components/schemas/first"),
            call("#/components/schemas/second"),
            call("#/components/schemas/first"),
        ])
        assert update_schemas_with_data.call_count == 3
        assert result.errors == [PropertyError()]
    def test_conflicting_properties_same_types(self, model_property_factory,
                                               string_property_factory):
        from openapi_python_client.parser.properties import Schemas
        from openapi_python_client.parser.properties.model_property import _process_properties

        data = oai.Schema.construct(allOf=[
            oai.Reference.construct(ref="#/First"),
            oai.Reference.construct(ref="#/Second")
        ])
        schemas = Schemas(
            classes_by_reference={
                "/First":
                model_property_factory(optional_properties=[
                    string_property_factory(default="abc")
                ]),
                "/Second":
                model_property_factory(
                    optional_properties=[string_property_factory()]),
            })

        result = _process_properties(data=data,
                                     schemas=schemas,
                                     class_name="",
                                     config=Config())

        assert isinstance(result, PropertyError)
    def test_property_from_data_ref_enum_with_invalid_default(
            self, enum_property_factory):
        from openapi_python_client.parser.properties import Class, Schemas, property_from_data

        name = "some_enum"
        data = oai.Schema.construct(
            default="x",
            allOf=[oai.Reference.construct(ref="#/components/schemas/MyEnum")])
        existing_enum = enum_property_factory(
            name="an_enum",
            default="MyEnum.A",
            values={
                "A": "a",
                "B": "b"
            },
            class_info=Class(name="MyEnum", module_name="my_enum"),
            python_name="an_enum",
        )
        schemas = Schemas(
            classes_by_reference={"/components/schemas/MyEnum": existing_enum})

        prop, new_schemas = property_from_data(name=name,
                                               required=False,
                                               data=data,
                                               schemas=schemas,
                                               parent_name="",
                                               config=Config())

        assert schemas == new_schemas
        assert prop == PropertyError(
            data=data, detail="x is an invalid default for enum MyEnum")
    def test_property_from_data_ref_enum(self, enum_property_factory):
        from openapi_python_client.parser.properties import Class, Schemas, property_from_data

        name = "some_enum"
        data = oai.Reference.construct(ref="#/components/schemas/MyEnum")
        existing_enum = enum_property_factory(
            name="an_enum",
            required=False,
            values={"A": "a"},
            class_info=Class(name="MyEnum", module_name="my_enum"),
        )
        schemas = Schemas(
            classes_by_reference={"/components/schemas/MyEnum": existing_enum})

        prop, new_schemas = property_from_data(name=name,
                                               required=False,
                                               data=data,
                                               schemas=schemas,
                                               parent_name="",
                                               config=Config())

        assert prop == enum_property_factory(
            name="some_enum",
            required=False,
            values={"A": "a"},
            class_info=Class(name="MyEnum", module_name="my_enum"),
        )
        assert schemas == new_schemas
    def test_allof_int_enums(self, model_property_factory,
                             enum_property_factory):
        from openapi_python_client.parser.properties import Schemas
        from openapi_python_client.parser.properties.model_property import _process_properties

        data = oai.Schema.construct(allOf=[
            oai.Reference.construct(ref="#/First"),
            oai.Reference.construct(ref="#/Second")
        ])
        enum_property1 = enum_property_factory(
            name="an_enum",
            values={
                "foo": 1,
                "bar": 2
            },
            value_type=int,
        )
        enum_property2 = enum_property_factory(
            name="an_enum",
            values={"foo": 1},
            value_type=int,
        )
        schemas = Schemas(
            classes_by_reference={
                "/First":
                model_property_factory(optional_properties=[enum_property1]),
                "/Second":
                model_property_factory(optional_properties=[enum_property2]),
            })

        result = _process_properties(data=data,
                                     schemas=schemas,
                                     class_name="",
                                     config=Config())
        assert result.required_props[0] == enum_property2
    def test_property_from_data_ref_model(self, model_property_factory):
        from openapi_python_client.parser.properties import Class, ModelProperty, Schemas, property_from_data

        name = "new_name"
        required = False
        class_name = "MyModel"
        data = oai.Reference.construct(
            ref=f"#/components/schemas/{class_name}")
        class_info = Class(name=class_name, module_name="my_model")

        existing_model = model_property_factory(
            name="old_name",
            class_info=class_info,
        )
        schemas = Schemas(classes_by_reference={
            f"/components/schemas/{class_name}": existing_model
        })

        prop, new_schemas = property_from_data(name=name,
                                               required=required,
                                               data=data,
                                               schemas=schemas,
                                               parent_name="",
                                               config=Config())

        assert prop == model_property_factory(
            name=name,
            required=required,
            class_info=class_info,
        )
        assert schemas == new_schemas
    def test_allof_enum_incompatible_type(self, model_property_factory,
                                          enum_property_factory,
                                          int_property_factory):
        from openapi_python_client.parser.properties import Schemas
        from openapi_python_client.parser.properties.model_property import _process_properties

        data = oai.Schema.construct(allOf=[
            oai.Reference.construct(ref="#/First"),
            oai.Reference.construct(ref="#/Second")
        ])
        enum_property = enum_property_factory(
            values={"foo": 1},
            value_type=str,
        )
        schemas = Schemas(
            classes_by_reference={
                "/First":
                model_property_factory(
                    optional_properties=[int_property_factory()]),
                "/Second":
                model_property_factory(optional_properties=[enum_property]),
            })

        result = _process_properties(data=data,
                                     schemas=schemas,
                                     class_name="",
                                     config=Config())
        assert isinstance(result, PropertyError)
    def test_allof_string_enum_and_string(self, model_property_factory,
                                          enum_property_factory,
                                          string_property_factory):
        from openapi_python_client.parser.properties import Schemas
        from openapi_python_client.parser.properties.model_property import _process_properties

        data = oai.Schema.construct(allOf=[
            oai.Reference.construct(ref="#/First"),
            oai.Reference.construct(ref="#/Second")
        ])
        enum_property = enum_property_factory(
            required=False,
            nullable=True,
            values={"foo": "foo"},
        )
        schemas = Schemas(
            classes_by_reference={
                "/First":
                model_property_factory(optional_properties=[enum_property]),
                "/Second":
                model_property_factory(optional_properties=[
                    string_property_factory(required=False, nullable=True)
                ]),
            })

        result = _process_properties(data=data,
                                     schemas=schemas,
                                     class_name="",
                                     config=Config())
        assert result.optional_props[0] == enum_property
    def test_property_from_data_union_of_one_element(self, mocker,
                                                     model_property_factory):
        from openapi_python_client.parser.properties import Class, ModelProperty, Schemas, property_from_data

        name = "new_name"
        required = False
        class_name = "MyModel"
        nullable = True
        existing_model = model_property_factory()
        schemas = Schemas(
            classes_by_reference={f"/{class_name}": existing_model})

        data = oai.Schema.construct(
            allOf=[oai.Reference.construct(ref=f"#/{class_name}")],
            nullable=nullable,
        )
        build_union_property = mocker.patch(
            f"{MODULE_NAME}.build_union_property")

        prop, schemas = property_from_data(name=name,
                                           required=required,
                                           data=data,
                                           schemas=schemas,
                                           parent_name="parent",
                                           config=Config())

        assert prop == attr.evolve(existing_model,
                                   name=name,
                                   required=required,
                                   nullable=nullable,
                                   python_name=name)
        build_union_property.assert_not_called()
    def test_skips_references_and_keeps_going(self, mocker):
        from openapi_python_client.parser.properties import Schemas, build_schemas
        from openapi_python_client.schema import Reference, Schema

        components = {
            "a_ref": Reference.construct(),
            "a_schema": Schema.construct()
        }
        update_schemas_with_data = mocker.patch(
            f"{MODULE_NAME}.update_schemas_with_data")
        parse_reference_path = mocker.patch(
            f"{MODULE_NAME}.parse_reference_path")
        config = Config()

        result = build_schemas(components=components,
                               schemas=Schemas(),
                               config=config)
        # Should not even try to parse a path for the Reference
        parse_reference_path.assert_called_once_with(
            "#/components/schemas/a_schema")
        update_schemas_with_data.assert_called_once_with(
            ref_path=parse_reference_path.return_value,
            config=config,
            data=components["a_schema"],
            schemas=Schemas(errors=[
                PropertyError(detail="Reference schemas are not supported.",
                              data=components["a_ref"])
            ]),
        )
        assert result == update_schemas_with_data.return_value
    def test_happy_path(self, model_property_factory, string_property_factory,
                        date_time_property_factory):
        from openapi_python_client.parser.properties import Class, Schemas, build_model_property

        name = "prop"
        nullable = False
        required = True

        data = oai.Schema.construct(
            required=["req"],
            title="MyModel",
            properties={
                "req": oai.Schema.construct(type="string"),
                "opt": oai.Schema(type="string", format="date-time"),
            },
            description="A class called MyModel",
            nullable=nullable,
        )
        schemas = Schemas(classes_by_reference={"OtherModel": None},
                          classes_by_name={"OtherModel": None})

        model, new_schemas = build_model_property(data=data,
                                                  name=name,
                                                  schemas=schemas,
                                                  required=required,
                                                  parent_name="parent",
                                                  config=Config())

        assert new_schemas != schemas
        assert new_schemas.classes_by_name == {
            "OtherModel": None,
            "ParentMyModel": model,
        }
        assert new_schemas.classes_by_reference == {
            "OtherModel": None,
        }
        assert model == model_property_factory(
            name=name,
            required=required,
            nullable=nullable,
            class_info=Class(name="ParentMyModel",
                             module_name="parent_my_model"),
            required_properties=[
                string_property_factory(name="req", required=True)
            ],
            optional_properties=[
                date_time_property_factory(name="opt", required=False)
            ],
            description=data.description,
            relative_imports={
                "from dateutil.parser import isoparse",
                "from typing import cast",
                "import datetime",
                "from ..types import UNSET, Unset",
                "from typing import Union",
            },
            additional_properties=True,
        )
def test_class_from_string_default_config():
    from openapi_python_client import Config
    from openapi_python_client.parser.properties import Class

    class_ = Class.from_string(string="#/components/schemas/PingResponse",
                               config=Config())

    assert class_.name == "PingResponse"
    assert class_.module_name == "ping_response"
    def test__string_based_property_binary_format(self, file_property_factory):
        from openapi_python_client.parser.properties import property_from_data

        name = "file_prop"
        required = True
        nullable = True
        data = oai.Schema.construct(type="string", schema_format="binary", nullable=nullable, default="a")

        p, _ = property_from_data(
            name=name, required=required, data=data, schemas=Schemas(), config=Config(), parent_name=None
        )
        assert p == file_property_factory(name=name, required=required, nullable=nullable)
    def test_datetime_bad_default(self):
        from openapi_python_client.parser.properties import property_from_data

        name = "datetime_prop"
        required = True
        data = oai.Schema.construct(type="string", schema_format="date-time", nullable=True, default="a")

        result, _ = property_from_data(
            name=name, required=required, data=data, schemas=Schemas(), config=Config(), parent_name=None
        )

        assert result == PropertyError(detail="Failed to validate default value", data=data)
Beispiel #16
0
def test_custom_templates(mocker):
    from openapi_python_client import GeneratorData, MetaType, Project

    openapi = mocker.MagicMock(
        autospec=GeneratorData,
        title="My Test API",
    )

    project = Project(openapi=openapi, meta=MetaType.POETRY, config=Config())
    assert isinstance(project.env.loader, jinja2.PackageLoader)

    project = Project(
        openapi=openapi,
        custom_template_path="../end_to_end_tests/test_custom_templates",
        meta=MetaType.POETRY,
        config=Config(),
    )
    assert isinstance(project.env.loader, jinja2.ChoiceLoader)
    assert len(project.env.loader.loaders) == 2
    assert isinstance(project.env.loader.loaders[0], jinja2.FileSystemLoader)
    assert isinstance(project.env.loader.loaders[1], jinja2.PackageLoader)
Beispiel #17
0
    def test___init___no_meta(self, mocker):
        openapi = mocker.MagicMock(title="My Test API")

        from openapi_python_client import MetaType, Project

        project = Project(openapi=openapi, meta=MetaType.NONE, config=Config())

        assert project.openapi == openapi
        assert project.package_description == "A client library for accessing My Test API"
        assert project.meta == MetaType.NONE
        assert project.project_dir == pathlib.Path.cwd()
        assert project.package_dir == pathlib.Path.cwd() / project.package_name
    def test__string_based_property_unsupported_format(self, string_property_factory):
        from openapi_python_client.parser.properties import property_from_data

        name = "unknown"
        required = True
        nullable = True
        data = oai.Schema.construct(type="string", schema_format="blah", nullable=nullable)

        p, _ = property_from_data(
            name=name, required=required, data=data, schemas=Schemas, config=Config(), parent_name=None
        )

        assert p == string_property_factory(name=name, required=required, nullable=nullable)
Beispiel #19
0
    def test_generate_url(self, _create_new_client):
        url = "cool.url"
        from openapi_python_client.cli import Config, MetaType, app

        result = runner.invoke(app, ["generate", f"--url={url}"])

        assert result.exit_code == 0
        _create_new_client.assert_called_once_with(url=url,
                                                   path=None,
                                                   custom_template_path=None,
                                                   meta=MetaType.POETRY,
                                                   file_encoding="utf-8",
                                                   config=Config())
Beispiel #20
0
def make_project(**kwargs):
    from unittest.mock import MagicMock

    from openapi_python_client import MetaType, Project

    kwargs = {
        "openapi": MagicMock(title="My Test API"),
        "meta": MetaType.POETRY,
        "config": Config(),
        **kwargs
    }

    return Project(**kwargs)
    def test_no_format(self, string_property_factory, nullable, required):
        from openapi_python_client.parser.properties import property_from_data

        name = "some_prop"
        data = oai.Schema.construct(type="string", nullable=nullable, default='"hello world"', pattern="abcdef")

        p, _ = property_from_data(
            name=name, required=required, data=data, parent_name=None, config=Config(), schemas=Schemas()
        )

        assert p == string_property_factory(
            name=name, required=required, nullable=nullable, default="'\\\\\"hello world\\\\\"'", pattern=data.pattern
        )
    def test_invalid_reference(self, model_property_factory):
        from openapi_python_client.parser.properties import Schemas
        from openapi_python_client.parser.properties.model_property import _process_properties

        data = oai.Schema.construct(
            allOf=[oai.Reference.construct(ref="ThisIsNotGood")])
        schemas = Schemas()

        result = _process_properties(data=data,
                                     schemas=schemas,
                                     class_name="",
                                     config=Config())

        assert isinstance(result, PropertyError)
    def test_model_bad_properties(self):
        from openapi_python_client.parser.properties import Schemas, build_model_property

        data = oai.Schema(properties={
            "bad":
            oai.Reference.construct(ref="#/components/schema/NotExist"),
        }, )
        result = build_model_property(data=data,
                                      name="prop",
                                      schemas=Schemas(),
                                      required=True,
                                      parent_name="parent",
                                      config=Config())[0]
        assert isinstance(result, PropertyError)
Beispiel #24
0
    def test_update_path(self, _update_existing_client):
        path = "cool/path"
        from openapi_python_client.cli import Config, MetaType, app

        result = runner.invoke(app, ["update", f"--path={path}"])

        assert result.exit_code == 0
        _update_existing_client.assert_called_once_with(
            url=None,
            path=Path(path),
            custom_template_path=None,
            meta=MetaType.POETRY,
            file_encoding="utf-8",
            config=Config(),
        )
    def test_process_properties_reference_not_exist(self):
        from openapi_python_client.parser.properties import Schemas
        from openapi_python_client.parser.properties.model_property import _process_properties

        data = oai.Schema(properties={
            "bad":
            oai.Reference.construct(ref="#/components/schema/NotExist"),
        }, )

        result = _process_properties(data=data,
                                     class_name="",
                                     schemas=Schemas(),
                                     config=Config())

        assert isinstance(result, PropertyError)
    def test_additional_schemas(self, additional_properties_schema,
                                expected_additional_properties):
        from openapi_python_client.parser.properties import Schemas, build_model_property

        data = oai.Schema.construct(
            additionalProperties=additional_properties_schema, )

        model, _ = build_model_property(data=data,
                                        name="prop",
                                        schemas=Schemas(),
                                        required=True,
                                        parent_name="parent",
                                        config=Config())

        assert model.additional_properties == expected_additional_properties
Beispiel #27
0
    def test_project_and_package_names(self, mocker, project_override,
                                       package_override, expected_project_name,
                                       expected_package_name):
        openapi = mocker.MagicMock(title="My Test API")

        from openapi_python_client import MetaType, Project

        project = Project(
            openapi=openapi,
            meta=MetaType.POETRY,
            config=Config(project_name_override=project_override,
                          package_name_override=package_override),
        )

        assert project.project_name == expected_project_name
        assert project.package_name == expected_package_name
Beispiel #28
0
    def test_generate_meta(self, _create_new_client):
        path = "cool/path"
        from openapi_python_client.cli import Config, MetaType, app

        result = runner.invoke(app,
                               ["generate", f"--path={path}", "--meta=none"])

        assert result.exit_code == 0
        _create_new_client.assert_called_once_with(
            url=None,
            path=Path(path),
            custom_template_path=None,
            meta=MetaType.NONE,
            file_encoding="utf-8",
            config=Config(),
        )
    def test_non_model_reference(self, enum_property_factory):
        from openapi_python_client.parser.properties import Schemas
        from openapi_python_client.parser.properties.model_property import _process_properties

        data = oai.Schema.construct(
            allOf=[oai.Reference.construct(ref="#/First")])
        schemas = Schemas(classes_by_reference={
            "/First": enum_property_factory(),
        })

        result = _process_properties(data=data,
                                     schemas=schemas,
                                     class_name="",
                                     config=Config())

        assert isinstance(result, PropertyError)
    def test_date_format(self, date_property_factory):
        from openapi_python_client.parser.properties import property_from_data

        name = "date_prop"
        required = True
        nullable = True

        data = oai.Schema.construct(type="string", schema_format="date", nullable=nullable, default="2020-11-06")

        p, _ = property_from_data(
            name=name, required=required, data=data, schemas=Schemas(), config=Config(), parent_name=None
        )

        assert p == date_property_factory(
            name=name, required=required, nullable=nullable, default=f"isoparse('{data.default}').date()"
        )