Update pattern to support Perl /pattern/modifiers convention

This commit is contained in:
Scott Williams 2016-05-09 01:11:29 +01:00
parent fed22a1f72
commit 25ebd5466d
6 changed files with 62 additions and 6 deletions

View File

@ -3,15 +3,21 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenParameter; import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.*; import io.swagger.models.properties.*;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@ -21,6 +27,8 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
protected String apiDocPath = "docs/"; protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/"; protected String modelDocPath = "docs/";
protected Map<Character, String> regexModifiers;
private String testFolder; private String testFolder;
public PythonClientCodegen() { public PythonClientCodegen() {
@ -87,6 +95,14 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
"assert", "else", "if", "pass", "yield", "break", "except", "import", "assert", "else", "if", "pass", "yield", "break", "except", "import",
"print", "class", "exec", "in", "raise", "continue", "finally", "is", "print", "class", "exec", "in", "raise", "continue", "finally", "is",
"return", "def", "for", "lambda", "try", "self")); "return", "def", "for", "lambda", "try", "self"));
regexModifiers = new HashMap<Character, String>();
regexModifiers.put('i', "IGNORECASE");
regexModifiers.put('l', "LOCALE");
regexModifiers.put('m', "MULTILINE");
regexModifiers.put('s', "DOTALL");
regexModifiers.put('u', "UNICODE");
regexModifiers.put('x', "VERBOSE");
cliOptions.clear(); cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "python package name (convention: snake_case).") cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "python package name (convention: snake_case).")
@ -143,6 +159,46 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
private static String dropDots(String str) { private static String dropDots(String str) {
return str.replaceAll("\\.", "_"); return str.replaceAll("\\.", "_");
} }
@Override
public void postProcessParameter(CodegenParameter parameter){
postProcessPattern(parameter.pattern, parameter.vendorExtensions);
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
postProcessPattern(property.pattern, property.vendorExtensions);
}
/*
* The swagger pattern spec follows the Perl convention and style of modifiers. Python
* does not support this in as natural a way so it needs to convert it. See
* https://docs.python.org/2/howto/regex.html#compilation-flags for details.
*/
public void postProcessPattern(String pattern, Map<String, Object> vendorExtensions){
if(pattern != null) {
int i = pattern.lastIndexOf('/');
//Must follow Perl /pattern/modifiers convention
if(pattern.charAt(0) != '/' || i < 2) {
throw new IllegalArgumentException("Pattern must follow the Perl "
+ "/pattern/modifiers convention. "+pattern+" is not valid.");
}
String regex = pattern.substring(1, i).replace("'", "\'");
List<String> modifiers = new ArrayList<String>();
for(char c : pattern.substring(i).toCharArray()) {
if(regexModifiers.containsKey(c)) {
String modifier = regexModifiers.get(c);
modifiers.add(modifier);
}
}
vendorExtensions.put("x-regex", regex);
vendorExtensions.put("x-modifiers", modifiers);
}
}
@Override @Override
public CodegenType getTag() { public CodegenType getTag() {

View File

@ -116,7 +116,7 @@ class {{classname}}(object):
raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than or equal to `{{minimum}}`") raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than or equal to `{{minimum}}`")
{{/minimum}} {{/minimum}}
{{#pattern}} {{#pattern}}
if '{{paramName}}' in params and not re.match('{{pattern}}', params['{{paramName}}']): if '{{paramName}}' in params and not re.search('{{vendorExtensions.x-regex}}', params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}):
raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{pattern}}`") raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{pattern}}`")
{{/pattern}} {{/pattern}}
{{/hasValidation}} {{/hasValidation}}

View File

@ -103,7 +103,7 @@ class {{classname}}(object):
raise ValueError("Invalid value for `{{name}}`, must be a value greater than or equal to `{{minimum}}`") raise ValueError("Invalid value for `{{name}}`, must be a value greater than or equal to `{{minimum}}`")
{{/minimum}} {{/minimum}}
{{#pattern}} {{#pattern}}
if not re.match('{{pattern}}', {{name}}): if not re.search('{{vendorExtensions.x-regex}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}):
raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{pattern}}`") raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{pattern}}`")
{{/pattern}} {{/pattern}}
{{/hasValidation}} {{/hasValidation}}

View File

@ -5,7 +5,7 @@ This Python package is automatically generated by the [Swagger Codegen](https://
- API version: 1.0.0 - API version: 1.0.0
- Package version: 1.0.0 - Package version: 1.0.0
- Build date: 2016-05-06T22:43:12.044+01:00 - Build date: 2016-05-09T01:08:25.311+01:00
- Build package: class io.swagger.codegen.languages.PythonClientCodegen - Build package: class io.swagger.codegen.languages.PythonClientCodegen
## Requirements. ## Requirements.

View File

@ -112,8 +112,8 @@ class FakeApi(object):
raise ValueError("Invalid value for parameter `double` when calling `test_endpoint_parameters`, must be a value less than or equal to `123.4`") raise ValueError("Invalid value for parameter `double` when calling `test_endpoint_parameters`, must be a value less than or equal to `123.4`")
if 'double' in params and params['double'] < 67.8: if 'double' in params and params['double'] < 67.8:
raise ValueError("Invalid value for parameter `double` when calling `test_endpoint_parameters`, must be a value greater than or equal to `67.8`") raise ValueError("Invalid value for parameter `double` when calling `test_endpoint_parameters`, must be a value greater than or equal to `67.8`")
if 'string' in params and not re.match('[a-z]+', params['string']): if 'string' in params and not re.search('[a-z]', params['string'], flags=re.IGNORECASE):
raise ValueError("Invalid value for parameter `string` when calling `test_endpoint_parameters`, must conform to the pattern `[a-z]+`") raise ValueError("Invalid value for parameter `string` when calling `test_endpoint_parameters`, must conform to the pattern `/[a-z]/i`")
if 'integer' in params and params['integer'] > 100.0: if 'integer' in params and params['integer'] > 100.0:
raise ValueError("Invalid value for parameter `integer` when calling `test_endpoint_parameters`, must be a value less than or equal to `100.0`") raise ValueError("Invalid value for parameter `integer` when calling `test_endpoint_parameters`, must be a value less than or equal to `100.0`")
if 'integer' in params and params['integer'] < 10.0: if 'integer' in params and params['integer'] < 10.0:

View File

@ -279,7 +279,7 @@ class FormatTest(object):
if not string: if not string:
raise ValueError("Invalid value for `string`, must not be `None`") raise ValueError("Invalid value for `string`, must not be `None`")
if not re.match('/[a-z]/i', string): if not re.search('[a-z]', string, flags=re.IGNORECASE):
raise ValueError("Invalid value for `string`, must be a follow pattern or equal to `/[a-z]/i`") raise ValueError("Invalid value for `string`, must be a follow pattern or equal to `/[a-z]/i`")
self._string = string self._string = string