Skip to content

Commit 287ddb5

Browse files
authoredNov 28, 2024
Merge pull request #76 from MarcoMuellner/pydantic_v2
Pydantic v2
2 parents 390ce1a + 62be018 commit 287ddb5

19 files changed

+2013
-1568
lines changed
 

‎docs/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ The key features of the generator are:
2323
- __Support for multiple rest frameworks.__ __OpenAPI python generator__ currently supports the following:
2424
- [httpx](https://pypi.org/project/httpx/)
2525
- [requests](https://pypi.org/project/requests/)
26+
- [aiohttp](https://pypi.org/project/aiohttp/)
2627
- __Async and sync code generation support__, depending on the framework. It will automatically create both for frameworks that support both.
2728
- __Easily extendable using Jinja2 templates__. The code is designed to be easily extendable and should support even more languages and frameworks in the future.
2829
- __Fully tested__. Every generated code is automatically tested against the OpenAPI spec and we have 100% coverage.

‎docs/references/index.md

+23-5
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,27 @@ Arguments:
1515

1616
Options:
1717
```console
18-
--library The library to use. Defaults to `httpx`.
19-
--env-token-name The name of the environment variable to use for the API key. Defaults to `access_token`.
20-
--use-orjson Use the `orjson` library for serialization. Defaults to `false`.
21-
--custom-template-path Use a custom template path to override the built in templates.
22-
-h, --help Show this help message and exit.
18+
--library [httpx|requests|aiohttp]
19+
HTTP library to use in the generation of the client.
20+
Defaults to 'httpx'.
21+
22+
--env-token-name TEXT Name of the environment variable that contains the token.
23+
If set, code expects this environment variable and will
24+
raise an error if not set.
25+
Defaults to 'access_token'.
26+
27+
--use-orjson Use the orjson library for JSON serialization. Enables
28+
faster processing and better type support.
29+
Defaults to False.
30+
31+
--custom-template-path TEXT
32+
Custom template path to use. Allows overriding of the
33+
built in templates.
34+
35+
--pydantic-version [v1|v2]
36+
Pydantic version to use for generated models.
37+
Defaults to 'v2'.
38+
39+
--version Show the version and exit.
40+
-h, --help Show this help message and exit.
2341
```

‎poetry.lock

+1,707-1,266
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pyproject.toml

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "openapi-python-generator"
3-
version = "0.5.0"
3+
version = "1.0.0"
44
description = "Openapi Python Generator"
55
authors = ["Marco Müllner <muellnermarco@gmail.com>"]
66
license = "MIT"
@@ -17,15 +17,15 @@ keywords = ["OpenAPI", "Generator", "Python", "async"]
1717
Changelog = "https://github.com/MarcoMuellner/openapi-python-generator/releases"
1818

1919
[tool.poetry.dependencies]
20-
python = "^3.7"
20+
python = "^3.8"
2121
httpx = {extras = ["all"], version = "^0.23.0"}
22-
pydantic = "^1.9.1"
23-
orjson = "^3.7.2"
24-
openapi-schema-pydantic = "^1.2.3"
22+
pydantic = "^2.10.2"
23+
orjson = "^3.9.15"
2524
Jinja2 = "^3.1.2"
2625
click = "^8.1.3"
2726
black = ">=21.10b0"
2827
isort = ">=5.10.1"
28+
openapi-pydantic = "^0.5.0"
2929

3030
[tool.poetry.dev-dependencies]
3131
Pygments = ">=2.10.0"
@@ -48,7 +48,7 @@ typeguard = ">=2.13.3"
4848
xdoctest = {extras = ["colors"], version = ">=0.15.10"}
4949
myst-parser = {version = ">=0.16.1"}
5050
pytest-cov = "^3.0.0"
51-
fastapi = "^0.78.0"
51+
fastapi = "^0.115.5"
5252
uvicorn = "^0.18.1"
5353
respx = "^0.20.1"
5454
aiohttp = "^3.8.3"

‎src/openapi_python_generator/__main__.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from typing import Optional
2+
from enum import Enum
23

34
import click
45

56
from openapi_python_generator import __version__
6-
from openapi_python_generator.common import HTTPLibrary
7+
from openapi_python_generator.common import HTTPLibrary, PydanticVersion
78
from openapi_python_generator.generate_data import generate_data
89

9-
1010
@click.command()
1111
@click.argument("source")
1212
@click.argument("output")
@@ -38,6 +38,13 @@
3838
default=None,
3939
help="Custom template path to use. Allows overriding of the built in templates",
4040
)
41+
@click.option(
42+
"--pydantic-version",
43+
type=click.Choice(["v1", "v2"]),
44+
default="v2",
45+
show_default=True,
46+
help="Pydantic version to use for generated models.",
47+
)
4148
@click.version_option(version=__version__)
4249
def main(
4350
source: str,
@@ -46,6 +53,7 @@ def main(
4653
env_token_name: Optional[str] = None,
4754
use_orjson: bool = False,
4855
custom_template_path: Optional[str] = None,
56+
pydantic_version: PydanticVersion = PydanticVersion.V2,
4957
) -> None:
5058
"""
5159
Generate Python code from an OpenAPI 3.0 specification.
@@ -54,9 +62,9 @@ def main(
5462
an OUTPUT path, where the resulting client is created.
5563
"""
5664
generate_data(
57-
source, output, library, env_token_name, use_orjson, custom_template_path
65+
source, output, library, env_token_name, use_orjson, custom_template_path,pydantic_version
5866
)
5967

6068

6169
if __name__ == "__main__": # pragma: no cover
62-
main()
70+
main()

‎src/openapi_python_generator/common.py

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class HTTPLibrary(str, Enum):
1414
requests = "requests"
1515
aiohttp = "aiohttp"
1616

17+
class PydanticVersion(str, Enum):
18+
V1 = "v1"
19+
V2 = "v2"
20+
1721

1822
library_config_dict: Dict[Optional[HTTPLibrary], LibraryConfig] = {
1923
HTTPLibrary.httpx: LibraryConfig(

‎src/openapi_python_generator/generate_data.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
from black import NothingChanged
1111
from httpx import ConnectError
1212
from httpx import ConnectTimeout
13-
from openapi_schema_pydantic import OpenAPI
13+
from openapi_pydantic.v3.v3_0 import OpenAPI
1414
from pydantic import ValidationError
1515

16-
from .common import HTTPLibrary
16+
from .common import HTTPLibrary, PydanticVersion
1717
from .common import library_config_dict
1818
from .language_converters.python.generator import generator
1919
from .language_converters.python.jinja_config import SERVICE_TEMPLATE
@@ -56,7 +56,8 @@ def get_open_api(source: Union[str, Path]) -> OpenAPI:
5656
return OpenAPI(**orjson.loads(httpx.get(source).text))
5757

5858
with open(source, "r") as f:
59-
return OpenAPI(**orjson.loads(f.read()))
59+
file_content = f.read()
60+
return OpenAPI(**orjson.loads(file_content))
6061
except FileNotFoundError:
6162
click.echo(
6263
f"File {source} not found. Please make sure to pass the path to the OpenAPI 3.0 specification."
@@ -139,6 +140,7 @@ def generate_data(
139140
env_token_name: Optional[str] = None,
140141
use_orjson: bool = False,
141142
custom_template_path: Optional[str] = None,
143+
pydantic_version: PydanticVersion = PydanticVersion.V2,
142144
) -> None:
143145
"""
144146
Generate Python code from an OpenAPI 3.0 specification.
@@ -152,6 +154,7 @@ def generate_data(
152154
env_token_name,
153155
use_orjson,
154156
custom_template_path,
157+
pydantic_version,
155158
)
156159

157160
write_data(result, output)

‎src/openapi_python_generator/language_converters/python/api_config_generator.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Optional
22

3-
from openapi_schema_pydantic import OpenAPI
3+
from openapi_pydantic.v3.v3_0 import OpenAPI
44

5+
from openapi_python_generator.common import PydanticVersion
56
from openapi_python_generator.language_converters.python.jinja_config import (
6-
API_CONFIG_TEMPLATE,
7+
API_CONFIG_TEMPLATE, API_CONFIG_TEMPLATE_PYDANTIC_V2,
78
)
89
from openapi_python_generator.language_converters.python.jinja_config import (
910
create_jinja_env,
@@ -12,15 +13,18 @@
1213

1314

1415
def generate_api_config(
15-
data: OpenAPI, env_token_name: Optional[str] = None
16+
data: OpenAPI, env_token_name: Optional[str] = None,
17+
pydantic_version: PydanticVersion = PydanticVersion.V2,
1618
) -> APIConfig:
1719
"""
1820
Generate the API model.
1921
"""
22+
23+
template_name = API_CONFIG_TEMPLATE_PYDANTIC_V2 if pydantic_version == PydanticVersion.V2 else API_CONFIG_TEMPLATE
2024
jinja_env = create_jinja_env()
2125
return APIConfig(
2226
file_name="api_config",
23-
content=jinja_env.get_template(API_CONFIG_TEMPLATE).render(
27+
content=jinja_env.get_template(template_name).render(
2428
env_token_name=env_token_name, **data.dict()
2529
),
2630
base_url=data.servers[0].url if len(data.servers) > 0 else "NO SERVER",

‎src/openapi_python_generator/language_converters/python/generator.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from typing import Optional
22

3-
from openapi_schema_pydantic import OpenAPI
3+
from openapi_pydantic.v3.v3_0 import OpenAPI
44

5+
from openapi_python_generator.common import PydanticVersion
56
from openapi_python_generator.language_converters.python import common
67
from openapi_python_generator.language_converters.python.api_config_generator import (
78
generate_api_config,
@@ -22,6 +23,7 @@ def generator(
2223
env_token_name: Optional[str] = None,
2324
use_orjson: bool = False,
2425
custom_template_path: Optional[str] = None,
26+
pydantic_version: PydanticVersion = PydanticVersion.V2,
2527
) -> ConversionResult:
2628
"""
2729
Generate Python code from an OpenAPI 3.0 specification.
@@ -31,7 +33,7 @@ def generator(
3133
common.set_custom_template_path(custom_template_path)
3234

3335
if data.components is not None:
34-
models = generate_models(data.components)
36+
models = generate_models(data.components, pydantic_version)
3537
else:
3638
models = []
3739

@@ -40,7 +42,7 @@ def generator(
4042
else:
4143
services = []
4244

43-
api_config = generate_api_config(data, env_token_name)
45+
api_config = generate_api_config(data, env_token_name, pydantic_version)
4446

4547
return ConversionResult(
4648
models=models,

‎src/openapi_python_generator/language_converters/python/jinja_config.py

+2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99

1010
ENUM_TEMPLATE = "enum.jinja2"
1111
MODELS_TEMPLATE = "models.jinja2"
12+
MODELS_TEMPLATE_PYDANTIC_V2 = "models_pydantic_2.jinja2"
1213
SERVICE_TEMPLATE = "service.jinja2"
1314
HTTPX_TEMPLATE = "httpx.jinja2"
1415
API_CONFIG_TEMPLATE = "apiconfig.jinja2"
16+
API_CONFIG_TEMPLATE_PYDANTIC_V2 = "apiconfig_pydantic_2.jinja2"
1517
TEMPLATE_PATH = Path(__file__).parent / "templates"
1618

1719

0 commit comments

Comments
 (0)