Skip to content
This repository was archived by the owner on Dec 25, 2024. It is now read-only.

Commit 4f82adf

Browse files
authored
v2 migration guides (#138)
* Adds migration guide hbs files * Adds another line of txt * Adds migration files * Improves indentation * Adds subheadings * Updates Api Access By Tags and Paths Updated * reason and action updated * Updates 200 migration guide * Adds new section to migration guide * Samples generated
1 parent b8a3620 commit 4f82adf

File tree

20 files changed

+1500
-440
lines changed

20 files changed

+1500
-440
lines changed

modules/openapi-json-schema-generator/src/main/java/org/openapijsonschematools/codegen/languages/PythonClientCodegen.java

+2
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,8 @@ public void processOpts() {
602602
readmeTemplate = "README_onlypackage.hbs";
603603
}
604604
supportingFiles.add(new SupportingFile(readmeTemplate, "", readmePath));
605+
supportingFiles.add(new SupportingFile("migration_2_0_0.hbs", "", "migration_2_0_0.md"));
606+
supportingFiles.add(new SupportingFile("migration_other_python_generators.hbs", "", "migration_other_python_generators.md"));
605607
supportingFiles.add(new SupportingFile("__init__package.hbs", packagePath(), "__init__.py"));
606608

607609
if (!generateSourceCodeOnly) {

modules/openapi-json-schema-generator/src/main/resources/python/README.hbs

+3-88
Original file line numberDiff line numberDiff line change
@@ -19,94 +19,9 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
1919

2020
Python {{generatorLanguageVersion}}
2121

22-
## Migration from other generators like python and python-legacy
23-
24-
### Changes
25-
1. This generator uses spec case for all (object) property names and parameter names.
26-
- So if the spec has a property name like camelCase, it will use camelCase rather than camel_case
27-
- So you will need to update how you input and read properties to use spec case
28-
2. Endpoint parameters are stored in dictionaries to prevent collisions (explanation below)
29-
- So you will need to update how you pass data in to endpoints
30-
3. Endpoint responses now include the original response, the deserialized response body, and (todo)the deserialized headers
31-
- So you will need to update your code to use response.body to access deserialized data
32-
4. All validated data is instantiated in an instance that subclasses all validated Schema classes and Decimal/str/tuple/frozendict/NoneClass/BoolClass/bytes/io.FileIO
33-
- This means that you can use isinstance to check if a payload validated against a schema class
34-
- This means that no data will be of type None/True/False
35-
- ingested None will subclass NoneClass
36-
- ingested True will subclass BoolClass
37-
- ingested False will subclass BoolClass
38-
- So if you need to check is True/False/None, instead use instance.is_true_()/.is_false_()/.is_none_()
39-
5. All validated class instances are immutable except for ones based on io.File
40-
- This is because if properties were changed after validation, that validation would no longer apply
41-
- So no changing values or property values after a class has been instantiated
42-
6. String + Number types with formats
43-
- String type data is stored as a string and if you need to access types based on its format like date,
44-
date-time, uuid, number etc then you will need to use accessor functions on the instance
45-
- type string + format: See .as_date_, .as_datetime_, .as_decimal_, .as_uuid_
46-
- type number + format: See .as_float_, .as_int_
47-
- this was done because openapi/json-schema defines constraints. string data may be type string with no format
48-
keyword in one schema, and include a format constraint in another schema
49-
- So if you need to access a string format based type, use as_date_/as_datetime_/as_decimal_/as_uuid_
50-
- So if you need to access a number format based type, use as_int_/as_float_
51-
7. Property access on AnyType(type unset) or object(dict) schemas
52-
- Only required keys with valid python names are properties like .someProp and have type hints
53-
- All optional keys may not exist, so properties are not defined for them
54-
- One can access optional values with dict_instance['optionalProp'] and KeyError will be raised if it does not exist
55-
- Use get_item_ if you need a way to always get a value whether or not the key exists
56-
- If the key does not exist, schemas.unset is returned from calling dict_instance.get_item_('optionalProp')
57-
- All required and optional keys have type hints for this method, and @typing.overload is used
58-
- A type hint is also generated for additionalProperties accessed using this method
59-
- So you will need to update you code to use some_instance['optionalProp'] to access optional property
60-
and additionalProperty values
61-
8. The location of the api classes has changed
62-
- Api classes are located in your_package.apis.tags.some_api
63-
- This change was made to eliminate redundant code generation
64-
- Legacy generators generated the same endpoint twice if it had > 1 tag on it
65-
- This generator defines an endpoint in one class, then inherits that class to generate
66-
apis by tags and by paths
67-
- This change reduces code and allows quicker run time if you use the path apis
68-
- path apis are at your_package.apis.paths.some_path
69-
- Those apis will only load their needed models, which is less to load than all of the resources needed in a tag api
70-
- So you will need to update your import paths to the api classes
71-
72-
### Why are Leading and Trailing Underscores in class and method names?
73-
Classes can have arbitrarily named properties set on them
74-
Endpoints can have arbitrary operationId method names set
75-
For those reasons, I use the prefix and suffix _ to greatly reduce the likelihood of collisions
76-
on protected + public classes/methods.
77-
78-
### Object property spec case
79-
This was done because when payloads are ingested, they can be validated against N number of schemas.
80-
If the input signature used a different property name then that has mutated the payload.
81-
So SchemaA and SchemaB must both see the camelCase spec named variable.
82-
Also it is possible to send in two properties, named camelCase and camel_case in the same payload.
83-
That use case should work, so spec case is used.
84-
85-
### Parameter spec case
86-
Parameters can be included in different locations including:
87-
- query
88-
- path
89-
- header
90-
- cookie
91-
92-
Any of those parameters could use the same parameter names, so if every parameter
93-
was included as an endpoint parameter in a function signature, they would collide.
94-
For that reason, each of those inputs have been separated out into separate typed dictionaries:
95-
- query_params
96-
- path_params
97-
- header_params
98-
- cookie_params
99-
100-
So when updating your code, you will need to pass endpoint parameters in using those
101-
dictionaries.
102-
103-
### Endpoint responses
104-
Endpoint responses have been enriched to now include more information.
105-
Any response reom an endpoint will now include the following properties:
106-
response: urllib3.HTTPResponse
107-
body: typing.Union[Unset, Schema]
108-
headers: typing.Union[Unset, TODO]
109-
Note: response header deserialization has not yet been added
22+
## Migration Guides
23+
- [2.0.0 Migration Guide](migration_2_0_0.md)
24+
- [Migration from Other Python Generators](migration_other_python_generators.md)
11025

11126

11227
## Installation & Usage
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# Migration v1.X.X to v2.0.0
2+
3+
- [Compatibility note for opeanpi-generator](#compatibility-note-for-opeanpi-generator)
4+
- [Component Generation](#component-generation)
5+
- [Packaging Changes](#packaging-changes)
6+
- [Path Generation](#path-generation)
7+
- [Configuration Info Refactored](#configuration-info-refactored)
8+
- [Servers and Security Generation](#servers-and-security-generation)
9+
- [Java Classes for Openapi Data Refactored](#java-classes-for-openapi-data-refactored)
10+
- [Api Access by Tags and Paths Updated](#api-access-by-tags-and-paths-updated)
11+
- [Some Method/Property/Input/Class Names Updated](#some-methodpropertyinputclass-names-updated)
12+
- [Documentation Updated](#documentation-updated)
13+
14+
## Compatibility note for opeanpi-generator
15+
The v1.0.4 release is nearly identical to the openapi-generator v6.3.0 release
16+
17+
Below is a summary of big changes when updating you code from v1.X.X to 2.0.0
18+
19+
## Component Generation
20+
Update:
21+
Openapi document components in "#/components/x" are now generated in a components/x packages
22+
Ths applies to:
23+
- headers
24+
- parameters
25+
- request_bodies
26+
- responses
27+
- schemas
28+
- security_schemes
29+
30+
The generator now writes a class for each of those generated components.
31+
32+
### Reason
33+
A lot of openapi data is $ref references throughout an openapi document.
34+
With this update, those $ref source locations are generated with file system paths that closely mirror the openapi
35+
document json schema path to that info. $ref definition is then imported in generated python code.
36+
This minimizes the amount of code that is generated, imposes well defined encapsulation and allows templates to be
37+
re-used for many types of data regardless of where the data is in the source openapi document.
38+
39+
### Action
40+
- Update where you are importing models from, models are now component schemas
41+
- File path change: model/pet.py -> components/schema/pet.py
42+
43+
## Packaging changes
44+
Code has been updated to use .toml packaging. Code is now distributed in a src directory
45+
46+
### Reason
47+
These updates follow latest python packaging best practices
48+
49+
### Action
50+
- if you are suppressing generation of any files, you will need to edit those file paths
51+
- File Path Change: package_name -> src/package_name
52+
53+
## Path Generation
54+
If paths contain inline descriptions of parameters, request bodies, responses, security, or servers,
55+
then those are now generated in separate files. Those files are imported into the endpoint code.
56+
File locations closely mirror the openapi data json schema path.
57+
58+
### Reason
59+
Generating those files in paths that closely mirror the json schema paths will allow
60+
the generator to use $ref to any location in the openapi document in the future, not just components.
61+
These could include:
62+
- relative $refs
63+
- a request body $ref referring to the request body in another endpoint
64+
65+
This also allowed the generation code to work the same way regardless of where the header/requestBody etc
66+
is in the source spec.
67+
68+
Note:
69+
Operations are now at
70+
paths/somePath/get/operation.py
71+
and not at
72+
paths/somePath/get/__init__.py
73+
to minimize the amount of memory needed when importing the python package.
74+
The configurations.api_configuration.py file imports all servers defined at:
75+
- openapi document root
76+
- pathItem
77+
- pathItem operation
78+
And if servers were defined in pathItem operations, then every operation that contains a server would be imported
79+
in api_configuration.py. Which could be many many files.
80+
81+
So instead
82+
- operation endpoint definition was moved to paths/somePath/get/operation.py
83+
- paths/somePath/get/__init__.py stays empty and does not need lots of memory when api_configuration.py imports servers
84+
- server information was kept in paths/somePath/get/servers/server_x.py
85+
86+
### Action
87+
- if you are importing any endpoint form its file, update your import
88+
- File path update: paths/somePath/get.py -> paths/somePath/get/operation.py
89+
90+
## Configuration Info Refactored
91+
Configuration information was separated into two classes
92+
- configurations/api_configuration.py ApiConfiguration for:
93+
- server info
94+
- security (auth) info
95+
- logging info
96+
- configurations/schema_configuration.py SchemaConfiguration for:
97+
- disabled openapi/json-schema keywords
98+
99+
### Reason
100+
Schema validation only relies on SchemaConfiguration data and does not need to know about any ApiConfiguration info
101+
General api configuration info was poorly structured in the legacy configuration class which had 13 inputs.
102+
The refactored ApiConfiguration now has 4 inputs which define servers and security info.
103+
Having these separate classes prevents circular imports when the schemas.py file imports its SchemaConfiguration class.
104+
105+
### Action
106+
- When you instantiate ApiClient, update your code to pass in an instance of SchemaConfiguration + ApiConfiguration
107+
108+
109+
## Servers and Security Generation
110+
Servers are now generated as separate files with one class per file wherever they were defined in the openapi document
111+
- servers/server_0.py
112+
- paths/somePath/servers/server_0.py
113+
- paths/somePath/get/servers/server_0.py
114+
Security requirements objects are now generated as separate files with one security requirement object per file
115+
wherever they were defined in the openapi document
116+
- security/security_requirement_object_0.py
117+
- paths/somePath/get/security/security_requirement_object_0.py
118+
119+
### Reason
120+
Server classes now re-use schema validation code to ensure that inputs to server variables are valid.
121+
Generating these separate files minimizes generated code and maximizes code re-use.
122+
123+
### Action
124+
- If endpoints need to use specific servers or security not at index 0, pass security_index_info + server_index_info
125+
into ApiConfiguration when instantiating it
126+
- If you use non-default server variable values, then update your code to pass in server_info into ApiConfiguration
127+
128+
## Java Classes for Openapi Data Refactored
129+
Almost every java class used to store openapi document data at generation time has been re-written or refactored.
130+
The new classes are much shorter and contain only what is needed to generate code and documentation.
131+
This will make it much easier to add new openapi v3.1.0 features like new json schema keywords.
132+
Generator interface methods were also refactored to simplify Java model instantiation and code generation.
133+
Almost all properties are now public static final and are:
134+
- immutable
135+
- publicly accessible to the templates
136+
137+
### Reason
138+
These updates make the code much more maintainable.
139+
The number of properties that have to be maintained is much smaller
140+
- Component Schema: ~100 properties in CodegenModel.java -> ~50 properties in CodegenSchema.java
141+
- PathItem Operation: ~75 properties CodegenOperation: ~25 properties
142+
143+
This will reduce bugs like: why can't I access this property in this template
144+
Because instances are mostly immutable it is very clear where the wrong value is being created/assigned.
145+
146+
### Action
147+
- if you are customizing the python generator, you will need to update your java code
148+
149+
## Api Access By Tags and Paths Updated
150+
Previously, keys togo from tags and paths to apis were enums.
151+
The code was updated to use a TypedDict and uses strings as the keys.
152+
153+
### Reason
154+
Making this change allows type hinting to work for the TypedDict with string keys
155+
156+
### Action
157+
- If you use path_to_api.py or tag_to_api.py, update the key that you use to access the api
158+
159+
## Some Method/Property/Input/Class Names Updated
160+
- is_true_oapg -> is_true_
161+
- is_false_oapg -> is_false_
162+
- is_none_oapg -> is_none_
163+
- as_date_oapg -> as_date_
164+
- as_datetime_oapg -> as_datetime_
165+
- as_decimal_oapg -> as_decimal_
166+
- as_uuid_oapg -> as_uuid_
167+
- as_float_oapg -> as_float_
168+
- as_int_oapg -> as_int_
169+
- get_item_oapg -> get_item_
170+
- from_openapi_data_oapg -> from_openapi_data_
171+
- _verify_typed_dict_inputs_oapg -> _verify_typed_dict_inputs
172+
- _configuration -> configuration_
173+
- _arg -> arg_
174+
- _args -> args_
175+
- MetaOapg -> Schema_
176+
- JsonSchema -> OpenApiSchema
177+
178+
### Reason
179+
Classes can have arbitrarily named properties set on them
180+
Endpoints can have arbitrary operationId method names set
181+
For those reasons, I use the prefix and suffix _ to greatly reduce the likelihood of collisions
182+
on protected + public classes/methods.
183+
184+
### Action
185+
- if you use the above methods/inputs/properties/classes update them to the latest names
186+
187+
## Documentation Updated
188+
- components now have sections in the readme
189+
- models became component schemas
190+
- one file is now generated for each endpoint
191+
- that file now has a table of contents
192+
- heading indentation levels now are indented correctly in descending order
193+
- endpoint now includes server and security info (if security exists)
194+
- servers section added to readme if servers were defined in the openapi document root
195+
- security section added to readme if security was defined in the openapi document root
196+
197+
### Reason
198+
Endpoint documentation had indentation and linking bugs before, this fixes them.
199+
When all endpoints docs were written in one file it was difficult to link ot the correct section.
200+
How to set server and security info was unclear before, the new docs and classes should clarify that.
201+
202+
### Action
203+
- if you link to specific parts of the documentation, update your links

0 commit comments

Comments
 (0)