diff --git a/README.md b/README.md index 711c79f72..80f02dcfa 100644 --- a/README.md +++ b/README.md @@ -146,5 +146,17 @@ Example: package_version_override: 1.2.3 ``` +## How to publish changes +Quip doc that highlights how to pull the dependency to Aurelia and publish using a buildkite pipeline can be found [here](https://benchling.quip.com/PgytA283Rlyo/2022-02-16-Guide-for-Publishing-a-Package) + +After changes are made to this package, to publish a new version of this package: +* Bump the version on pyproject.toml +* Install `gnu-sed` (assuming that you're running on a mac) by running `brew install gnu-sed` + * macOS uses BSD sed, which is similar to Linux's GNU sed but cannot explicitly edit files in place i.e. cannot utilize `-i` tag +* Set GNU sed PATH by running `brew info gnu-sed` to check for PATH +* Run `poetry run task gen-setuppy` which updates setup.py +* Kick off a buildkite pipeline build as highlighted in the quip doc (would need to designate the branch of which to check for publish) + + [changelog.md]: CHANGELOG.md [poetry]: https://python-poetry.org/ diff --git a/openapi_python_client/parser/openapi.py b/openapi_python_client/parser/openapi.py index a135b12cf..993c3c94a 100644 --- a/openapi_python_client/parser/openapi.py +++ b/openapi_python_client/parser/openapi.py @@ -102,7 +102,7 @@ class Endpoint: @staticmethod def parse_request_yaml_body( - *, body: oai.RequestBody, schemas: Schemas, parent_name: str + *, body: oai.RequestBody, schemas: Schemas, parent_name: str ) -> Tuple[Union[Property, PropertyError, None], Schemas]: """ Return yaml_body """ body_content = body.content diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index b26c05f93..2176c9033 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -443,7 +443,7 @@ def build_union_property( sub_properties.append(sub_prop) if data.discriminator is not None: reference_name_to_subprop[sub_prop.reference.class_name] = sub_prop - + discriminator_mappings: Dict[str, Property] = {} if data.discriminator is not None: for k, v in (data.discriminator.mapping if data.discriminator else {}).items(): @@ -571,13 +571,10 @@ def _property_from_data( elif data.type == "object" or data.allOf: return build_model_property(data=data, name=name, schemas=schemas, required=required, parent_name=parent_name) elif not data.type: - return NoneProperty( - name=name, - required=required, - nullable=False, - default=None, - description=data.description - ), schemas + return ( + NoneProperty(name=name, required=required, nullable=False, default=None, description=data.description), + schemas, + ) return PropertyError(data=data, detail=f"unknown type {data.type}"), schemas diff --git a/openapi_python_client/parser/responses.py b/openapi_python_client/parser/responses.py index 88bcad16f..3fa203a51 100644 --- a/openapi_python_client/parser/responses.py +++ b/openapi_python_client/parser/responses.py @@ -22,7 +22,7 @@ class Response: "application/json": "response.json()", "application/octet-stream": "response.content", "text/html": "response.text", - "text/yaml": "response.yaml", # Only used as an identifier, not the actual source + "text/yaml": "response.yaml", # Only used as an identifier, not the actual source } diff --git a/openapi_python_client/templates/endpoint_module.pyi b/openapi_python_client/templates/endpoint_module.pyi index 5869a584a..fe64bc15c 100644 --- a/openapi_python_client/templates/endpoint_module.pyi +++ b/openapi_python_client/templates/endpoint_module.pyi @@ -1,8 +1,8 @@ from typing import Any, Dict, List, Optional, Union, cast import httpx -from attr import asdict import yaml +from attr import asdict from ...client import AuthenticatedClient, Client from ...types import Response diff --git a/pyproject.toml b/pyproject.toml index eca2a06b4..3fba4ee1b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,8 @@ [tool.poetry] name = "openapi-python-client" -version = "0.7.3" +# Our versions have diverged and have no relation to upstream code changes +# Henceforth, openapi-python-package will be maintained internally +version = "1.0.0" description = "Generate modern Python clients from OpenAPI" repository = "https://github.com/triaxtec/openapi-python-client" license = "MIT" @@ -71,7 +73,8 @@ gen-setuppy = """ poetry build \ && tar --strip-components=1 -xvf "$(ls -1 dist/*tar.gz | tail -1)" '*/setup.py' \ && isort setup.py \ -&& black setup.py +&& black setup.py \ +&& sed -i 's/"openapi-python-client"/"benchling-openapi-python-client"/' setup.py """ [tool.black] diff --git a/setup.py b/setup.py index 6dfdd9e1f..ef23ffcd0 100644 --- a/setup.py +++ b/setup.py @@ -12,12 +12,12 @@ package_data = {"": ["*"], "openapi_python_client.templates": ["property_templates/*"]} install_requires = [ - "attrs>=20.1.0,<21.0.0", + "attrs>=20.1.0,<22.0", "autoflake>=1.4,<2.0", "black>=20.8b1", - "httpx>=0.15.4,<0.17.0", + "httpx>=0.15.4,<=0.22.0", "isort>=5.0.5,<6.0.0", - "jinja2>=3.1.1,<4.0.0", + "jinja2>=3.1.0,<4.0.0", "pydantic>=1.6.1,<2.0.0", "python-dateutil>=2.8.1,<3.0.0", "pyyaml>=5.3.1,<6.0.0", @@ -27,17 +27,17 @@ ] extras_require = { - ':python_version < "3.8"': ["importlib_metadata>=2.0.0,<3.0.0"], + ':python_version < "3.8"': ["importlib_metadata>=4.4"], ':sys_platform == "win32"': ["colorama>=0.4.3,<0.5.0"], } entry_points = {"console_scripts": ["openapi-python-client = openapi_python_client.cli:app"]} setup_kwargs = { - "name": "openapi-python-client", - "version": "0.7.0", + "name": "benchling-openapi-python-client", + "version": "1.0.0", "description": "Generate modern Python clients from OpenAPI", - "long_description": '[![triaxtec](https://circleci.com/gh/triaxtec/openapi-python-client.svg?style=svg)](https://circleci.com/gh/triaxtec/openapi-python-client)\n[![codecov](https://codecov.io/gh/triaxtec/openapi-python-client/branch/main/graph/badge.svg)](https://codecov.io/gh/triaxtec/openapi-python-client)\n[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)\n[![Generic badge](https://img.shields.io/badge/type_checked-mypy-informational.svg)](https://mypy.readthedocs.io/en/stable/introduction.html)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n[![PyPI version shields.io](https://img.shields.io/pypi/v/openapi-python-client.svg)](https://pypi.python.org/pypi/openapi-python-client/)\n[![Downloads](https://static.pepy.tech/personalized-badge/openapi-python-client?period=total&units=international_system&left_color=blue&right_color=green&left_text=Downloads)](https://pepy.tech/project/openapi-python-client)\n\n# openapi-python-client\n\nGenerate modern Python clients from OpenAPI 3.x documents.\n\n_This generator does not support OpenAPI 2.x FKA Swagger. If you need to use an older document, try upgrading it to\nversion 3 first with one of many available converters._\n\n**This project is still in development and does not support all OpenAPI features**\n\n## Why This?\n\nThe Python clients generated by openapi-generator support Python 2 and therefore come with a lot of baggage. This tool\naims to generate clients which:\n\n1. Use all the latest and greatest Python features like type annotations and dataclasses\n1. Don\'t carry around a bunch of compatibility code for older version of Python (e.g. the `six` package)\n1. Have better documentation and more obvious usage instructions\n\nAdditionally, because this generator is written in Python, it should be more accessible to contribution by the people\nusing it (Python developers).\n\n## Installation\n\nI recommend you install with [pipx](https://pipxproject.github.io/pipx/) so you don\'t conflict with any other packages\nyou might have: `pipx install openapi-python-client`.\n\nBetter yet, use `pipx run openapi-python-client ` to always use the latest version of the generator.\n\nYou can install with normal pip if you want to though: `pip install openapi-python-client`\n\nThen, if you want tab completion: `openapi-python-client --install-completion`\n\n## Usage\n\n### Create a new client\n\n`openapi-python-client generate --url https://my.api.com/openapi.json`\n\nThis will generate a new client library named based on the title in your OpenAPI spec. For example, if the title\nof your API is "My API", the expected output will be "my-api-client". If a folder already exists by that name, you\'ll\nget an error.\n\n### Update an existing client\n\n`openapi-python-client update --url https://my.api.com/openapi.json`\n\n> For more usage details run `openapi-python-client --help` or read [usage](usage.md)\n\n### Using custom templates\n\nThis feature leverages Jinja2\'s [ChoiceLoader](https://jinja.palletsprojects.com/en/2.11.x/api/#jinja2.ChoiceLoader) and [FileSystemLoader](https://jinja.palletsprojects.com/en/2.11.x/api/#jinja2.FileSystemLoader). This means you do _not_ need to customize every template. Simply copy the template(s) you want to customize from [the default template directory](openapi_python_client/templates) to your own custom template directory (file names _must_ match exactly) and pass the template directory through the `custom-template-path` flag to the `generate` and `update` commands. For instance,\n\n```\nopenapi-python-client update \\\n --url https://my.api.com/openapi.json \\\n --custom-template-path=relative/path/to/mytemplates\n```\n\n_Be forewarned, this is a beta-level feature in the sense that the API exposed in the templates is undocumented and unstable._\n\n## What You Get\n\n1. A `pyproject.toml` file with some basic metadata intended to be used with [Poetry].\n1. A `README.md` you\'ll most definitely need to update with your project\'s details\n1. A Python module named just like the auto-generated project name (e.g. "my_api_client") which contains:\n 1. A `client` module which will have both a `Client` class and an `AuthenticatedClient` class. You\'ll need these\n for calling the functions in the `api` module.\n 1. An `api` module which will contain one module for each tag in your OpenAPI spec, as well as a `default` module\n for endpoints without a tag. Each of these modules in turn contains one function for calling each endpoint.\n 1. A `models` module which has all the classes defined by the various schemas in your OpenAPI spec\n\nFor a full example you can look at the `end_to_end_tests` directory which has an `openapi.json` file.\n"golden-record" in that same directory is the generated client from that OpenAPI document.\n\n## OpenAPI features supported\n\n1. All HTTP Methods\n1. JSON and form bodies, path and query parameters\n1. File uploads with multipart/form-data bodies\n1. float, string, int, date, datetime, string enums, and custom schemas or lists containing any of those\n1. html/text or application/json responses containing any of the previous types\n1. Bearer token security\n\n## Configuration\n\nYou can pass a YAML (or JSON) file to openapi-python-client with the `--config` option in order to change some behavior.\nThe following parameters are supported:\n\n### class_overrides\n\nUsed to change the name of generated model classes. This param should be a mapping of existing class name\n(usually a key in the "schemas" section of your OpenAPI document) to class_name and module_name. As an example, if the\nname of the a model in OpenAPI (and therefore the generated class name) was something like "\\_PrivateInternalLongName"\nand you want the generated client\'s model to be called "ShortName" in a module called "short_name" you could do this:\n\nExample:\n\n```yaml\nclass_overrides:\n _PrivateInternalLongName:\n class_name: ShortName\n module_name: short_name\n```\n\nThe easiest way to find what needs to be overridden is probably to generate your client and go look at everything in the\nmodels folder.\n\n### project_name_override and package_name_override\n\nUsed to change the name of generated client library project/package. If the project name is changed but an override for the package name\nisn\'t provided, the package name will be converted from the project name using the standard convention (replacing `-`\'s with `_`\'s).\n\nExample:\n\n```yaml\nproject_name_override: my-special-project-name\npackage_name_override: my_extra_special_package_name\n```\n\n### field_prefix\n\nWhen generating properties, the `name` attribute of the OpenAPI schema will be used. When the `name` is not a valid\nPython identifier (e.g. begins with a number) this string will be prepended. Defaults to "field\\_".\n\nExample:\n\n```yaml\nfield_prefix: attr_\n```\n\n### package_version_override\n\nSpecify the package version of the generated client. If unset, the client will use the version of the OpenAPI spec.\n\nExample:\n\n```yaml\npackage_version_override: 1.2.3\n```\n\n[changelog.md]: CHANGELOG.md\n[poetry]: https://python-poetry.org/\n', + "long_description": '[![triaxtec](https://circleci.com/gh/triaxtec/openapi-python-client.svg?style=svg)](https://circleci.com/gh/triaxtec/openapi-python-client)\n[![codecov](https://codecov.io/gh/triaxtec/openapi-python-client/branch/main/graph/badge.svg)](https://codecov.io/gh/triaxtec/openapi-python-client)\n[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)\n[![Generic badge](https://img.shields.io/badge/type_checked-mypy-informational.svg)](https://mypy.readthedocs.io/en/stable/introduction.html)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n[![PyPI version shields.io](https://img.shields.io/pypi/v/openapi-python-client.svg)](https://pypi.python.org/pypi/openapi-python-client/)\n[![Downloads](https://static.pepy.tech/personalized-badge/openapi-python-client?period=total&units=international_system&left_color=blue&right_color=green&left_text=Downloads)](https://pepy.tech/project/openapi-python-client)\n\n# openapi-python-client\n\nGenerate modern Python clients from OpenAPI 3.x documents.\n\n_This generator does not support OpenAPI 2.x FKA Swagger. If you need to use an older document, try upgrading it to\nversion 3 first with one of many available converters._\n\n**This project is still in development and does not support all OpenAPI features**\n\n## Why This?\n\nThe Python clients generated by openapi-generator support Python 2 and therefore come with a lot of baggage. This tool\naims to generate clients which:\n\n1. Use all the latest and greatest Python features like type annotations and dataclasses\n1. Don\'t carry around a bunch of compatibility code for older version of Python (e.g. the `six` package)\n1. Have better documentation and more obvious usage instructions\n\nAdditionally, because this generator is written in Python, it should be more accessible to contribution by the people\nusing it (Python developers).\n\n## Installation\n\nI recommend you install with [pipx](https://pipxproject.github.io/pipx/) so you don\'t conflict with any other packages\nyou might have: `pipx install openapi-python-client`.\n\nBetter yet, use `pipx run openapi-python-client ` to always use the latest version of the generator.\n\nYou can install with normal pip if you want to though: `pip install openapi-python-client`\n\nThen, if you want tab completion: `openapi-python-client --install-completion`\n\n## Usage\n\n### Create a new client\n\n`openapi-python-client generate --url https://my.api.com/openapi.json`\n\nThis will generate a new client library named based on the title in your OpenAPI spec. For example, if the title\nof your API is "My API", the expected output will be "my-api-client". If a folder already exists by that name, you\'ll\nget an error.\n\n### Update an existing client\n\n`openapi-python-client update --url https://my.api.com/openapi.json`\n\n> For more usage details run `openapi-python-client --help` or read [usage](usage.md)\n\n### Using custom templates\n\nThis feature leverages Jinja2\'s [ChoiceLoader](https://jinja.palletsprojects.com/en/2.11.x/api/#jinja2.ChoiceLoader) and [FileSystemLoader](https://jinja.palletsprojects.com/en/2.11.x/api/#jinja2.FileSystemLoader). This means you do _not_ need to customize every template. Simply copy the template(s) you want to customize from [the default template directory](openapi_python_client/templates) to your own custom template directory (file names _must_ match exactly) and pass the template directory through the `custom-template-path` flag to the `generate` and `update` commands. For instance,\n\n```\nopenapi-python-client update \\\n --url https://my.api.com/openapi.json \\\n --custom-template-path=relative/path/to/mytemplates\n```\n\n_Be forewarned, this is a beta-level feature in the sense that the API exposed in the templates is undocumented and unstable._\n\n## What You Get\n\n1. A `pyproject.toml` file with some basic metadata intended to be used with [Poetry].\n1. A `README.md` you\'ll most definitely need to update with your project\'s details\n1. A Python module named just like the auto-generated project name (e.g. "my_api_client") which contains:\n 1. A `client` module which will have both a `Client` class and an `AuthenticatedClient` class. You\'ll need these\n for calling the functions in the `api` module.\n 1. An `api` module which will contain one module for each tag in your OpenAPI spec, as well as a `default` module\n for endpoints without a tag. Each of these modules in turn contains one function for calling each endpoint.\n 1. A `models` module which has all the classes defined by the various schemas in your OpenAPI spec\n\nFor a full example you can look at the `end_to_end_tests` directory which has an `openapi.json` file.\n"golden-record" in that same directory is the generated client from that OpenAPI document.\n\n## OpenAPI features supported\n\n1. All HTTP Methods\n1. JSON and form bodies, path and query parameters\n1. File uploads with multipart/form-data bodies\n1. float, string, int, date, datetime, string enums, and custom schemas or lists containing any of those\n1. html/text or application/json responses containing any of the previous types\n1. Bearer token security\n\n## Configuration\n\nYou can pass a YAML (or JSON) file to openapi-python-client with the `--config` option in order to change some behavior.\nThe following parameters are supported:\n\n### class_overrides\n\nUsed to change the name of generated model classes. This param should be a mapping of existing class name\n(usually a key in the "schemas" section of your OpenAPI document) to class_name and module_name. As an example, if the\nname of the a model in OpenAPI (and therefore the generated class name) was something like "\\_PrivateInternalLongName"\nand you want the generated client\'s model to be called "ShortName" in a module called "short_name" you could do this:\n\nExample:\n\n```yaml\nclass_overrides:\n _PrivateInternalLongName:\n class_name: ShortName\n module_name: short_name\n```\n\nThe easiest way to find what needs to be overridden is probably to generate your client and go look at everything in the\nmodels folder.\n\n### project_name_override and package_name_override\n\nUsed to change the name of generated client library project/package. If the project name is changed but an override for the package name\nisn\'t provided, the package name will be converted from the project name using the standard convention (replacing `-`\'s with `_`\'s).\n\nExample:\n\n```yaml\nproject_name_override: my-special-project-name\npackage_name_override: my_extra_special_package_name\n```\n\n### field_prefix\n\nWhen generating properties, the `name` attribute of the OpenAPI schema will be used. When the `name` is not a valid\nPython identifier (e.g. begins with a number) this string will be prepended. Defaults to "field\\_".\n\nExample:\n\n```yaml\nfield_prefix: attr_\n```\n\n### package_version_override\n\nSpecify the package version of the generated client. If unset, the client will use the version of the OpenAPI spec.\n\nExample:\n\n```yaml\npackage_version_override: 1.2.3\n```\n\n## How to publish changes\nQuip doc that highlights how to pull the dependency to Aurelia and publish using a buildkite pipeline can be found [here](https://benchling.quip.com/PgytA283Rlyo/2022-02-16-Guide-for-Publishing-a-Package)\n\nAfter changes are made to this package, to publish a new version of this package:\n* Bump the version on pyproject.toml\n* Install `gnu-sed` (assuming that you\'re running on a mac) by running `brew install gnu-sed`\n * macOS uses BSD sed, which is similar to Linux\'s GNU sed but cannot explicitly edit files in place i.e. cannot utilize `-i` tag\n* Set GNU sed PATH by running `brew info gnu-sed` to check for PATH\n* Run `poetry run task gen-setuppy` which updates setup.py\n* Kick off a buildkite pipeline build as highlighted in the quip doc (would need to designate the branch of which to check for publish)\n\n\n[changelog.md]: CHANGELOG.md\n[poetry]: https://python-poetry.org/\n', "author": "Dylan Anthony", "author_email": "danthony@triaxtec.com", "maintainer": None, @@ -48,7 +48,7 @@ "install_requires": install_requires, "extras_require": extras_require, "entry_points": entry_points, - "python_requires": ">=3.6,<4.0", + "python_requires": ">=3.7,<4.0", } diff --git a/tests/test_parser/test_openapi.py b/tests/test_parser/test_openapi.py index a3f7fab5b..619fbebee 100644 --- a/tests/test_parser/test_openapi.py +++ b/tests/test_parser/test_openapi.py @@ -68,10 +68,9 @@ def test_from_dict_invalid_schema(self, mocker): class TestEndpoint: def test_parse_yaml_body(self, mocker): from openapi_python_client.parser.openapi import Endpoint, Schemas + schema = mocker.MagicMock() - body = oai.RequestBody.construct( - content={"text/yaml": oai.MediaType.construct(media_type_schema=schema)} - ) + body = oai.RequestBody.construct(content={"text/yaml": oai.MediaType.construct(media_type_schema=schema)}) property_from_data = mocker.patch(f"{MODULE_NAME}.property_from_data") schemas = Schemas() diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 2c424007d..be3dc3ae1 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -201,21 +201,29 @@ def test_get_type_string(self, mocker): inner_property = mocker.MagicMock() inner_type_string = mocker.MagicMock() inner_property.get_type_string.return_value = inner_type_string - p = ListProperty(name="test", required=True, default=None, inner_property=inner_property, nullable=False, description=None) + p = ListProperty( + name="test", required=True, default=None, inner_property=inner_property, nullable=False, description=None + ) base_type_string = f"List[{inner_type_string}]" assert p.get_type_string() == base_type_string - p = ListProperty(name="test", required=True, default=None, inner_property=inner_property, nullable=True, description=None) + p = ListProperty( + name="test", required=True, default=None, inner_property=inner_property, nullable=True, description=None + ) assert p.get_type_string() == f"Optional[{base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string - p = ListProperty(name="test", required=False, default=None, inner_property=inner_property, nullable=True, description=None) + p = ListProperty( + name="test", required=False, default=None, inner_property=inner_property, nullable=True, description=None + ) assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string - p = ListProperty(name="test", required=False, default=None, inner_property=inner_property, nullable=False, description=None) + p = ListProperty( + name="test", required=False, default=None, inner_property=inner_property, nullable=False, description=None + ) assert p.get_type_string() == f"Union[Unset, {base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string @@ -226,14 +234,18 @@ def test_get_type_imports(self, mocker): inner_import = mocker.MagicMock() inner_property.get_imports.return_value = {inner_import} prefix = "..." - p = ListProperty(name="test", required=True, default=None, inner_property=inner_property, nullable=False, description=None) + p = ListProperty( + name="test", required=True, default=None, inner_property=inner_property, nullable=False, description=None + ) assert p.get_imports(prefix=prefix) == { inner_import, "from typing import cast, List", } - p = ListProperty(name="test", required=False, default=None, inner_property=inner_property, nullable=False, description=None) + p = ListProperty( + name="test", required=False, default=None, inner_property=inner_property, nullable=False, description=None + ) assert p.get_imports(prefix=prefix) == { inner_import, "from typing import cast, List", @@ -241,7 +253,9 @@ def test_get_type_imports(self, mocker): "from ...types import UNSET, Unset", } - p = ListProperty(name="test", required=False, default=None, inner_property=inner_property, nullable=True, description=None) + p = ListProperty( + name="test", required=False, default=None, inner_property=inner_property, nullable=True, description=None + ) assert p.get_imports(prefix=prefix) == { inner_import, "from typing import cast, List", @@ -690,7 +704,9 @@ def test_property_from_data_simple_types(self, openapi_type, prop_type, python_t name=name, required=required, data=data, schemas=schemas, parent_name="parent" ) - assert p == prop_type(name=name, required=required, default=python_type(data.default), nullable=False, description=None) + assert p == prop_type( + name=name, required=required, default=python_type(data.default), nullable=False, description=None + ) assert new_schemas == schemas # Test nullable values @@ -698,7 +714,9 @@ def test_property_from_data_simple_types(self, openapi_type, prop_type, python_t data.nullable = True p, _ = property_from_data(name=name, required=required, data=data, schemas=schemas, parent_name="parent") - assert p == prop_type(name=name, required=required, default=python_type(data.default), nullable=True, description=None) + assert p == prop_type( + name=name, required=required, default=python_type(data.default), nullable=True, description=None + ) # Test bad default value data.default = "a" @@ -900,7 +918,9 @@ def test_property_from_data_union(self, mocker): p, s = property_from_data(name=name, required=required, data=data, schemas=Schemas(), parent_name="parent") - FloatProperty.assert_called_once_with(name=name, required=required, default=0.0, nullable=False, description=None) + FloatProperty.assert_called_once_with( + name=name, required=required, default=0.0, nullable=False, description=None + ) IntProperty.assert_called_once_with(name=name, required=required, default=0, nullable=False, description=None) UnionProperty.assert_called_once_with( name=name, @@ -940,7 +960,9 @@ def test__string_based_property_no_format(self): p = _string_based_property(name=name, required=required, data=data) - assert p == StringProperty(name=name, required=required, nullable=True, default="'\\\\\"hello world\\\\\"'", description=None) + assert p == StringProperty( + name=name, required=required, nullable=True, default="'\\\\\"hello world\\\\\"'", description=None + ) data.pattern = "abcdef" data.nullable = False @@ -951,7 +973,12 @@ def test__string_based_property_no_format(self): data=data, ) assert p == StringProperty( - name=name, required=required, nullable=False, default="'\\\\\"hello world\\\\\"'", pattern="abcdef", description=None + name=name, + required=required, + nullable=False, + default="'\\\\\"hello world\\\\\"'", + pattern="abcdef", + description=None, ) def test__string_based_property_datetime_format(self): @@ -983,7 +1010,9 @@ def test__string_based_property_date_format(self): p = _string_based_property(name=name, required=required, data=data) - assert p == DateProperty(name=name, required=required, nullable=True, default="isoparse('2020-11-06').date()", description=None) + assert p == DateProperty( + name=name, required=required, nullable=True, default="isoparse('2020-11-06').date()", description=None + ) # Test bad default data.default = "a" @@ -1088,7 +1117,7 @@ def test_build_enums(mocker): (False, False), ( oai.Schema.construct(type="string"), - StringProperty(name="AdditionalProperty", required=True, nullable=False, default=None,description=None), + StringProperty(name="AdditionalProperty", required=True, nullable=False, default=None, description=None), ), ], ) @@ -1129,7 +1158,9 @@ def test_build_model_property(additional_properties_schema, expected_additional_ reference=Reference(class_name="ParentMyModel", module_name="parent_my_model"), references=[], required_properties=[StringProperty(name="req", required=True, nullable=False, default=None, description=None)], - optional_properties=[DateTimeProperty(name="opt", required=False, nullable=False, default=None, description=None)], + optional_properties=[ + DateTimeProperty(name="opt", required=False, nullable=False, default=None, description=None) + ], description=data.description, relative_imports={ "from dateutil.parser import isoparse", diff --git a/tests/test_templates/endpoint_module.py b/tests/test_templates/endpoint_module.py index 82cf93e9b..0d5c2096f 100644 --- a/tests/test_templates/endpoint_module.py +++ b/tests/test_templates/endpoint_module.py @@ -1,8 +1,8 @@ from typing import Any, Dict, List, Optional, Union, cast import httpx -from attr import asdict import yaml +from attr import asdict from ...client import AuthenticatedClient, Client from ...types import Response