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

Commit ac8c62d

Browse files
committed
v2 adds parameter, response, response header modules (#59)
* Adds parameter template and code to write it * Writes module for each parameter * Removes prependFormOrBodyParameters * Sample regenrated * Samples regenerated * Fixes readme example * simplifies setting items and additional_properties var names * Regenerates sample with fixed schema names * Samples regenerated * Fixes java docstirng typo * Fixes JavaModelTest tests * Fixes tests in JavaModelEnumTest * FIxes tests in JavaClientCodegenTest * FIxes tests in DefaultGeneratorTest * FIxes tests in DefaultCodegenTest * Adds HeaderParameterWithoutName to api_client * Sample regenerated, responses are now modules * Moves request body schemas to the root indentation level of the response modules * Adds code to generate response header modules * Updates fromParameter * Sample updated, fixed bug where form param was not seen as body * Samples regenerated * Fixes java tests
1 parent 1f40e26 commit ac8c62d

File tree

560 files changed

+11717
-8789
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

560 files changed

+11717
-8789
lines changed

modules/openapi-json-schema-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

Lines changed: 22 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ apiTemplateFiles are for API outputs only (controllers/handlers).
242242
protected Map<String, String> specialCharReplacements = new LinkedHashMap<>();
243243
// When a model is an alias for a simple type
244244
protected Map<String, String> typeAliases = null;
245-
protected Boolean prependFormOrBodyParameters = false;
246245
// The extension of the generated documentation files (defaults to markdown .md)
247246
protected String docExtension;
248247
protected String ignoreFilePathOverride;
@@ -338,11 +337,6 @@ public void processOpts() {
338337
.get(CodegenConstants.SORT_MODEL_PROPERTIES_BY_REQUIRED_FLAG).toString()));
339338
}
340339

