Skip to content

Commit 8fe695d

Browse files
committed
Merge branch 'master' into pr/29
2 parents ec5c87a + 50392cd commit 8fe695d

21 files changed

+104
-69
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## 0.3.0 - Unreleased
8+
### Additions
9+
- Link to the GitHub repository from PyPI (#26). Thanks @theY4Kman!
10+
11+
### Fixes
12+
- Fixed some typing issues in generated clients and incorporate mypy into end to end tests (#32). Thanks @acgray!
13+
714
## 0.2.1 - 2020-03-22
815
### Fixes
916
- Fixed import of errors.py in generated api modules

openapi_python_client/openapi_parser/openapi.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,10 @@ def dict(d: Dict[str, Dict[str, Any]], /) -> Dict[str, Schema]:
191191

192192
@dataclass
193193
class OpenAPI:
194-
""" Top level OpenAPI spec """
194+
""" Top level OpenAPI document """
195195

196196
title: str
197-
description: str
197+
description: Optional[str]
198198
version: str
199199
schemas: Dict[str, Schema]
200200
endpoint_collections_by_tag: Dict[str, EndpointCollection]
@@ -243,7 +243,7 @@ def from_dict(d: Dict[str, Dict[str, Any]], /) -> OpenAPI:
243243

244244
return OpenAPI(
245245
title=d["info"]["title"],
246-
description=d["info"]["description"],
246+
description=d["info"].get("description"),
247247
version=d["info"]["version"],
248248
endpoint_collections_by_tag=endpoint_collections_by_tag,
249249
schemas=schemas,

openapi_python_client/openapi_parser/properties.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,10 @@ def transform(self) -> str:
172172

173173
def constructor_from_dict(self, dict_name: str) -> str:
174174
""" How to load this property from a dict (used in generated model from_dict function """
175-
return f'{self.reference.class_name}({dict_name}["{self.name}"]) if "{self.name}" in {dict_name} else None'
175+
constructor = f'{self.reference.class_name}({dict_name}["{self.name}"])'
176+
if not self.required:
177+
constructor += f' if "{self.name}" in {dict_name} else None'
178+
return constructor
176179

177180
@staticmethod
178181
def values_from_list(l: List[str], /) -> Dict[str, str]:
@@ -213,15 +216,15 @@ def transform(self) -> str:
213216
class DictProperty(Property):
214217
""" Property that is a general Dict """
215218

216-
_type_string: ClassVar[str] = "Dict"
219+
_type_string: ClassVar[str] = "Dict[Any, Any]"
217220

218221

219222
_openapi_types_to_python_type_strings = {
220223
"string": "str",
221224
"number": "float",
222225
"integer": "int",
223226
"boolean": "bool",
224-
"object": "Dict",
227+
"object": "Dict[Any, Any]",
225228
}
226229

227230

openapi_python_client/openapi_parser/responses.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def return_string(self) -> str:
3333

3434
def constructor(self) -> str:
3535
""" How the return value of this response should be constructed """
36-
return f"[{self.reference.class_name}.from_dict(item) for item in response.json()]"
36+
return f"[{self.reference.class_name}.from_dict(item) for item in cast(List[Dict[str, Any]], response.json())]"
3737

3838

3939
@dataclass
@@ -48,7 +48,7 @@ def return_string(self) -> str:
4848

4949
def constructor(self) -> str:
5050
""" How the return value of this response should be constructed """
51-
return f"{self.reference.class_name}.from_dict(response.json())"
51+
return f"{self.reference.class_name}.from_dict(cast(Dict[str, Any], response.json()))"
5252

5353

5454
@dataclass

openapi_python_client/templates/async_endpoint_module.pyi

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import asdict
2-
from typing import Dict, List, Optional, Union
2+
from typing import Any, Dict, List, Optional, Union, cast
33

44
import httpx
55

@@ -65,8 +65,8 @@ async def {{ endpoint.name | snakecase }}(
6565
{% endfor %}
6666
{% endif %}
6767

68-
with httpx.AsyncClient() as client:
69-
response = await client.{{ endpoint.method }}(
68+
async with httpx.AsyncClient() as _client:
69+
response = await _client.{{ endpoint.method }}(
7070
url=url,
7171
headers=client.get_headers(),
7272
{% if endpoint.form_body_reference %}

openapi_python_client/templates/endpoint_module.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import asdict
2-
from typing import Dict, List, Optional, Union
2+
from typing import Any, Dict, List, Optional, Union, cast
33

44
import httpx
55

openapi_python_client/templates/model.pyi

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ from __future__ import annotations
22

33
from dataclasses import dataclass
44
from datetime import datetime
5-
from typing import Dict, List, Optional, cast
5+
from typing import Any, Dict, List, Optional, cast
66

77
{% for relative in schema.relative_imports %}
88
{{ relative }}
@@ -16,7 +16,7 @@ class {{ schema.reference.class_name }}:
1616
{{ property.to_string() }}
1717
{% endfor %}
1818

19-
def to_dict(self) -> Dict:
19+
def to_dict(self) -> Dict[str, Any]:
2020
return {
2121
{% for property in schema.required_properties %}
2222
"{{ property.name }}": self.{{ property.transform() }},
@@ -27,7 +27,7 @@ class {{ schema.reference.class_name }}:
2727
}
2828

2929
@staticmethod
30-
def from_dict(d: Dict) -> {{ schema.reference.class_name }}:
30+
def from_dict(d: Dict[str, Any]) -> {{ schema.reference.class_name }}:
3131
{% for property in schema.required_properties + schema.optional_properties %}
3232

3333
{% if property.constructor_template %}

poetry.lock

+24-19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
name = "openapi-python-client"
33
version = "0.2.1"
44
description = "Generate modern Python clients from OpenAPI"
5+
repository = "https://github.com./triaxtec/openapi-python-client"
56

67
authors = [
78
"Dylan Anthony <[email protected]>",
@@ -36,7 +37,7 @@ mypy = ">=0.761"
3637
taskipy = "^1.1.3"
3738
safety = "^1.8.5"
3839
pytest-cov = "^2.8.1"
39-
fastapi = "^0.52.0"
40+
fastapi = "^0.54.1"
4041

4142
[tool.taskipy.tasks]
4243
check = "isort --recursive --apply && black . && safety check && mypy openapi_python_client"

tests/test_end_to_end/golden-master/my_test_api_client/api/default.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import asdict
2-
from typing import Dict, List, Optional, Union
2+
from typing import Any, Dict, List, Optional, Union, cast
33

44
import httpx
55

@@ -19,6 +19,6 @@ def ping_ping_get(
1919
response = httpx.get(url=url, headers=client.get_headers(),)
2020

2121
if response.status_code == 200:
22-
return ABCResponse.from_dict(response.json())
22+
return ABCResponse.from_dict(cast(Dict[str, Any], response.json()))
2323
else:
2424
raise ApiResponseError(response=response)

tests/test_end_to_end/golden-master/my_test_api_client/api/users.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import asdict
2-
from typing import Dict, List, Optional, Union
2+
from typing import Any, Dict, List, Optional, Union, cast
33

44
import httpx
55

@@ -25,8 +25,8 @@ def get_list_tests__get(
2525
response = httpx.get(url=url, headers=client.get_headers(), params=params,)
2626

2727
if response.status_code == 200:
28-
return [AModel.from_dict(item) for item in response.json()]
28+
return [AModel.from_dict(item) for item in cast(List[Dict[str, Any]], response.json())]
2929
if response.status_code == 422:
30-
return HTTPValidationError.from_dict(response.json())
30+
return HTTPValidationError.from_dict(cast(Dict[str, Any], response.json()))
3131
else:
3232
raise ApiResponseError(response=response)

tests/test_end_to_end/golden-master/my_test_api_client/async_api/default.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import asdict
2-
from typing import Dict, List, Optional, Union
2+
from typing import Any, Dict, List, Optional, Union, cast
33

44
import httpx
55

@@ -16,10 +16,10 @@ async def ping_ping_get(
1616
""" A quick check to see if the system is running """
1717
url = f"{client.base_url}/ping"
1818

19-
with httpx.AsyncClient() as client:
20-
response = await client.get(url=url, headers=client.get_headers(),)
19+
async with httpx.AsyncClient() as _client:
20+
response = await _client.get(url=url, headers=client.get_headers(),)
2121

2222
if response.status_code == 200:
23-
return ABCResponse.from_dict(response.json())
23+
return ABCResponse.from_dict(cast(Dict[str, Any], response.json()))
2424
else:
2525
raise ApiResponseError(response=response)

tests/test_end_to_end/golden-master/my_test_api_client/async_api/users.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import asdict
2-
from typing import Dict, List, Optional, Union
2+
from typing import Any, Dict, List, Optional, Union, cast
33

44
import httpx
55

@@ -22,12 +22,12 @@ async def get_list_tests__get(
2222
"statuses": statuses,
2323
}
2424

25-
with httpx.AsyncClient() as client:
26-
response = await client.get(url=url, headers=client.get_headers(), params=params,)
25+
async with httpx.AsyncClient() as _client:
26+
response = await _client.get(url=url, headers=client.get_headers(), params=params,)
2727

2828
if response.status_code == 200:
29-
return [AModel.from_dict(item) for item in response.json()]
29+
return [AModel.from_dict(item) for item in cast(List[Dict[str, Any]], response.json())]
3030
if response.status_code == 422:
31-
return HTTPValidationError.from_dict(response.json())
31+
return HTTPValidationError.from_dict(cast(Dict[str, Any], response.json()))
3232
else:
3333
raise ApiResponseError(response=response)

tests/test_end_to_end/golden-master/my_test_api_client/models/a_model.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from dataclasses import dataclass
44
from datetime import datetime
5-
from typing import Dict, List, Optional, cast
5+
from typing import Any, Dict, List, Optional, cast
66

77
from .a_list_of_enums import AListOfEnums
88
from .an_enum_value import AnEnumValue
@@ -18,7 +18,7 @@ class AModel:
1818
a_list_of_strings: List[str]
1919
a_list_of_objects: List[OtherModel]
2020

21-
def to_dict(self) -> Dict:
21+
def to_dict(self) -> Dict[str, Any]:
2222
return {
2323
"an_enum_value": self.an_enum_value.value,
2424
"a_list_of_enums": self.a_list_of_enums,
@@ -27,9 +27,9 @@ def to_dict(self) -> Dict:
2727
}
2828

2929
@staticmethod
30-
def from_dict(d: Dict) -> AModel:
30+
def from_dict(d: Dict[str, Any]) -> AModel:
3131

32-
an_enum_value = AnEnumValue(d["an_enum_value"]) if "an_enum_value" in d else None
32+
an_enum_value = AnEnumValue(d["an_enum_value"])
3333

3434
a_list_of_enums = []
3535
for a_list_of_enums_item in d.get("a_list_of_enums", []):

0 commit comments

Comments
 (0)