diff --git a/modules/openapi-generator/src/main/resources/python-experimental/README.handlebars b/modules/openapi-generator/src/main/resources/python-experimental/README.handlebars index aee6b66db62..3ad16ce73ab 100644 --- a/modules/openapi-generator/src/main/resources/python-experimental/README.handlebars +++ b/modules/openapi-generator/src/main/resources/python-experimental/README.handlebars @@ -21,6 +21,70 @@ Python {{generatorLanguageVersion}} v3.9 is needed so one can combine classmethod and property decorators to define object schema properties as classes +## Migration from other generators like python and python-experimental + +### Changes +1. This generator uses spec case for all (object) property names and parameter names. + - So if the spec has a property name like camelCase, it will use camelCase rather than camel_case + - So you will need to update how you input and read properties to use spec case +2. Endpoint parameters are stored in dictionaries to prevent collisions (explanation below) + - So you will need to update how you pass data in to endpoints +3. Endpoint responses now include the original response, the deserialized response body, and (todo)the deserialized headers + - So you will need to update your code to use response.body to access deserialized data +4. All validated data is instantiated in an instance that subclasses all validated Schema classes and Decimal/str/list/tuple/frozendict/NoneClass/BoolClass/bytes/io.FileIO + - This means that you can use isinstance to check if a payload validated against a schema class + - This means that no data will be of type None/True/False + - ingested None will subclass NoneClass + - ingested True will subclass BoolClass + - ingested False will subclass BoolClass + - So if you need to check is True/False/None, instead use instance.is_true()/.is_false()/.is_none() +5. All validated class instances are immutable except for ones based on io.File + - This is because if properties were changed after validation, that validation would no longer apply + - So no changing values or property values after a class has been instantiated +6. String + Number types with formats + - String type data is stored as a string and if you need to access types based on its format like date, + date-time, uuid, number etc then you will need to use accessor functions on the instance + - type string + format: See .as_date, .as_datetime, .as_decimal, .as_uuid + - type number + format: See .as_float, .as_int + - this was done because openapi/json-schema defines constraints. string data may be type string with no format + keyword in one schema, and include a format constraint in another schema + - So if you need to access a string format based type, use as_date/as_datetime/as_decimal/as_uuid/ + - So if you need to access a number format based type, use as_int/as_float + +### Object property spec case +This was done because when payloads are ingested, they can be validated against N number of schemas. +If the input signature used a different property name then that has mutated the payload. +So SchemaA and SchemaB must both see the camelCase spec named variable. +Also it is possible to send in two properties, named camelCase and camel_case in the same payload. +That use case should be support so spec case is used. + +### Parameter spec case +Parameters can be included in different locations including: +- query +- path +- header +- cookie + +Any of those parameters could use the same parameter names, so if every parameter +was included as an endpoint parameter in a function signature, they would collide. +For that reason, each of those inputs have been separated out into separate typed dictionaries: +- query_params +- path_params +- header_params +- cookie_params + +So when updating your code, you will need to pass endpoint parameters in using those +dictionaries. + +### Endpoint responses +Endpoint responses have been enriched to now include more information. +Any response reom an endpoint will now include the following properties: +response: urllib3.HTTPResponse +body: typing.Union[Unset, Schema] +headers: typing.Union[Unset, TODO] +Note: response header deserialization has not yet been added + + ## Installation & Usage ### pip install diff --git a/modules/openapi-generator/src/main/resources/python-experimental/model_templates/schema.handlebars b/modules/openapi-generator/src/main/resources/python-experimental/model_templates/schema.handlebars index 3fed0491def..0edbaf61891 100644 --- a/modules/openapi-generator/src/main/resources/python-experimental/model_templates/schema.handlebars +++ b/modules/openapi-generator/src/main/resources/python-experimental/model_templates/schema.handlebars @@ -41,6 +41,16 @@ {{#if nameInSnakeCase}} locals()["{{{baseName}}}"] = {{name}} del locals()['{{name}}'] +""" +NOTE: +openapi/json-schema allows properties to have invalid python names +The above local assignment allows the code to keep those invalid python names +This allows properties to have names like 'some-name', '1 bad name' +Properties with these names are omitted from the __new__ + _from_openapi_data signatures +- __new__ these properties can be passed in as **kwargs +- _from_openapi_data these are passed in in a dict in the first positional argument *arg +If the property is required and was not passed in, an exception will be thrown +""" {{/if}} {{/if}} {{/unless}} \ No newline at end of file diff --git a/samples/openapi3/client/3_0_3_unit_test/python-experimental/README.md b/samples/openapi3/client/3_0_3_unit_test/python-experimental/README.md index 86018df9fe3..92b8b0d354d 100644 --- a/samples/openapi3/client/3_0_3_unit_test/python-experimental/README.md +++ b/samples/openapi3/client/3_0_3_unit_test/python-experimental/README.md @@ -13,6 +13,70 @@ Python >=3.9 v3.9 is needed so one can combine classmethod and property decorators to define object schema properties as classes +## Migration from other generators like python and python-experimental + +### Changes +1. This generator uses spec case for all (object) property names and parameter names. + - So if the spec has a property name like camelCase, it will use camelCase rather than camel_case + - So you will need to update how you input and read properties to use spec case +2. Endpoint parameters are stored in dictionaries to prevent collisions (explanation below) + - So you will need to update how you pass data in to endpoints +3. Endpoint responses now include the original response, the deserialized response body, and (todo)the deserialized headers + - So you will need to update your code to use response.body to access deserialized data +4. All validated data is instantiated in an instance that subclasses all validated Schema classes and Decimal/str/list/tuple/frozendict/NoneClass/BoolClass/bytes/io.FileIO + - This means that you can use isinstance to check if a payload validated against a schema class + - This means that no data will be of type None/True/False + - ingested None will subclass NoneClass + - ingested True will subclass BoolClass + - ingested False will subclass BoolClass + - So if you need to check is True/False/None, instead use instance.is_true()/.is_false()/.is_none() +5. All validated class instances are immutable except for ones based on io.File + - This is because if properties were changed after validation, that validation would no longer apply + - So no changing values or property values after a class has been instantiated +6. String + Number types with formats + - String type data is stored as a string and if you need to access types based on its format like date, + date-time, uuid, number etc then you will need to use accessor functions on the instance + - type string + format: See .as_date, .as_datetime, .as_decimal, .as_uuid + - type number + format: See .as_float, .as_int + - this was done because openapi/json-schema defines constraints. string data may be type string with no format + keyword in one schema, and include a format constraint in another schema + - So if you need to access a string format based type, use as_date/as_datetime/as_decimal/as_uuid/ + - So if you need to access a number format based type, use as_int/as_float + +### Object property spec case +This was done because when payloads are ingested, they can be validated against N number of schemas. +If the input signature used a different property name then that has mutated the payload. +So SchemaA and SchemaB must both see the camelCase spec named variable. +Also it is possible to send in two properties, named camelCase and camel_case in the same payload. +That use case should be support so spec case is used. + +### Parameter spec case +Parameters can be included in different locations including: +- query +- path +- header +- cookie + +Any of those parameters could use the same parameter names, so if every parameter +was included as an endpoint parameter in a function signature, they would collide. +For that reason, each of those inputs have been separated out into separate typed dictionaries: +- query_params +- path_params +- header_params +- cookie_params + +So when updating your code, you will need to pass endpoint parameters in using those +dictionaries. + +### Endpoint responses +Endpoint responses have been enriched to now include more information. +Any response reom an endpoint will now include the following properties: +response: urllib3.HTTPResponse +body: typing.Union[Unset, Schema] +headers: typing.Union[Unset, TODO] +Note: response header deserialization has not yet been added + + ## Installation & Usage ### pip install diff --git a/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/model/properties_with_escaped_characters.py b/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/model/properties_with_escaped_characters.py index e002e235506..3440c7c59f3 100644 --- a/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/model/properties_with_escaped_characters.py +++ b/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/model/properties_with_escaped_characters.py @@ -79,21 +79,81 @@ class PropertiesWithEscapedCharacters( foobar = NumberSchema locals()["foo\nbar"] = foobar del locals()['foobar'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ foobar = NumberSchema locals()["foo\"bar"] = foobar del locals()['foobar'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ foo_bar = NumberSchema locals()["foo\\bar"] = foo_bar del locals()['foo_bar'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ foobar = NumberSchema locals()["foo\rbar"] = foobar del locals()['foobar'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ foobar = NumberSchema locals()["foo\tbar"] = foobar del locals()['foobar'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ foobar = NumberSchema locals()["foo\fbar"] = foobar del locals()['foobar'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ def __new__( cls, diff --git a/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/model/property_named_ref_that_is_not_a_reference.py b/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/model/property_named_ref_that_is_not_a_reference.py index e041626a9a2..0b78a1b9b4d 100644 --- a/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/model/property_named_ref_that_is_not_a_reference.py +++ b/samples/openapi3/client/3_0_3_unit_test/python-experimental/unit_test_api/model/property_named_ref_that_is_not_a_reference.py @@ -79,6 +79,16 @@ class PropertyNamedRefThatIsNotAReference( ref = StrSchema locals()["$ref"] = ref del locals()['ref'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ def __new__( cls, diff --git a/samples/openapi3/client/petstore/python-experimental/README.md b/samples/openapi3/client/petstore/python-experimental/README.md index 83a2af8ec27..c2f0240a0ad 100644 --- a/samples/openapi3/client/petstore/python-experimental/README.md +++ b/samples/openapi3/client/petstore/python-experimental/README.md @@ -13,6 +13,70 @@ Python >=3.9 v3.9 is needed so one can combine classmethod and property decorators to define object schema properties as classes +## Migration from other generators like python and python-experimental + +### Changes +1. This generator uses spec case for all (object) property names and parameter names. + - So if the spec has a property name like camelCase, it will use camelCase rather than camel_case + - So you will need to update how you input and read properties to use spec case +2. Endpoint parameters are stored in dictionaries to prevent collisions (explanation below) + - So you will need to update how you pass data in to endpoints +3. Endpoint responses now include the original response, the deserialized response body, and (todo)the deserialized headers + - So you will need to update your code to use response.body to access deserialized data +4. All validated data is instantiated in an instance that subclasses all validated Schema classes and Decimal/str/list/tuple/frozendict/NoneClass/BoolClass/bytes/io.FileIO + - This means that you can use isinstance to check if a payload validated against a schema class + - This means that no data will be of type None/True/False + - ingested None will subclass NoneClass + - ingested True will subclass BoolClass + - ingested False will subclass BoolClass + - So if you need to check is True/False/None, instead use instance.is_true()/.is_false()/.is_none() +5. All validated class instances are immutable except for ones based on io.File + - This is because if properties were changed after validation, that validation would no longer apply + - So no changing values or property values after a class has been instantiated +6. String + Number types with formats + - String type data is stored as a string and if you need to access types based on its format like date, + date-time, uuid, number etc then you will need to use accessor functions on the instance + - type string + format: See .as_date, .as_datetime, .as_decimal, .as_uuid + - type number + format: See .as_float, .as_int + - this was done because openapi/json-schema defines constraints. string data may be type string with no format + keyword in one schema, and include a format constraint in another schema + - So if you need to access a string format based type, use as_date/as_datetime/as_decimal/as_uuid/ + - So if you need to access a number format based type, use as_int/as_float + +### Object property spec case +This was done because when payloads are ingested, they can be validated against N number of schemas. +If the input signature used a different property name then that has mutated the payload. +So SchemaA and SchemaB must both see the camelCase spec named variable. +Also it is possible to send in two properties, named camelCase and camel_case in the same payload. +That use case should be support so spec case is used. + +### Parameter spec case +Parameters can be included in different locations including: +- query +- path +- header +- cookie + +Any of those parameters could use the same parameter names, so if every parameter +was included as an endpoint parameter in a function signature, they would collide. +For that reason, each of those inputs have been separated out into separate typed dictionaries: +- query_params +- path_params +- header_params +- cookie_params + +So when updating your code, you will need to pass endpoint parameters in using those +dictionaries. + +### Endpoint responses +Endpoint responses have been enriched to now include more information. +Any response reom an endpoint will now include the following properties: +response: urllib3.HTTPResponse +body: typing.Union[Unset, Schema] +headers: typing.Union[Unset, TODO] +Note: response header deserialization has not yet been added + + ## Installation & Usage ### pip install diff --git a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/format_test.py b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/format_test.py index e8e97880008..5223a21aa99 100644 --- a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/format_test.py +++ b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/format_test.py @@ -128,6 +128,16 @@ class FormatTest( pass locals()["float"] = _float del locals()['_float'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ float32 = Float32Schema diff --git a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/model200_response.py b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/model200_response.py index edca0435ec9..c559fbc1168 100644 --- a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/model200_response.py +++ b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/model200_response.py @@ -82,6 +82,16 @@ class Model200Response( _class = StrSchema locals()["class"] = _class del locals()['_class'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ def __new__( cls, diff --git a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/model_return.py b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/model_return.py index 4fe5b613f54..1f9d1eca367 100644 --- a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/model_return.py +++ b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/model_return.py @@ -81,6 +81,16 @@ class ModelReturn( _return = Int32Schema locals()["return"] = _return del locals()['_return'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ def __new__( cls, diff --git a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/name.py b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/name.py index 7a0de5a3cb6..525d2e29df9 100644 --- a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/name.py +++ b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/name.py @@ -86,6 +86,16 @@ class Name( _property = StrSchema locals()["property"] = _property del locals()['_property'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ def __new__( cls, diff --git a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/object_with_difficultly_named_props.py b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/object_with_difficultly_named_props.py index 9a3dd40e835..682753cc697 100644 --- a/samples/openapi3/client/petstore/python-experimental/petstore_api/model/object_with_difficultly_named_props.py +++ b/samples/openapi3/client/petstore/python-experimental/petstore_api/model/object_with_difficultly_named_props.py @@ -84,12 +84,42 @@ class ObjectWithDifficultlyNamedProps( special_property_name = Int64Schema locals()["$special[property.name]"] = special_property_name del locals()['special_property_name'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ _123_list = StrSchema locals()["123-list"] = _123_list del locals()['_123_list'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ _123_number = IntSchema locals()["123Number"] = _123_number del locals()['_123_number'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ def __new__( diff --git a/samples/openapi3/client/petstore/python-experimental/petstore_api/paths/fake_1/post.py b/samples/openapi3/client/petstore/python-experimental/petstore_api/paths/fake_1/post.py index fb9922425e0..51d3874b038 100644 --- a/samples/openapi3/client/petstore/python-experimental/petstore_api/paths/fake_1/post.py +++ b/samples/openapi3/client/petstore/python-experimental/petstore_api/paths/fake_1/post.py @@ -122,6 +122,16 @@ class SchemaForRequestBodyApplicationXWwwFormUrlencoded( pass locals()["float"] = _float del locals()['_float'] + """ + NOTE: + openapi/json-schema allows properties to have invalid python names + The above local assignment allows the code to keep those invalid python names + This allows properties to have names like 'some-name', '1 bad name' + Properties with these names are omitted from the __new__ + _from_openapi_data signatures + - __new__ these properties can be passed in as **kwargs + - _from_openapi_data these are passed in in a dict in the first positional argument *arg + If the property is required and was not passed in, an exception will be thrown + """ class double(