diff --git a/apis/petstore.yml b/apis/petstore.yml new file mode 100644 index 0000000..1fe20cb --- /dev/null +++ b/apis/petstore.yml @@ -0,0 +1,867 @@ +openapi: 3.0.0 +info: + description: "This is a sample server Petstore server. For this sample, you can\ + \ use the api key `special-key` to test the authorization filters." + license: + name: Apache-2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + title: OpenAPI Petstore + version: 1.0.0 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: +- url: http://petstore.swagger.io/v2 +tags: +- description: Everything about your Pets + name: pet +- description: Access to Petstore orders + name: store +- description: Operations about user + name: user +paths: + /pet: + post: + description: "" + operationId: addPet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + summary: Add a new pet to the store + tags: + - pet + put: + description: "" + externalDocs: + description: API documentation for the updatePet operation + url: http://petstore.swagger.io/v2/doc/updatePet + operationId: updatePet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Pet not found + "405": + description: Validation exception + security: + - petstore_auth: + - write:pets + - read:pets + summary: Update an existing pet + tags: + - pet + /pet/findByStatus: + get: + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - deprecated: true + description: Status values that need to be considered for filter + explode: false + in: query + name: status + required: true + schema: + items: + default: available + enum: + - available + - pending + - sold + type: string + type: array + style: form + responses: + "200": + content: + application/xml: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + application/json: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + description: successful operation + "400": + description: Invalid status value + security: + - petstore_auth: + - read:pets + summary: Finds Pets by status + tags: + - pet + /pet/findByTags: + get: + deprecated: true + description: "Multiple tags can be provided with comma separated strings. Use\ + \ tag1, tag2, tag3 for testing." + operationId: findPetsByTags + parameters: + - description: Tags to filter by + explode: false + in: query + name: tags + required: true + schema: + items: + type: string + type: array + style: form + responses: + "200": + content: + application/xml: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + application/json: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + description: successful operation + "400": + description: Invalid tag value + security: + - petstore_auth: + - read:pets + summary: Finds Pets by tags + tags: + - pet + /pet/{petId}: + delete: + description: "" + operationId: deletePet + parameters: + - explode: false + in: header + name: api_key + required: false + schema: + type: string + style: simple + - description: Pet id to delete + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "400": + description: Invalid pet value + security: + - petstore_auth: + - write:pets + - read:pets + summary: Deletes a pet + tags: + - pet + get: + description: Returns a single pet + operationId: getPetById + parameters: + - description: ID of pet to return + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Pet not found + security: + - api_key: [] + summary: Find pet by ID + tags: + - pet + post: + description: "" + operationId: updatePetWithForm + parameters: + - description: ID of pet that needs to be updated + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/updatePetWithForm_request' + responses: + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + summary: Updates a pet in the store with form data + tags: + - pet + /pet/{petId}/uploadImage: + post: + description: "" + operationId: uploadFile + parameters: + - description: ID of pet to update + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/uploadFile_request' + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: successful operation + security: + - petstore_auth: + - write:pets + - read:pets + summary: uploads an image + tags: + - pet + /store/inventory: + get: + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + "200": + content: + application/json: + schema: + additionalProperties: + format: int32 + type: integer + type: object + description: successful operation + security: + - api_key: [] + summary: Returns pet inventories by status + tags: + - store + /store/order: + post: + description: "" + operationId: placeOrder + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + description: successful operation + "400": + description: Invalid Order + summary: Place an order for a pet + tags: + - store + /store/order/{orderId}: + delete: + description: For valid response try integer IDs with value < 1000. Anything + above 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - description: ID of the order that needs to be deleted + explode: false + in: path + name: orderId + required: true + schema: + type: string + style: simple + responses: + "400": + description: Invalid ID supplied + "404": + description: Order not found + summary: Delete purchase order by ID + tags: + - store + get: + description: For valid response try integer IDs with value <= 5 or > 10. Other + values will generate exceptions + operationId: getOrderById + parameters: + - description: ID of pet that needs to be fetched + explode: false + in: path + name: orderId + required: true + schema: + format: int64 + maximum: 5 + minimum: 1 + type: integer + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Order not found + summary: Find purchase order by ID + tags: + - store + /user: + post: + description: This can only be done by the logged in user. + operationId: createUser + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Create user + tags: + - user + /user/createWithArray: + post: + description: "" + operationId: createUsersWithArrayInput + requestBody: + $ref: '#/components/requestBodies/UserArray' + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Creates list of users with given input array + tags: + - user + /user/createWithList: + post: + description: "" + operationId: createUsersWithListInput + requestBody: + $ref: '#/components/requestBodies/UserArray' + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Creates list of users with given input array + tags: + - user + /user/login: + get: + description: "" + operationId: loginUser + parameters: + - description: The user name for login + explode: true + in: query + name: username + required: true + schema: + pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$" + type: string + style: form + - description: The password for login in clear text + explode: true + in: query + name: password + required: true + schema: + type: string + style: form + responses: + "200": + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + description: successful operation + headers: + Set-Cookie: + description: Cookie authentication key for use with the `api_key` apiKey + authentication. + explode: false + schema: + example: AUTH_KEY=abcde12345; Path=/; HttpOnly + type: string + style: simple + X-Rate-Limit: + description: calls per hour allowed by the user + explode: false + schema: + format: int32 + type: integer + style: simple + X-Expires-After: + description: date in UTC when token expires + explode: false + schema: + format: date-time + type: string + style: simple + "400": + description: Invalid username/password supplied + summary: Logs user into the system + tags: + - user + /user/logout: + get: + description: "" + operationId: logoutUser + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Logs out current logged in user session + tags: + - user + /user/{username}: + delete: + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - description: The name that needs to be deleted + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + responses: + "400": + description: Invalid username supplied + "404": + description: User not found + security: + - api_key: [] + summary: Delete user + tags: + - user + get: + description: "" + operationId: getUserByName + parameters: + - description: The name that needs to be fetched. Use user1 for testing. + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + description: successful operation + "400": + description: Invalid username supplied + "404": + description: User not found + summary: Get user by user name + tags: + - user + put: + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - description: name that need to be deleted + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + responses: + "400": + description: Invalid user supplied + "404": + description: User not found + security: + - api_key: [] + summary: Updated user + tags: + - user + /fake/query_param_default: + get: + description: "" + operationId: fake_query_param_default + parameters: + - description: has default value + explode: true + in: query + name: hasDefault + required: false + schema: + default: Hello World + type: string + style: form + - description: no default value + explode: true + in: query + name: noDefault + required: false + schema: + type: string + style: form + responses: + "400": + description: Invalid username supplied + "404": + description: User not found + summary: test query parameter default value + tags: + - fake +components: + requestBodies: + UserArray: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/User' + type: array + description: List of user object + required: true + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + schemas: + Order: + description: An order for a pets from the pet store + example: + petId: 6 + quantity: 1 + id: 0 + shipDate: 2000-01-23T04:56:07.000+00:00 + complete: false + status: placed + properties: + id: + format: int64 + title: id + type: integer + petId: + format: int64 + title: petId + type: integer + quantity: + format: int32 + title: quantity + type: integer + shipDate: + format: date-time + title: shipDate + type: string + status: + description: Order Status + enum: + - placed + - approved + - delivered + title: status + type: string + complete: + default: false + title: complete + type: boolean + title: Pet Order + type: object + xml: + name: Order + Category: + description: A category for a pet + example: + name: name + id: 6 + properties: + id: + format: int64 + title: id + type: integer + name: + pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$" + title: name + type: string + title: Pet category + type: object + xml: + name: Category + User: + description: A User who is purchasing from the pet store + example: + firstName: firstName + lastName: lastName + password: password + userStatus: 6 + phone: phone + id: 0 + email: email + username: username + properties: + id: + format: int64 + title: id + type: integer + username: + title: username + type: string + firstName: + title: firstName + type: string + lastName: + title: lastName + type: string + email: + title: email + type: string + password: + title: password + type: string + phone: + title: phone + type: string + userStatus: + description: User Status + format: int32 + title: userStatus + type: integer + title: a User + type: object + xml: + name: User + Tag: + description: A tag for a pet + example: + name: name + id: 1 + properties: + id: + format: int64 + title: id + type: integer + name: + title: name + type: string + title: Pet Tag + type: object + xml: + name: Tag + Pet: + description: A pet for sale in the pet store + example: + photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + properties: + id: + format: int64 + title: id + type: integer + category: + $ref: '#/components/schemas/Category' + name: + example: doggie + title: name + type: string + photoUrls: + items: + type: string + title: photoUrls + type: array + xml: + name: photoUrl + wrapped: true + tags: + items: + $ref: '#/components/schemas/Tag' + title: tags + type: array + xml: + name: tag + wrapped: true + status: + deprecated: true + description: pet status in the store + enum: + - available + - pending + - sold + title: status + type: string + required: + - name + - photoUrls + title: a Pet + type: object + xml: + name: Pet + ApiResponse: + description: Describes the result of uploading an image resource + example: + code: 0 + type: type + message: message + properties: + code: + format: int32 + title: code + type: integer + type: + title: type + type: string + message: + title: message + type: string + title: An uploaded response + type: object + updatePetWithForm_request: + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + type: object + uploadFile_request: + properties: + additionalMetadata: + description: Additional data to pass to server + type: string + file: + description: file to upload + format: binary + type: string + type: object + securitySchemes: + petstore_auth: + flows: + implicit: + authorizationUrl: http://petstore.swagger.io/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets + type: oauth2 + api_key: + in: header + name: api_key + type: apiKey diff --git a/generated-code-expected/.flake8 b/generated-code-expected/.flake8 new file mode 100644 index 0000000..9e008c5 --- /dev/null +++ b/generated-code-expected/.flake8 @@ -0,0 +1,3 @@ +[flake8] +max-line-length = 88 +exclude = .git,__pycache__,__init__.py,.mypy_cache,.pytest_cache,.venv diff --git a/generated-code-expected/.gitignore b/generated-code-expected/.gitignore new file mode 100644 index 0000000..a81c8ee --- /dev/null +++ b/generated-code-expected/.gitignore @@ -0,0 +1,138 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/generated-code-expected/.openapi-generator-ignore b/generated-code-expected/.openapi-generator-ignore new file mode 100644 index 0000000..7484ee5 --- /dev/null +++ b/generated-code-expected/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/generated-code-expected/.openapi-generator/FILES b/generated-code-expected/.openapi-generator/FILES new file mode 100644 index 0000000..bf45410 --- /dev/null +++ b/generated-code-expected/.openapi-generator/FILES @@ -0,0 +1,35 @@ +.flake8 +.gitignore +.openapi-generator-ignore +Dockerfile +README.md +docker-compose.yaml +openapi.yaml +openapi_server/dto/__init__.py +openapi_server/dto/api_response.py +openapi_server/dto/category.py +openapi_server/dto/extra_models.py +openapi_server/dto/order.py +openapi_server/dto/pet.py +openapi_server/dto/tag.py +openapi_server/dto/user.py +openapi_server/impl/__init__.py +openapi_server/main.py +openapi_server/security_api.py +openapi_server/service/__init__.py +openapi_server/service/fake_api.py +openapi_server/service/fake_api_base.py +openapi_server/service/pet_api.py +openapi_server/service/pet_api_base.py +openapi_server/service/store_api.py +openapi_server/service/store_api_base.py +openapi_server/service/user_api.py +openapi_server/service/user_api_base.py +pyproject.toml +requirements.txt +setup.cfg +tests/conftest.py +tests/test_fake_api.py +tests/test_pet_api.py +tests/test_store_api.py +tests/test_user_api.py diff --git a/generated-code-expected/.openapi-generator/VERSION b/generated-code-expected/.openapi-generator/VERSION new file mode 100644 index 0000000..5f84a81 --- /dev/null +++ b/generated-code-expected/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.12.0 diff --git a/generated-code-expected/Dockerfile b/generated-code-expected/Dockerfile new file mode 100644 index 0000000..b66458e --- /dev/null +++ b/generated-code-expected/Dockerfile @@ -0,0 +1,30 @@ +FROM python:3.7 AS builder + +WORKDIR /usr/src/app + +RUN python3 -m venv /venv +ENV PATH="/venv/bin:$PATH" + +RUN pip install --upgrade pip + +COPY . . +RUN pip install --no-cache-dir . + + +FROM python:3.7 AS test_runner +WORKDIR /tmp +COPY --from=builder /venv /venv +COPY --from=builder /usr/src/app/tests tests +ENV PATH=/venv/bin:$PATH + +# install test dependencies +RUN pip install pytest + +# run tests +RUN pytest tests + + +FROM python:3.7 AS service +WORKDIR /root/app/site-packages +COPY --from=test_runner /venv /venv +ENV PATH=/venv/bin:$PATH diff --git a/generated-code-expected/README.md b/generated-code-expected/README.md new file mode 100644 index 0000000..763dc39 --- /dev/null +++ b/generated-code-expected/README.md @@ -0,0 +1,39 @@ +# OpenAPI generated FastAPI server + +This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: + +- API version: 1.0.0 +- Generator version: 7.12.0 +- Build package: org.openapitools.codegen.languages.PythonFastAPIServerCodegen + +## Requirements. + +Python >= 3.7 + +## Installation & Usage + +To run the server, please execute the following from the root directory: + +```bash +pip3 install -r requirements.txt +PYTHONPATH=src uvicorn openapi_server.main:app --host 0.0.0.0 --port 8080 +``` + +and open your browser at `http://localhost:8080/docs/` to see the docs. + +## Running with Docker + +To run the server on a Docker container, please execute the following from the root directory: + +```bash +docker-compose up --build +``` + +## Tests + +To run the tests: + +```bash +pip3 install pytest +PYTHONPATH=src pytest tests +``` diff --git a/generated-code-expected/docker-compose.yaml b/generated-code-expected/docker-compose.yaml new file mode 100644 index 0000000..638e4e0 --- /dev/null +++ b/generated-code-expected/docker-compose.yaml @@ -0,0 +1,9 @@ +version: '3.6' +services: + service: + build: + context: . + target: service + ports: + - "8080:8080" + command: uvicorn openapi_server.main:app --host 0.0.0.0 --port 8080 diff --git a/generated-code-expected/openapi.yaml b/generated-code-expected/openapi.yaml new file mode 100644 index 0000000..1fe20cb --- /dev/null +++ b/generated-code-expected/openapi.yaml @@ -0,0 +1,867 @@ +openapi: 3.0.0 +info: + description: "This is a sample server Petstore server. For this sample, you can\ + \ use the api key `special-key` to test the authorization filters." + license: + name: Apache-2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + title: OpenAPI Petstore + version: 1.0.0 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: +- url: http://petstore.swagger.io/v2 +tags: +- description: Everything about your Pets + name: pet +- description: Access to Petstore orders + name: store +- description: Operations about user + name: user +paths: + /pet: + post: + description: "" + operationId: addPet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + summary: Add a new pet to the store + tags: + - pet + put: + description: "" + externalDocs: + description: API documentation for the updatePet operation + url: http://petstore.swagger.io/v2/doc/updatePet + operationId: updatePet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Pet not found + "405": + description: Validation exception + security: + - petstore_auth: + - write:pets + - read:pets + summary: Update an existing pet + tags: + - pet + /pet/findByStatus: + get: + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - deprecated: true + description: Status values that need to be considered for filter + explode: false + in: query + name: status + required: true + schema: + items: + default: available + enum: + - available + - pending + - sold + type: string + type: array + style: form + responses: + "200": + content: + application/xml: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + application/json: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + description: successful operation + "400": + description: Invalid status value + security: + - petstore_auth: + - read:pets + summary: Finds Pets by status + tags: + - pet + /pet/findByTags: + get: + deprecated: true + description: "Multiple tags can be provided with comma separated strings. Use\ + \ tag1, tag2, tag3 for testing." + operationId: findPetsByTags + parameters: + - description: Tags to filter by + explode: false + in: query + name: tags + required: true + schema: + items: + type: string + type: array + style: form + responses: + "200": + content: + application/xml: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + application/json: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + description: successful operation + "400": + description: Invalid tag value + security: + - petstore_auth: + - read:pets + summary: Finds Pets by tags + tags: + - pet + /pet/{petId}: + delete: + description: "" + operationId: deletePet + parameters: + - explode: false + in: header + name: api_key + required: false + schema: + type: string + style: simple + - description: Pet id to delete + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "400": + description: Invalid pet value + security: + - petstore_auth: + - write:pets + - read:pets + summary: Deletes a pet + tags: + - pet + get: + description: Returns a single pet + operationId: getPetById + parameters: + - description: ID of pet to return + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Pet not found + security: + - api_key: [] + summary: Find pet by ID + tags: + - pet + post: + description: "" + operationId: updatePetWithForm + parameters: + - description: ID of pet that needs to be updated + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/updatePetWithForm_request' + responses: + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + summary: Updates a pet in the store with form data + tags: + - pet + /pet/{petId}/uploadImage: + post: + description: "" + operationId: uploadFile + parameters: + - description: ID of pet to update + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/uploadFile_request' + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: successful operation + security: + - petstore_auth: + - write:pets + - read:pets + summary: uploads an image + tags: + - pet + /store/inventory: + get: + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + "200": + content: + application/json: + schema: + additionalProperties: + format: int32 + type: integer + type: object + description: successful operation + security: + - api_key: [] + summary: Returns pet inventories by status + tags: + - store + /store/order: + post: + description: "" + operationId: placeOrder + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + description: successful operation + "400": + description: Invalid Order + summary: Place an order for a pet + tags: + - store + /store/order/{orderId}: + delete: + description: For valid response try integer IDs with value < 1000. Anything + above 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - description: ID of the order that needs to be deleted + explode: false + in: path + name: orderId + required: true + schema: + type: string + style: simple + responses: + "400": + description: Invalid ID supplied + "404": + description: Order not found + summary: Delete purchase order by ID + tags: + - store + get: + description: For valid response try integer IDs with value <= 5 or > 10. Other + values will generate exceptions + operationId: getOrderById + parameters: + - description: ID of pet that needs to be fetched + explode: false + in: path + name: orderId + required: true + schema: + format: int64 + maximum: 5 + minimum: 1 + type: integer + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Order not found + summary: Find purchase order by ID + tags: + - store + /user: + post: + description: This can only be done by the logged in user. + operationId: createUser + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Create user + tags: + - user + /user/createWithArray: + post: + description: "" + operationId: createUsersWithArrayInput + requestBody: + $ref: '#/components/requestBodies/UserArray' + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Creates list of users with given input array + tags: + - user + /user/createWithList: + post: + description: "" + operationId: createUsersWithListInput + requestBody: + $ref: '#/components/requestBodies/UserArray' + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Creates list of users with given input array + tags: + - user + /user/login: + get: + description: "" + operationId: loginUser + parameters: + - description: The user name for login + explode: true + in: query + name: username + required: true + schema: + pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$" + type: string + style: form + - description: The password for login in clear text + explode: true + in: query + name: password + required: true + schema: + type: string + style: form + responses: + "200": + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + description: successful operation + headers: + Set-Cookie: + description: Cookie authentication key for use with the `api_key` apiKey + authentication. + explode: false + schema: + example: AUTH_KEY=abcde12345; Path=/; HttpOnly + type: string + style: simple + X-Rate-Limit: + description: calls per hour allowed by the user + explode: false + schema: + format: int32 + type: integer + style: simple + X-Expires-After: + description: date in UTC when token expires + explode: false + schema: + format: date-time + type: string + style: simple + "400": + description: Invalid username/password supplied + summary: Logs user into the system + tags: + - user + /user/logout: + get: + description: "" + operationId: logoutUser + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Logs out current logged in user session + tags: + - user + /user/{username}: + delete: + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - description: The name that needs to be deleted + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + responses: + "400": + description: Invalid username supplied + "404": + description: User not found + security: + - api_key: [] + summary: Delete user + tags: + - user + get: + description: "" + operationId: getUserByName + parameters: + - description: The name that needs to be fetched. Use user1 for testing. + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + description: successful operation + "400": + description: Invalid username supplied + "404": + description: User not found + summary: Get user by user name + tags: + - user + put: + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - description: name that need to be deleted + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + responses: + "400": + description: Invalid user supplied + "404": + description: User not found + security: + - api_key: [] + summary: Updated user + tags: + - user + /fake/query_param_default: + get: + description: "" + operationId: fake_query_param_default + parameters: + - description: has default value + explode: true + in: query + name: hasDefault + required: false + schema: + default: Hello World + type: string + style: form + - description: no default value + explode: true + in: query + name: noDefault + required: false + schema: + type: string + style: form + responses: + "400": + description: Invalid username supplied + "404": + description: User not found + summary: test query parameter default value + tags: + - fake +components: + requestBodies: + UserArray: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/User' + type: array + description: List of user object + required: true + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + schemas: + Order: + description: An order for a pets from the pet store + example: + petId: 6 + quantity: 1 + id: 0 + shipDate: 2000-01-23T04:56:07.000+00:00 + complete: false + status: placed + properties: + id: + format: int64 + title: id + type: integer + petId: + format: int64 + title: petId + type: integer + quantity: + format: int32 + title: quantity + type: integer + shipDate: + format: date-time + title: shipDate + type: string + status: + description: Order Status + enum: + - placed + - approved + - delivered + title: status + type: string + complete: + default: false + title: complete + type: boolean + title: Pet Order + type: object + xml: + name: Order + Category: + description: A category for a pet + example: + name: name + id: 6 + properties: + id: + format: int64 + title: id + type: integer + name: + pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$" + title: name + type: string + title: Pet category + type: object + xml: + name: Category + User: + description: A User who is purchasing from the pet store + example: + firstName: firstName + lastName: lastName + password: password + userStatus: 6 + phone: phone + id: 0 + email: email + username: username + properties: + id: + format: int64 + title: id + type: integer + username: + title: username + type: string + firstName: + title: firstName + type: string + lastName: + title: lastName + type: string + email: + title: email + type: string + password: + title: password + type: string + phone: + title: phone + type: string + userStatus: + description: User Status + format: int32 + title: userStatus + type: integer + title: a User + type: object + xml: + name: User + Tag: + description: A tag for a pet + example: + name: name + id: 1 + properties: + id: + format: int64 + title: id + type: integer + name: + title: name + type: string + title: Pet Tag + type: object + xml: + name: Tag + Pet: + description: A pet for sale in the pet store + example: + photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + properties: + id: + format: int64 + title: id + type: integer + category: + $ref: '#/components/schemas/Category' + name: + example: doggie + title: name + type: string + photoUrls: + items: + type: string + title: photoUrls + type: array + xml: + name: photoUrl + wrapped: true + tags: + items: + $ref: '#/components/schemas/Tag' + title: tags + type: array + xml: + name: tag + wrapped: true + status: + deprecated: true + description: pet status in the store + enum: + - available + - pending + - sold + title: status + type: string + required: + - name + - photoUrls + title: a Pet + type: object + xml: + name: Pet + ApiResponse: + description: Describes the result of uploading an image resource + example: + code: 0 + type: type + message: message + properties: + code: + format: int32 + title: code + type: integer + type: + title: type + type: string + message: + title: message + type: string + title: An uploaded response + type: object + updatePetWithForm_request: + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + type: object + uploadFile_request: + properties: + additionalMetadata: + description: Additional data to pass to server + type: string + file: + description: file to upload + format: binary + type: string + type: object + securitySchemes: + petstore_auth: + flows: + implicit: + authorizationUrl: http://petstore.swagger.io/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets + type: oauth2 + api_key: + in: header + name: api_key + type: apiKey diff --git a/generated-code-expected/openapi_server/dto/__init__.py b/generated-code-expected/openapi_server/dto/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/generated-code-expected/openapi_server/dto/api_response.py b/generated-code-expected/openapi_server/dto/api_response.py new file mode 100644 index 0000000..441c3b8 --- /dev/null +++ b/generated-code-expected/openapi_server/dto/api_response.py @@ -0,0 +1,94 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class ApiResponse(BaseModel): + """ + Describes the result of uploading an image resource + """ # noqa: E501 + code: Optional[StrictInt] = None + type: Optional[StrictStr] = None + message: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["code", "type", "message"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of ApiResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of ApiResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "code": obj.get("code"), + "type": obj.get("type"), + "message": obj.get("message") + }) + return _obj + + diff --git a/generated-code-expected/openapi_server/dto/category.py b/generated-code-expected/openapi_server/dto/category.py new file mode 100644 index 0000000..48b689c --- /dev/null +++ b/generated-code-expected/openapi_server/dto/category.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Category(BaseModel): + """ + A category for a pet + """ # noqa: E501 + id: Optional[StrictInt] = None + name: Optional[Annotated[str, Field(strict=True)]] = None + __properties: ClassVar[List[str]] = ["id", "name"] + + @field_validator('name') + def name_validate_regular_expression(cls, value): + """Validates the regular expression""" + if value is None: + return value + + if not re.match(r"^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$", value): + raise ValueError(r"must validate the regular expression /^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$/") + return value + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Category from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Category from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "name": obj.get("name") + }) + return _obj + + diff --git a/generated-code-expected/openapi_server/dto/extra_models.py b/generated-code-expected/openapi_server/dto/extra_models.py new file mode 100644 index 0000000..a3a283f --- /dev/null +++ b/generated-code-expected/openapi_server/dto/extra_models.py @@ -0,0 +1,8 @@ +# coding: utf-8 + +from pydantic import BaseModel + +class TokenModel(BaseModel): + """Defines a token model.""" + + sub: str diff --git a/generated-code-expected/openapi_server/dto/order.py b/generated-code-expected/openapi_server/dto/order.py new file mode 100644 index 0000000..7a5a38c --- /dev/null +++ b/generated-code-expected/openapi_server/dto/order.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Order(BaseModel): + """ + An order for a pets from the pet store + """ # noqa: E501 + id: Optional[StrictInt] = None + pet_id: Optional[StrictInt] = Field(default=None, alias="petId") + quantity: Optional[StrictInt] = None + ship_date: Optional[datetime] = Field(default=None, alias="shipDate") + status: Optional[StrictStr] = Field(default=None, description="Order Status") + complete: Optional[StrictBool] = False + __properties: ClassVar[List[str]] = ["id", "petId", "quantity", "shipDate", "status", "complete"] + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in ('placed', 'approved', 'delivered',): + raise ValueError("must be one of enum values ('placed', 'approved', 'delivered')") + return value + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Order from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Order from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "petId": obj.get("petId"), + "quantity": obj.get("quantity"), + "shipDate": obj.get("shipDate"), + "status": obj.get("status"), + "complete": obj.get("complete") if obj.get("complete") is not None else False + }) + return _obj + + diff --git a/generated-code-expected/openapi_server/dto/pet.py b/generated-code-expected/openapi_server/dto/pet.py new file mode 100644 index 0000000..1273dc2 --- /dev/null +++ b/generated-code-expected/openapi_server/dto/pet.py @@ -0,0 +1,120 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from openapi_server.dto.category import Category +from openapi_server.dto.tag import Tag +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Pet(BaseModel): + """ + A pet for sale in the pet store + """ # noqa: E501 + id: Optional[StrictInt] = None + category: Optional[Category] = None + name: StrictStr + photo_urls: List[StrictStr] = Field(alias="photoUrls") + tags: Optional[List[Tag]] = None + status: Optional[StrictStr] = Field(default=None, description="pet status in the store") + __properties: ClassVar[List[str]] = ["id", "category", "name", "photoUrls", "tags", "status"] + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in ('available', 'pending', 'sold',): + raise ValueError("must be one of enum values ('available', 'pending', 'sold')") + return value + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Pet from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of category + if self.category: + _dict['category'] = self.category.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in tags (list) + _items = [] + if self.tags: + for _item in self.tags: + if _item: + _items.append(_item.to_dict()) + _dict['tags'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Pet from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "category": Category.from_dict(obj.get("category")) if obj.get("category") is not None else None, + "name": obj.get("name"), + "photoUrls": obj.get("photoUrls"), + "tags": [Tag.from_dict(_item) for _item in obj.get("tags")] if obj.get("tags") is not None else None, + "status": obj.get("status") + }) + return _obj diff --git a/generated-code-expected/openapi_server/dto/tag.py b/generated-code-expected/openapi_server/dto/tag.py new file mode 100644 index 0000000..8b21d36 --- /dev/null +++ b/generated-code-expected/openapi_server/dto/tag.py @@ -0,0 +1,92 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Tag(BaseModel): + """ + A tag for a pet + """ # noqa: E501 + id: Optional[StrictInt] = None + name: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["id", "name"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Tag from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Tag from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "name": obj.get("name") + }) + return _obj + + diff --git a/generated-code-expected/openapi_server/dto/user.py b/generated-code-expected/openapi_server/dto/user.py new file mode 100644 index 0000000..cb98a57 --- /dev/null +++ b/generated-code-expected/openapi_server/dto/user.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class User(BaseModel): + """ + A User who is purchasing from the pet store + """ # noqa: E501 + id: Optional[StrictInt] = None + username: Optional[StrictStr] = None + first_name: Optional[StrictStr] = Field(default=None, alias="firstName") + last_name: Optional[StrictStr] = Field(default=None, alias="lastName") + email: Optional[StrictStr] = None + password: Optional[StrictStr] = None + phone: Optional[StrictStr] = None + user_status: Optional[StrictInt] = Field(default=None, description="User Status", alias="userStatus") + __properties: ClassVar[List[str]] = ["id", "username", "firstName", "lastName", "email", "password", "phone", "userStatus"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of User from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of User from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "username": obj.get("username"), + "firstName": obj.get("firstName"), + "lastName": obj.get("lastName"), + "email": obj.get("email"), + "password": obj.get("password"), + "phone": obj.get("phone"), + "userStatus": obj.get("userStatus") + }) + return _obj + + diff --git a/generated-code-expected/openapi_server/impl/__init__.py b/generated-code-expected/openapi_server/impl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/generated-code-expected/openapi_server/main.py b/generated-code-expected/openapi_server/main.py new file mode 100644 index 0000000..e058783 --- /dev/null +++ b/generated-code-expected/openapi_server/main.py @@ -0,0 +1,31 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from fastapi import FastAPI + +from openapi_server.service.fake_api import router as FakeApiRouter +from openapi_server.service.pet_api import router as PetApiRouter +from openapi_server.service.store_api import router as StoreApiRouter +from openapi_server.service.user_api import router as UserApiRouter + +app = FastAPI( + title="OpenAPI Petstore", + description="This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.", + version="1.0.0", +) + +app.include_router(FakeApiRouter) +app.include_router(PetApiRouter) +app.include_router(StoreApiRouter) +app.include_router(UserApiRouter) diff --git a/generated-code-expected/openapi_server/security_api.py b/generated-code-expected/openapi_server/security_api.py new file mode 100644 index 0000000..7aeb8be --- /dev/null +++ b/generated-code-expected/openapi_server/security_api.py @@ -0,0 +1,83 @@ +# coding: utf-8 + +from typing import List + +from fastapi import Depends, Security # noqa: F401 +from fastapi.openapi.models import OAuthFlowImplicit, OAuthFlows # noqa: F401 +from fastapi.security import ( # noqa: F401 + HTTPAuthorizationCredentials, + HTTPBasic, + HTTPBasicCredentials, + HTTPBearer, + OAuth2, + OAuth2AuthorizationCodeBearer, + OAuth2PasswordBearer, + SecurityScopes, +) +from fastapi.security.api_key import APIKeyCookie, APIKeyHeader, APIKeyQuery # noqa: F401 + +from openapi_server.dto.extra_models import TokenModel + +oauth2_implicit = OAuth2( + flows=OAuthFlows( + implicit=OAuthFlowImplicit( + authorizationUrl="http://petstore.swagger.io/api/oauth/dialog", + scopes={ + "write:pets": "modify pets in your account", + "read:pets": "read your pets", + } + ) + ) +) + + +def get_token_petstore_auth( + security_scopes: SecurityScopes, token: str = Depends(oauth2_implicit) +) -> TokenModel: + """ + Validate and decode token. + + :param token Token provided by Authorization header + :type token: str + :return: Decoded token information or None if token is invalid + :rtype: TokenModel | None + """ + + ... + + +def validate_scope_petstore_auth( + required_scopes: SecurityScopes, token_scopes: List[str] +) -> bool: + """ + Validate required scopes are included in token scope + + :param required_scopes Required scope to access called API + :type required_scopes: List[str] + :param token_scopes Scope present in token + :type token_scopes: List[str] + :return: True if access to called API is allowed + :rtype: bool + """ + + return False + + +def get_token_api_key( + token_api_key_header: str = Security( + APIKeyHeader(name="api_key", auto_error=False) + ), +) -> TokenModel: + """ + Check and retrieve authentication information from api_key. + + :param token_api_key_header API key provided by Authorization[api_key] header + + + :type token_api_key_header: str + :return: Information attached to provided api_key or None if api_key is invalid or does not allow access to called API + :rtype: TokenModel | None + """ + + ... + diff --git a/generated-code-expected/openapi_server/service/__init__.py b/generated-code-expected/openapi_server/service/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/generated-code-expected/openapi_server/service/fake_api.py b/generated-code-expected/openapi_server/service/fake_api.py new file mode 100644 index 0000000..a36ca27 --- /dev/null +++ b/generated-code-expected/openapi_server/service/fake_api.py @@ -0,0 +1,55 @@ +# coding: utf-8 + +from typing import Dict, List # noqa: F401 +import importlib +import pkgutil + +from openapi_server.service.fake_api_base import BaseFakeApi +import openapi_server.impl + +from fastapi import ( # noqa: F401 + APIRouter, + Body, + Cookie, + Depends, + Form, + Header, + HTTPException, + Path, + Query, + Response, + Security, + status, +) + +from openapi_server.dto.extra_models import TokenModel # noqa: F401 +from pydantic import Field, StrictStr +from typing import Any, Optional +from typing_extensions import Annotated + + +router = APIRouter() + +ns_pkg = openapi_server.impl +for _, name, _ in pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + "."): + importlib.import_module(name) + + +@router.get( + "/fake/query_param_default", + responses={ + 400: {"description": "Invalid username supplied"}, + 404: {"description": "User not found"}, + }, + tags=["fake"], + summary="test query parameter default value", + response_model_by_alias=True, +) +async def fake_query_param_default( + has_default: Annotated[Optional[StrictStr], Field(description="has default value")] = Query('Hello World', description="has default value", alias="hasDefault"), + no_default: Annotated[Optional[StrictStr], Field(description="no default value")] = Query(None, description="no default value", alias="noDefault"), +) -> None: + """""" + if not BaseFakeApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseFakeApi.subclasses[0]().fake_query_param_default(has_default, no_default) diff --git a/generated-code-expected/openapi_server/service/fake_api_base.py b/generated-code-expected/openapi_server/service/fake_api_base.py new file mode 100644 index 0000000..1c71537 --- /dev/null +++ b/generated-code-expected/openapi_server/service/fake_api_base.py @@ -0,0 +1,22 @@ +# coding: utf-8 + +from typing import ClassVar, Dict, List, Tuple # noqa: F401 + +from pydantic import Field, StrictStr +from typing import Any, Optional +from typing_extensions import Annotated + + +class BaseFakeApi: + subclasses: ClassVar[Tuple] = () + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + BaseFakeApi.subclasses = BaseFakeApi.subclasses + (cls,) + async def fake_query_param_default( + self, + has_default: Annotated[Optional[StrictStr], Field(description="has default value")], + no_default: Annotated[Optional[StrictStr], Field(description="no default value")], + ) -> None: + """""" + ... diff --git a/generated-code-expected/openapi_server/service/pet_api.py b/generated-code-expected/openapi_server/service/pet_api.py new file mode 100644 index 0000000..a6bb3c3 --- /dev/null +++ b/generated-code-expected/openapi_server/service/pet_api.py @@ -0,0 +1,218 @@ +# coding: utf-8 + +from typing import Dict, List # noqa: F401 +import importlib +import pkgutil + +from openapi_server.service.pet_api_base import BasePetApi +import openapi_server.impl + +from fastapi import ( # noqa: F401 + APIRouter, + Body, + Cookie, + Depends, + Form, + Header, + HTTPException, + Path, + Query, + Response, + Security, + status, +) + +from openapi_server.dto.extra_models import TokenModel # noqa: F401 +from pydantic import Field, StrictBytes, StrictInt, StrictStr, field_validator +from typing import Any, List, Optional, Tuple, Union +from typing_extensions import Annotated +from openapi_server.dto.api_response import ApiResponse +from openapi_server.dto.pet import Pet +from openapi_server.security_api import get_token_petstore_auth, get_token_api_key + +router = APIRouter() + +ns_pkg = openapi_server.impl +for _, name, _ in pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + "."): + importlib.import_module(name) + + +@router.post( + "/pet", + responses={ + 200: {"model": Pet, "description": "successful operation"}, + 405: {"description": "Invalid input"}, + }, + tags=["pet"], + summary="Add a new pet to the store", + response_model_by_alias=True, +) +async def add_pet( + pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")] = Body(None, description="Pet object that needs to be added to the store"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> Pet: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().add_pet(pet) + + +@router.delete( + "/pet/{petId}", + responses={ + 400: {"description": "Invalid pet value"}, + }, + tags=["pet"], + summary="Deletes a pet", + response_model_by_alias=True, +) +async def delete_pet( + petId: Annotated[StrictInt, Field(description="Pet id to delete")] = Path(..., description="Pet id to delete"), + api_key: Optional[StrictStr] = Header(None, description=""), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> None: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().delete_pet(petId, api_key) + + +@router.get( + "/pet/findByStatus", + responses={ + 200: {"model": List[Pet], "description": "successful operation"}, + 400: {"description": "Invalid status value"}, + }, + tags=["pet"], + summary="Finds Pets by status", + response_model_by_alias=True, +) +async def find_pets_by_status( + status: Annotated[List[StrictStr], Field(description="Status values that need to be considered for filter")] = Query(None, description="Status values that need to be considered for filter", alias="status"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["read:pets"] + ), +) -> List[Pet]: + """Multiple status values can be provided with comma separated strings""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().find_pets_by_status(status) + + +@router.get( + "/pet/findByTags", + responses={ + 200: {"model": List[Pet], "description": "successful operation"}, + 400: {"description": "Invalid tag value"}, + }, + tags=["pet"], + summary="Finds Pets by tags", + response_model_by_alias=True, +) +async def find_pets_by_tags( + tags: Annotated[List[StrictStr], Field(description="Tags to filter by")] = Query(None, description="Tags to filter by", alias="tags"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["read:pets"] + ), +) -> List[Pet]: + """Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().find_pets_by_tags(tags) + + +@router.get( + "/pet/{petId}", + responses={ + 200: {"model": Pet, "description": "successful operation"}, + 400: {"description": "Invalid ID supplied"}, + 404: {"description": "Pet not found"}, + }, + tags=["pet"], + summary="Find pet by ID", + response_model_by_alias=True, +) +async def get_pet_by_id( + petId: Annotated[StrictInt, Field(description="ID of pet to return")] = Path(..., description="ID of pet to return"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> Pet: + """Returns a single pet""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().get_pet_by_id(petId) + + +@router.put( + "/pet", + responses={ + 200: {"model": Pet, "description": "successful operation"}, + 400: {"description": "Invalid ID supplied"}, + 404: {"description": "Pet not found"}, + 405: {"description": "Validation exception"}, + }, + tags=["pet"], + summary="Update an existing pet", + response_model_by_alias=True, +) +async def update_pet( + pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")] = Body(None, description="Pet object that needs to be added to the store"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> Pet: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().update_pet(pet) + + +@router.post( + "/pet/{petId}", + responses={ + 405: {"description": "Invalid input"}, + }, + tags=["pet"], + summary="Updates a pet in the store with form data", + response_model_by_alias=True, +) +async def update_pet_with_form( + petId: Annotated[StrictInt, Field(description="ID of pet that needs to be updated")] = Path(..., description="ID of pet that needs to be updated"), + name: Annotated[Optional[StrictStr], Field(description="Updated name of the pet")] = Form(None, description="Updated name of the pet"), + status: Annotated[Optional[StrictStr], Field(description="Updated status of the pet")] = Form(None, description="Updated status of the pet"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> None: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().update_pet_with_form(petId, name, status) + + +@router.post( + "/pet/{petId}/uploadImage", + responses={ + 200: {"model": ApiResponse, "description": "successful operation"}, + }, + tags=["pet"], + summary="uploads an image", + response_model_by_alias=True, +) +async def upload_file( + petId: Annotated[StrictInt, Field(description="ID of pet to update")] = Path(..., description="ID of pet to update"), + additional_metadata: Annotated[Optional[StrictStr], Field(description="Additional data to pass to server")] = Form(None, description="Additional data to pass to server"), + file: Annotated[Optional[Union[StrictBytes, StrictStr, Tuple[StrictStr, StrictBytes]]], Field(description="file to upload")] = Form(None, description="file to upload"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> ApiResponse: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().upload_file(petId, additional_metadata, file) diff --git a/generated-code-expected/openapi_server/service/pet_api_base.py b/generated-code-expected/openapi_server/service/pet_api_base.py new file mode 100644 index 0000000..de1e743 --- /dev/null +++ b/generated-code-expected/openapi_server/service/pet_api_base.py @@ -0,0 +1,84 @@ +# coding: utf-8 + +from typing import ClassVar, Dict, List, Tuple # noqa: F401 + +from pydantic import Field, StrictBytes, StrictInt, StrictStr, field_validator +from typing import Any, List, Optional, Tuple, Union +from typing_extensions import Annotated +from openapi_server.dto.api_response import ApiResponse +from openapi_server.dto.pet import Pet +from openapi_server.security_api import get_token_petstore_auth, get_token_api_key + +class BasePetApi: + subclasses: ClassVar[Tuple] = () + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + BasePetApi.subclasses = BasePetApi.subclasses + (cls,) + async def add_pet( + self, + pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")], + ) -> Pet: + """""" + ... + + + async def delete_pet( + self, + petId: Annotated[StrictInt, Field(description="Pet id to delete")], + api_key: Optional[StrictStr], + ) -> None: + """""" + ... + + + async def find_pets_by_status( + self, + status: Annotated[List[StrictStr], Field(description="Status values that need to be considered for filter")], + ) -> List[Pet]: + """Multiple status values can be provided with comma separated strings""" + ... + + + async def find_pets_by_tags( + self, + tags: Annotated[List[StrictStr], Field(description="Tags to filter by")], + ) -> List[Pet]: + """Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.""" + ... + + + async def get_pet_by_id( + self, + petId: Annotated[StrictInt, Field(description="ID of pet to return")], + ) -> Pet: + """Returns a single pet""" + ... + + + async def update_pet( + self, + pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")], + ) -> Pet: + """""" + ... + + + async def update_pet_with_form( + self, + petId: Annotated[StrictInt, Field(description="ID of pet that needs to be updated")], + name: Annotated[Optional[StrictStr], Field(description="Updated name of the pet")], + status: Annotated[Optional[StrictStr], Field(description="Updated status of the pet")], + ) -> None: + """""" + ... + + + async def upload_file( + self, + petId: Annotated[StrictInt, Field(description="ID of pet to update")], + additional_metadata: Annotated[Optional[StrictStr], Field(description="Additional data to pass to server")], + file: Annotated[Optional[Union[StrictBytes, StrictStr, Tuple[StrictStr, StrictBytes]]], Field(description="file to upload")], + ) -> ApiResponse: + """""" + ... diff --git a/generated-code-expected/openapi_server/service/store_api.py b/generated-code-expected/openapi_server/service/store_api.py new file mode 100644 index 0000000..515f590 --- /dev/null +++ b/generated-code-expected/openapi_server/service/store_api.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +from typing import Dict, List # noqa: F401 +import importlib +import pkgutil + +from openapi_server.service.store_api_base import BaseStoreApi +import openapi_server.impl + +from fastapi import ( # noqa: F401 + APIRouter, + Body, + Cookie, + Depends, + Form, + Header, + HTTPException, + Path, + Query, + Response, + Security, + status, +) + +from openapi_server.dto.extra_models import TokenModel # noqa: F401 +from pydantic import Field, StrictInt, StrictStr +from typing import Any, Dict +from typing_extensions import Annotated +from openapi_server.dto.order import Order +from openapi_server.security_api import get_token_api_key + +router = APIRouter() + +ns_pkg = openapi_server.impl +for _, name, _ in pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + "."): + importlib.import_module(name) + + +@router.delete( + "/store/order/{orderId}", + responses={ + 400: {"description": "Invalid ID supplied"}, + 404: {"description": "Order not found"}, + }, + tags=["store"], + summary="Delete purchase order by ID", + response_model_by_alias=True, +) +async def delete_order( + orderId: Annotated[StrictStr, Field(description="ID of the order that needs to be deleted")] = Path(..., description="ID of the order that needs to be deleted"), +) -> None: + """For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors""" + if not BaseStoreApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseStoreApi.subclasses[0]().delete_order(orderId) + + +@router.get( + "/store/inventory", + responses={ + 200: {"model": Dict[str, int], "description": "successful operation"}, + }, + tags=["store"], + summary="Returns pet inventories by status", + response_model_by_alias=True, +) +async def get_inventory( + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> Dict[str, int]: + """Returns a map of status codes to quantities""" + if not BaseStoreApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseStoreApi.subclasses[0]().get_inventory() + + +@router.get( + "/store/order/{orderId}", + responses={ + 200: {"model": Order, "description": "successful operation"}, + 400: {"description": "Invalid ID supplied"}, + 404: {"description": "Order not found"}, + }, + tags=["store"], + summary="Find purchase order by ID", + response_model_by_alias=True, +) +async def get_order_by_id( + orderId: Annotated[int, Field(le=5, strict=True, ge=1, description="ID of pet that needs to be fetched")] = Path(..., description="ID of pet that needs to be fetched", ge=1, le=5), +) -> Order: + """For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions""" + if not BaseStoreApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseStoreApi.subclasses[0]().get_order_by_id(orderId) + + +@router.post( + "/store/order", + responses={ + 200: {"model": Order, "description": "successful operation"}, + 400: {"description": "Invalid Order"}, + }, + tags=["store"], + summary="Place an order for a pet", + response_model_by_alias=True, +) +async def place_order( + order: Annotated[Order, Field(description="order placed for purchasing the pet")] = Body(None, description="order placed for purchasing the pet"), +) -> Order: + """""" + if not BaseStoreApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseStoreApi.subclasses[0]().place_order(order) diff --git a/generated-code-expected/openapi_server/service/store_api_base.py b/generated-code-expected/openapi_server/service/store_api_base.py new file mode 100644 index 0000000..9c7311c --- /dev/null +++ b/generated-code-expected/openapi_server/service/store_api_base.py @@ -0,0 +1,45 @@ +# coding: utf-8 + +from typing import ClassVar, Dict, List, Tuple # noqa: F401 + +from pydantic import Field, StrictInt, StrictStr +from typing import Any, Dict +from typing_extensions import Annotated +from openapi_server.dto.order import Order +from openapi_server.security_api import get_token_api_key + +class BaseStoreApi: + subclasses: ClassVar[Tuple] = () + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + BaseStoreApi.subclasses = BaseStoreApi.subclasses + (cls,) + async def delete_order( + self, + orderId: Annotated[StrictStr, Field(description="ID of the order that needs to be deleted")], + ) -> None: + """For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors""" + ... + + + async def get_inventory( + self, + ) -> Dict[str, int]: + """Returns a map of status codes to quantities""" + ... + + + async def get_order_by_id( + self, + orderId: Annotated[int, Field(le=5, strict=True, ge=1, description="ID of pet that needs to be fetched")], + ) -> Order: + """For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions""" + ... + + + async def place_order( + self, + order: Annotated[Order, Field(description="order placed for purchasing the pet")], + ) -> Order: + """""" + ... diff --git a/generated-code-expected/openapi_server/service/user_api.py b/generated-code-expected/openapi_server/service/user_api.py new file mode 100644 index 0000000..7ead272 --- /dev/null +++ b/generated-code-expected/openapi_server/service/user_api.py @@ -0,0 +1,204 @@ +# coding: utf-8 + +from typing import Dict, List # noqa: F401 +import importlib +import pkgutil + +from openapi_server.service.user_api_base import BaseUserApi +import openapi_server.impl + +from fastapi import ( # noqa: F401 + APIRouter, + Body, + Cookie, + Depends, + Form, + Header, + HTTPException, + Path, + Query, + Response, + Security, + status, +) + +from openapi_server.dto.extra_models import TokenModel # noqa: F401 +from pydantic import Field, StrictStr, field_validator +from typing import Any, List +from typing_extensions import Annotated +from openapi_server.dto.user import User +from openapi_server.security_api import get_token_api_key + +router = APIRouter() + +ns_pkg = openapi_server.impl +for _, name, _ in pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + "."): + importlib.import_module(name) + + +@router.post( + "/user", + responses={ + 200: {"description": "successful operation"}, + }, + tags=["user"], + summary="Create user", + response_model_by_alias=True, +) +async def create_user( + user: Annotated[User, Field(description="Created user object")] = Body(None, description="Created user object"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """This can only be done by the logged in user.""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().create_user(user) + + +@router.post( + "/user/createWithArray", + responses={ + 200: {"description": "successful operation"}, + }, + tags=["user"], + summary="Creates list of users with given input array", + response_model_by_alias=True, +) +async def create_users_with_array_input( + user: Annotated[List[User], Field(description="List of user object")] = Body(None, description="List of user object"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().create_users_with_array_input(user) + + +@router.post( + "/user/createWithList", + responses={ + 200: {"description": "successful operation"}, + }, + tags=["user"], + summary="Creates list of users with given input array", + response_model_by_alias=True, +) +async def create_users_with_list_input( + user: Annotated[List[User], Field(description="List of user object")] = Body(None, description="List of user object"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().create_users_with_list_input(user) + + +@router.delete( + "/user/{username}", + responses={ + 400: {"description": "Invalid username supplied"}, + 404: {"description": "User not found"}, + }, + tags=["user"], + summary="Delete user", + response_model_by_alias=True, +) +async def delete_user( + username: Annotated[StrictStr, Field(description="The name that needs to be deleted")] = Path(..., description="The name that needs to be deleted"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """This can only be done by the logged in user.""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().delete_user(username) + + +@router.get( + "/user/{username}", + responses={ + 200: {"model": User, "description": "successful operation"}, + 400: {"description": "Invalid username supplied"}, + 404: {"description": "User not found"}, + }, + tags=["user"], + summary="Get user by user name", + response_model_by_alias=True, +) +async def get_user_by_name( + username: Annotated[StrictStr, Field(description="The name that needs to be fetched. Use user1 for testing.")] = Path(..., description="The name that needs to be fetched. Use user1 for testing."), +) -> User: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().get_user_by_name(username) + + +@router.get( + "/user/login", + responses={ + 200: {"model": str, "description": "successful operation"}, + 400: {"description": "Invalid username/password supplied"}, + }, + tags=["user"], + summary="Logs user into the system", + response_model_by_alias=True, +) +async def login_user( + username: Annotated[str, Field(strict=True, description="The user name for login")] = Query(None, description="The user name for login", alias="username", regex=r"/^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$/"), + password: Annotated[StrictStr, Field(description="The password for login in clear text")] = Query(None, description="The password for login in clear text", alias="password"), +) -> str: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().login_user(username, password) + + +@router.get( + "/user/logout", + responses={ + 200: {"description": "successful operation"}, + }, + tags=["user"], + summary="Logs out current logged in user session", + response_model_by_alias=True, +) +async def logout_user( + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().logout_user() + + +@router.put( + "/user/{username}", + responses={ + 400: {"description": "Invalid user supplied"}, + 404: {"description": "User not found"}, + }, + tags=["user"], + summary="Updated user", + response_model_by_alias=True, +) +async def update_user( + username: Annotated[StrictStr, Field(description="name that need to be deleted")] = Path(..., description="name that need to be deleted"), + user: Annotated[User, Field(description="Updated user object")] = Body(None, description="Updated user object"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """This can only be done by the logged in user.""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().update_user(username, user) diff --git a/generated-code-expected/openapi_server/service/user_api_base.py b/generated-code-expected/openapi_server/service/user_api_base.py new file mode 100644 index 0000000..230f714 --- /dev/null +++ b/generated-code-expected/openapi_server/service/user_api_base.py @@ -0,0 +1,79 @@ +# coding: utf-8 + +from typing import ClassVar, Dict, List, Tuple # noqa: F401 + +from pydantic import Field, StrictStr, field_validator +from typing import Any, List +from typing_extensions import Annotated +from openapi_server.dto.user import User +from openapi_server.security_api import get_token_api_key + +class BaseUserApi: + subclasses: ClassVar[Tuple] = () + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + BaseUserApi.subclasses = BaseUserApi.subclasses + (cls,) + async def create_user( + self, + user: Annotated[User, Field(description="Created user object")], + ) -> None: + """This can only be done by the logged in user.""" + ... + + + async def create_users_with_array_input( + self, + user: Annotated[List[User], Field(description="List of user object")], + ) -> None: + """""" + ... + + + async def create_users_with_list_input( + self, + user: Annotated[List[User], Field(description="List of user object")], + ) -> None: + """""" + ... + + + async def delete_user( + self, + username: Annotated[StrictStr, Field(description="The name that needs to be deleted")], + ) -> None: + """This can only be done by the logged in user.""" + ... + + + async def get_user_by_name( + self, + username: Annotated[StrictStr, Field(description="The name that needs to be fetched. Use user1 for testing.")], + ) -> User: + """""" + ... + + + async def login_user( + self, + username: Annotated[str, Field(strict=True, description="The user name for login")], + password: Annotated[StrictStr, Field(description="The password for login in clear text")], + ) -> str: + """""" + ... + + + async def logout_user( + self, + ) -> None: + """""" + ... + + + async def update_user( + self, + username: Annotated[StrictStr, Field(description="name that need to be deleted")], + user: Annotated[User, Field(description="Updated user object")], + ) -> None: + """This can only be done by the logged in user.""" + ... diff --git a/generated-code-expected/pyproject.toml b/generated-code-expected/pyproject.toml new file mode 100644 index 0000000..c2826df --- /dev/null +++ b/generated-code-expected/pyproject.toml @@ -0,0 +1,30 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.black] +line-length = 88 +exclude = ''' +( + /( + \.eggs # exclude a few common directories in the + | \.git # root of the project + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + )/ +) +''' + +[tool.isort] +profile = "black" +skip = [ + '.eggs', '.git', '.hg', '.mypy_cache', '.nox', '.pants.d', '.tox', + '.venv', '_build', 'buck-out', 'build', 'dist', 'node_modules', 'venv', +] +skip_gitignore = true diff --git a/generated-code-expected/requirements.txt b/generated-code-expected/requirements.txt new file mode 100644 index 0000000..a32429e --- /dev/null +++ b/generated-code-expected/requirements.txt @@ -0,0 +1,36 @@ +aiofiles==23.1.0 +aniso8601==7.0.0 +async-exit-stack==1.0.1 +async-generator==1.10 +certifi==2024.7.4 +chardet==4.0.0 +click==7.1.2 +dnspython==2.6.1 +email-validator==2.0.0 +fastapi==0.115.2 +graphene==2.1.8 +graphql-core==2.3.2 +graphql-relay==2.0.1 +h11==0.12.0 +httptools>=0.3.0,<0.7.0 +httpx==0.24.1 +idna==3.7 +itsdangerous==1.1.0 +Jinja2==3.1.4 +MarkupSafe==2.0.1 +orjson==3.9.15 +promise==2.3 +pydantic>=2 +python-dotenv==0.17.1 +python-multipart==0.0.18 +PyYAML>=5.4.1,<6.1.0 +requests==2.32.0 +Rx==1.6.1 +starlette==0.40.0 +typing-extensions==4.8.0 +ujson==4.0.2 +urllib3==1.26.19 +uvicorn==0.13.4 +uvloop==0.19.0 +watchgod==0.7 +websockets==10.0 diff --git a/generated-code-expected/setup.cfg b/generated-code-expected/setup.cfg new file mode 100644 index 0000000..2c484a1 --- /dev/null +++ b/generated-code-expected/setup.cfg @@ -0,0 +1,20 @@ +[metadata] +name = openapi_server +version = 1.0.0 +description = This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +long_description = file: README.md +keywords = OpenAPI OpenAPI Petstore +python_requires = >= 3.7.* +classifiers = + Operating System :: OS Independent + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.7 + +[options] +install_requires = fastapi[all] +setup_requires = setuptools +package_dir = = +packages = find_namespace: + +[options.packages.find] +where = diff --git a/generated-code-expected/tests/conftest.py b/generated-code-expected/tests/conftest.py new file mode 100644 index 0000000..cbde552 --- /dev/null +++ b/generated-code-expected/tests/conftest.py @@ -0,0 +1,17 @@ +import pytest +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from openapi_server.main import app as application + + +@pytest.fixture +def app() -> FastAPI: + application.dependency_overrides = {} + + return application + + +@pytest.fixture +def client(app) -> TestClient: + return TestClient(app) diff --git a/generated-code-expected/tests/test_fake_api.py b/generated-code-expected/tests/test_fake_api.py new file mode 100644 index 0000000..4f1fcf3 --- /dev/null +++ b/generated-code-expected/tests/test_fake_api.py @@ -0,0 +1,29 @@ +# coding: utf-8 + +from fastapi.testclient import TestClient + + +from pydantic import Field, StrictStr # noqa: F401 +from typing import Any, Optional # noqa: F401 +from typing_extensions import Annotated # noqa: F401 + + +def test_fake_query_param_default(client: TestClient): + """Test case for fake_query_param_default + + test query parameter default value + """ + params = [("has_default", 'Hello World'), ("no_default", 'no_default_example')] + headers = { + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/fake/query_param_default", + # headers=headers, + # params=params, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + diff --git a/generated-code-expected/tests/test_pet_api.py b/generated-code-expected/tests/test_pet_api.py new file mode 100644 index 0000000..5b2ce40 --- /dev/null +++ b/generated-code-expected/tests/test_pet_api.py @@ -0,0 +1,188 @@ +# coding: utf-8 + +from fastapi.testclient import TestClient + + +from pydantic import Field, StrictBytes, StrictInt, StrictStr, field_validator # noqa: F401 +from typing import Any, List, Optional, Tuple, Union # noqa: F401 +from typing_extensions import Annotated # noqa: F401 +from openapi_server.models.api_response import ApiResponse # noqa: F401 +from openapi_server.models.pet import Pet # noqa: F401 + + +def test_add_pet(client: TestClient): + """Test case for add_pet + + Add a new pet to the store + """ + pet = {"photo_urls":["photoUrls","photoUrls"],"name":"doggie","id":0,"category":{"name":"name","id":6},"tags":[{"name":"name","id":1},{"name":"name","id":1}],"status":"available"} + + headers = { + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/pet", + # headers=headers, + # json=pet, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_delete_pet(client: TestClient): + """Test case for delete_pet + + Deletes a pet + """ + + headers = { + "api_key": 'api_key_example', + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "DELETE", + # "/pet/{petId}".format(petId=56), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_find_pets_by_status(client: TestClient): + """Test case for find_pets_by_status + + Finds Pets by status + """ + params = [("status", ['status_example'])] + headers = { + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/pet/findByStatus", + # headers=headers, + # params=params, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_find_pets_by_tags(client: TestClient): + """Test case for find_pets_by_tags + + Finds Pets by tags + """ + params = [("tags", ['tags_example'])] + headers = { + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/pet/findByTags", + # headers=headers, + # params=params, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_get_pet_by_id(client: TestClient): + """Test case for get_pet_by_id + + Find pet by ID + """ + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/pet/{petId}".format(petId=56), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_update_pet(client: TestClient): + """Test case for update_pet + + Update an existing pet + """ + pet = {"photo_urls":["photoUrls","photoUrls"],"name":"doggie","id":0,"category":{"name":"name","id":6},"tags":[{"name":"name","id":1},{"name":"name","id":1}],"status":"available"} + + headers = { + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "PUT", + # "/pet", + # headers=headers, + # json=pet, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_update_pet_with_form(client: TestClient): + """Test case for update_pet_with_form + + Updates a pet in the store with form data + """ + + headers = { + "Authorization": "Bearer special-key", + } + data = { + "name": 'name_example', + "status": 'status_example' + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/pet/{petId}".format(petId=56), + # headers=headers, + # data=data, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_upload_file(client: TestClient): + """Test case for upload_file + + uploads an image + """ + + headers = { + "Authorization": "Bearer special-key", + } + data = { + "additional_metadata": 'additional_metadata_example', + "file": '/path/to/file' + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/pet/{petId}/uploadImage".format(petId=56), + # headers=headers, + # data=data, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + diff --git a/generated-code-expected/tests/test_store_api.py b/generated-code-expected/tests/test_store_api.py new file mode 100644 index 0000000..05bc4ae --- /dev/null +++ b/generated-code-expected/tests/test_store_api.py @@ -0,0 +1,89 @@ +# coding: utf-8 + +from fastapi.testclient import TestClient + + +from pydantic import Field, StrictInt, StrictStr # noqa: F401 +from typing import Any, Dict # noqa: F401 +from typing_extensions import Annotated # noqa: F401 +from openapi_server.models.order import Order # noqa: F401 + + +def test_delete_order(client: TestClient): + """Test case for delete_order + + Delete purchase order by ID + """ + + headers = { + } + # uncomment below to make a request + #response = client.request( + # "DELETE", + # "/store/order/{orderId}".format(orderId='order_id_example'), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_get_inventory(client: TestClient): + """Test case for get_inventory + + Returns pet inventories by status + """ + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/store/inventory", + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_get_order_by_id(client: TestClient): + """Test case for get_order_by_id + + Find purchase order by ID + """ + + headers = { + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/store/order/{orderId}".format(orderId=56), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_place_order(client: TestClient): + """Test case for place_order + + Place an order for a pet + """ + order = {"pet_id":6,"quantity":1,"id":0,"ship_date":"2000-01-23T04:56:07.000+00:00","complete":0,"status":"placed"} + + headers = { + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/store/order", + # headers=headers, + # json=order, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + diff --git a/generated-code-expected/tests/test_user_api.py b/generated-code-expected/tests/test_user_api.py new file mode 100644 index 0000000..532f04c --- /dev/null +++ b/generated-code-expected/tests/test_user_api.py @@ -0,0 +1,177 @@ +# coding: utf-8 + +from fastapi.testclient import TestClient + + +from pydantic import Field, StrictStr, field_validator # noqa: F401 +from typing import Any, List # noqa: F401 +from typing_extensions import Annotated # noqa: F401 +from openapi_server.models.user import User # noqa: F401 + + +def test_create_user(client: TestClient): + """Test case for create_user + + Create user + """ + user = {"first_name":"firstName","last_name":"lastName","password":"password","user_status":6,"phone":"phone","id":0,"email":"email","username":"username"} + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/user", + # headers=headers, + # json=user, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_create_users_with_array_input(client: TestClient): + """Test case for create_users_with_array_input + + Creates list of users with given input array + """ + user = [{"first_name":"firstName","last_name":"lastName","password":"password","user_status":6,"phone":"phone","id":0,"email":"email","username":"username"}] + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/user/createWithArray", + # headers=headers, + # json=user, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_create_users_with_list_input(client: TestClient): + """Test case for create_users_with_list_input + + Creates list of users with given input array + """ + user = [{"first_name":"firstName","last_name":"lastName","password":"password","user_status":6,"phone":"phone","id":0,"email":"email","username":"username"}] + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/user/createWithList", + # headers=headers, + # json=user, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_delete_user(client: TestClient): + """Test case for delete_user + + Delete user + """ + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "DELETE", + # "/user/{username}".format(username='username_example'), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_get_user_by_name(client: TestClient): + """Test case for get_user_by_name + + Get user by user name + """ + + headers = { + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/user/{username}".format(username='username_example'), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_login_user(client: TestClient): + """Test case for login_user + + Logs user into the system + """ + params = [("username", 'username_example'), ("password", 'password_example')] + headers = { + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/user/login", + # headers=headers, + # params=params, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_logout_user(client: TestClient): + """Test case for logout_user + + Logs out current logged in user session + """ + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/user/logout", + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_update_user(client: TestClient): + """Test case for update_user + + Updated user + """ + user = {"first_name":"firstName","last_name":"lastName","password":"password","user_status":6,"phone":"phone","id":0,"email":"email","username":"username"} + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "PUT", + # "/user/{username}".format(username='username_example'), + # headers=headers, + # json=user, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + diff --git a/generated-code/.flake8 b/generated-code/.flake8 new file mode 100644 index 0000000..9e008c5 --- /dev/null +++ b/generated-code/.flake8 @@ -0,0 +1,3 @@ +[flake8] +max-line-length = 88 +exclude = .git,__pycache__,__init__.py,.mypy_cache,.pytest_cache,.venv diff --git a/generated-code/.gitignore b/generated-code/.gitignore new file mode 100644 index 0000000..a81c8ee --- /dev/null +++ b/generated-code/.gitignore @@ -0,0 +1,138 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/generated-code/.openapi-generator-ignore b/generated-code/.openapi-generator-ignore new file mode 100644 index 0000000..7484ee5 --- /dev/null +++ b/generated-code/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/generated-code/.openapi-generator/FILES b/generated-code/.openapi-generator/FILES new file mode 100644 index 0000000..bf45410 --- /dev/null +++ b/generated-code/.openapi-generator/FILES @@ -0,0 +1,35 @@ +.flake8 +.gitignore +.openapi-generator-ignore +Dockerfile +README.md +docker-compose.yaml +openapi.yaml +openapi_server/dto/__init__.py +openapi_server/dto/api_response.py +openapi_server/dto/category.py +openapi_server/dto/extra_models.py +openapi_server/dto/order.py +openapi_server/dto/pet.py +openapi_server/dto/tag.py +openapi_server/dto/user.py +openapi_server/impl/__init__.py +openapi_server/main.py +openapi_server/security_api.py +openapi_server/service/__init__.py +openapi_server/service/fake_api.py +openapi_server/service/fake_api_base.py +openapi_server/service/pet_api.py +openapi_server/service/pet_api_base.py +openapi_server/service/store_api.py +openapi_server/service/store_api_base.py +openapi_server/service/user_api.py +openapi_server/service/user_api_base.py +pyproject.toml +requirements.txt +setup.cfg +tests/conftest.py +tests/test_fake_api.py +tests/test_pet_api.py +tests/test_store_api.py +tests/test_user_api.py diff --git a/generated-code/.openapi-generator/VERSION b/generated-code/.openapi-generator/VERSION new file mode 100644 index 0000000..5f84a81 --- /dev/null +++ b/generated-code/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.12.0 diff --git a/generated-code/Dockerfile b/generated-code/Dockerfile new file mode 100644 index 0000000..b66458e --- /dev/null +++ b/generated-code/Dockerfile @@ -0,0 +1,30 @@ +FROM python:3.7 AS builder + +WORKDIR /usr/src/app + +RUN python3 -m venv /venv +ENV PATH="/venv/bin:$PATH" + +RUN pip install --upgrade pip + +COPY . . +RUN pip install --no-cache-dir . + + +FROM python:3.7 AS test_runner +WORKDIR /tmp +COPY --from=builder /venv /venv +COPY --from=builder /usr/src/app/tests tests +ENV PATH=/venv/bin:$PATH + +# install test dependencies +RUN pip install pytest + +# run tests +RUN pytest tests + + +FROM python:3.7 AS service +WORKDIR /root/app/site-packages +COPY --from=test_runner /venv /venv +ENV PATH=/venv/bin:$PATH diff --git a/generated-code/README.md b/generated-code/README.md new file mode 100644 index 0000000..763dc39 --- /dev/null +++ b/generated-code/README.md @@ -0,0 +1,39 @@ +# OpenAPI generated FastAPI server + +This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: + +- API version: 1.0.0 +- Generator version: 7.12.0 +- Build package: org.openapitools.codegen.languages.PythonFastAPIServerCodegen + +## Requirements. + +Python >= 3.7 + +## Installation & Usage + +To run the server, please execute the following from the root directory: + +```bash +pip3 install -r requirements.txt +PYTHONPATH=src uvicorn openapi_server.main:app --host 0.0.0.0 --port 8080 +``` + +and open your browser at `http://localhost:8080/docs/` to see the docs. + +## Running with Docker + +To run the server on a Docker container, please execute the following from the root directory: + +```bash +docker-compose up --build +``` + +## Tests + +To run the tests: + +```bash +pip3 install pytest +PYTHONPATH=src pytest tests +``` diff --git a/generated-code/docker-compose.yaml b/generated-code/docker-compose.yaml new file mode 100644 index 0000000..638e4e0 --- /dev/null +++ b/generated-code/docker-compose.yaml @@ -0,0 +1,9 @@ +version: '3.6' +services: + service: + build: + context: . + target: service + ports: + - "8080:8080" + command: uvicorn openapi_server.main:app --host 0.0.0.0 --port 8080 diff --git a/generated-code/openapi.yaml b/generated-code/openapi.yaml new file mode 100644 index 0000000..1fe20cb --- /dev/null +++ b/generated-code/openapi.yaml @@ -0,0 +1,867 @@ +openapi: 3.0.0 +info: + description: "This is a sample server Petstore server. For this sample, you can\ + \ use the api key `special-key` to test the authorization filters." + license: + name: Apache-2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + title: OpenAPI Petstore + version: 1.0.0 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: +- url: http://petstore.swagger.io/v2 +tags: +- description: Everything about your Pets + name: pet +- description: Access to Petstore orders + name: store +- description: Operations about user + name: user +paths: + /pet: + post: + description: "" + operationId: addPet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + summary: Add a new pet to the store + tags: + - pet + put: + description: "" + externalDocs: + description: API documentation for the updatePet operation + url: http://petstore.swagger.io/v2/doc/updatePet + operationId: updatePet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Pet not found + "405": + description: Validation exception + security: + - petstore_auth: + - write:pets + - read:pets + summary: Update an existing pet + tags: + - pet + /pet/findByStatus: + get: + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - deprecated: true + description: Status values that need to be considered for filter + explode: false + in: query + name: status + required: true + schema: + items: + default: available + enum: + - available + - pending + - sold + type: string + type: array + style: form + responses: + "200": + content: + application/xml: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + application/json: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + description: successful operation + "400": + description: Invalid status value + security: + - petstore_auth: + - read:pets + summary: Finds Pets by status + tags: + - pet + /pet/findByTags: + get: + deprecated: true + description: "Multiple tags can be provided with comma separated strings. Use\ + \ tag1, tag2, tag3 for testing." + operationId: findPetsByTags + parameters: + - description: Tags to filter by + explode: false + in: query + name: tags + required: true + schema: + items: + type: string + type: array + style: form + responses: + "200": + content: + application/xml: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + application/json: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + description: successful operation + "400": + description: Invalid tag value + security: + - petstore_auth: + - read:pets + summary: Finds Pets by tags + tags: + - pet + /pet/{petId}: + delete: + description: "" + operationId: deletePet + parameters: + - explode: false + in: header + name: api_key + required: false + schema: + type: string + style: simple + - description: Pet id to delete + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "400": + description: Invalid pet value + security: + - petstore_auth: + - write:pets + - read:pets + summary: Deletes a pet + tags: + - pet + get: + description: Returns a single pet + operationId: getPetById + parameters: + - description: ID of pet to return + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Pet not found + security: + - api_key: [] + summary: Find pet by ID + tags: + - pet + post: + description: "" + operationId: updatePetWithForm + parameters: + - description: ID of pet that needs to be updated + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/updatePetWithForm_request' + responses: + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + summary: Updates a pet in the store with form data + tags: + - pet + /pet/{petId}/uploadImage: + post: + description: "" + operationId: uploadFile + parameters: + - description: ID of pet to update + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/uploadFile_request' + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: successful operation + security: + - petstore_auth: + - write:pets + - read:pets + summary: uploads an image + tags: + - pet + /store/inventory: + get: + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + "200": + content: + application/json: + schema: + additionalProperties: + format: int32 + type: integer + type: object + description: successful operation + security: + - api_key: [] + summary: Returns pet inventories by status + tags: + - store + /store/order: + post: + description: "" + operationId: placeOrder + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + description: successful operation + "400": + description: Invalid Order + summary: Place an order for a pet + tags: + - store + /store/order/{orderId}: + delete: + description: For valid response try integer IDs with value < 1000. Anything + above 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - description: ID of the order that needs to be deleted + explode: false + in: path + name: orderId + required: true + schema: + type: string + style: simple + responses: + "400": + description: Invalid ID supplied + "404": + description: Order not found + summary: Delete purchase order by ID + tags: + - store + get: + description: For valid response try integer IDs with value <= 5 or > 10. Other + values will generate exceptions + operationId: getOrderById + parameters: + - description: ID of pet that needs to be fetched + explode: false + in: path + name: orderId + required: true + schema: + format: int64 + maximum: 5 + minimum: 1 + type: integer + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Order not found + summary: Find purchase order by ID + tags: + - store + /user: + post: + description: This can only be done by the logged in user. + operationId: createUser + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Create user + tags: + - user + /user/createWithArray: + post: + description: "" + operationId: createUsersWithArrayInput + requestBody: + $ref: '#/components/requestBodies/UserArray' + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Creates list of users with given input array + tags: + - user + /user/createWithList: + post: + description: "" + operationId: createUsersWithListInput + requestBody: + $ref: '#/components/requestBodies/UserArray' + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Creates list of users with given input array + tags: + - user + /user/login: + get: + description: "" + operationId: loginUser + parameters: + - description: The user name for login + explode: true + in: query + name: username + required: true + schema: + pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$" + type: string + style: form + - description: The password for login in clear text + explode: true + in: query + name: password + required: true + schema: + type: string + style: form + responses: + "200": + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + description: successful operation + headers: + Set-Cookie: + description: Cookie authentication key for use with the `api_key` apiKey + authentication. + explode: false + schema: + example: AUTH_KEY=abcde12345; Path=/; HttpOnly + type: string + style: simple + X-Rate-Limit: + description: calls per hour allowed by the user + explode: false + schema: + format: int32 + type: integer + style: simple + X-Expires-After: + description: date in UTC when token expires + explode: false + schema: + format: date-time + type: string + style: simple + "400": + description: Invalid username/password supplied + summary: Logs user into the system + tags: + - user + /user/logout: + get: + description: "" + operationId: logoutUser + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Logs out current logged in user session + tags: + - user + /user/{username}: + delete: + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - description: The name that needs to be deleted + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + responses: + "400": + description: Invalid username supplied + "404": + description: User not found + security: + - api_key: [] + summary: Delete user + tags: + - user + get: + description: "" + operationId: getUserByName + parameters: + - description: The name that needs to be fetched. Use user1 for testing. + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + description: successful operation + "400": + description: Invalid username supplied + "404": + description: User not found + summary: Get user by user name + tags: + - user + put: + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - description: name that need to be deleted + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + responses: + "400": + description: Invalid user supplied + "404": + description: User not found + security: + - api_key: [] + summary: Updated user + tags: + - user + /fake/query_param_default: + get: + description: "" + operationId: fake_query_param_default + parameters: + - description: has default value + explode: true + in: query + name: hasDefault + required: false + schema: + default: Hello World + type: string + style: form + - description: no default value + explode: true + in: query + name: noDefault + required: false + schema: + type: string + style: form + responses: + "400": + description: Invalid username supplied + "404": + description: User not found + summary: test query parameter default value + tags: + - fake +components: + requestBodies: + UserArray: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/User' + type: array + description: List of user object + required: true + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + schemas: + Order: + description: An order for a pets from the pet store + example: + petId: 6 + quantity: 1 + id: 0 + shipDate: 2000-01-23T04:56:07.000+00:00 + complete: false + status: placed + properties: + id: + format: int64 + title: id + type: integer + petId: + format: int64 + title: petId + type: integer + quantity: + format: int32 + title: quantity + type: integer + shipDate: + format: date-time + title: shipDate + type: string + status: + description: Order Status + enum: + - placed + - approved + - delivered + title: status + type: string + complete: + default: false + title: complete + type: boolean + title: Pet Order + type: object + xml: + name: Order + Category: + description: A category for a pet + example: + name: name + id: 6 + properties: + id: + format: int64 + title: id + type: integer + name: + pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$" + title: name + type: string + title: Pet category + type: object + xml: + name: Category + User: + description: A User who is purchasing from the pet store + example: + firstName: firstName + lastName: lastName + password: password + userStatus: 6 + phone: phone + id: 0 + email: email + username: username + properties: + id: + format: int64 + title: id + type: integer + username: + title: username + type: string + firstName: + title: firstName + type: string + lastName: + title: lastName + type: string + email: + title: email + type: string + password: + title: password + type: string + phone: + title: phone + type: string + userStatus: + description: User Status + format: int32 + title: userStatus + type: integer + title: a User + type: object + xml: + name: User + Tag: + description: A tag for a pet + example: + name: name + id: 1 + properties: + id: + format: int64 + title: id + type: integer + name: + title: name + type: string + title: Pet Tag + type: object + xml: + name: Tag + Pet: + description: A pet for sale in the pet store + example: + photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + properties: + id: + format: int64 + title: id + type: integer + category: + $ref: '#/components/schemas/Category' + name: + example: doggie + title: name + type: string + photoUrls: + items: + type: string + title: photoUrls + type: array + xml: + name: photoUrl + wrapped: true + tags: + items: + $ref: '#/components/schemas/Tag' + title: tags + type: array + xml: + name: tag + wrapped: true + status: + deprecated: true + description: pet status in the store + enum: + - available + - pending + - sold + title: status + type: string + required: + - name + - photoUrls + title: a Pet + type: object + xml: + name: Pet + ApiResponse: + description: Describes the result of uploading an image resource + example: + code: 0 + type: type + message: message + properties: + code: + format: int32 + title: code + type: integer + type: + title: type + type: string + message: + title: message + type: string + title: An uploaded response + type: object + updatePetWithForm_request: + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + type: object + uploadFile_request: + properties: + additionalMetadata: + description: Additional data to pass to server + type: string + file: + description: file to upload + format: binary + type: string + type: object + securitySchemes: + petstore_auth: + flows: + implicit: + authorizationUrl: http://petstore.swagger.io/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets + type: oauth2 + api_key: + in: header + name: api_key + type: apiKey diff --git a/generated-code/openapi_server/dto/__init__.py b/generated-code/openapi_server/dto/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/generated-code/openapi_server/dto/api_response.py b/generated-code/openapi_server/dto/api_response.py new file mode 100644 index 0000000..441c3b8 --- /dev/null +++ b/generated-code/openapi_server/dto/api_response.py @@ -0,0 +1,94 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class ApiResponse(BaseModel): + """ + Describes the result of uploading an image resource + """ # noqa: E501 + code: Optional[StrictInt] = None + type: Optional[StrictStr] = None + message: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["code", "type", "message"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of ApiResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of ApiResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "code": obj.get("code"), + "type": obj.get("type"), + "message": obj.get("message") + }) + return _obj + + diff --git a/generated-code/openapi_server/dto/category.py b/generated-code/openapi_server/dto/category.py new file mode 100644 index 0000000..48b689c --- /dev/null +++ b/generated-code/openapi_server/dto/category.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Category(BaseModel): + """ + A category for a pet + """ # noqa: E501 + id: Optional[StrictInt] = None + name: Optional[Annotated[str, Field(strict=True)]] = None + __properties: ClassVar[List[str]] = ["id", "name"] + + @field_validator('name') + def name_validate_regular_expression(cls, value): + """Validates the regular expression""" + if value is None: + return value + + if not re.match(r"^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$", value): + raise ValueError(r"must validate the regular expression /^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$/") + return value + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Category from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Category from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "name": obj.get("name") + }) + return _obj + + diff --git a/generated-code/openapi_server/dto/extra_models.py b/generated-code/openapi_server/dto/extra_models.py new file mode 100644 index 0000000..a3a283f --- /dev/null +++ b/generated-code/openapi_server/dto/extra_models.py @@ -0,0 +1,8 @@ +# coding: utf-8 + +from pydantic import BaseModel + +class TokenModel(BaseModel): + """Defines a token model.""" + + sub: str diff --git a/generated-code/openapi_server/dto/order.py b/generated-code/openapi_server/dto/order.py new file mode 100644 index 0000000..7a5a38c --- /dev/null +++ b/generated-code/openapi_server/dto/order.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Order(BaseModel): + """ + An order for a pets from the pet store + """ # noqa: E501 + id: Optional[StrictInt] = None + pet_id: Optional[StrictInt] = Field(default=None, alias="petId") + quantity: Optional[StrictInt] = None + ship_date: Optional[datetime] = Field(default=None, alias="shipDate") + status: Optional[StrictStr] = Field(default=None, description="Order Status") + complete: Optional[StrictBool] = False + __properties: ClassVar[List[str]] = ["id", "petId", "quantity", "shipDate", "status", "complete"] + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in ('placed', 'approved', 'delivered',): + raise ValueError("must be one of enum values ('placed', 'approved', 'delivered')") + return value + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Order from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Order from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "petId": obj.get("petId"), + "quantity": obj.get("quantity"), + "shipDate": obj.get("shipDate"), + "status": obj.get("status"), + "complete": obj.get("complete") if obj.get("complete") is not None else False + }) + return _obj + + diff --git a/generated-code/openapi_server/dto/pet.py b/generated-code/openapi_server/dto/pet.py new file mode 100644 index 0000000..450c1b7 --- /dev/null +++ b/generated-code/openapi_server/dto/pet.py @@ -0,0 +1,122 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from openapi_server.models.category import Category +from openapi_server.models.tag import Tag +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Pet(BaseModel): + """ + A pet for sale in the pet store + """ # noqa: E501 + id: Optional[StrictInt] = None + category: Optional[Category] = None + name: StrictStr + photo_urls: List[StrictStr] = Field(alias="photoUrls") + tags: Optional[List[Tag]] = None + status: Optional[StrictStr] = Field(default=None, description="pet status in the store") + __properties: ClassVar[List[str]] = ["id", "category", "name", "photoUrls", "tags", "status"] + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in ('available', 'pending', 'sold',): + raise ValueError("must be one of enum values ('available', 'pending', 'sold')") + return value + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Pet from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of category + if self.category: + _dict['category'] = self.category.to_dict() + # override the default output from pydantic by calling `to_dict()` of each item in tags (list) + _items = [] + if self.tags: + for _item in self.tags: + if _item: + _items.append(_item.to_dict()) + _dict['tags'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Pet from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "category": Category.from_dict(obj.get("category")) if obj.get("category") is not None else None, + "name": obj.get("name"), + "photoUrls": obj.get("photoUrls"), + "tags": [Tag.from_dict(_item) for _item in obj.get("tags")] if obj.get("tags") is not None else None, + "status": obj.get("status") + }) + return _obj + + diff --git a/generated-code/openapi_server/dto/tag.py b/generated-code/openapi_server/dto/tag.py new file mode 100644 index 0000000..8b21d36 --- /dev/null +++ b/generated-code/openapi_server/dto/tag.py @@ -0,0 +1,92 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class Tag(BaseModel): + """ + A tag for a pet + """ # noqa: E501 + id: Optional[StrictInt] = None + name: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["id", "name"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of Tag from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of Tag from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "name": obj.get("name") + }) + return _obj + + diff --git a/generated-code/openapi_server/dto/user.py b/generated-code/openapi_server/dto/user.py new file mode 100644 index 0000000..cb98a57 --- /dev/null +++ b/generated-code/openapi_server/dto/user.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + + + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class User(BaseModel): + """ + A User who is purchasing from the pet store + """ # noqa: E501 + id: Optional[StrictInt] = None + username: Optional[StrictStr] = None + first_name: Optional[StrictStr] = Field(default=None, alias="firstName") + last_name: Optional[StrictStr] = Field(default=None, alias="lastName") + email: Optional[StrictStr] = None + password: Optional[StrictStr] = None + phone: Optional[StrictStr] = None + user_status: Optional[StrictInt] = Field(default=None, description="User Status", alias="userStatus") + __properties: ClassVar[List[str]] = ["id", "username", "firstName", "lastName", "email", "password", "phone", "userStatus"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True, + "protected_namespaces": (), + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of User from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of User from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "username": obj.get("username"), + "firstName": obj.get("firstName"), + "lastName": obj.get("lastName"), + "email": obj.get("email"), + "password": obj.get("password"), + "phone": obj.get("phone"), + "userStatus": obj.get("userStatus") + }) + return _obj + + diff --git a/generated-code/openapi_server/impl/__init__.py b/generated-code/openapi_server/impl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/generated-code/openapi_server/main.py b/generated-code/openapi_server/main.py new file mode 100644 index 0000000..fff75f5 --- /dev/null +++ b/generated-code/openapi_server/main.py @@ -0,0 +1,31 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from fastapi import FastAPI + +from service.fake_api import router as FakeApiRouter +from service.pet_api import router as PetApiRouter +from service.store_api import router as StoreApiRouter +from service.user_api import router as UserApiRouter + +app = FastAPI( + title="OpenAPI Petstore", + description="This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.", + version="1.0.0", +) + +app.include_router(FakeApiRouter) +app.include_router(PetApiRouter) +app.include_router(StoreApiRouter) +app.include_router(UserApiRouter) diff --git a/generated-code/openapi_server/security_api.py b/generated-code/openapi_server/security_api.py new file mode 100644 index 0000000..7aeb8be --- /dev/null +++ b/generated-code/openapi_server/security_api.py @@ -0,0 +1,83 @@ +# coding: utf-8 + +from typing import List + +from fastapi import Depends, Security # noqa: F401 +from fastapi.openapi.models import OAuthFlowImplicit, OAuthFlows # noqa: F401 +from fastapi.security import ( # noqa: F401 + HTTPAuthorizationCredentials, + HTTPBasic, + HTTPBasicCredentials, + HTTPBearer, + OAuth2, + OAuth2AuthorizationCodeBearer, + OAuth2PasswordBearer, + SecurityScopes, +) +from fastapi.security.api_key import APIKeyCookie, APIKeyHeader, APIKeyQuery # noqa: F401 + +from openapi_server.dto.extra_models import TokenModel + +oauth2_implicit = OAuth2( + flows=OAuthFlows( + implicit=OAuthFlowImplicit( + authorizationUrl="http://petstore.swagger.io/api/oauth/dialog", + scopes={ + "write:pets": "modify pets in your account", + "read:pets": "read your pets", + } + ) + ) +) + + +def get_token_petstore_auth( + security_scopes: SecurityScopes, token: str = Depends(oauth2_implicit) +) -> TokenModel: + """ + Validate and decode token. + + :param token Token provided by Authorization header + :type token: str + :return: Decoded token information or None if token is invalid + :rtype: TokenModel | None + """ + + ... + + +def validate_scope_petstore_auth( + required_scopes: SecurityScopes, token_scopes: List[str] +) -> bool: + """ + Validate required scopes are included in token scope + + :param required_scopes Required scope to access called API + :type required_scopes: List[str] + :param token_scopes Scope present in token + :type token_scopes: List[str] + :return: True if access to called API is allowed + :rtype: bool + """ + + return False + + +def get_token_api_key( + token_api_key_header: str = Security( + APIKeyHeader(name="api_key", auto_error=False) + ), +) -> TokenModel: + """ + Check and retrieve authentication information from api_key. + + :param token_api_key_header API key provided by Authorization[api_key] header + + + :type token_api_key_header: str + :return: Information attached to provided api_key or None if api_key is invalid or does not allow access to called API + :rtype: TokenModel | None + """ + + ... + diff --git a/generated-code/openapi_server/service/__init__.py b/generated-code/openapi_server/service/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/generated-code/openapi_server/service/fake_api.py b/generated-code/openapi_server/service/fake_api.py new file mode 100644 index 0000000..b46fdfe --- /dev/null +++ b/generated-code/openapi_server/service/fake_api.py @@ -0,0 +1,55 @@ +# coding: utf-8 + +from typing import Dict, List # noqa: F401 +import importlib +import pkgutil + +from service.fake_api_base import BaseFakeApi +import openapi_server.impl + +from fastapi import ( # noqa: F401 + APIRouter, + Body, + Cookie, + Depends, + Form, + Header, + HTTPException, + Path, + Query, + Response, + Security, + status, +) + +from dto.extra_models import TokenModel # noqa: F401 +from pydantic import Field, StrictStr +from typing import Any, Optional +from typing_extensions import Annotated + + +router = APIRouter() + +ns_pkg = openapi_server.impl +for _, name, _ in pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + "."): + importlib.import_module(name) + + +@router.get( + "/fake/query_param_default", + responses={ + 400: {"description": "Invalid username supplied"}, + 404: {"description": "User not found"}, + }, + tags=["fake"], + summary="test query parameter default value", + response_model_by_alias=True, +) +async def fake_query_param_default( + has_default: Annotated[Optional[StrictStr], Field(description="has default value")] = Query('Hello World', description="has default value", alias="hasDefault"), + no_default: Annotated[Optional[StrictStr], Field(description="no default value")] = Query(None, description="no default value", alias="noDefault"), +) -> None: + """""" + if not BaseFakeApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseFakeApi.subclasses[0]().fake_query_param_default(has_default, no_default) diff --git a/generated-code/openapi_server/service/fake_api_base.py b/generated-code/openapi_server/service/fake_api_base.py new file mode 100644 index 0000000..1c71537 --- /dev/null +++ b/generated-code/openapi_server/service/fake_api_base.py @@ -0,0 +1,22 @@ +# coding: utf-8 + +from typing import ClassVar, Dict, List, Tuple # noqa: F401 + +from pydantic import Field, StrictStr +from typing import Any, Optional +from typing_extensions import Annotated + + +class BaseFakeApi: + subclasses: ClassVar[Tuple] = () + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + BaseFakeApi.subclasses = BaseFakeApi.subclasses + (cls,) + async def fake_query_param_default( + self, + has_default: Annotated[Optional[StrictStr], Field(description="has default value")], + no_default: Annotated[Optional[StrictStr], Field(description="no default value")], + ) -> None: + """""" + ... diff --git a/generated-code/openapi_server/service/pet_api.py b/generated-code/openapi_server/service/pet_api.py new file mode 100644 index 0000000..7f5246e --- /dev/null +++ b/generated-code/openapi_server/service/pet_api.py @@ -0,0 +1,218 @@ +# coding: utf-8 + +from typing import Dict, List # noqa: F401 +import importlib +import pkgutil + +from service.pet_api_base import BasePetApi +import openapi_server.impl + +from fastapi import ( # noqa: F401 + APIRouter, + Body, + Cookie, + Depends, + Form, + Header, + HTTPException, + Path, + Query, + Response, + Security, + status, +) + +from dto.extra_models import TokenModel # noqa: F401 +from pydantic import Field, StrictBytes, StrictInt, StrictStr, field_validator +from typing import Any, List, Optional, Tuple, Union +from typing_extensions import Annotated +from openapi_server.models.api_response import ApiResponse +from openapi_server.models.pet import Pet +from openapi_server.security_api import get_token_petstore_auth, get_token_api_key + +router = APIRouter() + +ns_pkg = openapi_server.impl +for _, name, _ in pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + "."): + importlib.import_module(name) + + +@router.post( + "/pet", + responses={ + 200: {"model": Pet, "description": "successful operation"}, + 405: {"description": "Invalid input"}, + }, + tags=["pet"], + summary="Add a new pet to the store", + response_model_by_alias=True, +) +async def add_pet( + pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")] = Body(None, description="Pet object that needs to be added to the store"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> Pet: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().add_pet(pet) + + +@router.delete( + "/pet/{petId}", + responses={ + 400: {"description": "Invalid pet value"}, + }, + tags=["pet"], + summary="Deletes a pet", + response_model_by_alias=True, +) +async def delete_pet( + petId: Annotated[StrictInt, Field(description="Pet id to delete")] = Path(..., description="Pet id to delete"), + api_key: Optional[StrictStr] = Header(None, description=""), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> None: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().delete_pet(petId, api_key) + + +@router.get( + "/pet/findByStatus", + responses={ + 200: {"model": List[Pet], "description": "successful operation"}, + 400: {"description": "Invalid status value"}, + }, + tags=["pet"], + summary="Finds Pets by status", + response_model_by_alias=True, +) +async def find_pets_by_status( + status: Annotated[List[StrictStr], Field(description="Status values that need to be considered for filter")] = Query(None, description="Status values that need to be considered for filter", alias="status"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["read:pets"] + ), +) -> List[Pet]: + """Multiple status values can be provided with comma separated strings""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().find_pets_by_status(status) + + +@router.get( + "/pet/findByTags", + responses={ + 200: {"model": List[Pet], "description": "successful operation"}, + 400: {"description": "Invalid tag value"}, + }, + tags=["pet"], + summary="Finds Pets by tags", + response_model_by_alias=True, +) +async def find_pets_by_tags( + tags: Annotated[List[StrictStr], Field(description="Tags to filter by")] = Query(None, description="Tags to filter by", alias="tags"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["read:pets"] + ), +) -> List[Pet]: + """Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().find_pets_by_tags(tags) + + +@router.get( + "/pet/{petId}", + responses={ + 200: {"model": Pet, "description": "successful operation"}, + 400: {"description": "Invalid ID supplied"}, + 404: {"description": "Pet not found"}, + }, + tags=["pet"], + summary="Find pet by ID", + response_model_by_alias=True, +) +async def get_pet_by_id( + petId: Annotated[StrictInt, Field(description="ID of pet to return")] = Path(..., description="ID of pet to return"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> Pet: + """Returns a single pet""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().get_pet_by_id(petId) + + +@router.put( + "/pet", + responses={ + 200: {"model": Pet, "description": "successful operation"}, + 400: {"description": "Invalid ID supplied"}, + 404: {"description": "Pet not found"}, + 405: {"description": "Validation exception"}, + }, + tags=["pet"], + summary="Update an existing pet", + response_model_by_alias=True, +) +async def update_pet( + pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")] = Body(None, description="Pet object that needs to be added to the store"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> Pet: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().update_pet(pet) + + +@router.post( + "/pet/{petId}", + responses={ + 405: {"description": "Invalid input"}, + }, + tags=["pet"], + summary="Updates a pet in the store with form data", + response_model_by_alias=True, +) +async def update_pet_with_form( + petId: Annotated[StrictInt, Field(description="ID of pet that needs to be updated")] = Path(..., description="ID of pet that needs to be updated"), + name: Annotated[Optional[StrictStr], Field(description="Updated name of the pet")] = Form(None, description="Updated name of the pet"), + status: Annotated[Optional[StrictStr], Field(description="Updated status of the pet")] = Form(None, description="Updated status of the pet"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> None: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().update_pet_with_form(petId, name, status) + + +@router.post( + "/pet/{petId}/uploadImage", + responses={ + 200: {"model": ApiResponse, "description": "successful operation"}, + }, + tags=["pet"], + summary="uploads an image", + response_model_by_alias=True, +) +async def upload_file( + petId: Annotated[StrictInt, Field(description="ID of pet to update")] = Path(..., description="ID of pet to update"), + additional_metadata: Annotated[Optional[StrictStr], Field(description="Additional data to pass to server")] = Form(None, description="Additional data to pass to server"), + file: Annotated[Optional[Union[StrictBytes, StrictStr, Tuple[StrictStr, StrictBytes]]], Field(description="file to upload")] = Form(None, description="file to upload"), + token_petstore_auth: TokenModel = Security( + get_token_petstore_auth, scopes=["write:pets", "read:pets"] + ), +) -> ApiResponse: + """""" + if not BasePetApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BasePetApi.subclasses[0]().upload_file(petId, additional_metadata, file) diff --git a/generated-code/openapi_server/service/pet_api_base.py b/generated-code/openapi_server/service/pet_api_base.py new file mode 100644 index 0000000..608762c --- /dev/null +++ b/generated-code/openapi_server/service/pet_api_base.py @@ -0,0 +1,84 @@ +# coding: utf-8 + +from typing import ClassVar, Dict, List, Tuple # noqa: F401 + +from pydantic import Field, StrictBytes, StrictInt, StrictStr, field_validator +from typing import Any, List, Optional, Tuple, Union +from typing_extensions import Annotated +from openapi_server.models.api_response import ApiResponse +from openapi_server.models.pet import Pet +from openapi_server.security_api import get_token_petstore_auth, get_token_api_key + +class BasePetApi: + subclasses: ClassVar[Tuple] = () + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + BasePetApi.subclasses = BasePetApi.subclasses + (cls,) + async def add_pet( + self, + pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")], + ) -> Pet: + """""" + ... + + + async def delete_pet( + self, + petId: Annotated[StrictInt, Field(description="Pet id to delete")], + api_key: Optional[StrictStr], + ) -> None: + """""" + ... + + + async def find_pets_by_status( + self, + status: Annotated[List[StrictStr], Field(description="Status values that need to be considered for filter")], + ) -> List[Pet]: + """Multiple status values can be provided with comma separated strings""" + ... + + + async def find_pets_by_tags( + self, + tags: Annotated[List[StrictStr], Field(description="Tags to filter by")], + ) -> List[Pet]: + """Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.""" + ... + + + async def get_pet_by_id( + self, + petId: Annotated[StrictInt, Field(description="ID of pet to return")], + ) -> Pet: + """Returns a single pet""" + ... + + + async def update_pet( + self, + pet: Annotated[Pet, Field(description="Pet object that needs to be added to the store")], + ) -> Pet: + """""" + ... + + + async def update_pet_with_form( + self, + petId: Annotated[StrictInt, Field(description="ID of pet that needs to be updated")], + name: Annotated[Optional[StrictStr], Field(description="Updated name of the pet")], + status: Annotated[Optional[StrictStr], Field(description="Updated status of the pet")], + ) -> None: + """""" + ... + + + async def upload_file( + self, + petId: Annotated[StrictInt, Field(description="ID of pet to update")], + additional_metadata: Annotated[Optional[StrictStr], Field(description="Additional data to pass to server")], + file: Annotated[Optional[Union[StrictBytes, StrictStr, Tuple[StrictStr, StrictBytes]]], Field(description="file to upload")], + ) -> ApiResponse: + """""" + ... diff --git a/generated-code/openapi_server/service/store_api.py b/generated-code/openapi_server/service/store_api.py new file mode 100644 index 0000000..c6b0961 --- /dev/null +++ b/generated-code/openapi_server/service/store_api.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +from typing import Dict, List # noqa: F401 +import importlib +import pkgutil + +from service.store_api_base import BaseStoreApi +import openapi_server.impl + +from fastapi import ( # noqa: F401 + APIRouter, + Body, + Cookie, + Depends, + Form, + Header, + HTTPException, + Path, + Query, + Response, + Security, + status, +) + +from dto.extra_models import TokenModel # noqa: F401 +from pydantic import Field, StrictInt, StrictStr +from typing import Any, Dict +from typing_extensions import Annotated +from openapi_server.models.order import Order +from openapi_server.security_api import get_token_api_key + +router = APIRouter() + +ns_pkg = openapi_server.impl +for _, name, _ in pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + "."): + importlib.import_module(name) + + +@router.delete( + "/store/order/{orderId}", + responses={ + 400: {"description": "Invalid ID supplied"}, + 404: {"description": "Order not found"}, + }, + tags=["store"], + summary="Delete purchase order by ID", + response_model_by_alias=True, +) +async def delete_order( + orderId: Annotated[StrictStr, Field(description="ID of the order that needs to be deleted")] = Path(..., description="ID of the order that needs to be deleted"), +) -> None: + """For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors""" + if not BaseStoreApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseStoreApi.subclasses[0]().delete_order(orderId) + + +@router.get( + "/store/inventory", + responses={ + 200: {"model": Dict[str, int], "description": "successful operation"}, + }, + tags=["store"], + summary="Returns pet inventories by status", + response_model_by_alias=True, +) +async def get_inventory( + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> Dict[str, int]: + """Returns a map of status codes to quantities""" + if not BaseStoreApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseStoreApi.subclasses[0]().get_inventory() + + +@router.get( + "/store/order/{orderId}", + responses={ + 200: {"model": Order, "description": "successful operation"}, + 400: {"description": "Invalid ID supplied"}, + 404: {"description": "Order not found"}, + }, + tags=["store"], + summary="Find purchase order by ID", + response_model_by_alias=True, +) +async def get_order_by_id( + orderId: Annotated[int, Field(le=5, strict=True, ge=1, description="ID of pet that needs to be fetched")] = Path(..., description="ID of pet that needs to be fetched", ge=1, le=5), +) -> Order: + """For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions""" + if not BaseStoreApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseStoreApi.subclasses[0]().get_order_by_id(orderId) + + +@router.post( + "/store/order", + responses={ + 200: {"model": Order, "description": "successful operation"}, + 400: {"description": "Invalid Order"}, + }, + tags=["store"], + summary="Place an order for a pet", + response_model_by_alias=True, +) +async def place_order( + order: Annotated[Order, Field(description="order placed for purchasing the pet")] = Body(None, description="order placed for purchasing the pet"), +) -> Order: + """""" + if not BaseStoreApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseStoreApi.subclasses[0]().place_order(order) diff --git a/generated-code/openapi_server/service/store_api_base.py b/generated-code/openapi_server/service/store_api_base.py new file mode 100644 index 0000000..2062962 --- /dev/null +++ b/generated-code/openapi_server/service/store_api_base.py @@ -0,0 +1,45 @@ +# coding: utf-8 + +from typing import ClassVar, Dict, List, Tuple # noqa: F401 + +from pydantic import Field, StrictInt, StrictStr +from typing import Any, Dict +from typing_extensions import Annotated +from openapi_server.models.order import Order +from openapi_server.security_api import get_token_api_key + +class BaseStoreApi: + subclasses: ClassVar[Tuple] = () + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + BaseStoreApi.subclasses = BaseStoreApi.subclasses + (cls,) + async def delete_order( + self, + orderId: Annotated[StrictStr, Field(description="ID of the order that needs to be deleted")], + ) -> None: + """For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors""" + ... + + + async def get_inventory( + self, + ) -> Dict[str, int]: + """Returns a map of status codes to quantities""" + ... + + + async def get_order_by_id( + self, + orderId: Annotated[int, Field(le=5, strict=True, ge=1, description="ID of pet that needs to be fetched")], + ) -> Order: + """For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions""" + ... + + + async def place_order( + self, + order: Annotated[Order, Field(description="order placed for purchasing the pet")], + ) -> Order: + """""" + ... diff --git a/generated-code/openapi_server/service/user_api.py b/generated-code/openapi_server/service/user_api.py new file mode 100644 index 0000000..2604cac --- /dev/null +++ b/generated-code/openapi_server/service/user_api.py @@ -0,0 +1,204 @@ +# coding: utf-8 + +from typing import Dict, List # noqa: F401 +import importlib +import pkgutil + +from service.user_api_base import BaseUserApi +import openapi_server.impl + +from fastapi import ( # noqa: F401 + APIRouter, + Body, + Cookie, + Depends, + Form, + Header, + HTTPException, + Path, + Query, + Response, + Security, + status, +) + +from dto.extra_models import TokenModel # noqa: F401 +from pydantic import Field, StrictStr, field_validator +from typing import Any, List +from typing_extensions import Annotated +from openapi_server.models.user import User +from openapi_server.security_api import get_token_api_key + +router = APIRouter() + +ns_pkg = openapi_server.impl +for _, name, _ in pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + "."): + importlib.import_module(name) + + +@router.post( + "/user", + responses={ + 200: {"description": "successful operation"}, + }, + tags=["user"], + summary="Create user", + response_model_by_alias=True, +) +async def create_user( + user: Annotated[User, Field(description="Created user object")] = Body(None, description="Created user object"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """This can only be done by the logged in user.""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().create_user(user) + + +@router.post( + "/user/createWithArray", + responses={ + 200: {"description": "successful operation"}, + }, + tags=["user"], + summary="Creates list of users with given input array", + response_model_by_alias=True, +) +async def create_users_with_array_input( + user: Annotated[List[User], Field(description="List of user object")] = Body(None, description="List of user object"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().create_users_with_array_input(user) + + +@router.post( + "/user/createWithList", + responses={ + 200: {"description": "successful operation"}, + }, + tags=["user"], + summary="Creates list of users with given input array", + response_model_by_alias=True, +) +async def create_users_with_list_input( + user: Annotated[List[User], Field(description="List of user object")] = Body(None, description="List of user object"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().create_users_with_list_input(user) + + +@router.delete( + "/user/{username}", + responses={ + 400: {"description": "Invalid username supplied"}, + 404: {"description": "User not found"}, + }, + tags=["user"], + summary="Delete user", + response_model_by_alias=True, +) +async def delete_user( + username: Annotated[StrictStr, Field(description="The name that needs to be deleted")] = Path(..., description="The name that needs to be deleted"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """This can only be done by the logged in user.""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().delete_user(username) + + +@router.get( + "/user/{username}", + responses={ + 200: {"model": User, "description": "successful operation"}, + 400: {"description": "Invalid username supplied"}, + 404: {"description": "User not found"}, + }, + tags=["user"], + summary="Get user by user name", + response_model_by_alias=True, +) +async def get_user_by_name( + username: Annotated[StrictStr, Field(description="The name that needs to be fetched. Use user1 for testing.")] = Path(..., description="The name that needs to be fetched. Use user1 for testing."), +) -> User: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().get_user_by_name(username) + + +@router.get( + "/user/login", + responses={ + 200: {"model": str, "description": "successful operation"}, + 400: {"description": "Invalid username/password supplied"}, + }, + tags=["user"], + summary="Logs user into the system", + response_model_by_alias=True, +) +async def login_user( + username: Annotated[str, Field(strict=True, description="The user name for login")] = Query(None, description="The user name for login", alias="username", regex=r"/^[a-zA-Z0-9]+[a-zA-Z0-9\.\-_]*[a-zA-Z0-9]+$/"), + password: Annotated[StrictStr, Field(description="The password for login in clear text")] = Query(None, description="The password for login in clear text", alias="password"), +) -> str: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().login_user(username, password) + + +@router.get( + "/user/logout", + responses={ + 200: {"description": "successful operation"}, + }, + tags=["user"], + summary="Logs out current logged in user session", + response_model_by_alias=True, +) +async def logout_user( + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().logout_user() + + +@router.put( + "/user/{username}", + responses={ + 400: {"description": "Invalid user supplied"}, + 404: {"description": "User not found"}, + }, + tags=["user"], + summary="Updated user", + response_model_by_alias=True, +) +async def update_user( + username: Annotated[StrictStr, Field(description="name that need to be deleted")] = Path(..., description="name that need to be deleted"), + user: Annotated[User, Field(description="Updated user object")] = Body(None, description="Updated user object"), + token_api_key: TokenModel = Security( + get_token_api_key + ), +) -> None: + """This can only be done by the logged in user.""" + if not BaseUserApi.subclasses: + raise HTTPException(status_code=500, detail="Not implemented") + return await BaseUserApi.subclasses[0]().update_user(username, user) diff --git a/generated-code/openapi_server/service/user_api_base.py b/generated-code/openapi_server/service/user_api_base.py new file mode 100644 index 0000000..fb86c92 --- /dev/null +++ b/generated-code/openapi_server/service/user_api_base.py @@ -0,0 +1,79 @@ +# coding: utf-8 + +from typing import ClassVar, Dict, List, Tuple # noqa: F401 + +from pydantic import Field, StrictStr, field_validator +from typing import Any, List +from typing_extensions import Annotated +from openapi_server.models.user import User +from openapi_server.security_api import get_token_api_key + +class BaseUserApi: + subclasses: ClassVar[Tuple] = () + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + BaseUserApi.subclasses = BaseUserApi.subclasses + (cls,) + async def create_user( + self, + user: Annotated[User, Field(description="Created user object")], + ) -> None: + """This can only be done by the logged in user.""" + ... + + + async def create_users_with_array_input( + self, + user: Annotated[List[User], Field(description="List of user object")], + ) -> None: + """""" + ... + + + async def create_users_with_list_input( + self, + user: Annotated[List[User], Field(description="List of user object")], + ) -> None: + """""" + ... + + + async def delete_user( + self, + username: Annotated[StrictStr, Field(description="The name that needs to be deleted")], + ) -> None: + """This can only be done by the logged in user.""" + ... + + + async def get_user_by_name( + self, + username: Annotated[StrictStr, Field(description="The name that needs to be fetched. Use user1 for testing.")], + ) -> User: + """""" + ... + + + async def login_user( + self, + username: Annotated[str, Field(strict=True, description="The user name for login")], + password: Annotated[StrictStr, Field(description="The password for login in clear text")], + ) -> str: + """""" + ... + + + async def logout_user( + self, + ) -> None: + """""" + ... + + + async def update_user( + self, + username: Annotated[StrictStr, Field(description="name that need to be deleted")], + user: Annotated[User, Field(description="Updated user object")], + ) -> None: + """This can only be done by the logged in user.""" + ... diff --git a/generated-code/pyproject.toml b/generated-code/pyproject.toml new file mode 100644 index 0000000..c2826df --- /dev/null +++ b/generated-code/pyproject.toml @@ -0,0 +1,30 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.black] +line-length = 88 +exclude = ''' +( + /( + \.eggs # exclude a few common directories in the + | \.git # root of the project + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + )/ +) +''' + +[tool.isort] +profile = "black" +skip = [ + '.eggs', '.git', '.hg', '.mypy_cache', '.nox', '.pants.d', '.tox', + '.venv', '_build', 'buck-out', 'build', 'dist', 'node_modules', 'venv', +] +skip_gitignore = true diff --git a/generated-code/requirements.txt b/generated-code/requirements.txt new file mode 100644 index 0000000..a32429e --- /dev/null +++ b/generated-code/requirements.txt @@ -0,0 +1,36 @@ +aiofiles==23.1.0 +aniso8601==7.0.0 +async-exit-stack==1.0.1 +async-generator==1.10 +certifi==2024.7.4 +chardet==4.0.0 +click==7.1.2 +dnspython==2.6.1 +email-validator==2.0.0 +fastapi==0.115.2 +graphene==2.1.8 +graphql-core==2.3.2 +graphql-relay==2.0.1 +h11==0.12.0 +httptools>=0.3.0,<0.7.0 +httpx==0.24.1 +idna==3.7 +itsdangerous==1.1.0 +Jinja2==3.1.4 +MarkupSafe==2.0.1 +orjson==3.9.15 +promise==2.3 +pydantic>=2 +python-dotenv==0.17.1 +python-multipart==0.0.18 +PyYAML>=5.4.1,<6.1.0 +requests==2.32.0 +Rx==1.6.1 +starlette==0.40.0 +typing-extensions==4.8.0 +ujson==4.0.2 +urllib3==1.26.19 +uvicorn==0.13.4 +uvloop==0.19.0 +watchgod==0.7 +websockets==10.0 diff --git a/generated-code/setup.cfg b/generated-code/setup.cfg new file mode 100644 index 0000000..2c484a1 --- /dev/null +++ b/generated-code/setup.cfg @@ -0,0 +1,20 @@ +[metadata] +name = openapi_server +version = 1.0.0 +description = This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +long_description = file: README.md +keywords = OpenAPI OpenAPI Petstore +python_requires = >= 3.7.* +classifiers = + Operating System :: OS Independent + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.7 + +[options] +install_requires = fastapi[all] +setup_requires = setuptools +package_dir = = +packages = find_namespace: + +[options.packages.find] +where = diff --git a/generated-code/tests/conftest.py b/generated-code/tests/conftest.py new file mode 100644 index 0000000..cbde552 --- /dev/null +++ b/generated-code/tests/conftest.py @@ -0,0 +1,17 @@ +import pytest +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from openapi_server.main import app as application + + +@pytest.fixture +def app() -> FastAPI: + application.dependency_overrides = {} + + return application + + +@pytest.fixture +def client(app) -> TestClient: + return TestClient(app) diff --git a/generated-code/tests/test_fake_api.py b/generated-code/tests/test_fake_api.py new file mode 100644 index 0000000..4f1fcf3 --- /dev/null +++ b/generated-code/tests/test_fake_api.py @@ -0,0 +1,29 @@ +# coding: utf-8 + +from fastapi.testclient import TestClient + + +from pydantic import Field, StrictStr # noqa: F401 +from typing import Any, Optional # noqa: F401 +from typing_extensions import Annotated # noqa: F401 + + +def test_fake_query_param_default(client: TestClient): + """Test case for fake_query_param_default + + test query parameter default value + """ + params = [("has_default", 'Hello World'), ("no_default", 'no_default_example')] + headers = { + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/fake/query_param_default", + # headers=headers, + # params=params, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + diff --git a/generated-code/tests/test_pet_api.py b/generated-code/tests/test_pet_api.py new file mode 100644 index 0000000..5b2ce40 --- /dev/null +++ b/generated-code/tests/test_pet_api.py @@ -0,0 +1,188 @@ +# coding: utf-8 + +from fastapi.testclient import TestClient + + +from pydantic import Field, StrictBytes, StrictInt, StrictStr, field_validator # noqa: F401 +from typing import Any, List, Optional, Tuple, Union # noqa: F401 +from typing_extensions import Annotated # noqa: F401 +from openapi_server.models.api_response import ApiResponse # noqa: F401 +from openapi_server.models.pet import Pet # noqa: F401 + + +def test_add_pet(client: TestClient): + """Test case for add_pet + + Add a new pet to the store + """ + pet = {"photo_urls":["photoUrls","photoUrls"],"name":"doggie","id":0,"category":{"name":"name","id":6},"tags":[{"name":"name","id":1},{"name":"name","id":1}],"status":"available"} + + headers = { + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/pet", + # headers=headers, + # json=pet, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_delete_pet(client: TestClient): + """Test case for delete_pet + + Deletes a pet + """ + + headers = { + "api_key": 'api_key_example', + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "DELETE", + # "/pet/{petId}".format(petId=56), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_find_pets_by_status(client: TestClient): + """Test case for find_pets_by_status + + Finds Pets by status + """ + params = [("status", ['status_example'])] + headers = { + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/pet/findByStatus", + # headers=headers, + # params=params, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_find_pets_by_tags(client: TestClient): + """Test case for find_pets_by_tags + + Finds Pets by tags + """ + params = [("tags", ['tags_example'])] + headers = { + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/pet/findByTags", + # headers=headers, + # params=params, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_get_pet_by_id(client: TestClient): + """Test case for get_pet_by_id + + Find pet by ID + """ + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/pet/{petId}".format(petId=56), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_update_pet(client: TestClient): + """Test case for update_pet + + Update an existing pet + """ + pet = {"photo_urls":["photoUrls","photoUrls"],"name":"doggie","id":0,"category":{"name":"name","id":6},"tags":[{"name":"name","id":1},{"name":"name","id":1}],"status":"available"} + + headers = { + "Authorization": "Bearer special-key", + } + # uncomment below to make a request + #response = client.request( + # "PUT", + # "/pet", + # headers=headers, + # json=pet, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_update_pet_with_form(client: TestClient): + """Test case for update_pet_with_form + + Updates a pet in the store with form data + """ + + headers = { + "Authorization": "Bearer special-key", + } + data = { + "name": 'name_example', + "status": 'status_example' + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/pet/{petId}".format(petId=56), + # headers=headers, + # data=data, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_upload_file(client: TestClient): + """Test case for upload_file + + uploads an image + """ + + headers = { + "Authorization": "Bearer special-key", + } + data = { + "additional_metadata": 'additional_metadata_example', + "file": '/path/to/file' + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/pet/{petId}/uploadImage".format(petId=56), + # headers=headers, + # data=data, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + diff --git a/generated-code/tests/test_store_api.py b/generated-code/tests/test_store_api.py new file mode 100644 index 0000000..05bc4ae --- /dev/null +++ b/generated-code/tests/test_store_api.py @@ -0,0 +1,89 @@ +# coding: utf-8 + +from fastapi.testclient import TestClient + + +from pydantic import Field, StrictInt, StrictStr # noqa: F401 +from typing import Any, Dict # noqa: F401 +from typing_extensions import Annotated # noqa: F401 +from openapi_server.models.order import Order # noqa: F401 + + +def test_delete_order(client: TestClient): + """Test case for delete_order + + Delete purchase order by ID + """ + + headers = { + } + # uncomment below to make a request + #response = client.request( + # "DELETE", + # "/store/order/{orderId}".format(orderId='order_id_example'), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_get_inventory(client: TestClient): + """Test case for get_inventory + + Returns pet inventories by status + """ + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/store/inventory", + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_get_order_by_id(client: TestClient): + """Test case for get_order_by_id + + Find purchase order by ID + """ + + headers = { + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/store/order/{orderId}".format(orderId=56), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_place_order(client: TestClient): + """Test case for place_order + + Place an order for a pet + """ + order = {"pet_id":6,"quantity":1,"id":0,"ship_date":"2000-01-23T04:56:07.000+00:00","complete":0,"status":"placed"} + + headers = { + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/store/order", + # headers=headers, + # json=order, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + diff --git a/generated-code/tests/test_user_api.py b/generated-code/tests/test_user_api.py new file mode 100644 index 0000000..532f04c --- /dev/null +++ b/generated-code/tests/test_user_api.py @@ -0,0 +1,177 @@ +# coding: utf-8 + +from fastapi.testclient import TestClient + + +from pydantic import Field, StrictStr, field_validator # noqa: F401 +from typing import Any, List # noqa: F401 +from typing_extensions import Annotated # noqa: F401 +from openapi_server.models.user import User # noqa: F401 + + +def test_create_user(client: TestClient): + """Test case for create_user + + Create user + """ + user = {"first_name":"firstName","last_name":"lastName","password":"password","user_status":6,"phone":"phone","id":0,"email":"email","username":"username"} + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/user", + # headers=headers, + # json=user, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_create_users_with_array_input(client: TestClient): + """Test case for create_users_with_array_input + + Creates list of users with given input array + """ + user = [{"first_name":"firstName","last_name":"lastName","password":"password","user_status":6,"phone":"phone","id":0,"email":"email","username":"username"}] + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/user/createWithArray", + # headers=headers, + # json=user, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_create_users_with_list_input(client: TestClient): + """Test case for create_users_with_list_input + + Creates list of users with given input array + """ + user = [{"first_name":"firstName","last_name":"lastName","password":"password","user_status":6,"phone":"phone","id":0,"email":"email","username":"username"}] + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "POST", + # "/user/createWithList", + # headers=headers, + # json=user, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_delete_user(client: TestClient): + """Test case for delete_user + + Delete user + """ + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "DELETE", + # "/user/{username}".format(username='username_example'), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_get_user_by_name(client: TestClient): + """Test case for get_user_by_name + + Get user by user name + """ + + headers = { + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/user/{username}".format(username='username_example'), + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_login_user(client: TestClient): + """Test case for login_user + + Logs user into the system + """ + params = [("username", 'username_example'), ("password", 'password_example')] + headers = { + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/user/login", + # headers=headers, + # params=params, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_logout_user(client: TestClient): + """Test case for logout_user + + Logs out current logged in user session + """ + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "GET", + # "/user/logout", + # headers=headers, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 + + +def test_update_user(client: TestClient): + """Test case for update_user + + Updated user + """ + user = {"first_name":"firstName","last_name":"lastName","password":"password","user_status":6,"phone":"phone","id":0,"email":"email","username":"username"} + + headers = { + "api_key": "special-key", + } + # uncomment below to make a request + #response = client.request( + # "PUT", + # "/user/{username}".format(username='username_example'), + # headers=headers, + # json=user, + #) + + # uncomment below to assert the status code of the HTTP response + #assert response.status_code == 200 +