forked from loafle/openapi-generator-original
[python-fastapi] auto generate impl folder (#17852)
* auto generate impl folder * fix working dir * install pytest * add new file * update, fix * test with py 3.9 * fix tests * update doc
This commit is contained in:
parent
b0c9456add
commit
4810dd52c3
33
.github/workflows/samples-python-fastapi-server.yaml
vendored
Normal file
33
.github/workflows/samples-python-fastapi-server.yaml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
name: Python FastAPI Server
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- samples/server/petstore/python-fastapi/**
|
||||
pull_request:
|
||||
paths:
|
||||
- samples/server/petstore/python-fastapi/**
|
||||
jobs:
|
||||
build:
|
||||
name: Test Python FastAPI server
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sample:
|
||||
# servers
|
||||
- samples/server/petstore/python-fastapi/
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
- name: Install dependencies
|
||||
working-directory: ${{ matrix.sample }}
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install pytest
|
||||
- name: Test
|
||||
working-directory: ${{ matrix.sample }}
|
||||
run: PYTHONPATH=src pytest
|
@ -23,7 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
||||
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|
||||
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|
||||
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
|
||||
|fastapiImplementationPackage|python package name for the implementation code (convention: snake_case).| |openapi_server.impl|
|
||||
|fastapiImplementationPackage|python package name for the implementation code (convention: snake_case).| |impl|
|
||||
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|
||||
|packageName|python package name (convention: snake_case).| |openapi_server|
|
||||
|packageVersion|python package version.| |1.0.0|
|
||||
|
@ -126,7 +126,7 @@ public class PythonFastAPIServerCodegen extends AbstractPythonCodegen {
|
||||
apiPackage = "apis";
|
||||
modelPackage = "models";
|
||||
testPackage = "tests";
|
||||
implPackage = DEFAULT_PACKAGE_NAME.concat(".impl");
|
||||
implPackage = "impl";
|
||||
apiTestTemplateFiles().put("api_test.mustache", ".py");
|
||||
|
||||
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "python package name (convention: snake_case).")
|
||||
@ -138,7 +138,7 @@ public class PythonFastAPIServerCodegen extends AbstractPythonCodegen {
|
||||
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "directory for generated python source code")
|
||||
.defaultValue(DEFAULT_SOURCE_FOLDER));
|
||||
cliOptions.add(new CliOption(CodegenConstants.FASTAPI_IMPLEMENTATION_PACKAGE, "python package name for the implementation code (convention: snake_case).")
|
||||
.defaultValue(DEFAULT_PACKAGE_NAME.concat(".impl")));
|
||||
.defaultValue(implPackage));
|
||||
|
||||
}
|
||||
|
||||
@ -178,6 +178,7 @@ public class PythonFastAPIServerCodegen extends AbstractPythonCodegen {
|
||||
}
|
||||
supportingFiles.add(new SupportingFile("__init__.mustache", StringUtils.substringAfter(modelFileFolder(), outputFolder), "__init__.py"));
|
||||
supportingFiles.add(new SupportingFile("__init__.mustache", StringUtils.substringAfter(apiFileFolder(), outputFolder), "__init__.py"));
|
||||
supportingFiles.add(new SupportingFile("__init__.mustache", StringUtils.substringAfter(apiImplFileFolder(), outputFolder), "__init__.py"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("conftest.mustache", testPackage.replace('.', File.separatorChar), "conftest.py"));
|
||||
|
||||
@ -304,6 +305,10 @@ public class PythonFastAPIServerCodegen extends AbstractPythonCodegen {
|
||||
return String.join(File.separator, new String[]{outputFolder, sourceFolder, apiPackage().replace('.', File.separatorChar)});
|
||||
}
|
||||
|
||||
public String apiImplFileFolder() {
|
||||
return String.join(File.separator, new String[]{outputFolder, sourceFolder, implPackage.replace('.', File.separatorChar)});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return String.join(File.separator, new String[]{outputFolder, sourceFolder, modelPackage().replace('.', File.separatorChar)});
|
||||
|
@ -38,14 +38,15 @@ def test_{{operationId}}(client: TestClient):
|
||||
}
|
||||
{{/-last}}
|
||||
{{/formParams}}
|
||||
response = client.request(
|
||||
"{{httpMethod}}",
|
||||
"{{{path}}}"{{#pathParams}}{{#-first}}.format({{/-first}}{{baseName}}={{{example}}}{{^-last}}, {{/-last}}{{#-last}}){{/-last}}{{/pathParams}},
|
||||
headers=headers,{{#bodyParam}}
|
||||
json={{paramName}},{{/bodyParam}}{{#formParams}}{{#-first}}
|
||||
data=data,{{/-first}}{{/formParams}}{{#queryParams}}{{#-first}}
|
||||
params=params,{{/-first}}{{/queryParams}}
|
||||
)
|
||||
# uncomment below to make a request
|
||||
#response = client.request(
|
||||
# "{{httpMethod}}",
|
||||
# "{{{path}}}"{{#pathParams}}{{#-first}}.format({{/-first}}{{baseName}}={{{example}}}{{^-last}}, {{/-last}}{{#-last}}){{/-last}}{{/pathParams}},
|
||||
# headers=headers,{{#bodyParam}}
|
||||
# json={{paramName}},{{/bodyParam}}{{#formParams}}{{#-first}}
|
||||
# data=data,{{/-first}}{{/formParams}}{{#queryParams}}{{#-first}}
|
||||
# params=params,{{/-first}}{{/queryParams}}
|
||||
#)
|
||||
|
||||
# uncomment below to assert the status code of the HTTP response
|
||||
#assert response.status_code == 200
|
||||
|
@ -31,6 +31,6 @@ typing-extensions==3.10.0.0
|
||||
ujson==4.0.2
|
||||
urllib3==1.26.5
|
||||
uvicorn==0.13.4
|
||||
uvloop==0.14.0
|
||||
uvloop==0.19.0
|
||||
watchgod==0.7
|
||||
websockets==10.0
|
||||
|
@ -16,6 +16,7 @@ src/openapi_server/apis/store_api.py
|
||||
src/openapi_server/apis/store_api_base.py
|
||||
src/openapi_server/apis/user_api.py
|
||||
src/openapi_server/apis/user_api_base.py
|
||||
src/openapi_server/impl/__init__.py
|
||||
src/openapi_server/main.py
|
||||
src/openapi_server/models/__init__.py
|
||||
src/openapi_server/models/api_response.py
|
||||
|
@ -31,6 +31,6 @@ typing-extensions==3.10.0.0
|
||||
ujson==4.0.2
|
||||
urllib3==1.26.5
|
||||
uvicorn==0.13.4
|
||||
uvloop==0.14.0
|
||||
uvloop==0.19.0
|
||||
watchgod==0.7
|
||||
websockets==10.0
|
||||
|
@ -13,12 +13,13 @@ def test_fake_query_param_default(client: TestClient):
|
||||
params = [("has_default", 'Hello World'), ("no_default", 'no_default_example')]
|
||||
headers = {
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/fake/query_param_default",
|
||||
headers=headers,
|
||||
params=params,
|
||||
)
|
||||
# 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
|
||||
|
@ -17,12 +17,13 @@ def test_add_pet(client: TestClient):
|
||||
headers = {
|
||||
"Authorization": "Bearer special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"POST",
|
||||
"/pet",
|
||||
headers=headers,
|
||||
json=pet,
|
||||
)
|
||||
# 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
|
||||
@ -38,11 +39,12 @@ def test_delete_pet(client: TestClient):
|
||||
"api_key": 'api_key_example',
|
||||
"Authorization": "Bearer special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"DELETE",
|
||||
"/pet/{petId}".format(petId=56),
|
||||
headers=headers,
|
||||
)
|
||||
# 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
|
||||
@ -57,12 +59,13 @@ def test_find_pets_by_status(client: TestClient):
|
||||
headers = {
|
||||
"Authorization": "Bearer special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/pet/findByStatus",
|
||||
headers=headers,
|
||||
params=params,
|
||||
)
|
||||
# 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
|
||||
@ -77,12 +80,13 @@ def test_find_pets_by_tags(client: TestClient):
|
||||
headers = {
|
||||
"Authorization": "Bearer special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/pet/findByTags",
|
||||
headers=headers,
|
||||
params=params,
|
||||
)
|
||||
# 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
|
||||
@ -97,11 +101,12 @@ def test_get_pet_by_id(client: TestClient):
|
||||
headers = {
|
||||
"api_key": "special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/pet/{petId}".format(petId=56),
|
||||
headers=headers,
|
||||
)
|
||||
# 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
|
||||
@ -117,12 +122,13 @@ def test_update_pet(client: TestClient):
|
||||
headers = {
|
||||
"Authorization": "Bearer special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"PUT",
|
||||
"/pet",
|
||||
headers=headers,
|
||||
json=pet,
|
||||
)
|
||||
# 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
|
||||
@ -141,12 +147,13 @@ def test_update_pet_with_form(client: TestClient):
|
||||
"name": 'name_example',
|
||||
"status": 'status_example'
|
||||
}
|
||||
response = client.request(
|
||||
"POST",
|
||||
"/pet/{petId}".format(petId=56),
|
||||
headers=headers,
|
||||
data=data,
|
||||
)
|
||||
# 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
|
||||
@ -165,12 +172,13 @@ def test_upload_file(client: TestClient):
|
||||
"additional_metadata": 'additional_metadata_example',
|
||||
"file": '/path/to/file'
|
||||
}
|
||||
response = client.request(
|
||||
"POST",
|
||||
"/pet/{petId}/uploadImage".format(petId=56),
|
||||
headers=headers,
|
||||
data=data,
|
||||
)
|
||||
# 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
|
||||
|
@ -14,11 +14,12 @@ def test_delete_order(client: TestClient):
|
||||
|
||||
headers = {
|
||||
}
|
||||
response = client.request(
|
||||
"DELETE",
|
||||
"/store/order/{orderId}".format(orderId='order_id_example'),
|
||||
headers=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
|
||||
@ -33,11 +34,12 @@ def test_get_inventory(client: TestClient):
|
||||
headers = {
|
||||
"api_key": "special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/store/inventory",
|
||||
headers=headers,
|
||||
)
|
||||
# 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
|
||||
@ -51,11 +53,12 @@ def test_get_order_by_id(client: TestClient):
|
||||
|
||||
headers = {
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/store/order/{orderId}".format(orderId=56),
|
||||
headers=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
|
||||
@ -70,12 +73,13 @@ def test_place_order(client: TestClient):
|
||||
|
||||
headers = {
|
||||
}
|
||||
response = client.request(
|
||||
"POST",
|
||||
"/store/order",
|
||||
headers=headers,
|
||||
json=order,
|
||||
)
|
||||
# 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
|
||||
|
@ -16,12 +16,13 @@ def test_create_user(client: TestClient):
|
||||
headers = {
|
||||
"api_key": "special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"POST",
|
||||
"/user",
|
||||
headers=headers,
|
||||
json=user,
|
||||
)
|
||||
# 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
|
||||
@ -37,12 +38,13 @@ def test_create_users_with_array_input(client: TestClient):
|
||||
headers = {
|
||||
"api_key": "special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"POST",
|
||||
"/user/createWithArray",
|
||||
headers=headers,
|
||||
json=user,
|
||||
)
|
||||
# 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
|
||||
@ -58,12 +60,13 @@ def test_create_users_with_list_input(client: TestClient):
|
||||
headers = {
|
||||
"api_key": "special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"POST",
|
||||
"/user/createWithList",
|
||||
headers=headers,
|
||||
json=user,
|
||||
)
|
||||
# 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
|
||||
@ -78,11 +81,12 @@ def test_delete_user(client: TestClient):
|
||||
headers = {
|
||||
"api_key": "special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"DELETE",
|
||||
"/user/{username}".format(username='username_example'),
|
||||
headers=headers,
|
||||
)
|
||||
# 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
|
||||
@ -96,11 +100,12 @@ def test_get_user_by_name(client: TestClient):
|
||||
|
||||
headers = {
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/user/{username}".format(username='username_example'),
|
||||
headers=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
|
||||
@ -114,12 +119,13 @@ def test_login_user(client: TestClient):
|
||||
params = [("username", 'username_example'), ("password", 'password_example')]
|
||||
headers = {
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/user/login",
|
||||
headers=headers,
|
||||
params=params,
|
||||
)
|
||||
# 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
|
||||
@ -134,11 +140,12 @@ def test_logout_user(client: TestClient):
|
||||
headers = {
|
||||
"api_key": "special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"GET",
|
||||
"/user/logout",
|
||||
headers=headers,
|
||||
)
|
||||
# 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
|
||||
@ -154,12 +161,13 @@ def test_update_user(client: TestClient):
|
||||
headers = {
|
||||
"api_key": "special-key",
|
||||
}
|
||||
response = client.request(
|
||||
"PUT",
|
||||
"/user/{username}".format(username='username_example'),
|
||||
headers=headers,
|
||||
json=user,
|
||||
)
|
||||
# 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user