From 6491223ed9c9b5e7a3628d8d6d75e2eae36b7ff8 Mon Sep 17 00:00:00 2001 From: Fleque Date: Thu, 22 Jan 2015 23:01:44 +0100 Subject: [PATCH 1/5] First attempt to port pythong code generation --- .../languages/PythonClientCodegen.java | 117 ++++++++++++++++++ .../com.wordnik.swagger.codegen.CodegenConfig | 3 +- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100755 src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java diff --git a/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java b/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java new file mode 100755 index 00000000000..c3cf3648123 --- /dev/null +++ b/src/main/java/com/wordnik/swagger/codegen/languages/PythonClientCodegen.java @@ -0,0 +1,117 @@ +/** + * Copyright 2014 Wordnik, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.wordnik.swagger.codegen.languages; + +import com.wordnik.swagger.codegen.*; +import com.wordnik.swagger.models.properties.*; + +public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig { + + public String getName() { + return "python"; + } + + public String getHelp() { + return "Generates a Python client library."; + } + + public PythonClientCodegen() { + super(); + outputFolder = "generated-code/python"; + modelTemplateFiles.put("model.mustache", ".py"); + apiTemplateFiles.put("api.mustache", ".py"); + templateDir = "python"; + + apiPackage = ""; + modelPackage = "models"; + + languageSpecificPrimitives.clear(); + languageSpecificPrimitives.add("int"); + languageSpecificPrimitives.add("float"); + languageSpecificPrimitives.add("long"); + languageSpecificPrimitives.add("list"); + languageSpecificPrimitives.add("bool"); + languageSpecificPrimitives.add("str"); + languageSpecificPrimitives.add("datetime"); + + typeMapping.clear(); + typeMapping.put("integer", "int"); + typeMapping.put("float", "float"); + typeMapping.put("long", "long"); + typeMapping.put("double", "float"); + typeMapping.put("array", "list"); + typeMapping.put("map", "map"); + typeMapping.put("boolean", "bool"); + typeMapping.put("string", "str"); + typeMapping.put("date", "datetime"); + + + supportingFiles.add(new SupportingFile("swagger.mustache", "", "swagger.py")); + supportingFiles.add(new SupportingFile("__init__.mustache", "", "__init__.py")); + supportingFiles.add(new SupportingFile("__init__.mustache", modelPackage, "__init__.py")); + + } + + @Override + public String escapeReservedWord(String name) { + return "_" + name; + } + + @Override + public String apiFileFolder() { + return outputFolder + "/" + apiPackage().replaceAll("\\.", "/"); + } + + public String modelFileFolder() { + return outputFolder + "/" + modelPackage().replaceAll("\\.", "/"); + } + + @Override + public String getTypeDeclaration(Property p) { + if(p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]"; + } + else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + + return getSwaggerType(p) + "(String, " + getTypeDeclaration(inner) + ")"; + } + return super.getTypeDeclaration(p); + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type = null; + if(typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if(languageSpecificPrimitives.contains(type)) { + return type; + } + } + else + type = swaggerType; + return type; + } + + public String toDefaultValue(Property p) { + // TODO: Support Python def value + return "null"; + } +} diff --git a/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig b/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig index 6930e094927..6d2443369db 100644 --- a/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig +++ b/src/main/resources/META-INF/services/com.wordnik.swagger.codegen.CodegenConfig @@ -8,4 +8,5 @@ com.wordnik.swagger.codegen.languages.StaticDocCodegen com.wordnik.swagger.codegen.languages.StaticHtmlGenerator com.wordnik.swagger.codegen.languages.SwaggerGenerator com.wordnik.swagger.codegen.languages.TizenClientCodegen -com.wordnik.swagger.codegen.languages.PhpClientCodegen \ No newline at end of file +com.wordnik.swagger.codegen.languages.PhpClientCodegen +com.wordnik.swagger.codegen.languages.PythonClientCodegen \ No newline at end of file From 556485538fca9e972bf83181fb99ed97552bdd68 Mon Sep 17 00:00:00 2001 From: Ikuo Matsumura Date: Sat, 24 Jan 2015 16:07:12 +0900 Subject: [PATCH 2/5] Added @JsonProperty to Java/model.mustache --- src/main/resources/Java/model.mustache | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/resources/Java/model.mustache b/src/main/resources/Java/model.mustache index 0d60aedd068..60aa5d72a35 100644 --- a/src/main/resources/Java/model.mustache +++ b/src/main/resources/Java/model.mustache @@ -4,6 +4,7 @@ package {{package}}; {{/imports}} import com.wordnik.swagger.annotations.*; +import com.fasterxml.jackson.annotation.JsonProperty; {{#models}} {{#model}}{{#description}} @@ -24,6 +25,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} { {{#vars} * maximum: {{maximum}}{{/maximum}} **/ @ApiModelProperty(required = {{required}}, value = "{{{description}}}") + @JsonProperty("{{name}}") public {{{datatype}}} {{getter}}() { return {{name}}; } @@ -44,4 +46,4 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} { {{#vars} } } {{/model}} -{{/models}} \ No newline at end of file +{{/models}} From ea11b4fc35043e1b72c344e80a3e0621e69efdb4 Mon Sep 17 00:00:00 2001 From: Ikuo Matsumura Date: Sat, 24 Jan 2015 16:17:40 +0900 Subject: [PATCH 3/5] Added spec on upper-case property name --- src/test/scala/Java/JavaModelTest.scala | 28 ++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/test/scala/Java/JavaModelTest.scala b/src/test/scala/Java/JavaModelTest.scala index 7e1cd709340..b747268b874 100644 --- a/src/test/scala/Java/JavaModelTest.scala +++ b/src/test/scala/Java/JavaModelTest.scala @@ -239,4 +239,30 @@ class JavaModelTest extends FlatSpec with Matchers { cm.imports.size should be (3) (cm.imports.asScala.toSet & Set("Map", "HashMap", "Children")).size should be (3) } -} \ No newline at end of file + + it should "convert a model with upper-case property name" in { + val model = new ModelImpl() + .description("a model with upper-case property name") + .property("NAME", new StringProperty()) + .required("NAME") + + val codegen = new JavaClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.vars.size should be (1) + + val vars = cm.vars + vars.get(0).baseName should be ("NAME") + vars.get(0).getter should be ("getNAME") + vars.get(0).setter should be ("setNAME") + vars.get(0).datatype should be ("String") + vars.get(0).name should be ("NAME") + vars.get(0).defaultValue should be ("null") + vars.get(0).baseType should be ("String") + vars.get(0).hasMore should equal (null) + vars.get(0).required should equal (true) + vars.get(0).isNotContainer should equal (true) + } +} From b49572005bce2bd18ed11328af471da6dd5234bc Mon Sep 17 00:00:00 2001 From: Ikuo Matsumura Date: Sat, 24 Jan 2015 16:32:38 +0900 Subject: [PATCH 4/5] Fix typo name{ -> s} --- src/test/scala/Java/JavaModelTest.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/scala/Java/JavaModelTest.scala b/src/test/scala/Java/JavaModelTest.scala index b747268b874..513786e4609 100644 --- a/src/test/scala/Java/JavaModelTest.scala +++ b/src/test/scala/Java/JavaModelTest.scala @@ -240,9 +240,9 @@ class JavaModelTest extends FlatSpec with Matchers { (cm.imports.asScala.toSet & Set("Map", "HashMap", "Children")).size should be (3) } - it should "convert a model with upper-case property name" in { + it should "convert a model with upper-case property names" in { val model = new ModelImpl() - .description("a model with upper-case property name") + .description("a model with upper-case property names") .property("NAME", new StringProperty()) .required("NAME") From 35dc8d4e5dbc04dd877f4cbf459e0d4f60354e8a Mon Sep 17 00:00:00 2001 From: Fleque Date: Tue, 27 Jan 2015 22:47:49 +0100 Subject: [PATCH 5/5] Fix for the selection of the methodResponse from an operation during code generation. Now all the smallest 2xx code is used --- .../java/com/wordnik/swagger/codegen/DefaultCodegen.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java b/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java index 480e092b74e..98dcb7bcee3 100644 --- a/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java +++ b/src/main/java/com/wordnik/swagger/codegen/DefaultCodegen.java @@ -4,6 +4,7 @@ import com.wordnik.swagger.models.*; import com.wordnik.swagger.models.parameters.*; import com.wordnik.swagger.models.properties.*; import com.wordnik.swagger.util.Json; + import org.apache.commons.lang.StringUtils; import java.util.*; @@ -577,10 +578,12 @@ public class DefaultCodegen { } if(operation.getResponses() != null) { - for(String responseCode: operation.getResponses().keySet()) { + for(String responseCode: new TreeSet(operation.getResponses().keySet())) { Response response = operation.getResponses().get(responseCode); - if("200".equals(responseCode)) { + if (responseCode.startsWith("2")) { + // use the first, i.e. the smallest 2xx response status as methodResponse methodResponse = response; + break; } } if(methodResponse == null && operation.getResponses().keySet().contains("default")) {