openapi-python-generator 1.2.1.dev1757310194__tar.gz → 1.2.1.dev1757315868__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/PKG-INFO +3 -3
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/pyproject.toml +26 -8
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/setup.py +3 -2
- openapi_python_generator-1.2.1.dev1757315868/src/openapi_python_generator/__init__.py +17 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/__main__.py +1 -1
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/common.py +1 -2
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/generate_data.py +7 -11
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/api_config_generator.py +0 -2
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/common.py +1 -2
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/generator.py +1 -2
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/jinja_config.py +1 -4
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/model_generator.py +21 -20
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/service_generator.py +57 -38
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/models.py +9 -2
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/parsers/__init__.py +2 -2
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/parsers/openapi_30.py +1 -1
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/parsers/openapi_31.py +1 -1
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/version_detector.py +1 -1
- openapi_python_generator-1.2.1.dev1757310194/src/openapi_python_generator/__init__.py +0 -13
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/LICENSE +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/README.md +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/__init__.py +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/__init__.py +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/aiohttp.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/apiconfig.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/apiconfig_pydantic_2.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/enum.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/httpx.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/models.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/models_pydantic_2.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/requests.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/python/templates/service.jinja2 +0 -0
- {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/py.typed +0 -0
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: openapi-python-generator
|
|
3
|
-
Version: 1.2.1.
|
|
3
|
+
Version: 1.2.1.dev1757315868
|
|
4
4
|
Summary: Openapi Python Generator
|
|
5
5
|
Home-page: https://github.com/MarcoMuellner/openapi-python-generator
|
|
6
6
|
License: MIT
|
|
7
7
|
Keywords: OpenAPI,Generator,Python,async
|
|
8
8
|
Author: Marco Müllner
|
|
9
9
|
Author-email: muellnermarco@gmail.com
|
|
10
|
-
Requires-Python: >=3.
|
|
10
|
+
Requires-Python: >=3.9,<4.0
|
|
11
11
|
Classifier: Development Status :: 3 - Alpha
|
|
12
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -19,6 +18,7 @@ Requires-Dist: Jinja2 (>=3.1.2,<4.0.0)
|
|
|
19
18
|
Requires-Dist: black (>=21.10b0)
|
|
20
19
|
Requires-Dist: click (>=8.1.3,<9.0.0)
|
|
21
20
|
Requires-Dist: httpx[all] (>=0.28.0,<0.29.0)
|
|
21
|
+
Requires-Dist: importlib-metadata (>=8.7.0,<9.0.0)
|
|
22
22
|
Requires-Dist: isort (>=5.10.1)
|
|
23
23
|
Requires-Dist: openapi-pydantic (>=0.5.1,<0.6.0)
|
|
24
24
|
Requires-Dist: orjson (>=3.9.15,<4.0.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "openapi-python-generator"
|
|
3
|
-
version = "1.2.1.dev.
|
|
3
|
+
version = "1.2.1.dev.1757315868"
|
|
4
4
|
description = "Openapi Python Generator"
|
|
5
5
|
authors = ["Marco Müllner <muellnermarco@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -17,7 +17,7 @@ keywords = ["OpenAPI", "Generator", "Python", "async"]
|
|
|
17
17
|
Changelog = "https://github.com/MarcoMuellner/openapi-python-generator/releases"
|
|
18
18
|
|
|
19
19
|
[tool.poetry.dependencies]
|
|
20
|
-
python = "^3.
|
|
20
|
+
python = "^3.9"
|
|
21
21
|
httpx = {extras = ["all"], version = "^0.28.0"}
|
|
22
22
|
pydantic = "^2.10.2"
|
|
23
23
|
orjson = "^3.9.15"
|
|
@@ -27,18 +27,15 @@ black = ">=21.10b0"
|
|
|
27
27
|
isort = ">=5.10.1"
|
|
28
28
|
openapi-pydantic = "^0.5.1"
|
|
29
29
|
pyyaml = "^6.0.2"
|
|
30
|
+
importlib-metadata = "^8.7.0"
|
|
30
31
|
|
|
31
32
|
[tool.poetry.group.dev.dependencies]
|
|
32
33
|
Pygments = ">=2.10.0"
|
|
33
34
|
coverage = {extras = ["toml"], version = "^6.4.1"}
|
|
34
35
|
darglint = ">=1.8.1"
|
|
35
|
-
|
|
36
|
-
flake8-bandit = ">=2.1.2"
|
|
37
|
-
flake8-bugbear = ">=21.9.2"
|
|
38
|
-
flake8-docstrings = ">=1.6.0"
|
|
39
|
-
flake8-rst-docstrings = ">=0.2.5"
|
|
36
|
+
ruff = ">=0.12.12"
|
|
40
37
|
furo = ">=2021.11.12"
|
|
41
|
-
|
|
38
|
+
ty = "^0.0.1a20"
|
|
42
39
|
pep8-naming = ">=0.10.1"
|
|
43
40
|
pre-commit = ">=2.16.0"
|
|
44
41
|
pre-commit-hooks = ">=4.1.0"
|
|
@@ -53,6 +50,7 @@ fastapi = "^0.115.5"
|
|
|
53
50
|
uvicorn = "^0.18.1"
|
|
54
51
|
respx = "^0.22.0"
|
|
55
52
|
aiohttp = "^3.8.3"
|
|
53
|
+
responses = "^0.25.8"
|
|
56
54
|
|
|
57
55
|
[tool.poetry.scripts]
|
|
58
56
|
openapi-python-generator = "openapi_python_generator.__main__:main"
|
|
@@ -86,3 +84,23 @@ show_error_context = true
|
|
|
86
84
|
[build-system]
|
|
87
85
|
requires = ["poetry-core>=1.0.0"]
|
|
88
86
|
build-backend = "poetry.core.masonry.api"
|
|
87
|
+
|
|
88
|
+
[tool.ruff]
|
|
89
|
+
exclude = ["tests/*"]
|
|
90
|
+
line-length = 120
|
|
91
|
+
|
|
92
|
+
[tool.ruff.lint]
|
|
93
|
+
ignore = ["E501"]
|
|
94
|
+
select = [
|
|
95
|
+
"B",
|
|
96
|
+
"B9",
|
|
97
|
+
"C",
|
|
98
|
+
"E",
|
|
99
|
+
"F",
|
|
100
|
+
"I",
|
|
101
|
+
"S",
|
|
102
|
+
"W",
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
[tool.ruff.lint.mccabe]
|
|
106
|
+
max-complexity = 25
|
|
@@ -19,6 +19,7 @@ install_requires = \
|
|
|
19
19
|
'black>=21.10b0',
|
|
20
20
|
'click>=8.1.3,<9.0.0',
|
|
21
21
|
'httpx[all]>=0.28.0,<0.29.0',
|
|
22
|
+
'importlib-metadata>=8.7.0,<9.0.0',
|
|
22
23
|
'isort>=5.10.1',
|
|
23
24
|
'openapi-pydantic>=0.5.1,<0.6.0',
|
|
24
25
|
'orjson>=3.9.15,<4.0.0',
|
|
@@ -31,7 +32,7 @@ entry_points = \
|
|
|
31
32
|
|
|
32
33
|
setup_kwargs = {
|
|
33
34
|
'name': 'openapi-python-generator',
|
|
34
|
-
'version': '1.2.1.
|
|
35
|
+
'version': '1.2.1.dev1757315868',
|
|
35
36
|
'description': 'Openapi Python Generator',
|
|
36
37
|
'long_description': "# Openapi Python Generator\n\n[][pypi_]\n[][status]\n[][python version]\n[][license]\n\n[][documentation]\n[][tests]\n[][codecov]\n\n[][pre-commit]\n[][black]\n\n[pypi_]: https://pypi.org/project/openapi-python-generator/\n[status]: https://pypi.org/project/openapi-python-generator/\n[python version]: https://pypi.org/project/openapi-python-generator\n[documentation]: https://marcomuellner.github.io/openapi-python-generator/\n[tests]: https://github.com/MarcoMuellner/openapi-python-generator/actions?workflow=Tests\n[codecov]: https://app.codecov.io/gh/MarcoMuellner/openapi-python-generator\n[pre-commit]: https://github.com/pre-commit/pre-commit\n[black]: https://github.com/psf/black\n\n\n\n---\n__Documentation:__ [here][documentation]\n\n---\n\n## Features\n\n- __Ease of use__. Provide input, output and the library, and the generator will do the rest.\n- __Type safety and type hinting.__ __OpenAPI python generator__ makes heavy use of pydantic models to provide type-safe data structures.\n- __Support for multiple rest frameworks.__ __OpenAPI python generator__ currently supports the following:\n - [httpx](https://pypi.org/project/httpx/)\n - [requests](https://pypi.org/project/requests/)\n - [aiohttp](https://pypi.org/project/aiohttp/)\n- __Async and sync code generation support__, depending on the framework. It will automatically create both for frameworks that support both.\n- __Easily extendable using Jinja2 templates__. The code is designed to be easily extendable and should support even more languages and frameworks in the future.\n- __Fully tested__. Every generated code is automatically tested against the OpenAPI spec and we have 100% coverage.\n- __Usage as CLI or as library__.\n\n## Requirements\n\n- Python 3.7+\n\n## Installation\n\nYou can install _Openapi Python Generator_ via [pip] from [PyPI]:\n\n```console\n$ pip install openapi-python-generator\n```\n\n## Usage\n\nPlease see the [Quick start page] for details.\n\n## Roadmap\n\n- Support for all commonly used http libraries in the python ecosystem (~~requests~~, urllib, ...)\n- Support for multiple languages\n- Support for multiple authentication schemes\n- Support custom themes\n\n## Contributing\n\nContributions are very welcome.\nTo learn more, see the [Contributor Guide].\n\n## License\n\nDistributed under the terms of the [MIT license][license],\n_Openapi Python Generator_ is free and open source software.\n\n## Issues\n\nIf you encounter any problems,\nplease [file an issue] along with a detailed description.\n\n## Credits\n\nSpecial thanks to the peeps from [openapi-schema-pydantic](https://github.com/kuimono/openapi-schema-pydantic),\nwhich already did a lot of the legwork by providing a pydantic schema for the OpenAPI 3.0.0+ specification.\n\nThis project was generated from [@cjolowicz]'s [Hypermodern Python Cookiecutter] template.\n\n[@cjolowicz]: https://github.com/cjolowicz\n[pypi]: https://pypi.org/\n[hypermodern python cookiecutter]: https://github.com/cjolowicz/cookiecutter-hypermodern-python\n[file an issue]: https://github.com/MarcoMuellner/openapi-python-generator/issues\n[pip]: https://pip.pypa.io/\n\n<!-- github-only -->\n\n[license]: https://github.com/MarcoMuellner/openapi-python-generator/blob/main/LICENSE\n[contributor guide]: https://github.com/MarcoMuellner/openapi-python-generator/blob/main/CONTRIBUTING.md\n[Quick start page]: https://marcomuellner.github.io/openapi-python-generator/quick_start/\n",
|
|
37
38
|
'author': 'Marco Müllner',
|
|
@@ -44,7 +45,7 @@ setup_kwargs = {
|
|
|
44
45
|
'package_data': package_data,
|
|
45
46
|
'install_requires': install_requires,
|
|
46
47
|
'entry_points': entry_points,
|
|
47
|
-
'python_requires': '>=3.
|
|
48
|
+
'python_requires': '>=3.9,<4.0',
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Python client from an OPENAPI 3.0+ specification in seconds."""
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from importlib.metadata import (
|
|
5
|
+
PackageNotFoundError, # type: ignore
|
|
6
|
+
version,
|
|
7
|
+
)
|
|
8
|
+
except ImportError: # pragma: no cover
|
|
9
|
+
from importlib_metadata import (
|
|
10
|
+
PackageNotFoundError, # type: ignore
|
|
11
|
+
version, # type: ignore
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
__version__ = version(__name__)
|
|
16
|
+
except PackageNotFoundError: # pragma: no cover
|
|
17
|
+
__version__ = "unknown"
|
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import List
|
|
3
|
-
from typing import Optional
|
|
4
|
-
from typing import Union
|
|
2
|
+
from typing import List, Optional, Union
|
|
5
3
|
|
|
6
4
|
import black
|
|
7
|
-
from black.report import NothingChanged # type: ignore
|
|
8
5
|
import click
|
|
9
6
|
import httpx
|
|
10
7
|
import isort
|
|
11
8
|
import orjson
|
|
12
9
|
import yaml # type: ignore
|
|
13
|
-
from
|
|
14
|
-
from httpx import ConnectTimeout
|
|
10
|
+
from black.report import NothingChanged # type: ignore
|
|
11
|
+
from httpx import ConnectError, ConnectTimeout
|
|
15
12
|
from pydantic import ValidationError
|
|
16
13
|
|
|
17
14
|
from .common import FormatOptions, Formatter, HTTPLibrary, PydanticVersion
|
|
18
|
-
from .language_converters.python.jinja_config import SERVICE_TEMPLATE
|
|
19
|
-
from .language_converters.python.jinja_config import create_jinja_env
|
|
15
|
+
from .language_converters.python.jinja_config import SERVICE_TEMPLATE, create_jinja_env
|
|
20
16
|
from .models import ConversionResult
|
|
21
|
-
from .version_detector import detect_openapi_version
|
|
22
17
|
from .parsers import (
|
|
23
|
-
parse_openapi_3_0,
|
|
24
|
-
parse_openapi_3_1,
|
|
25
18
|
generate_code_3_0,
|
|
26
19
|
generate_code_3_1,
|
|
20
|
+
parse_openapi_3_0,
|
|
21
|
+
parse_openapi_3_1,
|
|
27
22
|
)
|
|
23
|
+
from .version_detector import detect_openapi_version
|
|
28
24
|
|
|
29
25
|
|
|
30
26
|
def write_code(path: Path, content: str, formatter: Formatter) -> None:
|
|
@@ -6,8 +6,6 @@ from openapi_python_generator.common import PydanticVersion
|
|
|
6
6
|
from openapi_python_generator.language_converters.python.jinja_config import (
|
|
7
7
|
API_CONFIG_TEMPLATE,
|
|
8
8
|
API_CONFIG_TEMPLATE_PYDANTIC_V2,
|
|
9
|
-
)
|
|
10
|
-
from openapi_python_generator.language_converters.python.jinja_config import (
|
|
11
9
|
create_jinja_env,
|
|
12
10
|
)
|
|
13
11
|
from openapi_python_generator.models import APIConfig
|
|
@@ -14,8 +14,7 @@ from openapi_python_generator.language_converters.python.model_generator import
|
|
|
14
14
|
from openapi_python_generator.language_converters.python.service_generator import (
|
|
15
15
|
generate_services,
|
|
16
16
|
)
|
|
17
|
-
from openapi_python_generator.models import ConversionResult
|
|
18
|
-
from openapi_python_generator.models import LibraryConfig
|
|
17
|
+
from openapi_python_generator.models import ConversionResult, LibraryConfig
|
|
19
18
|
|
|
20
19
|
# Type alias for both OpenAPI versions
|
|
21
20
|
OpenAPISpec = Union[OpenAPI30, OpenAPI31]
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
-
from jinja2 import ChoiceLoader
|
|
4
|
-
from jinja2 import Environment
|
|
5
|
-
from jinja2 import FileSystemLoader
|
|
3
|
+
from jinja2 import ChoiceLoader, Environment, FileSystemLoader
|
|
6
4
|
|
|
7
5
|
from . import common
|
|
8
6
|
|
|
9
|
-
|
|
10
7
|
ENUM_TEMPLATE = "enum.jinja2"
|
|
11
8
|
MODELS_TEMPLATE = "models.jinja2"
|
|
12
9
|
MODELS_TEMPLATE_PYDANTIC_V2 = "models_pydantic_2.jinja2"
|
|
@@ -1,40 +1,41 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
import re
|
|
3
|
-
from typing import List, Union
|
|
4
|
-
from typing import Optional
|
|
3
|
+
from typing import List, Optional, Union
|
|
5
4
|
|
|
6
5
|
import click
|
|
7
6
|
from openapi_pydantic.v3.v3_0 import (
|
|
8
|
-
Schema as Schema30,
|
|
9
|
-
Reference as Reference30,
|
|
10
7
|
Components as Components30,
|
|
11
8
|
)
|
|
9
|
+
from openapi_pydantic.v3.v3_0 import (
|
|
10
|
+
Reference as Reference30,
|
|
11
|
+
)
|
|
12
|
+
from openapi_pydantic.v3.v3_0 import (
|
|
13
|
+
Schema as Schema30,
|
|
14
|
+
)
|
|
12
15
|
from openapi_pydantic.v3.v3_1 import (
|
|
13
|
-
Schema as Schema31,
|
|
14
|
-
Reference as Reference31,
|
|
15
16
|
Components as Components31,
|
|
16
17
|
)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
from openapi_pydantic.v3.v3_1 import (
|
|
19
|
+
Reference as Reference31,
|
|
20
|
+
)
|
|
21
|
+
from openapi_pydantic.v3.v3_1 import (
|
|
22
|
+
Schema as Schema31,
|
|
23
|
+
)
|
|
22
24
|
|
|
23
25
|
from openapi_python_generator.common import PydanticVersion
|
|
24
26
|
from openapi_python_generator.language_converters.python import common
|
|
25
27
|
from openapi_python_generator.language_converters.python.jinja_config import (
|
|
26
28
|
ENUM_TEMPLATE,
|
|
27
|
-
MODELS_TEMPLATE_PYDANTIC_V2,
|
|
28
|
-
)
|
|
29
|
-
from openapi_python_generator.language_converters.python.jinja_config import (
|
|
30
29
|
MODELS_TEMPLATE,
|
|
31
|
-
|
|
32
|
-
from openapi_python_generator.language_converters.python.jinja_config import (
|
|
30
|
+
MODELS_TEMPLATE_PYDANTIC_V2,
|
|
33
31
|
create_jinja_env,
|
|
34
32
|
)
|
|
35
|
-
from openapi_python_generator.models import Model
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
from openapi_python_generator.models import Model, Property, TypeConversion
|
|
34
|
+
|
|
35
|
+
# Type aliases for compatibility
|
|
36
|
+
Schema = Union[Schema30, Schema31]
|
|
37
|
+
Reference = Union[Reference30, Reference31]
|
|
38
|
+
Components = Union[Components30, Components31]
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
def type_converter( # noqa: C901
|
|
@@ -88,7 +89,7 @@ def type_converter( # noqa: C901
|
|
|
88
89
|
conversions.append(type_converter(sub_schema, True))
|
|
89
90
|
else:
|
|
90
91
|
import_type = common.normalize_symbol(sub_schema.ref.split("/")[-1])
|
|
91
|
-
if import_type == model_name:
|
|
92
|
+
if import_type == model_name and model_name is not None:
|
|
92
93
|
conversions.append(
|
|
93
94
|
TypeConversion(
|
|
94
95
|
original_type=sub_schema.ref,
|
|
@@ -1,34 +1,40 @@
|
|
|
1
1
|
import re
|
|
2
|
-
from typing import Any
|
|
3
|
-
from typing import Dict
|
|
4
|
-
from typing import List
|
|
5
|
-
from typing import Literal
|
|
6
|
-
from typing import Optional
|
|
7
|
-
from typing import Tuple
|
|
8
|
-
from typing import Union
|
|
2
|
+
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
|
|
9
3
|
|
|
10
4
|
import click
|
|
11
5
|
from openapi_pydantic.v3 import (
|
|
12
|
-
Reference,
|
|
13
|
-
Schema,
|
|
14
6
|
Operation,
|
|
15
7
|
Parameter,
|
|
16
|
-
Response,
|
|
17
8
|
PathItem,
|
|
9
|
+
Reference,
|
|
10
|
+
Response,
|
|
11
|
+
Schema,
|
|
12
|
+
)
|
|
13
|
+
from openapi_pydantic.v3.v3_0 import (
|
|
14
|
+
MediaType as MediaType30,
|
|
18
15
|
)
|
|
19
16
|
|
|
20
17
|
# Import version-specific types for isinstance checks
|
|
21
18
|
from openapi_pydantic.v3.v3_0 import (
|
|
22
19
|
Reference as Reference30,
|
|
23
|
-
|
|
20
|
+
)
|
|
21
|
+
from openapi_pydantic.v3.v3_0 import (
|
|
24
22
|
Response as Response30,
|
|
25
|
-
|
|
23
|
+
)
|
|
24
|
+
from openapi_pydantic.v3.v3_0 import (
|
|
25
|
+
Schema as Schema30,
|
|
26
|
+
)
|
|
27
|
+
from openapi_pydantic.v3.v3_1 import (
|
|
28
|
+
MediaType as MediaType31,
|
|
26
29
|
)
|
|
27
30
|
from openapi_pydantic.v3.v3_1 import (
|
|
28
31
|
Reference as Reference31,
|
|
29
|
-
|
|
32
|
+
)
|
|
33
|
+
from openapi_pydantic.v3.v3_1 import (
|
|
30
34
|
Response as Response31,
|
|
31
|
-
|
|
35
|
+
)
|
|
36
|
+
from openapi_pydantic.v3.v3_1 import (
|
|
37
|
+
Schema as Schema31,
|
|
32
38
|
)
|
|
33
39
|
|
|
34
40
|
from openapi_python_generator.language_converters.python import common
|
|
@@ -39,11 +45,13 @@ from openapi_python_generator.language_converters.python.jinja_config import (
|
|
|
39
45
|
from openapi_python_generator.language_converters.python.model_generator import (
|
|
40
46
|
type_converter,
|
|
41
47
|
)
|
|
42
|
-
from openapi_python_generator.models import
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
from openapi_python_generator.models import (
|
|
49
|
+
LibraryConfig,
|
|
50
|
+
OpReturnType,
|
|
51
|
+
Service,
|
|
52
|
+
ServiceOperation,
|
|
53
|
+
TypeConversion,
|
|
54
|
+
)
|
|
47
55
|
|
|
48
56
|
|
|
49
57
|
# Helper functions for isinstance checks across OpenAPI versions
|
|
@@ -52,16 +60,18 @@ def is_response_type(obj) -> bool:
|
|
|
52
60
|
return isinstance(obj, (Response30, Response31))
|
|
53
61
|
|
|
54
62
|
|
|
55
|
-
def create_media_type_for_reference(
|
|
63
|
+
def create_media_type_for_reference(
|
|
64
|
+
reference_obj: Response30 | Reference30 | Response31 | Reference31,
|
|
65
|
+
):
|
|
56
66
|
"""Create a MediaType wrapper for a reference object, using the correct version"""
|
|
57
67
|
# Check which version the reference object belongs to
|
|
58
68
|
if isinstance(reference_obj, Reference30):
|
|
59
|
-
return MediaType30(schema=reference_obj)
|
|
69
|
+
return MediaType30(schema=reference_obj) # type: ignore - pydantic issue with generics
|
|
60
70
|
elif isinstance(reference_obj, Reference31):
|
|
61
|
-
return MediaType31(schema=reference_obj)
|
|
71
|
+
return MediaType31(schema=reference_obj) # type: ignore - pydantic issue with generics
|
|
62
72
|
else:
|
|
63
73
|
# Fallback to v3.0 for generic Reference
|
|
64
|
-
return MediaType30(schema=reference_obj)
|
|
74
|
+
return MediaType30(schema=reference_obj) # type: ignore - pydantic issue with generics
|
|
65
75
|
|
|
66
76
|
|
|
67
77
|
def is_media_type(obj) -> bool:
|
|
@@ -183,13 +193,16 @@ def generate_params(operation: Operation) -> str:
|
|
|
183
193
|
if isinstance(rb_content, dict) and any(
|
|
184
194
|
rb_content.get(i) is not None for i in operation_request_body_types
|
|
185
195
|
):
|
|
186
|
-
get_keyword = [
|
|
187
|
-
|
|
188
|
-
]
|
|
196
|
+
get_keyword = [
|
|
197
|
+
i for i in operation_request_body_types if rb_content.get(i)
|
|
198
|
+
][0]
|
|
189
199
|
content = rb_content.get(get_keyword)
|
|
190
200
|
if content is not None and hasattr(content, "media_type_schema"):
|
|
191
201
|
mts = getattr(content, "media_type_schema", None)
|
|
192
|
-
if isinstance(
|
|
202
|
+
if isinstance(
|
|
203
|
+
mts,
|
|
204
|
+
(Reference, Reference30, Reference31, Schema, Schema30, Schema31),
|
|
205
|
+
):
|
|
193
206
|
params += f"{_generate_params_from_content(mts)}, "
|
|
194
207
|
else: # pragma: no cover
|
|
195
208
|
raise Exception(
|
|
@@ -256,8 +269,8 @@ def generate_return_type(operation: Operation) -> OpReturnType:
|
|
|
256
269
|
|
|
257
270
|
if is_response_type(chosen_response):
|
|
258
271
|
# It's a Response type, access content safely
|
|
259
|
-
if hasattr(chosen_response, "content") and
|
|
260
|
-
media_type_schema =
|
|
272
|
+
if hasattr(chosen_response, "content") and chosen_response.content is not None: # type: ignore
|
|
273
|
+
media_type_schema = chosen_response.content.get("application/json") # type: ignore
|
|
261
274
|
elif is_reference_type(chosen_response):
|
|
262
275
|
media_type_schema = create_media_type_for_reference(chosen_response)
|
|
263
276
|
|
|
@@ -281,9 +294,8 @@ def generate_return_type(operation: Operation) -> OpReturnType:
|
|
|
281
294
|
)
|
|
282
295
|
elif is_schema_type(inner_schema):
|
|
283
296
|
converted_result = type_converter(inner_schema, True) # type: ignore
|
|
284
|
-
if (
|
|
285
|
-
|
|
286
|
-
and isinstance(converted_result.import_types, list)
|
|
297
|
+
if "array" in converted_result.original_type and isinstance(
|
|
298
|
+
converted_result.import_types, list
|
|
287
299
|
):
|
|
288
300
|
matched = re.findall(r"List\[(.+)\]", converted_result.converted_type)
|
|
289
301
|
if len(matched) > 0:
|
|
@@ -332,8 +344,8 @@ def generate_services(
|
|
|
332
344
|
# operation-level parameters so they get turned into function args.
|
|
333
345
|
try:
|
|
334
346
|
path_level_params = []
|
|
335
|
-
if hasattr(path, "parameters") and
|
|
336
|
-
path_level_params = [p for p in
|
|
347
|
+
if hasattr(path, "parameters") and path.parameters is not None: # type: ignore
|
|
348
|
+
path_level_params = [p for p in path.parameters if p is not None] # type: ignore
|
|
337
349
|
if path_level_params:
|
|
338
350
|
existing_names = set()
|
|
339
351
|
if op.parameters is not None:
|
|
@@ -346,21 +358,28 @@ def generate_services(
|
|
|
346
358
|
op.parameters = [] # type: ignore
|
|
347
359
|
op.parameters.append(p) # type: ignore
|
|
348
360
|
except Exception: # pragma: no cover
|
|
361
|
+
print(
|
|
362
|
+
f"Error merging path-level parameters for {path_name}"
|
|
363
|
+
) # pragma: no cover
|
|
349
364
|
pass
|
|
350
365
|
|
|
351
366
|
params = generate_params(op)
|
|
352
367
|
# Fallback: ensure all {placeholders} in path are present as function params
|
|
353
368
|
try:
|
|
354
|
-
placeholder_names = [
|
|
369
|
+
placeholder_names = [
|
|
370
|
+
m.group(1) for m in re.finditer(r"\{([^}/]+)\}", path_name)
|
|
371
|
+
]
|
|
355
372
|
existing_param_names = {
|
|
356
|
-
p.split(":")[0].strip()
|
|
357
|
-
for p in params.split(",") if ":" in p
|
|
373
|
+
p.split(":")[0].strip() for p in params.split(",") if ":" in p
|
|
358
374
|
}
|
|
359
375
|
for ph in placeholder_names:
|
|
360
376
|
norm_ph = common.normalize_symbol(ph)
|
|
361
377
|
if norm_ph not in existing_param_names and norm_ph:
|
|
362
378
|
params = f"{norm_ph}: Any, " + params
|
|
363
379
|
except Exception: # pragma: no cover
|
|
380
|
+
print(
|
|
381
|
+
f"Error ensuring path placeholders in params for {path_name}"
|
|
382
|
+
) # pragma: no cover
|
|
364
383
|
pass
|
|
365
384
|
operation_id = generate_operation_id(op, http_operation, path_name)
|
|
366
385
|
query_params = generate_query_params(op)
|
|
@@ -419,7 +438,7 @@ def generate_services(
|
|
|
419
438
|
if not so.tag:
|
|
420
439
|
so.tag = "default"
|
|
421
440
|
|
|
422
|
-
tags =
|
|
441
|
+
tags = list({so.tag for so in service_ops})
|
|
423
442
|
|
|
424
443
|
for tag in tags:
|
|
425
444
|
services.append(
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
from typing import List, Union
|
|
2
|
-
from typing import Optional
|
|
1
|
+
from typing import List, Optional, Union
|
|
3
2
|
|
|
4
3
|
from openapi_pydantic.v3.v3_0 import (
|
|
5
4
|
Operation as Operation30,
|
|
5
|
+
)
|
|
6
|
+
from openapi_pydantic.v3.v3_0 import (
|
|
6
7
|
PathItem as PathItem30,
|
|
8
|
+
)
|
|
9
|
+
from openapi_pydantic.v3.v3_0 import (
|
|
7
10
|
Schema as Schema30,
|
|
8
11
|
)
|
|
9
12
|
from openapi_pydantic.v3.v3_1 import (
|
|
10
13
|
Operation as Operation31,
|
|
14
|
+
)
|
|
15
|
+
from openapi_pydantic.v3.v3_1 import (
|
|
11
16
|
PathItem as PathItem31,
|
|
17
|
+
)
|
|
18
|
+
from openapi_pydantic.v3.v3_1 import (
|
|
12
19
|
Schema as Schema31,
|
|
13
20
|
)
|
|
14
21
|
from pydantic import BaseModel
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
OpenAPI parsers for different specification versions.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .openapi_30 import
|
|
6
|
-
from .openapi_31 import
|
|
5
|
+
from .openapi_30 import generate_code_3_0, parse_openapi_3_0
|
|
6
|
+
from .openapi_31 import generate_code_3_1, parse_openapi_3_1
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
9
|
"parse_openapi_3_0",
|
|
@@ -26,7 +26,7 @@ def parse_openapi_3_0(spec_data: dict) -> OpenAPI:
|
|
|
26
26
|
Raises:
|
|
27
27
|
ValidationError: If the specification is invalid
|
|
28
28
|
"""
|
|
29
|
-
return OpenAPI(**spec_data)
|
|
29
|
+
return OpenAPI(**spec_data) # type: ignore - pydantic issue with extra fields
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def generate_code_3_0(
|
|
@@ -26,7 +26,7 @@ def parse_openapi_3_1(spec_data: dict) -> OpenAPI:
|
|
|
26
26
|
Raises:
|
|
27
27
|
ValidationError: If the specification is invalid
|
|
28
28
|
"""
|
|
29
|
-
return OpenAPI(**spec_data)
|
|
29
|
+
return OpenAPI(**spec_data) # type: ignore - pydantic issue with extra fields
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def generate_code_3_1(
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"""Python client from an OPENAPI 3.0+ specification in seconds."""
|
|
2
|
-
|
|
3
|
-
try:
|
|
4
|
-
from importlib.metadata import PackageNotFoundError # type: ignore
|
|
5
|
-
from importlib.metadata import version
|
|
6
|
-
except ImportError: # pragma: no cover
|
|
7
|
-
from importlib_metadata import PackageNotFoundError # type: ignore
|
|
8
|
-
from importlib_metadata import version # type: ignore
|
|
9
|
-
|
|
10
|
-
try:
|
|
11
|
-
__version__ = version(__name__)
|
|
12
|
-
except PackageNotFoundError: # pragma: no cover
|
|
13
|
-
__version__ = "unknown"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|