341-
if (additionalProperties.containsKey(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS)) {
342-
this.setPrependFormOrBodyParameters(Boolean.valueOf(additionalProperties
343-
.get(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS).toString()));
344-
}
345-
346340
if (additionalProperties.containsKey(CodegenConstants.ENSURE_UNIQUE_PARAMS)) {
347341
this.setEnsureUniqueParams(Boolean.valueOf(additionalProperties
348342
.get(CodegenConstants.ENSURE_UNIQUE_PARAMS).toString()));
@@ -1339,15 +1333,6 @@ public Boolean getSortModelPropertiesByRequiredFlag() {
13391333
public void setSortModelPropertiesByRequiredFlag(Boolean sortModelPropertiesByRequiredFlag) {
13401334
this.sortModelPropertiesByRequiredFlag = sortModelPropertiesByRequiredFlag;
13411335
}
1342-
1343-
public Boolean getPrependFormOrBodyParameters() {
1344-
return prependFormOrBodyParameters;
1345-
}
1346-
1347-
public void setPrependFormOrBodyParameters(Boolean prependFormOrBodyParameters) {
1348-
this.prependFormOrBodyParameters = prependFormOrBodyParameters;
1349-
}
1350-
13511336
public Boolean getEnsureUniqueParams() {
13521337
return ensureUniqueParams;
13531338
}
@@ -2934,7 +2919,7 @@ public CodegenModel fromModel(String name, Schema schema) {
29342919
m.setFormat(schema.getFormat());
29352920
m.setComposedSchemas(getComposedSchemas(schema));
29362921
if (ModelUtils.isArraySchema(schema)) {
2937-
CodegenProperty arrayProperty = fromProperty(name, schema, false);
2922+
CodegenProperty arrayProperty = fromProperty("items", schema, false);
29382923
m.setItems(arrayProperty.items);
29392924
m.arrayModelType = arrayProperty.complexType;
29402925
addParentContainer(m, name, schema);
@@ -3849,17 +3834,9 @@ public CodegenProperty fromProperty(String name, Schema p, boolean required, boo
38493834
property.xmlName = p.getXml().getName();
38503835
}
38513836

3852-
// handle inner property
3853-
String itemName = null;
3854-
if (p.getExtensions() != null && p.getExtensions().get("x-item-name") != null) {
3855-
itemName = p.getExtensions().get("x-item-name").toString();
3856-
}
3857-
if (itemName == null) {
3858-
itemName = property.name;
3859-
}
38603837
ArraySchema arraySchema = (ArraySchema) p;
38613838
Schema innerSchema = unaliasSchema(getSchemaItems(arraySchema));
3862-
CodegenProperty cp = fromProperty(itemName, innerSchema, false);
3839+
CodegenProperty cp = fromProperty("items", innerSchema, false);
38633840
updatePropertyForArray(property, cp);
38643841
} else if (ModelUtils.isTypeObjectSchema(p)) {
38653842
updatePropertyForObject(property, p);
@@ -4265,7 +4242,7 @@ public CodegenOperation fromOperation(String path,
42654242
for (Entry<String, Header> entry : headers.entrySet()) {
42664243
String headerName = entry.getKey();
42674244
Header header = ModelUtils.getReferencedHeader(this.openAPI, entry.getValue());
4268-
CodegenParameter responseHeader = headerToCodegenParameter(header, headerName, r.imports, String.format(Locale.ROOT, "%sResponseParameter", r.code));
4245+
CodegenParameter responseHeader = headerToCodegenParameter(header, headerName, r.imports, "");
42694246
responseHeaders.add(responseHeader);
42704247
}
42714248
r.setResponseHeaders(responseHeaders);
@@ -4354,11 +4331,8 @@ public CodegenOperation fromOperation(String path,
43544331
setParameterEncodingValues(cp, requestBody.getContent().get(contentType));
43554332
postProcessParameter(cp);
43564333
}
4357-
// add form parameters to the beginning of all parameter list
4358-
if (prependFormOrBodyParameters) {
4359-
for (CodegenParameter cp : formParams) {
4360-
allParams.add(cp.copy());
4361-
}
4334+
if (formParams.size() == 1) {
4335+
bodyParam = formParams.get(0);
43624336
}
43634337
} else {
43644338
// process body parameter
@@ -4374,10 +4348,6 @@ public CodegenOperation fromOperation(String path,
43744348

43754349
bodyParams.add(bodyParam);
43764350

4377-
if (prependFormOrBodyParameters) {
4378-
allParams.add(bodyParam);
4379-
}
4380-
43814351
// add example
43824352
if (schemas != null && !isSkipOperationExample()) {
43834353
op.requestBodyExamples = new ExampleGenerator(schemas, this.openAPI).generate(null, new ArrayList<>(getConsumesInfo(this.openAPI, operation)), bodyParam.baseType);
@@ -4386,20 +4356,14 @@ public CodegenOperation fromOperation(String path,
43864356
}
43874357

43884358
if (parameters != null) {
4359+
Integer i = 0;
43894360
for (Parameter param : parameters) {
43904361
param = ModelUtils.getReferencedParameter(this.openAPI, param);
43914362

4392-
CodegenParameter p = fromParameter(param, imports);
4393-
p.setContent(getContent(param.getContent(), imports, param.getName()));
4394-
4395-
// ensure unique params
4396-
if (ensureUniqueParams) {
4397-
while (!isParameterNameUnique(p, allParams)) {
4398-
p.paramName = generateNextName(p.paramName);
4399-
}
4400-
}
4401-
4363+
CodegenParameter p = fromParameter(param, imports, i.toString());
4364+
p.setContent(getContent(param.getContent(), imports, "schema"));
44024365
allParams.add(p);
4366+
i++;
44034367

44044368
if (param instanceof QueryParameter || "query".equalsIgnoreCase(param.getIn())) {
44054369
queryParams.add(p.copy());
@@ -4416,27 +4380,6 @@ public CodegenOperation fromOperation(String path,
44164380
}
44174381
}
44184382

4419-
// add form/body parameter (if any) to the end of all parameter list
4420-
if (!prependFormOrBodyParameters) {
4421-
for (CodegenParameter cp : formParams) {
4422-
if (ensureUniqueParams) {
4423-
while (!isParameterNameUnique(cp, allParams)) {
4424-
cp.paramName = generateNextName(cp.paramName);
4425-
}
4426-
}
4427-
allParams.add(cp.copy());
4428-
}
4429-
4430-
for (CodegenParameter cp : bodyParams) {
4431-
if (ensureUniqueParams) {
4432-
while (!isParameterNameUnique(cp, allParams)) {
4433-
cp.paramName = generateNextName(cp.paramName);
4434-
}
4435-
}
4436-
allParams.add(cp.copy());
4437-
}
4438-
}
4439-
44404383
// create optional, required parameters
44414384
for (CodegenParameter cp : allParams) {
44424385
if (cp.required) { //required parameters
@@ -4446,6 +4389,14 @@ public CodegenOperation fromOperation(String path,
44464389
op.hasOptionalParams = true;
44474390
}
44484391
}
4392+
if (bodyParam != null) {
4393+
if (bodyParam.required) {
4394+
requiredParams.add(bodyParam.copy());
4395+
} else {
4396+
optionalParams.add(bodyParam.copy());
4397+
op.hasOptionalParams = true;
4398+
}
4399+
}
44494400

44504401
// add imports to operation import tag
44514402
for (String i : imports) {
@@ -4817,7 +4768,7 @@ protected void updateParameterForString(CodegenParameter codegenParameter, Schem
48174768
* @param imports set of imports for library/package/module
48184769
* @return Codegen Parameter object
48194770
*/
4820-
public CodegenParameter fromParameter(Parameter parameter, Set<String> imports) {
4771+
public CodegenParameter fromParameter(Parameter parameter, Set<String> imports, String priorJsonPathFragment) {
48214772
CodegenParameter codegenParameter = CodegenModelFactory.newInstance(CodegenModelType.PARAMETER);
48224773

48234774
codegenParameter.baseName = parameter.getName();
@@ -4851,9 +4802,9 @@ public CodegenParameter fromParameter(Parameter parameter, Set<String> imports)
48514802
parameterModelName = getParameterDataType(parameter, parameterSchema);
48524803
CodegenProperty prop;
48534804
if (getUseInlineModelResolver()) {
4854-
prop = fromProperty(parameter.getName(), getReferencedSchemaWhenNotEnum(parameterSchema), false);
4805+
prop = fromProperty("schema", getReferencedSchemaWhenNotEnum(parameterSchema), false);
48554806
} else {
4856-
prop = fromProperty(parameter.getName(), parameterSchema, false);
4807+
prop = fromProperty("schema", parameterSchema, false);
48574808
}
48584809
codegenParameter.setSchema(prop);
48594810
if (addSchemaImportsFromV3SpecLocations) {
@@ -5042,7 +4993,7 @@ public CodegenParameter fromParameter(Parameter parameter, Set<String> imports)
50424993
if ("multi".equals(collectionFormat)) {
50434994
codegenParameter.isCollectionFormatMulti = true;
50444995
}
5045-
codegenParameter.paramName = toParamName(parameter.getName());
4996+
codegenParameter.paramName = toParamName(priorJsonPathFragment);
50464997
if (!addSchemaImportsFromV3SpecLocations) {
50474998
// import
50484999
if (codegenProperty.complexType != null) {
@@ -7111,7 +7062,7 @@ private CodegenParameter headerToCodegenParameter(Header header, String headerNa
71117062
headerParam.setExample(header.getExample());
71127063
headerParam.setContent(header.getContent());
71137064
headerParam.setExtensions(header.getExtensions());
7114-
CodegenParameter param = fromParameter(headerParam, imports);
7065+
CodegenParameter param = fromParameter(headerParam, imports, headerName);
71157066
param.setContent(getContent(headerParam.getContent(), imports, mediaTypeSchemaSuffix));
71167067
return param;
71177068
}

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

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767

6868
import static org.openapitools.codegen.utils.OnceLogger.once;
6969
import static org.openapitools.codegen.utils.StringUtils.camelize;
70+
import static org.openapitools.codegen.utils.StringUtils.escape;
7071
import static org.openapitools.codegen.utils.StringUtils.underscore;
7172

7273
public class PythonClientCodegen extends AbstractPythonCodegen {
@@ -113,7 +114,10 @@ public PythonClientCodegen() {
113114
importBaseType = false;
114115
addSchemaImportsFromV3SpecLocations = true;
115116
sortModelPropertiesByRequiredFlag = Boolean.TRUE;
116-
sortParamsByRequiredFlag = Boolean.TRUE;
117+
// this must be false for parameter numbers to stay the same as the ones in the spec
118+
// if another schema $refs a schema in a parameter, the json path
119+
// and generated module must have the same parameter index as the spec
120+
sortParamsByRequiredFlag = Boolean.FALSE;
117121
addSuffixToDuplicateOperationNicknames = false;
118122

119123
modifyFeatureSet(features -> features
@@ -588,9 +592,23 @@ protected void generateEndpoints(OperationsMap objs) {
588592
outputFilename = packageFilename(Arrays.asList("paths", pathModuleName, co.httpMethod, "request_body.py"));
589593
pathsFiles.add(Arrays.asList(paramMap, "endpoint_request_body.handlebars", outputFilename));
590594
}
595+
// paths.some_path.post.parameter_0.py
596+
Integer i = 0;
597+
for (CodegenParameter cp: co.allParams) {
598+
Map<String, Object> paramMap = new HashMap<>();
599+
paramMap.put("parameter", cp);
600+
// TODO consolidate imports into body param only
601+
paramMap.put("imports", co.imports);
602+
paramMap.put("packageName", packageName);
603+
outputFilename = packageFilename(Arrays.asList("paths", pathModuleName, co.httpMethod, toParamName(i.toString())+".py"));
604+
pathsFiles.add(Arrays.asList(paramMap, "endpoint_parameter.handlebars", outputFilename));
605+
i++;
606+
}
591607

592608
for (CodegenResponse response: co.responses) {
593-
// paths.some_path.post.response_for_200.py (file per response)
609+
// paths.some_path.post.response_for_200.__init__.py (file per response)
610+
// response is a package because responses have Headers which can be refed
611+
// so each inline header should be a module in the response package
594612
Map<String, Object> responseMap = new HashMap<>();
595613
responseMap.put("response", response);
596614
responseMap.put("packageName", packageName);
@@ -600,8 +618,17 @@ protected void generateEndpoints(OperationsMap objs) {
600618
} else {
601619
responseModuleName += response.code;
602620
}
603-
String responseFilename = packageFilename(Arrays.asList("paths", pathModuleName, co.httpMethod, responseModuleName+ ".py"));
621+
String responseFilename = packageFilename(Arrays.asList("paths", pathModuleName, co.httpMethod, responseModuleName, "__init__.py"));
604622
pathsFiles.add(Arrays.asList(responseMap, "endpoint_response.handlebars", responseFilename));
623+
for (CodegenParameter header: response.getResponseHeaders()) {
624+
Map<String, Object> headerMap = new HashMap<>();
625+
headerMap.put("parameter", header);
626+
// TODO consolidate imports into header param only
627+
headerMap.put("imports", co.imports);
628+
headerMap.put("packageName", packageName);
629+
String headerFilename = packageFilename(Arrays.asList("paths", pathModuleName, co.httpMethod, responseModuleName, toParamName(header.baseName) + ".py"));
630+
pathsFiles.add(Arrays.asList(headerMap, "endpoint_response_header.handlebars", headerFilename));
631+
}
605632
}
606633
/*
607634
This stub file exists to allow pycharm to read and use typing.overload decorators for it to see that
@@ -938,8 +965,8 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
938965
return objs;
939966
}
940967

941-
public CodegenParameter fromParameter(Parameter parameter, Set<String> imports) {
942-
CodegenParameter cp = super.fromParameter(parameter, imports);
968+
public CodegenParameter fromParameter(Parameter parameter, Set<String> imports, String priorJsonPathFragment) {
969+
CodegenParameter cp = super.fromParameter(parameter, imports, priorJsonPathFragment);
943970
if (parameter.getStyle() != null) {
944971
switch(parameter.getStyle()) {
945972
case MATRIX:
@@ -1020,19 +1047,9 @@ public CodegenProperty fromProperty(String name, Schema p, boolean required, boo
10201047
if (cp.isPrimitiveType && unaliasedSchema.get$ref() != null) {
10211048
cp.complexType = cp.dataType;
10221049
}
1023-
setAdditionalPropsAndItemsVarNames(cp);
10241050
return cp;
10251051
}
10261052

1027-
private void setAdditionalPropsAndItemsVarNames(IJsonSchemaValidationProperties item) {
1028-
if (item.getAdditionalProperties() != null) {
1029-
item.getAdditionalProperties().setBaseName("additional_properties");
1030-
}
1031-
if (item.getItems() != null) {
1032-
item.getItems().setBaseName("items");
1033-
}
1034-
}
1035-
10361053
/**
10371054
* checks if the data should be classified as "string" in enum
10381055
* e.g. double in C# needs to be double-quoted (e.g. "2.8") by treating it as a string
@@ -1456,7 +1473,6 @@ public CodegenModel fromModel(String name, Schema sc) {
14561473
cm.setHasMultipleTypes(true);
14571474
}
14581475
Boolean isNotPythonModelSimpleModel = (ModelUtils.isComposedSchema(sc) || ModelUtils.isObjectSchema(sc) || ModelUtils.isMapSchema(sc));
1459-
setAdditionalPropsAndItemsVarNames(cm);
14601476
if (isNotPythonModelSimpleModel) {
14611477
return cm;
14621478
}
@@ -2218,7 +2234,7 @@ protected void setAddProps(Schema schema, IJsonSchemaValidationProperties proper
22182234
if (addPropsSchema == null) {
22192235
return;
22202236
}
2221-
CodegenProperty addPropProp = fromProperty("", addPropsSchema, false, false);
2237+
CodegenProperty addPropProp = fromProperty("additional_properties", addPropsSchema, false, false);
22222238
property.setAdditionalProperties(addPropProp);
22232239
}
22242240

@@ -2736,6 +2752,18 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
27362752
return objs;
27372753
}
27382754

2755+
@Override
2756+
public String toParamName(String name) {
2757+
try {
2758+
Integer.parseInt(name);
2759+
// for parameters in path, or an endpoint
2760+
return "parameter_" + name;
2761+
} catch (NumberFormatException nfe) {
2762+
// for header parameters in responses
2763+
return "parameter_" + toModelFilename(name);
2764+
}
2765+
}
2766+
27392767
@Override
27402768
public void postProcess() {
27412769
System.out.println("################################################################################");

modules/openapi-json-schema-generator/src/main/resources/python/README_common.handlebars

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,16 @@
1-
```python
2-
{{#with apiInfo}}{{#each apis}}{{#unless hasMore}}{{#if hasHttpSignatureMethods}}import datetime{{/if}}{{/unless}}{{/each}}{{/with}}
3-
import time
4-
import {{{packageName}}}
5-
from pprint import pprint
61
{{#with apiInfo}}
72
{{#each apis}}
83
{{#if @first}}
9-
from {{packageName}}.{{apiPackage}}.tags import {{classFilename}}
10-
{{#each imports}}
11-
{{{import}}}
12-
{{/each}}
134
{{#with operations}}
145
{{#each operation}}
156
{{#if @first}}
16-
{{> doc_auth_partial}}
17-
18-
# Enter a context with an instance of the API client
19-
with {{{packageName}}}.ApiClient(configuration) as api_client:
20-
# Create an instance of the API class
21-
api_instance = {{classFilename}}.{{{classname}}}(api_client)
22-
{{#each allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{#unless required}} (optional){{/unless}}{{#if defaultValue}} (default to {{{.}}}){{/if}}
23-
{{/each}}
24-
25-
try:
26-
{{#if summary}} # {{{summary}}}
27-
{{/if}} {{#if returnType}}api_response = {{/if}}api_instance.{{{operationId}}}({{#each allParams}}{{#if required}}{{paramName}}{{/if}}{{#unless required}}{{paramName}}={{paramName}}{{/unless}}{{#if hasMore}}, {{/if}}{{/each}}){{#if returnType}}
28-
pprint(api_response){{/if}}
29-
except {{{packageName}}}.ApiException as e:
30-
print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e)
7+
{{> api_doc_example }}
318
{{/if}}
329
{{/each}}
3310
{{/with}}
3411
{{/if}}
3512
{{/each}}
3613
{{/with}}
37-
```
3814

3915
## Documentation for API Endpoints
4016

0 commit comments

Comments
 (0)