Skip to content

Commit 2c2f40c

Browse files
Merge origin/benchling-issue-285
2 parents e100cae + 75d250d commit 2c2f40c

File tree

103 files changed

+1163
-619
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+1163
-619
lines changed

.circleci/config.yml

Lines changed: 0 additions & 81 deletions
This file was deleted.

.github/workflows/checks.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Run Checks
2+
3+
on:
4+
push:
5+
branches: ["**"]
6+
pull_request:
7+
# The branches below must be a subset of the branches above
8+
branches: [main]
9+
schedule:
10+
- cron: '0 23 * * 2'
11+
12+
jobs:
13+
test:
14+
runs-on: ubuntu-latest
15+
strategy:
16+
matrix:
17+
python: [ 3.6, 3.7, 3.8, 3.9 ]
18+
steps:
19+
- uses: actions/checkout@v2
20+
- name: Set up Python
21+
uses: actions/setup-python@v1
22+
with:
23+
python-version: ${{ matrix.python }}
24+
- name: Cache dependencies
25+
uses: actions/cache@v2
26+
with:
27+
path: .venv
28+
key: ${{ runner.os }}-${{ matrix.python }}-dependencies-${{ hashFiles('**/poetry.lock') }}
29+
restore-keys: |
30+
${{ runner.os }}-${{ matrix.python }}-dependencies-
31+
- name: Install dependencies
32+
uses: triaxtec/github-actions/python/install-and-configure-poetry@main
33+
- name: Run Checks
34+
uses: triaxtec/github-actions/python/run-checks@main
35+
with:
36+
module: openapi_python_client
37+
38+
- name: End to End Tests
39+
run: poetry run pytest --cov=openapi_python_client end_to_end_tests
40+
41+
- name: Generate E2E Coverage
42+
run: poetry run coverage xml -o e2e-coverage.xml
43+
44+
- uses: codecov/codecov-action@v1
45+
with:
46+
files: ./coverage.xml,./e2e-coverage.xml

