Skip to content

Commit b2adc2c

Browse files
authored
fix!: Omit any None passed as a query param in generated clients. Closes #285 (#331)
1 parent fdeea99 commit b2adc2c

12 files changed

+49
-66
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## 0.8.0 - Unreleased
99

10+
### Breaking Changes
11+
12+
- Generated clients will no longer pass through `None` to query parameters. Previously, any query params set to `None` would surface as empty strings (per the default behavior of `httpx`). This is contrary to the defaults indicated by the OpenAPI 3.0.3 spec. Ommitting these parameters makes us more compliant. If you require a style of `null` to be passed to your query parameters, please request support for the OpenAPI "style" attribute. Thank you to @forest-benchling and @bowenwr for a ton of input on this.
13+
1014
### Additions
1115

1216
- New `--meta` command line option for specifying what type of metadata should be generated:

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

+13-21
Original file line numberDiff line numberDiff line change
@@ -89,27 +89,19 @@ def httpx_request(
8989
if not isinstance(enum_prop, Unset):
9090
json_enum_prop = enum_prop
9191

92-
params: Dict[str, Any] = {}
93-
if string_prop is not UNSET:
94-
params["string_prop"] = string_prop
95-
if datetime_prop is not UNSET:
96-
params["datetime_prop"] = json_datetime_prop
97-
if date_prop is not UNSET:
98-
params["date_prop"] = json_date_prop
99-
if float_prop is not UNSET:
100-
params["float_prop"] = float_prop
101-
if int_prop is not UNSET:
102-
params["int_prop"] = int_prop
103-
if boolean_prop is not UNSET:
104-
params["boolean_prop"] = boolean_prop
105-
if list_prop is not UNSET:
106-
params["list_prop"] = json_list_prop
107-
if union_prop is not UNSET:
108-
params["union_prop"] = json_union_prop
109-
if union_prop_with_ref is not UNSET:
110-
params["union_prop_with_ref"] = json_union_prop_with_ref
111-
if enum_prop is not UNSET:
112-
params["enum_prop"] = json_enum_prop
92+
params: Dict[str, Any] = {
93+
"string_prop": string_prop,
94+
"datetime_prop": json_datetime_prop,
95+
"date_prop": json_date_prop,
96+
"float_prop": float_prop,
97+
"int_prop": int_prop,
98+
"boolean_prop": boolean_prop,
99+
"list_prop": json_list_prop,
100+
"union_prop": json_union_prop,
101+
"union_prop_with_ref": json_union_prop_with_ref,
102+
"enum_prop": json_enum_prop,
103+
}
104+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
113105

114106
response = client.request(
115107
"post",

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

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def httpx_request(
6262
"an_enum_value": json_an_enum_value,
6363
"some_date": json_some_date,
6464
}
65+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
6566

6667
response = client.request(
6768
"get",

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

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def httpx_request(
4444
params: Dict[str, Any] = {
4545
"int_enum": json_int_enum,
4646
}
47+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
4748

4849
response = client.request(
4950
"post",

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ def httpx_request(
4343
if not isinstance(query_param, Unset):
4444
json_query_param = query_param
4545

46-
params: Dict[str, Any] = {}
47-
if query_param is not UNSET:
48-
params["query_param"] = json_query_param
46+
params: Dict[str, Any] = {
47+
"query_param": json_query_param,
48+
}
49+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
4950

5051
response = client.request(
5152
"get",

end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py

+13-21
Original file line numberDiff line numberDiff line change
@@ -65,27 +65,19 @@ def _get_kwargs(
6565
if not isinstance(enum_prop, Unset):
6666
json_enum_prop = enum_prop
6767

68-
params: Dict[str, Any] = {}
69-
if string_prop is not UNSET:
70-
params["string_prop"] = string_prop
71-
if datetime_prop is not UNSET:
72-
params["datetime_prop"] = json_datetime_prop
73-
if date_prop is not UNSET:
74-
params["date_prop"] = json_date_prop
75-
if float_prop is not UNSET:
76-
params["float_prop"] = float_prop
77-
if int_prop is not UNSET:
78-
params["int_prop"] = int_prop
79-
if boolean_prop is not UNSET:
80-
params["boolean_prop"] = boolean_prop
81-
if list_prop is not UNSET:
82-
params["list_prop"] = json_list_prop
83-
if union_prop is not UNSET:
84-
params["union_prop"] = json_union_prop
85-
if union_prop_with_ref is not UNSET:
86-
params["union_prop_with_ref"] = json_union_prop_with_ref
87-
if enum_prop is not UNSET:
88-
params["enum_prop"] = json_enum_prop
68+
params: Dict[str, Any] = {
69+
"string_prop": string_prop,
70+
"datetime_prop": json_datetime_prop,
71+
"date_prop": json_date_prop,
72+
"float_prop": float_prop,
73+
"int_prop": int_prop,
74+
"boolean_prop": boolean_prop,
75+
"list_prop": json_list_prop,
76+
"union_prop": json_union_prop,
77+
"union_prop_with_ref": json_union_prop_with_ref,
78+
"enum_prop": json_enum_prop,
79+
}
80+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
8981

9082
return {
9183
"url": url,

end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from ...models.a_model import AModel
88
from ...models.an_enum import AnEnum
99
from ...models.http_validation_error import HTTPValidationError
10-
from ...types import Response
10+
from ...types import UNSET, Response
1111

1212

1313
def _get_kwargs(
@@ -35,6 +35,7 @@ def _get_kwargs(
3535
"an_enum_value": json_an_enum_value,
3636
"some_date": json_some_date,
3737
}
38+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
3839

3940
return {
4041
"url": url,

end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from ...client import Client
66
from ...models.an_int_enum import AnIntEnum
77
from ...models.http_validation_error import HTTPValidationError
8-
from ...types import Response
8+
from ...types import UNSET, Response
99

1010

1111
def _get_kwargs(
@@ -22,6 +22,7 @@ def _get_kwargs(
2222
params: Dict[str, Any] = {
2323
"int_enum": json_int_enum,
2424
}
25+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
2526

2627
return {
2728
"url": url,

end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ def _get_kwargs(
2020
if not isinstance(query_param, Unset):
2121
json_query_param = query_param
2222

23-
params: Dict[str, Any] = {}
24-
if query_param is not UNSET:
25-
params["query_param"] = json_query_param
23+
params: Dict[str, Any] = {
24+
"query_param": json_query_param,
25+
}
26+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
2627

2728
return {
2829
"url": url,

openapi_python_client/templates/endpoint_macros.py.jinja

+3-14
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,14 @@ if {{ parameter.python_name }} is not UNSET:
2222
{% endfor %}
2323
params: Dict[str, Any] = {
2424
{% for property in endpoint.query_parameters %}
25-
{% if property.required %}
26-
{% if property.template %}
25+
{% if property.template %}
2726
"{{ property.name }}": {{ "json_" + property.python_name }},
28-
{% else %}
27+
{% else %}
2928
"{{ property.name }}": {{ property.python_name }},
30-
{% endif %}
3129
{% endif %}
3230
{% endfor %}
3331
}
34-
{% for property in endpoint.query_parameters %}
35-
{% if not property.required %}
36-
if {{ property.python_name }} is not UNSET:
37-
{% if property.template %}
38-
params["{{ property.name }}"] = {{ "json_" + property.python_name }}
39-
{% else %}
40-
params["{{ property.name }}"] = {{ property.python_name }}
41-
{% endif %}
42-
{% endif %}
43-
{% endfor %}
32+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
4433
{% endif %}
4534
{% endmacro %}
4635

openapi_python_client/templates/endpoint_module.py.jinja

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import httpx
44
from attr import asdict
55

66
from ...client import AuthenticatedClient, Client
7-
from ...types import Response
7+
from ...types import Response, UNSET
88

99
{% for relative in endpoint.relative_imports %}
1010
{{ relative }}

tests/test_templates/endpoint_module.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from attr import asdict
55

66
from ...client import AuthenticatedClient, Client
7-
from ...types import Response
7+
from ...types import Response, UNSET
88

99
import this
1010
from __future__ import braces

0 commit comments

Comments
 (0)