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.
Files changed (33) hide show
  1. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/PKG-INFO +3 -3
  2. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/pyproject.toml +26 -8
  3. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/setup.py +3 -2
  4. openapi_python_generator-1.2.1.dev1757315868/src/openapi_python_generator/__init__.py +17 -0
  5. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/__main__.py +1 -1
  6. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/common.py +1 -2
  7. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/generate_data.py +7 -11
  8. {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
  9. {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
  10. {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
  11. {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
  12. {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
  13. {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
  14. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/models.py +9 -2
  15. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/parsers/__init__.py +2 -2
  16. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/parsers/openapi_30.py +1 -1
  17. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/parsers/openapi_31.py +1 -1
  18. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/version_detector.py +1 -1
  19. openapi_python_generator-1.2.1.dev1757310194/src/openapi_python_generator/__init__.py +0 -13
  20. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/LICENSE +0 -0
  21. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/README.md +0 -0
  22. {openapi_python_generator-1.2.1.dev1757310194 → openapi_python_generator-1.2.1.dev1757315868}/src/openapi_python_generator/language_converters/__init__.py +0 -0
  23. {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
  24. {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
  25. {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
  26. {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
  27. {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
  28. {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
  29. {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
  30. {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
  31. {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
  32. {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
  33. {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.dev1757310194
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.8,<4.0
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.1757310194"
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.8"
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
- flake8 = ">=3.0.1"
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
- mypy = ">=0.930"
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.dev1757310194',
35
+ 'version': '1.2.1.dev1757315868',
35
36
  'description': 'Openapi Python Generator',
36
37
  'long_description': "# Openapi Python Generator\n\n[![PyPI](https://img.shields.io/pypi/v/openapi-python-generator.svg)][pypi_]\n[![Status](https://img.shields.io/pypi/status/openapi-python-generator.svg)][status]\n[![Python Version](https://img.shields.io/pypi/pyversions/openapi-python-generator)][python version]\n[![License](https://img.shields.io/pypi/l/openapi-python-generator)][license]\n\n[![](https://img.shields.io/static/v1?label=documentation&message=enabled&color=<COLOR>)][documentation]\n[![Tests](https://github.com/MarcoMuellner/openapi-python-generator/workflows/Tests/badge.svg)][tests]\n[![Codecov](https://codecov.io/gh/MarcoMuellner/openapi-python-generator/branch/main/graph/badge.svg)][codecov]\n\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)][pre-commit]\n[![Black](https://img.shields.io/badge/code%20style-black-000000.svg)][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![](logo.png)\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.8,<4.0',
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"
@@ -72,7 +72,7 @@ def main(
72
72
  generate_data(
73
73
  source,
74
74
  output,
75
- library,
75
+ library if library is not None else HTTPLibrary.httpx,
76
76
  env_token_name,
77
77
  use_orjson,
78
78
  custom_template_path,
@@ -1,6 +1,5 @@
1
1
  from enum import Enum
2
- from typing import Dict
3
- from typing import Optional
2
+ from typing import Dict, Optional
4
3
 
5
4
  from openapi_python_generator.models import LibraryConfig
6
5
 
@@ -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 httpx import ConnectError
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
@@ -2,9 +2,8 @@ import keyword
2
2
  import re
3
3
  from typing import Optional
4
4
 
5
-
6
5
  _use_orjson: bool = False
7
- _custom_template_path: str = None
6
+ _custom_template_path: Optional[str] = None
8
7
  _symbol_ascii_strip_re = re.compile(r"[^A-Za-z0-9_]")
9
8
 
10
9
 
@@ -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
- # Type aliases for compatibility
19
- Schema = Union[Schema30, Schema31]
20
- Reference = Union[Reference30, Reference31]
21
- Components = Union[Components30, Components31]
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
- from openapi_python_generator.models import Property
37
- from openapi_python_generator.models import TypeConversion
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
- Schema as Schema30,
20
+ )
21
+ from openapi_pydantic.v3.v3_0 import (
24
22
  Response as Response30,
25
- MediaType as MediaType30,
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
- Schema as Schema31,
32
+ )
33
+ from openapi_pydantic.v3.v3_1 import (
30
34
  Response as Response31,
31
- MediaType as MediaType31,
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 LibraryConfig
43
- from openapi_python_generator.models import OpReturnType
44
- from openapi_python_generator.models import Service
45
- from openapi_python_generator.models import ServiceOperation
46
- from openapi_python_generator.models import TypeConversion
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(reference_obj):
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 = [i for i in operation_request_body_types if rb_content.get(i)][
187
- 0
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(mts, (Reference, Reference30, Reference31, Schema, Schema30, Schema31)):
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 getattr(chosen_response, "content") is not None: # type: ignore
260
- media_type_schema = getattr(chosen_response, "content").get("application/json") # type: ignore
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
- "array" in converted_result.original_type
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 getattr(path, "parameters") is not None: # type: ignore
336
- path_level_params = [p for p in getattr(path, "parameters") if p is not None] # type: ignore
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 = [m.group(1) for m in re.finditer(r"\{([^}/]+)\}", path_name)]
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 = set([so.tag for so in service_ops])
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 parse_openapi_3_0, generate_code_3_0
6
- from .openapi_31 import parse_openapi_3_1, generate_code_3_1
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(
@@ -2,7 +2,7 @@
2
2
  OpenAPI version detection utilities.
3
3
  """
4
4
 
5
- from typing import Dict, Any, Literal
5
+ from typing import Any, Dict, Literal
6
6
 
7
7
  OpenAPIVersion = Literal["3.0", "3.1"]
8
8
 
@@ -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"