CHANGELOG.md

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,63 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## 0.8.0 - Unreleased
9+
10+
### Additions
11+
12+
- New `--meta` command line option for specifying what type of metadata should be generated:
13+
- `poetry` is the default value, same behavior you're used to in previous versions
14+
- `setup` will generate a pyproject.toml with no Poetry information, and instead create a `setup.py` with the
15+
project info.
16+
- `none` will not create a project folder at all, only the inner package folder (which won't be inner anymore)
17+
- Attempt to detect and alert users if they are using an unsupported version of OpenAPI (#281).
18+
19+
### Changes
20+
21+
- Lowered the minimum version of `python-dateutil` to 2.8.0 for improved compatibility (#298 & #299). Thanks @bowenwr!
22+
- The `from_dict` method on generated models is now a `@classmethod` instead of `@staticmethod` (#215 & #292). Thanks @forest-benchling!
23+
824
## 0.7.3 - 2020-12-21
25+
926
### Fixes
27+
1028
- Spacing and extra returns for Union types of `additionalProperties` (#266 & #268). Thanks @joshzana & @packyg!
1129
- Title of inline schemas will no longer be missing characters (#271 & #274). Thanks @kalzoo!
12-
- Handling of nulls (Nones) when parsing or constructing dates (#267). Thanks @fyhertz!
30+
- Handling of nulls (Nones) when parsing or constructing dates (#267). Thanks @fyhertz!
1331

1432
## 0.7.2 - 2020-12-08
33+
1534
### Fixes
35+
1636
- A bug in handling optional properties that are themselves models (introduced in 0.7.1) (#262). Thanks @packyg!
1737

1838
## 0.7.1 - 2020-12-08
39+
1940
### Additions
41+
2042
- Support for additionalProperties attribute in OpenAPI schemas and "free-form" objects by adding an `additional_properties` attribute to generated models. **COMPATIBILITY NOTE**: this will prevent any model property with a name that would be coerced to "additional_properties" in the generated client from generating properly (#218 & #252). Thanks @packyg!
2143

2244
### Fixes
45+
2346
- Enums will once again work with query parameters (#259). Thanks @packyg!
2447
- Generated Poetry metadata in pyproject.toml will properly indicate Python 3.6 compatibility (#258). Thanks @bowenwr!
2548

2649
## 0.7.0 - 2020-11-25
2750

2851
### Breaking Changes
2952

30-
- Any request/response field that is not `required` and wasn't specified is now set to `UNSET` instead of `None`.
53+
- Any request/response field that is not `required` and wasn't specified is now set to `UNSET` instead of `None`.
3154
- Values that are `UNSET` will not be sent along in API calls
32-
- Schemas defined with `type=object` will now be converted into classes, just like if they were created as ref components.
33-
The previous behavior was a combination of skipping and using generic Dicts for these schemas.
34-
- Response schema handling was unified with input schema handling, meaning that responses will behave differently than before.
35-
Specifically, instead of the content-type deciding what the generated Python type is, the schema itself will.
36-
- As a result of this, endpoints that used to return `bytes` when content-type was application/octet-stream will now return a `File` object if the type of the data is "binary", just like if you were submitting that type instead of receiving it.
55+
- Schemas defined with `type=object` will now be converted into classes, just like if they were created as ref components.
56+
The previous behavior was a combination of skipping and using generic Dicts for these schemas.
57+
- Response schema handling was unified with input schema handling, meaning that responses will behave differently than before.
58+
Specifically, instead of the content-type deciding what the generated Python type is, the schema itself will.
59+
- As a result of this, endpoints that used to return `bytes` when content-type was application/octet-stream will now return a `File` object if the type of the data is "binary", just like if you were submitting that type instead of receiving it.
3760
- Instead of skipping input properties with no type, enum, anyOf, or oneOf declared, the property will be declared as `None`.
38-
- Class (models and Enums) names will now contain the name of their parent element (if any). For example, a property
39-
declared in an endpoint will be named like {endpoint_name}_{previous_class_name}. Classes will no longer be
40-
deduplicated by appending a number to the end of the generated name, so if two names conflict with this new naming
41-
scheme, there will be an error instead.
61+
- Class (models and Enums) names will now contain the name of their parent element (if any). For example, a property
62+
declared in an endpoint will be named like {endpoint*name}*{previous_class_name}. Classes will no longer be
63+
deduplicated by appending a number to the end of the generated name, so if two names conflict with this new naming
64+
scheme, there will be an error instead.
4265

4366
### Additions
4467

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![triaxtec](https://circleci.com/gh/triaxtec/openapi-python-client.svg?style=svg)](https://circleci.com/gh/triaxtec/openapi-python-client)
1+
![Run Checks](https://github.com/triaxtec/openapi-python-client/workflows/Run%20Checks/badge.svg)
22
[![codecov](https://codecov.io/gh/triaxtec/openapi-python-client/branch/main/graph/badge.svg)](https://codecov.io/gh/triaxtec/openapi-python-client)
33
[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)
44
[![Generic badge](https://img.shields.io/badge/type_checked-mypy-informational.svg)](https://mypy.readthedocs.io/en/stable/introduction.html)

end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -40,42 +40,42 @@ def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPVal
4040
def httpx_request(
4141
*,
4242
client: Client,
43-
string_prop: Union[Unset, str] = "the default string",
44-
datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"),
45-
date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(),
46-
float_prop: Union[Unset, float] = 3.14,
47-
int_prop: Union[Unset, int] = 7,
48-
boolean_prop: Union[Unset, bool] = False,
49-
list_prop: Union[Unset, List[AnEnum]] = UNSET,
50-
union_prop: Union[Unset, float, str] = "not a float",
51-
union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6,
52-
enum_prop: Union[Unset, AnEnum] = UNSET,
43+
string_prop: Union[Unset, None, str] = "the default string",
44+
datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"),
45+
date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(),
46+
float_prop: Union[Unset, None, float] = 3.14,
47+
int_prop: Union[Unset, None, int] = 7,
48+
boolean_prop: Union[Unset, None, bool] = False,
49+
list_prop: Union[Unset, None, List[AnEnum]] = UNSET,
50+
union_prop: Union[Unset, None, float, str] = "not a float",
51+
union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6,
52+
enum_prop: Union[Unset, None, AnEnum] = UNSET,
5353
) -> Response[Union[None, HTTPValidationError]]:
5454

5555
json_datetime_prop: Union[Unset, str] = UNSET
56-
if not isinstance(datetime_prop, Unset):
56+
if not isinstance(datetime_prop, Unset) and datetime_prop is not None:
5757
json_datetime_prop = datetime_prop.isoformat()
5858

5959
json_date_prop: Union[Unset, str] = UNSET
60-
if not isinstance(date_prop, Unset):
60+
if not isinstance(date_prop, Unset) and date_prop is not None:
6161
json_date_prop = date_prop.isoformat()
6262

6363
json_list_prop: Union[Unset, List[Any]] = UNSET
64-
if not isinstance(list_prop, Unset):
64+
if not isinstance(list_prop, Unset) and list_prop is not None:
6565
json_list_prop = []
6666
for list_prop_item_data in list_prop:
6767
list_prop_item = list_prop_item_data.value
6868

6969
json_list_prop.append(list_prop_item)
7070

7171
json_union_prop: Union[Unset, float, str]
72-
if isinstance(union_prop, Unset):
72+
if isinstance(union_prop, Unset) or union_prop is None:
7373
json_union_prop = UNSET
7474
else:
7575
json_union_prop = union_prop
7676

7777
json_union_prop_with_ref: Union[Unset, float, AnEnum]
78-
if isinstance(union_prop_with_ref, Unset):
78+
if isinstance(union_prop_with_ref, Unset) or union_prop_with_ref is None:
7979
json_union_prop_with_ref = UNSET
8080
elif isinstance(union_prop_with_ref, AnEnum):
8181
json_union_prop_with_ref = UNSET
@@ -86,29 +86,29 @@ def httpx_request(
8686
json_union_prop_with_ref = union_prop_with_ref
8787

8888
json_enum_prop: Union[Unset, AnEnum] = UNSET
89-
if not isinstance(enum_prop, Unset):
89+
if not isinstance(enum_prop, Unset) and enum_prop is not None:
9090
json_enum_prop = enum_prop
9191

9292
params: Dict[str, Any] = {}
93-
if string_prop is not UNSET:
93+
if string_prop is not UNSET and string_prop is not None:
9494
params["string_prop"] = string_prop
95-
if datetime_prop is not UNSET:
95+
if datetime_prop is not UNSET and datetime_prop is not None:
9696
params["datetime_prop"] = json_datetime_prop
97-
if date_prop is not UNSET:
97+
if date_prop is not UNSET and date_prop is not None:
9898
params["date_prop"] = json_date_prop
99-
if float_prop is not UNSET:
99+
if float_prop is not UNSET and float_prop is not None:
100100
params["float_prop"] = float_prop
101-
if int_prop is not UNSET:
101+
if int_prop is not UNSET and int_prop is not None:
102102
params["int_prop"] = int_prop
103-
if boolean_prop is not UNSET:
103+
if boolean_prop is not UNSET and boolean_prop is not None:
104104
params["boolean_prop"] = boolean_prop
105-
if list_prop is not UNSET:
105+
if list_prop is not UNSET and list_prop is not None:
106106
params["list_prop"] = json_list_prop
107-
if union_prop is not UNSET:
107+
if union_prop is not UNSET and union_prop is not None:
108108
params["union_prop"] = json_union_prop
109-
if union_prop_with_ref is not UNSET:
109+
if union_prop_with_ref is not UNSET and union_prop_with_ref is not None:
110110
params["union_prop_with_ref"] = json_union_prop_with_ref
111-
if enum_prop is not UNSET:
111+
if enum_prop is not UNSET and enum_prop is not None:
112112
params["enum_prop"] = json_enum_prop
113113

114114
response = client.request(

end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPVal
3636
def httpx_request(
3737
*,
3838
client: Client,
39-
query_param: Union[Unset, List[str]] = UNSET,
39+
query_param: Union[Unset, None, List[str]] = UNSET,
4040
) -> Response[Union[None, HTTPValidationError]]:
4141

4242
json_query_param: Union[Unset, List[Any]] = UNSET
43-
if not isinstance(query_param, Unset):
43+
if not isinstance(query_param, Unset) and query_param is not None:
4444
json_query_param = query_param
4545

4646
params: Dict[str, Any] = {}
47-
if query_param is not UNSET:
47+
if query_param is not UNSET and query_param is not None:
4848
params["query_param"] = json_query_param
4949

5050
response = client.request(

end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import datetime
2-
from typing import Any, Dict, List, Optional, Union, cast
2+
from typing import Any, Dict, List, Optional, Type, TypeVar, Union, cast
33

44
import attr
55
from dateutil.parser import isoparse
@@ -8,6 +8,8 @@
88
from ..models.different_enum import DifferentEnum
99
from ..types import UNSET, Unset
1010

11+
T = TypeVar("T", bound="AModel")
12+
1113

1214
@attr.s(auto_attribs=True)
1315
class AModel:
@@ -21,7 +23,7 @@ class AModel:
2123
required_nullable: Optional[str]
2224
nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET
2325
attr_1_leading_digit: Union[Unset, str] = UNSET
24-
not_required_nullable: Union[Unset, Optional[str]] = UNSET
26+
not_required_nullable: Union[Unset, None, str] = UNSET
2527
not_required_not_nullable: Union[Unset, str] = UNSET
2628

2729
def to_dict(self) -> Dict[str, Any]:
@@ -75,8 +77,8 @@ def to_dict(self) -> Dict[str, Any]:
7577

7678
return field_dict
7779

78-
@staticmethod
79-
def from_dict(src_dict: Dict[str, Any]) -> "AModel":
80+
@classmethod
81+
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
8082
d = src_dict.copy()
8183
an_enum_value = AnEnum(d.pop("an_enum_value"))
8284

@@ -124,7 +126,7 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat
124126

125127
not_required_not_nullable = d.pop("not_required_not_nullable", UNSET)
126128

127-
a_model = AModel(
129+
a_model = cls(
128130
an_enum_value=an_enum_value,
129131
a_camel_date_time=a_camel_date_time,
130132
a_date=a_date,

0 commit comments

Comments
 (0)