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() {
@ -88,6 +96,14 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
"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).")
.defaultValue("swagger_client")); .defaultValue("swagger_client"));
@ -144,6 +160,46 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
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() {
return CodegenType.CLIENT; return CodegenType.CLIENT;

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