Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,4 @@ dmypy.json
.pyre/
/.idea/
/testclient/
/tests/test_result/
10 changes: 5 additions & 5 deletions docs/tutorial/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -647,10 +647,10 @@ take a look at the `User.py` and the `Team.py` files:

``` py
from typing import *

from pydantic import BaseModel, Field


class User(BaseModel):
"""
User model
Expand All @@ -675,9 +675,9 @@ take a look at the `User.py` and the `Team.py` files:

``` py
from typing import *

from pydantic import BaseModel, Field

from .User import User


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import keyword
import re


_use_orjson: bool = False
_symbol_ascii_strip_re = re.compile(r"[^A-Za-z0-9_]")

Expand Down Expand Up @@ -30,7 +31,7 @@ def normalize_symbol(symbol: str) -> str:
:return: normalized identifier name
"""
symbol = symbol.replace("-", "_")
normalized_symbol = _symbol_ascii_strip_re.sub('', symbol)
normalized_symbol = _symbol_ascii_strip_re.sub("", symbol)
if normalized_symbol in keyword.kwlist:
normalized_symbol = normalized_symbol + '_'
normalized_symbol = normalized_symbol + "_"
return normalized_symbol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
from openapi_python_generator.models import TypeConversion


def type_converter(schema: Schema, required: bool = False, model_name: Optional[str] = None,) -> TypeConversion:
def type_converter( # noqa: C901
schema: Schema,
required: bool = False,
model_name: Optional[str] = None,
) -> TypeConversion:
"""
Converts an OpenAPI type to a Python type.
:param schema: Schema containing the type to be converted
Expand Down Expand Up @@ -119,7 +123,11 @@ def type_converter(schema: Schema, required: bool = False, model_name: Optional
schema.schema_format is None or not common.get_use_orjson()
):
converted_type = pre_type + "str" + post_type
elif schema.type == "string" and schema.schema_format.startswith("uuid") and common.get_use_orjson():
elif (
schema.type == "string"
and schema.schema_format.startswith("uuid")
and common.get_use_orjson()
):
if len(schema.schema_format) > 4 and schema.schema_format[4].isnumeric():
uuid_type = schema.schema_format.upper()
converted_type = pre_type + uuid_type + post_type
Expand All @@ -139,7 +147,9 @@ def type_converter(schema: Schema, required: bool = False, model_name: Optional
elif schema.type == "array":
retVal = pre_type + "List["
if isinstance(schema.items, Reference):
converted_reference = _generate_property_from_reference(model_name, "", schema.items, schema, required)
converted_reference = _generate_property_from_reference(
model_name, "", schema.items, schema, required
)
import_types = converted_reference.type.import_types
original_type = "array<" + converted_reference.type.original_type + ">"
retVal += converted_reference.type.converted_type
Expand All @@ -166,7 +176,7 @@ def type_converter(schema: Schema, required: bool = False, model_name: Optional


def _generate_property_from_schema(
model_name : str, name: str, schema: Schema, parent_schema: Optional[Schema] = None
model_name: str, name: str, schema: Schema, parent_schema: Optional[Schema] = None
) -> Property:
"""
Generates a property from a schema. It takes the type of the schema and converts it to a python type, and then
Expand All @@ -191,7 +201,11 @@ def _generate_property_from_schema(


def _generate_property_from_reference(
model_name: str, name: str, reference: Reference, parent_schema: Optional[Schema] = None, force_required: bool = False
model_name: str,
name: str,
reference: Reference,
parent_schema: Optional[Schema] = None,
force_required: bool = False,
) -> Property:
"""
Generates a property from a reference. It takes the name of the reference as the type, and then
Expand All @@ -212,13 +226,17 @@ def _generate_property_from_reference(
if import_model == model_name:
type_conv = TypeConversion(
original_type=reference.ref,
converted_type=import_model if required else 'Optional["' + import_model + '"]',
import_types=None
converted_type=import_model
if required
else 'Optional["' + import_model + '"]',
import_types=None,
)
else:
type_conv = TypeConversion(
original_type=reference.ref,
converted_type=import_model if required else "Optional[" + import_model + "]",
converted_type=import_model
if required
else "Optional[" + import_model + "]",
import_types=[f"from .{import_model} import {import_model}"],
)
return Property(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import re
from typing import Dict, Literal
from typing import Dict
from typing import List
from typing import Literal
from typing import Tuple
from typing import Union

Expand Down Expand Up @@ -159,24 +160,29 @@ def generate_operation_id(operation: Operation, http_op: str) -> str:
raise Exception(f"OperationId is not defined for {http_op}") # pragma: no cover


def _generate_params(operation: Operation, param_in : Literal["query", "header"] = "query"):
def _generate_params(
operation: Operation, param_in: Literal["query", "header"] = "query"
):
if operation.parameters is None:
return []

params = []
for param in operation.parameters:
if isinstance(param, Parameter) and param.param_in == param_in:
param_name_cleaned = common.normalize_symbol(param.name)
params.append(f"'{param.name}' : {param_name_cleaned}")
params.append(f"{param.name!r} : {param_name_cleaned}")

return params


def generate_query_params(operation: Operation) -> List[str]:
return _generate_params(operation, "query")


def generate_header_params(operation: Operation) -> List[str]:
return _generate_params(operation, "header")


def generate_return_type(operation: Operation) -> OpReturnType:
if operation.responses is None:
return OpReturnType(type=None, status_code=200, complex_type=False)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ with httpx.Client(base_url=base_path, verify=api_config.verify) as client:
{% if use_orjson %}
content=orjson.dumps({{ body_param }})
{% else %}
json = json.dumps({{ body_param }})
json = {{ body_param }}
{% endif %}
{% endif %}
)
Expand Down
2 changes: 1 addition & 1 deletion tests/regression/test_issue_11.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def runner() -> CliRunner:
"""Fixture for invoking command-line interfaces."""
return CliRunner()


@pytest.mark.parametrize(
"library",
[HTTPLibrary.httpx, HTTPLibrary.requests, HTTPLibrary.aiohttp],
Expand All @@ -30,4 +31,3 @@ def test_issue_11(runner: CliRunner, model_data_with_cleanup, library) -> None:
],
)
assert result.exit_code == 0

9 changes: 5 additions & 4 deletions tests/regression/test_issue_17.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def runner() -> CliRunner:
"""Fixture for invoking command-line interfaces."""
return CliRunner()


@pytest.mark.parametrize(
"library",
[HTTPLibrary.httpx, HTTPLibrary.aiohttp, HTTPLibrary.requests],
Expand All @@ -21,7 +22,7 @@ def test_issue_11(runner: CliRunner, model_data_with_cleanup, library) -> None:
"""
https://github.com/MarcoMuellner/openapi-python-generator/issues/7
"""
assert generate_data(test_data_folder / "issue_17.json",
test_result_path,
library) is None

assert (
generate_data(test_data_folder / "issue_17.json", test_result_path, library)
is None
)
10 changes: 7 additions & 3 deletions tests/regression/test_issue_illegal_py_symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ def runner() -> CliRunner:
"library",
[HTTPLibrary.httpx, HTTPLibrary.requests, HTTPLibrary.aiohttp],
)
def test_issue_keyword_parameter_name(runner: CliRunner, model_data_with_cleanup, library) -> None:
def test_issue_keyword_parameter_name(
runner: CliRunner, model_data_with_cleanup, library
) -> None:
result = runner.invoke(
main,
[
Expand All @@ -34,7 +36,9 @@ def test_issue_keyword_parameter_name(runner: CliRunner, model_data_with_cleanup
"library",
[HTTPLibrary.httpx, HTTPLibrary.requests, HTTPLibrary.aiohttp],
)
def test_issue_illegal_character_in_operation_id(runner: CliRunner, model_data_with_cleanup, library) -> None:
def test_issue_illegal_character_in_operation_id(
runner: CliRunner, model_data_with_cleanup, library
) -> None:
result = runner.invoke(
main,
[
Expand All @@ -44,4 +48,4 @@ def test_issue_illegal_character_in_operation_id(runner: CliRunner, model_data_w
library.value,
],
)
assert result.exit_code == 0
assert result.exit_code == 0
2 changes: 1 addition & 1 deletion tests/test_data/gitea_issue_11.json

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions tests/test_generated_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,9 @@ def test_generate_code(model_data_with_cleanup, library, use_orjson, custom_ip):

passed_api_config = None



if custom_ip:
from .test_result.api_config import APIConfig

passed_api_config = APIConfig()
passed_api_config.base_path = custom_ip

Expand Down Expand Up @@ -283,7 +282,16 @@ def test_generate_code(model_data_with_cleanup, library, use_orjson, custom_ip):
_locals,
)
assert get_user_route.called
assert len([(key,value) for key,value in get_user_route.calls[0][0].headers.raw if b'api-key' in key and b'test' in value]) == 1
assert (
len(
[
(key, value)
for key, value in get_user_route.calls[0][0].headers.raw
if b"api-key" in key and b"test" in value
]
)
== 1
)

data = dict(
id=1, username="user1", email="[email protected]", password="123456", is_active=True
Expand Down
46 changes: 32 additions & 14 deletions tests/test_model_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,12 @@
def test_type_converter_simple(test_openapi_types, expected_python_types):
assert type_converter(test_openapi_types, True) == expected_python_types

if test_openapi_types.type == "array" and isinstance(test_openapi_types.items, Reference):
expected_type = expected_python_types.converted_type.split("[")[-1].split("]")[0]
if test_openapi_types.type == "array" and isinstance(
test_openapi_types.items, Reference
):
expected_type = expected_python_types.converted_type.split("[")[-1].split("]")[
0
]

assert (
type_converter(test_openapi_types, False).converted_type
Expand Down Expand Up @@ -160,48 +164,56 @@ def test_type_converter_simple(test_openapi_types, expected_python_types):
),
(
Schema(type="string", schema_format="uuid"),
TypeConversion(original_type="string", converted_type="UUID", import_types=['from uuid import UUID']),
TypeConversion(
original_type="string",
converted_type="UUID",
import_types=["from uuid import UUID"],
),
),
(
Schema(type="string", schema_format="uuid1"),
TypeConversion(
original_type="string",
converted_type="UUID1",
import_types=['from pydantic import UUID1']
import_types=["from pydantic import UUID1"],
),
),
(
Schema(type="string", schema_format="uuid3"),
TypeConversion(
original_type="string",
converted_type="UUID3",
import_types=['from pydantic import UUID3']
import_types=["from pydantic import UUID3"],
),
),
(
Schema(type="string", schema_format="uuid4"),
TypeConversion(
original_type="string",
converted_type="UUID4",
import_types=['from pydantic import UUID4']
import_types=["from pydantic import UUID4"],
),
),
(
Schema(type="string", schema_format="uuid5"),
TypeConversion(
original_type="string",
converted_type="UUID5",
import_types=['from pydantic import UUID5']
import_types=["from pydantic import UUID5"],
),
)
),
],
)
def test_type_converter_simple_orjson(test_openapi_types, expected_python_types):
orjson_usage = common.get_use_orjson()
common.set_use_orjson(True)
assert type_converter(test_openapi_types, True) == expected_python_types
if test_openapi_types.type == "array" and isinstance(test_openapi_types.items, Reference):
expected_type = expected_python_types.converted_type.split("[")[-1].split("]")[0]
if test_openapi_types.type == "array" and isinstance(
test_openapi_types.items, Reference
):
expected_type = expected_python_types.converted_type.split("[")[-1].split("]")[
0
]

assert (
type_converter(test_openapi_types, False).converted_type
Expand Down Expand Up @@ -318,8 +330,12 @@ def test_type_converter_exceptions():
Schema(allOf=[Reference(ref="#/components/schemas/SomeModel")]),
Schema(type="object", required=["SomeModel"]),
Property(
name='SomeModel',
type=TypeConversion(original_type='tuple<#/components/schemas/SomeModel>', converted_type='"SomeModel"',import_types = []),
name="SomeModel",
type=TypeConversion(
original_type="tuple<#/components/schemas/SomeModel>",
converted_type='"SomeModel"',
import_types=[],
),
required=True,
imported_type=[],
),
Expand All @@ -330,7 +346,9 @@ def test_type_converter_property(
test_model_name, test_name, test_schema, test_parent_schema, expected_property
):
assert (
_generate_property_from_schema(test_model_name,test_name, test_schema, test_parent_schema)
_generate_property_from_schema(
test_model_name, test_name, test_schema, test_parent_schema
)
== expected_property
)

Expand Down Expand Up @@ -376,7 +394,7 @@ def test_type_converter_property_reference(
test_name, test_reference, parent_schema, expected_property
):
assert (
_generate_property_from_reference("",test_name, test_reference, parent_schema)
_generate_property_from_reference("", test_name, test_reference, parent_schema)
== expected_property
)

Expand Down
Loading