This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: " \
This Python package is automatically generated by the OpenAPI JSON Schema Generator project:
- API version: 1.0.0
- Package version: 1.0.0
- Build package: PythonClientCodegen
Python >=3.7
If the python package is hosted on a repository, you can install directly using:
pip install git+https://github.com/GIT_USER_ID/GIT_REPO_ID.git(you may need to run pip with root permission: sudo pip install git+https://github.com/GIT_USER_ID/GIT_REPO_ID.git)
Then import the package:
import petstore_apiInstall via Setuptools.
python -m pip install . --user(or python -m pip install . to install the package for all users)
Then import the package:
import petstore_apiThis python code validates data to schema classes and return back an immutable instance containing the data which subclasses all validated schema classes. This ensure that
- valid data cannot be mutated and become invalid to a set of schemas
- the one exception is that files are not immutable, so schema instances storing/sending/receiving files are not immutable
- one can use isinstance to check if a instance or property is valid to a schema class
- this means that expensive validation does not need to be run twice
Reason
To do that, some changes had to be made. Python bool and NoneType cannot be subclassed, so to be able to meet the above design goals, I implemented BoolClass and NoneClass classes to allow schemas to subclass them.
In python 0 == False and 1 == True. This is a problem for json schema which is language independent. The json schema test suite has explicit tests that require that 0 != False and 1 != True Using the above described BoolClass and NoneClasses allows those tests to pass.
- Another example of a package using it's own boolean class is numpy's bool_
If you need to check is True/False/None, instead use instance.is_true_()/.is_false_()/.is_none_()
Here is the mapping from json schema types to python subclassed types:
| Json Schema Type | Python Base Class |
|---|---|
| object | frozendict.frozendict |
| array | tuple |
| string | str |
| number | decimal.Decimal |
| integer | decimal.Decimal |
| boolean | BoolClass |
| null | NoneClass |
| AnyType (unset) | typing.Union[frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass, NoneClass] |
In openapi v3.0.3 there are ~ 28 json schema keywords. Almost all of them can apply if type is unset. This data could be stored as
- class properties
- in a container in the class like in a dict or in a nested class
This data is stored in a nested class named Schema_. Storing this data as a nested class ensures that the data is encapsulated, does not collide with class properties, and allows for deeper complex inline definitions.
Reason
If the data were stored at the class property level, then the keywords could collide with type object property names. To avoid that, one could make the properties semi or fully private with a single or double underscore prefix, but that it a lot of data to put there. Better to separate out json schema data from type object properties at the class property level.
If the data were stored in a container that would segregate the different data which is good. But json schemas can be inlined to any depth. Those complex deeper schemas would need to be included. One could define them higher in the class file and then refer to them in the dict. That would required iterating over schemas and adding all of the inner into a collection, and then generate that collection.
The schema definitions are already nested from the json schema definition. The easiest solution is to use a nested json schema definition class which holds that data. That way:
- the data is separated from class properties
- deeper complicated schemas can still be stored
So a nested class was chosen to store json schema data, this class is named Schema_.
Most component schemas (models) are probably of type object. Which is a map data structure. Json schema allows string keys in this map, which means schema properties can have key names that are invalid python variable names. Names like:
- "hi-there"
- "1variable"
- "@now"
- " "
- "from"
To allow these use cases to work, frozendict.frozendict is used as the base class of type object schemas. This means that one can use normal dict methods on instances of these classes.
Other Details
- optional properties which were not set will not exist in the instance
- None is only allowed in as a value if type: "null" was included or nullable: true was set
- type hints are written for accessing values by key literals like instance["hi-there"]
- and there is a method instance.get_item_["hi-there"] which returns an schemas.Unset value if the key was not set
- required properties with valid python names are accessible with instance.SomeRequiredProp
which uses the exact key from the openapi document
- preserving the original key names is required to properly validate a payload to multiple json schemas
N schemas can be validated on the same payload. To allow multiple schemas to validate, the data must be stored using one base class whether or not a json schema format constraint exists in the schema. See te below accessors for string data:
- type string + format: See .as_date_, .as_datetime_, .as_decimal_, .as_uuid_
In json schema, type: number with no format validates both integers and floats, so decimal.Decimal is used to store them. See te below accessors for number data:
- type number + format: See .as_float_, .as_int_
String + Date Example
For example the string payload '2023-12-20' is validates to both of these schemas:
- string only
- type: string
- string and date format
- type: string
format: date
Because of use cases like this, a datetime.date is allowed as an input to this schema, but the data is stored as a string, with a date accessor, instance.as_date_
Please follow the installation procedure and then run the following:
import petstore_api
from petstore_api.configurations import api_configuration
from petstore_api.apis.tags import fake_api
from pprint import pprint
used_configuration = api_configuration.ApiConfiguration(
)
# Enter a context with an instance of the API client
with petstore_api.ApiClient(used_configuration) as api_client:
# Create an instance of the API class
api_instance = fake_api.FakeApi(api_client)
# example, this endpoint has no required or optional parameters
try:
# slash route
api_response = api_instance.slash_route()
pprint(api_response)
except petstore_api.ApiException as e:
print("Exception when calling FakeApi->slash_route: %s\n" % e)| server_index | Class | Description |
|---|---|---|
| 0 | Server0 | petstore server |
| 1 | Server1 | The local server |
| 2 | Server2 | staging server with no variables |
All URIs are relative to the selected server
- The server is selected by passing in server_info and server_index into api_configuration.ApiConfiguration
- Code samples in endpoints documents show how to do this
- server_index can also be passed in to endpoint calls, see endpoint documentation
| HTTP request | Method | Description |
|---|---|---|
| / get | FakeApi.slash_route | slash route |
| /another-fake/dummy patch | AnotherFakeApi.call_123_test__special_tags | To test special tags |
| /fake delete | FakeApi.group_parameters | Fake endpoint to test group parameters (optional) |
| /fake get | FakeApi.enum_parameters | To test enum parameters |
| /fake patch | FakeApi.client_model | To test "client" model |
| /fake post | FakeApi.endpoint_parameters | Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 |
| /fake/additional-properties-with-array-of-enums get | FakeApi.additional_properties_with_array_of_enums | Additional Properties with Array of Enums |
| /fake/body-with-file-schema put | FakeApi.body_with_file_schema | |
| /fake/body-with-query-params put | FakeApi.body_with_query_params | |
| /fake/case-sensitive-params put | FakeApi.case_sensitive_params | |
| /fake/deleteCoffee/{id} delete | FakeApi.delete_coffee | Delete coffee |
| /fake/health get | FakeApi.fake_health_get | Health check endpoint |
| /fake/inline-additionalProperties post | FakeApi.inline_additional_properties | test inline additionalProperties |
| /fake/inlineComposition/ post | FakeApi.inline_composition | testing composed schemas at inline locations |
| /fake/jsonFormData get | FakeApi.json_form_data | test json serialization of form data |
| /fake/jsonPatch patch | FakeApi.json_patch | json patch |
| /fake/jsonWithCharset post | FakeApi.json_with_charset | json with charset tx and rx |
| /fake/multipleResponseBodies get | FakeApi.multiple_response_bodies | multiple responses have response bodies |
| /fake/multipleSecurities get | FakeApi.multiple_securities | multiple security requirements |
| /fake/objInQuery get | FakeApi.object_in_query | user list |
| /fake/parameterCollisions/{1}/{aB}/{Ab}/{self}/{A-B}/ post | FakeApi.parameter_collisions | parameter collision case |
| /fake/queryParamWithJsonContentType get | FakeApi.query_param_with_json_content_type | query param with json content-type |
| /fake/redirection get | FakeApi.redirection | operation with redirection responses |
| /fake/refObjInQuery get | FakeApi.ref_object_in_query | user list |
| /fake/refs/array-of-enums post | FakeApi.array_of_enums | Array of Enums |
| /fake/refs/arraymodel post | FakeApi.array_model | |
| /fake/refs/boolean post | FakeApi.boolean | |
| /fake/refs/composed_one_of_number_with_validations post | FakeApi.composed_one_of_different_types | |
| /fake/refs/enum post | FakeApi.string_enum | |
| /fake/refs/mammal post | FakeApi.mammal | |
| /fake/refs/number post | FakeApi.number_with_validations | |
| /fake/refs/object_model_with_ref_props post | FakeApi.object_model_with_ref_props | |
| /fake/refs/string post | FakeApi.string | |
| /fake/responseWithoutSchema get | FakeApi.response_without_schema | receives a response without schema |
| /fake/test-query-paramters put | FakeApi.query_parameter_collection_format | |
| /fake/uploadDownloadFile post | FakeApi.upload_download_file | uploads a file and downloads a file using application/octet-stream |
| /fake/uploadFile post | FakeApi.upload_file | uploads a file using multipart/form-data |
| /fake/uploadFiles post | FakeApi.upload_files | uploads files using multipart/form-data |
| /fake/wildCardResponses get | FakeApi.wild_card_responses | operation with wildcard responses |
| /fake/{petId}/uploadImageWithRequiredFile post | PetApi.upload_file_with_required_file | uploads an image (required) |
| /fake_classname_test patch | FakeClassnameTags123Api.classname | To test class name in snake case |
| /foo get | DefaultApi.foo_get | |
| /pet post | PetApi.add_pet | Add a new pet to the store |
| /pet put | PetApi.update_pet | Update an existing pet |
| /pet/findByStatus get | PetApi.find_pets_by_status | Finds Pets by status |
| /pet/findByTags get | PetApi.find_pets_by_tags | Finds Pets by tags |
| /pet/{petId} delete | PetApi.delete_pet | Deletes a pet |
| /pet/{petId} get | PetApi.get_pet_by_id | Find pet by ID |
| /pet/{petId} post | PetApi.update_pet_with_form | Updates a pet in the store with form data |
| /pet/{petId}/uploadImage post | PetApi.upload_image | uploads an image |
| /store/inventory get | StoreApi.get_inventory | Returns pet inventories by status |
| /store/order post | StoreApi.place_order | Place an order for a pet |
| /store/order/{order_id} delete | StoreApi.delete_order | Delete purchase order by ID |
| /store/order/{order_id} get | StoreApi.get_order_by_id | Find purchase order by ID |
| /user post | UserApi.create_user | Create user |
| /user/createWithArray post | UserApi.create_users_with_array_input | Creates list of users with given input array |
| /user/createWithList post | UserApi.create_users_with_list_input | Creates list of users with given input array |
| /user/login get | UserApi.login_user | Logs user into the system |
| /user/logout get | UserApi.logout_user | Logs out current logged in user session |
| /user/{username} delete | UserApi.delete_user | Delete user |
| /user/{username} get | UserApi.get_user_by_name | Get user by user name |
| /user/{username} put | UserApi.update_user | Updated user |
| Class | Description |
|---|---|
| Client | client model |
| Pet | Pet object that needs to be added to the store, multiple content types |
| RefUserArray | |
| UserArray | List of user object |
| Class | Description |
|---|---|
| RefSuccessDescriptionOnly | |
| RefSuccessfulXmlAndJsonArrayOfPet | |
| SuccessDescriptionOnly | Success |
| SuccessInlineContentAndHeader | successful operation |
| SuccessWithJsonApiResponse | successful operation |
| SuccessfulXmlAndJsonArrayOfPet | successful operation, multiple content types |
| Class | Description |
|---|---|
| Int32JsonContentTypeHeader | int32 JSON content-type header |
| NumberHeader | number header description |
| RefContentSchemaHeader | int32 JSON content-type header |
| RefSchemaHeader | header that has a ref in the schema |
| RefStringHeader | |
| StringHeader | string header description |
| Class | Description |
|---|---|
| ComponentRefSchemaStringWithValidation | a path string with validation |
| PathUserName | the use name to use |
| RefPathUserName | |
| RefSchemaStringWithValidation | a path string with validation |
| Class | Description |
|---|---|
| ApiKey | apiKey in header |
| ApiKeyQuery | apiKey in query |
| BearerTest | http bearer with JWT bearer format |
| HttpBasicTest | http basic |
| HttpSignatureTest | http + signature |
| OpenIdConnectTest | openIdConnect |
| PetstoreAuth | oauth2 implicit flow with two scopes |
If the OpenAPI document is large, imports in petstore_api.apis.tags.tag_to_api and petstore_api.components.schemas may fail with a RecursionError indicating the maximum recursion limit has been exceeded. In that case, there are a couple of solutions:
Solution 1: Use specific imports for apis and models like:
- tagged api:
from petstore_api.apis.tags.default_api import DefaultApi - api for one path:
from petstore_api.apis.paths.some_path import SomePath - api for one operation (path + verb):
from petstore_api.paths.some_path.get import ApiForget - single model import:
from petstore_api.components.schema.pet import Pet
Solution 2: Before importing the package, adjust the maximum recursion limit as shown below:
import sys
sys.setrecursionlimit(1500)
import petstore_api
from petstore_api.apis.tags.tag_to_api import *
from petstore_api.components.schemas import *