Skip to content

Commit 11515da

Browse files
authored
Python client - fixes boolean enum use case (#9926)
* Adds boolean enum component and object property and tests of it * Regenerates samples * Passes needed locale argument to toUpperCase * Regenerates samples
1 parent 02835b3 commit 11515da

13 files changed

Lines changed: 416 additions & 5 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonClientCodegen.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,8 @@ public String toEnumVarName(String value, String datatype) {
574574
public String toEnumValue(String value, String datatype) {
575575
if ("int".equals(datatype) || "float".equals(datatype)) {
576576
return value;
577+
} else if ("bool".equals(datatype)) {
578+
return value.substring(0, 1).toUpperCase(Locale.ROOT) + value.substring(1);
577579
} else {
578580
return ensureQuotes(value);
579581
}

modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1779,6 +1779,12 @@ components:
17791779
enum:
17801780
- 1.1
17811781
- -1.2
1782+
enum_bool:
1783+
type: boolean
1784+
enum:
1785+
- false
1786+
boolEnum:
1787+
$ref: '#/components/schemas/BooleanEnum'
17821788
stringEnum:
17831789
$ref: '#/components/schemas/StringEnum'
17841790
IntegerEnum:
@@ -2444,4 +2450,8 @@ components:
24442450
hearing:
24452451
type: boolean
24462452
seeingGhosts:
2447-
type: boolean
2453+
type: boolean
2454+
BooleanEnum:
2455+
type: boolean
2456+
enum:
2457+
- true

samples/openapi3/client/petstore/python/.openapi-generator/FILES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ docs/ArrayTest.md
1818
docs/Banana.md
1919
docs/BananaReq.md
2020
docs/BasquePig.md
21+
docs/BooleanEnum.md
2122
docs/Capitalization.md
2223
docs/Cat.md
2324
docs/CatAllOf.md
@@ -131,6 +132,7 @@ petstore_api/model/array_test.py
131132
petstore_api/model/banana.py
132133
petstore_api/model/banana_req.py
133134
petstore_api/model/basque_pig.py
135+
petstore_api/model/boolean_enum.py
134136
petstore_api/model/capitalization.py
135137
petstore_api/model/cat.py
136138
petstore_api/model/cat_all_of.py

samples/openapi3/client/petstore/python/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ Class | Method | HTTP request | Description
149149
- [Banana](docs/Banana.md)
150150
- [BananaReq](docs/BananaReq.md)
151151
- [BasquePig](docs/BasquePig.md)
152+
- [BooleanEnum](docs/BooleanEnum.md)
152153
- [Capitalization](docs/Capitalization.md)
153154
- [Cat](docs/Cat.md)
154155
- [CatAllOf](docs/CatAllOf.md)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# BooleanEnum
2+
3+
4+
## Properties
5+
Name | Type | Description | Notes
6+
------------ | ------------- | ------------- | -------------
7+
**value** | **bool** | | defaults to True, must be one of [True, ]
8+
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
9+
10+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
11+
12+

samples/openapi3/client/petstore/python/docs/EnumTest.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Name | Type | Description | Notes
88
**enum_string** | **str** | | [optional]
99
**enum_integer** | **int** | | [optional]
1010
**enum_number** | **float** | | [optional]
11+
**enum_bool** | **bool** | | [optional] if omitted the server will use the default value of False
12+
**bool_enum** | [**BooleanEnum**](BooleanEnum.md) | | [optional]
1113
**string_enum** | [**StringEnum**](StringEnum.md) | | [optional]
1214
**integer_enum** | [**IntegerEnum**](IntegerEnum.md) | | [optional]
1315
**string_enum_with_default_value** | [**StringEnumWithDefaultValue**](StringEnumWithDefaultValue.md) | | [optional]

samples/openapi3/client/petstore/python/docs/FakeApi.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,8 @@ with petstore_api.ApiClient() as api_client:
454454
enum_string_required="UPPER",
455455
enum_integer=1,
456456
enum_number=1.1,
457+
enum_bool=False,
458+
bool_enum=BooleanEnum(True),
457459
string_enum=StringEnum("placed"),
458460
integer_enum=IntegerEnum(0),
459461
string_enum_with_default_value=StringEnumWithDefaultValue("placed"),
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
"""
2+
OpenAPI Petstore
3+
4+
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501
5+
6+
The version of the OpenAPI document: 1.0.0
7+
Generated by: https://openapi-generator.tech
8+
"""
9+
10+
11+
import re # noqa: F401
12+
import sys # noqa: F401
13+
14+
from petstore_api.model_utils import ( # noqa: F401
15+
ApiTypeError,
16+
ModelComposed,
17+
ModelNormal,
18+
ModelSimple,
19+
cached_property,
20+
change_keys_js_to_python,
21+
convert_js_args_to_python_args,
22+
date,
23+
datetime,
24+
file_type,
25+
none_type,
26+
validate_get_composed_info,
27+
)
28+
from ..model_utils import OpenApiModel
29+
from petstore_api.exceptions import ApiAttributeError
30+
31+
32+
33+
class BooleanEnum(ModelSimple):
34+
"""NOTE: This class is auto generated by OpenAPI Generator.
35+
Ref: https://openapi-generator.tech
36+
37+
Do not edit the class manually.
38+
39+
Attributes:
40+
allowed_values (dict): The key is the tuple path to the attribute
41+
and the for var_name this is (var_name,). The value is a dict
42+
with a capitalized key describing the allowed value and an allowed
43+
value. These dicts store the allowed enum values.
44+
validations (dict): The key is the tuple path to the attribute
45+
and the for var_name this is (var_name,). The value is a dict
46+
that stores validations for max_length, min_length, max_items,
47+
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
48+
inclusive_minimum, and regex.
49+
additional_properties_type (tuple): A tuple of classes accepted
50+
as additional properties values.
51+
"""
52+
53+
allowed_values = {
54+
('value',): {
55+
'TRUE': True,
56+
},
57+
}
58+
59+
validations = {
60+
}
61+
62+
@cached_property
63+
def additional_properties_type():
64+
"""
65+
This must be a method because a model may have properties that are
66+
of type self, this must run after the class is loaded
67+
"""
68+
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
69+
70+
_nullable = False
71+
72+
@cached_property
73+
def openapi_types():
74+
"""
75+
This must be a method because a model may have properties that are
76+
of type self, this must run after the class is loaded
77+
78+
Returns
79+
openapi_types (dict): The key is attribute name
80+
and the value is attribute type.
81+
"""
82+
return {
83+
'value': (bool,),
84+
}
85+
86+
@cached_property
87+
def discriminator():
88+
return None
89+
90+
91+
attribute_map = {}
92+
93+
read_only_vars = set()
94+
95+
_composed_schemas = None
96+
97+
required_properties = set([
98+
'_data_store',
99+
'_check_type',
100+
'_spec_property_naming',
101+
'_path_to_item',
102+
'_configuration',
103+
'_visited_composed_classes',
104+
])
105+
106+
@convert_js_args_to_python_args
107+
def __init__(self, *args, **kwargs):
108+
"""BooleanEnum - a model defined in OpenAPI
109+
110+
Note that value can be passed either in args or in kwargs, but not in both.
111+
112+
Args:
113+
args[0] (bool): if omitted defaults to True, must be one of [True, ] # noqa: E501
114+
115+
Keyword Args:
116+
value (bool): if omitted defaults to True, must be one of [True, ] # noqa: E501
117+
_check_type (bool): if True, values for parameters in openapi_types
118+
will be type checked and a TypeError will be
119+
raised if the wrong type is input.
120+
Defaults to True
121+
_path_to_item (tuple/list): This is a list of keys or values to
122+
drill down to the model in received_data
123+
when deserializing a response
124+
_spec_property_naming (bool): True if the variable names in the input data
125+
are serialized names, as specified in the OpenAPI document.
126+
False if the variable names in the input data
127+
are pythonic names, e.g. snake case (default)
128+
_configuration (Configuration): the instance to use when
129+
deserializing a file_type parameter.
130+
If passed, type conversion is attempted
131+
If omitted no type conversion is done.
132+
_visited_composed_classes (tuple): This stores a tuple of
133+
classes that we have traveled through so that
134+
if we see that class again we will not use its
135+
discriminator again.
136+
When traveling through a discriminator, the
137+
composed schema that is
138+
is traveled through is added to this set.
139+
For example if Animal has a discriminator
140+
petType and we pass in "Dog", and the class Dog
141+
allOf includes Animal, we move through Animal
142+
once using the discriminator, and pick Dog.
143+
Then in Dog, we will make an instance of the
144+
Animal class but this time we won't travel
145+
through its discriminator because we passed in
146+
_visited_composed_classes = (Animal,)
147+
"""
148+
# required up here when default value is not given
149+
_path_to_item = kwargs.pop('_path_to_item', ())
150+
151+
if 'value' in kwargs:
152+
value = kwargs.pop('value')
153+
elif args:
154+
args = list(args)
155+
value = args.pop(0)
156+
else:
157+
value = True
158+
159+
_check_type = kwargs.pop('_check_type', True)
160+
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
161+
_configuration = kwargs.pop('_configuration', None)
162+
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
163+
164+
if args:
165+
raise ApiTypeError(
166+
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
167+
args,
168+
self.__class__.__name__,
169+
),
170+
path_to_item=_path_to_item,
171+
valid_classes=(self.__class__,),
172+
)
173+
174+
self._data_store = {}
175+
self._check_type = _check_type
176+
self._spec_property_naming = _spec_property_naming
177+
self._path_to_item = _path_to_item
178+
self._configuration = _configuration
179+
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
180+
self.value = value
181+
if kwargs:
182+
raise ApiTypeError(
183+
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
184+
kwargs,
185+
self.__class__.__name__,
186+
),
187+
path_to_item=_path_to_item,
188+
valid_classes=(self.__class__,),
189+
)
190+
191+
@classmethod
192+
@convert_js_args_to_python_args
193+
def _from_openapi_data(cls, *args, **kwargs):
194+
"""BooleanEnum - a model defined in OpenAPI
195+
196+
Note that value can be passed either in args or in kwargs, but not in both.
197+
198+
Args:
199+
args[0] (bool): if omitted defaults to True, must be one of [True, ] # noqa: E501
200+
201+
Keyword Args:
202+
value (bool): if omitted defaults to True, must be one of [True, ] # noqa: E501
203+
_check_type (bool): if True, values for parameters in openapi_types
204+
will be type checked and a TypeError will be
205+
raised if the wrong type is input.
206+
Defaults to True
207+
_path_to_item (tuple/list): This is a list of keys or values to
208+
drill down to the model in received_data
209+
when deserializing a response
210+
_spec_property_naming (bool): True if the variable names in the input data
211+
are serialized names, as specified in the OpenAPI document.
212+
False if the variable names in the input data
213+
are pythonic names, e.g. snake case (default)
214+
_configuration (Configuration): the instance to use when
215+
deserializing a file_type parameter.
216+
If passed, type conversion is attempted
217+
If omitted no type conversion is done.
218+
_visited_composed_classes (tuple): This stores a tuple of
219+
classes that we have traveled through so that
220+
if we see that class again we will not use its
221+
discriminator again.
222+
When traveling through a discriminator, the
223+
composed schema that is
224+
is traveled through is added to this set.
225+
For example if Animal has a discriminator
226+
petType and we pass in "Dog", and the class Dog
227+
allOf includes Animal, we move through Animal
228+
once using the discriminator, and pick Dog.
229+
Then in Dog, we will make an instance of the
230+
Animal class but this time we won't travel
231+
through its discriminator because we passed in
232+
_visited_composed_classes = (Animal,)
233+
"""
234+
# required up here when default value is not given
235+
_path_to_item = kwargs.pop('_path_to_item', ())
236+
237+
self = super(OpenApiModel, cls).__new__(cls)
238+
239+
if 'value' in kwargs:
240+
value = kwargs.pop('value')
241+
elif args:
242+
args = list(args)
243+
value = args.pop(0)
244+
else:
245+
value = True
246+
247+
_check_type = kwargs.pop('_check_type', True)
248+
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
249+
_configuration = kwargs.pop('_configuration', None)
250+
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
251+
252+
if args:
253+
raise ApiTypeError(
254+
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
255+
args,
256+
self.__class__.__name__,
257+
),
258+
path_to_item=_path_to_item,
259+
valid_classes=(self.__class__,),
260+
)
261+
262+
self._data_store = {}
263+
self._check_type = _check_type
264+
self._spec_property_naming = _spec_property_naming
265+
self._path_to_item = _path_to_item
266+
self._configuration = _configuration
267+
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
268+
self.value = value
269+
if kwargs:
270+
raise ApiTypeError(
271+
"Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % (
272+
kwargs,
273+
self.__class__.__name__,
274+
),
275+
path_to_item=_path_to_item,
276+
valid_classes=(self.__class__,),
277+
)
278+
279+
return self

0 commit comments

Comments
 (0)