Skip to content

Commit 47b8dfe

Browse files
authored
Merge pull request #2 from guokr/master
merge
2 parents 3c5360c + 841abfe commit 47b8dfe

23 files changed

+185
-56
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ dist/
77
*.egg-info
88
*.egg
99
.idea
10+
*~
11+
*.pyc

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
language: python
22
python:
33
- "2.7"
4+
- "3.5"
45
install:
56
- python setup.py install
67
before_script:

AUTHORS

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ Contributors:
77

88
* yimiqisan (yimiqisan@gmail.com);
99
* softlns (softliunaisen@gmai.com);
10+
* Justin (justinli.ljt@gmail.com);
1011
* teknolog2000 (https://github.com/teknolog2000);
1112
* ChaosEternal (https://github.com/ChaosEternal);
1213
* SimplicityGuy (https://github.com/SimplicityGuy);
14+
* Roy Williams (https://github.com/rowillia);
15+
* Vinod Gupta (https://github.com/codervinod)

setup.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
from __future__ import absolute_import
12
import re
23
import ast
34
from setuptools import setup
45

56
_version_re = re.compile(r'__version__\s+=\s+(.*)')
67

7-
with open('swagger_py_codegen/__init__.py', 'rb') as f:
8+
with open('swagger_py_codegen/_version.py', 'rb') as f:
89
version = str(ast.literal_eval(_version_re.search(
910
f.read().decode('utf-8')).group(1)))
1011

@@ -23,11 +24,12 @@
2324
'swagger_py_codegen=swagger_py_codegen:generate'
2425
]
2526
},
26-
install_requires=['PyYAML', 'click', 'jinja2', 'dpath'],
27+
install_requires=['PyYAML', 'click', 'jinja2', 'dpath', 'six'],
2728
tests_require=['pytest'],
2829
classifiers=[
2930
'Development Status :: 3 - Alpha',
3031
'License :: OSI Approved :: MIT License',
3132
'Programming Language :: Python :: 2.7',
33+
'Programming Language :: Python :: 3',
3234
],
3335
)

swagger_py_codegen/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
from .command import generate
1+
from __future__ import absolute_import
22

3-
__version__ = '0.1.19'
3+
from ._version import __version__
4+
from .command import generate

swagger_py_codegen/__main__.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import absolute_import
2+
13
from .command import generate
24

35
generate()

swagger_py_codegen/_version.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"""Version information."""
2+
3+
# The following line *must* be the last in the module, exactly as formatted:
4+
__version__ = "0.2.4"

swagger_py_codegen/base.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import absolute_import
12
import os
23

34
from jinja2 import Environment, FileSystemLoader

swagger_py_codegen/command.py

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
from __future__ import absolute_import
12
import codecs
23
try:
34
import simplejson as json
45
except ImportError:
56
import json
7+
from multiprocessing import Pool
68
from os import makedirs
79
from os.path import join, exists, dirname
810

911
import yaml
1012
import click
1113

14+
from ._version import __version__
1215
from .flask import FlaskGenerator
1316
from .parser import Swagger
1417
from .base import Template
@@ -53,6 +56,13 @@ def _copy_ui_dir(ui_dest, ui_src):
5356
return status
5457

5558

59+
def print_version(ctx, param, value):
60+
if not value or ctx.resilient_parsing:
61+
return
62+
click.echo('current version: %s' % __version__)
63+
ctx.exit()
64+
65+
5666
@click.command()
5767
@click.argument('destination', required=True)
5868
@click.option('-s', '--swagger', '--swagger-doc',
@@ -69,12 +79,17 @@ def _copy_ui_dir(ui_dest, ui_src):
6979
@click.option('--ui',
7080
default=False, is_flag=True,
7181
help='Generate swagger ui.')
82+
@click.option('-j', '--jobs',
83+
default=4, help='Parallel jobs for processing.')
84+
@click.option('--version', is_flag=True, callback=print_version,
85+
expose_value=False, is_eager=True,
86+
help='Show current version.')
7287
def generate(destination, swagger_doc, force=False, package=None,
73-
template_dir=None, specification=False, ui=False):
74-
88+
template_dir=None, specification=False, ui=False, jobs=4):
89+
pool = Pool(processes=int(jobs))
7590
package = package or destination.replace('-', '_')
7691
data = spec_load(swagger_doc)
77-
swagger = Swagger(data)
92+
swagger = Swagger(data, pool)
7893
generator = FlaskGenerator(swagger)
7994
generator.with_spec = specification
8095
generator.with_ui = ui

swagger_py_codegen/flask.py

+20-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from __future__ import absolute_import
12
import re
23
from collections import OrderedDict
34

45
from .base import Code, CodeGenerator
56
from .jsonschema import Schema, SchemaGenerator, build_default
7+
import six
68

79
SUPPORT_METHODS = ['get', 'post', 'put', 'delete', 'patch', 'options', 'head']
810

@@ -94,13 +96,21 @@ def _type(parameters):
9496

9597
return url, params
9698

99+
if six.PY3:
100+
def _remove_characters(text, deletechars):
101+
return text.translate({ord(x): None for x in deletechars})
102+
else:
103+
def _remove_characters(text, deletechars):
104+
return text.translate(None, deletechars)
97105

98106
def _path_to_endpoint(swagger_path):
99-
return swagger_path.strip('/').replace('/', '_').replace('-', '_').translate(None, '{}')
107+
return _remove_characters(
108+
swagger_path.strip('/').replace('/', '_').replace('-', '_'),
109+
'{}')
100110

101111

102112
def _path_to_resource_name(swagger_path):
103-
return swagger_path.title().translate(None, '{}/_-')
113+
return _remove_characters(swagger_path.title(), '{}/_-')
104114

105115

106116
def _location(swagger_location):
@@ -130,18 +140,18 @@ def _dependence_callback(self, code):
130140
# use flask endpoint to replace default validator's key,
131141
# example: `('some_path_param', 'method')`
132142
validators = OrderedDict()
133-
for k, v in schemas.data['validators'].iteritems():
134-
locations = {_location(loc): val for loc, val in v.iteritems()}
143+
for k, v in six.iteritems(schemas.data['validators']):
144+
locations = {_location(loc): val for loc, val in six.iteritems(v)}
135145
validators[(_path_to_endpoint(k[0]), k[1])] = locations
136146

137147
# filters
138148
filters = OrderedDict()
139-
for k, v in schemas.data['filters'].iteritems():
149+
for k, v in six.iteritems(schemas.data['filters']):
140150
filters[(_path_to_endpoint(k[0]), k[1])] = v
141151

142152
# scopes
143153
scopes = OrderedDict()
144-
for k, v in schemas.data['scopes'].iteritems():
154+
for k, v in six.iteritems(schemas.data['scopes']):
145155
scopes[(_path_to_endpoint(k[0]), k[1])] = v
146156

147157
schemas.data['validators'] = validators
@@ -169,11 +179,12 @@ def _process_data(self):
169179
methods[method] = {}
170180
validator = self.validators.get((endpoint, method.upper()))
171181
if validator:
172-
methods[method]['requests'] = validator.keys()
182+
methods[method]['requests'] = list(validator.keys())
173183

174-
for status, res_data in data[method].get('responses', {}).iteritems():
184+
for status, res_data in six.iteritems(data[method].get('responses', {})):
175185
if isinstance(status, int) or status.isdigit():
176-
example = res_data.get('schema', {}).get('application/json')
186+
example = res_data.get('examples', {}).get('application/json')
187+
177188
if not example:
178189
example = build_default(res_data.get('schema'))
179190
response = example, int(status), build_default(res_data.get('headers'))

swagger_py_codegen/jsonschema.py

+19-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from __future__ import absolute_import
12
from collections import OrderedDict
23
from inspect import getsource
34

45
from .base import Code, CodeGenerator
56
from .parser import schema_var_name
7+
import six
68

79

810
class Schema(Code):
@@ -74,7 +76,7 @@ def build_data(swagger):
7476
responses = data.get('responses')
7577
if responses:
7678
filter = {}
77-
for status, res_data in responses.iteritems():
79+
for status, res_data in six.iteritems(responses):
7880
if isinstance(status, int) or status.isdigit():
7981
filter[int(status)] = dict(
8082
headers=res_data.get('headers'),
@@ -84,7 +86,7 @@ def build_data(swagger):
8486

8587
# scopes
8688
for security in data.get('security', []):
87-
scopes[(endpoint, method)] = security.values().pop()
89+
scopes[(endpoint, method)] = list(security.values()).pop()
8890
break
8991

9092
schemas = OrderedDict([(schema_var_name(path), swagger.get(path)) for path in swagger.definitions])
@@ -106,7 +108,7 @@ def _process(self):
106108
yield Schema(build_data(self.swagger))
107109

108110

109-
def merge_default(schema, value):
111+
def merge_default(schema, value, get_first=True):
110112
# TODO: more types support
111113
type_defaults = {
112114
'integer': 9573,
@@ -116,7 +118,10 @@ def merge_default(schema, value):
116118
'boolean': False
117119
}
118120

119-
return normalize(schema, value, type_defaults)[0]
121+
results = normalize(schema, value, type_defaults)
122+
if get_first:
123+
return results[0]
124+
return results
120125

121126

122127
def build_default(schema):
@@ -125,6 +130,8 @@ def build_default(schema):
125130

126131
def normalize(schema, data, required_defaults=None):
127132

133+
import six
134+
128135
if required_defaults is None:
129136
required_defaults = {}
130137
errors = []
@@ -147,8 +154,8 @@ def has(self, key):
147154

148155
def keys(self):
149156
if isinstance(self.data, dict):
150-
return self.data.keys()
151-
return vars(self.data).keys()
157+
return list(self.data.keys())
158+
return list(vars(self.data).keys())
152159

153160
def get_check(self, key, default=None):
154161
if isinstance(self.data, dict):
@@ -169,13 +176,9 @@ def _normalize_dict(schema, data):
169176
if not isinstance(data, DataWrapper):
170177
data = DataWrapper(data)
171178

172-
for key, _schema in schema.get('properties', {}).iteritems():
179+
for key, _schema in six.iteritems(schema.get('properties', {})):
173180
# set default
174181
type_ = _schema.get('type', 'object')
175-
if ('default' not in _schema
176-
and key in schema.get('required', [])
177-
and type_ in required_defaults):
178-
_schema['default'] = required_defaults[type_]
179182

180183
# get value
181184
value, has_key = data.get_check(key)
@@ -184,8 +187,11 @@ def _normalize_dict(schema, data):
184187
elif 'default' in _schema:
185188
result[key] = _schema['default']
186189
elif key in schema.get('required', []):
187-
errors.append(dict(name='property_missing',
188-
message='`%s` is required' % key))
190+
if type_ in required_defaults:
191+
result[key] = required_defaults[type_]
192+
else:
193+
errors.append(dict(name='property_missing',
194+
message='`%s` is required' % key))
189195

190196
for _schema in schema.get('allOf', []):
191197
rs_component = _normalize(_schema, data)

0 commit comments

Comments
 (0)