|
| 1 | +import codecs |
| 2 | +try: |
| 3 | + import simplejson as json |
| 4 | +except ImportError: |
| 5 | + import json |
| 6 | +from os import makedirs |
| 7 | +from os.path import join, exists, dirname |
| 8 | + |
| 9 | +import yaml |
| 10 | +import click |
| 11 | + |
| 12 | +from .flask import FlaskGenerator |
| 13 | +from .parser import Swagger |
| 14 | +from .base import Template |
| 15 | + |
| 16 | + |
| 17 | +def spec_load(filename): |
| 18 | + if filename.endswith('.json'): |
| 19 | + loader = json.load |
| 20 | + elif filename.endswith('.yml') or filename.endswith('.yaml'): |
| 21 | + loader = yaml.load |
| 22 | + else: |
| 23 | + with codecs.open(filename, 'r', 'utf-8') as f: |
| 24 | + contents = f.read() |
| 25 | + contents = contents.strip() |
| 26 | + if contents[0] in ['{', '[']: |
| 27 | + loader = json.load |
| 28 | + else: |
| 29 | + loader = yaml.load |
| 30 | + with codecs.open(filename, 'r', 'utf-8') as f: |
| 31 | + return loader(f) |
| 32 | + |
| 33 | + |
| 34 | +def write(dist, content): |
| 35 | + dir_ = dirname(dist) |
| 36 | + if not exists(dir_): |
| 37 | + makedirs(dir_) |
| 38 | + with codecs.open(dist, 'w', 'utf-8') as f: |
| 39 | + f.write(content) |
| 40 | + |
| 41 | + |
| 42 | +def _copy_ui_dir(ui_dest, ui_src): |
| 43 | + from distutils.dir_util import copy_tree |
| 44 | + from os import unlink |
| 45 | + |
| 46 | + if exists(ui_dest): |
| 47 | + status = 'skip' |
| 48 | + else: |
| 49 | + status = 'generate' |
| 50 | + makedirs(ui_dest) |
| 51 | + copy_tree(ui_src, ui_dest) |
| 52 | + unlink(join(ui_dest, 'index.html')) |
| 53 | + return status |
| 54 | + |
| 55 | + |
| 56 | +@click.command() |
| 57 | +@click.argument('destination', required=True) |
| 58 | +@click.option('-s', '--swagger', '--swagger-doc', |
| 59 | + required=True, help='Swagger doc file.') |
| 60 | +@click.option('-f', '--force', |
| 61 | + default=False, is_flag=True, help='Force overwrite.') |
| 62 | +@click.option('-p', '--package', |
| 63 | + help='Package name / application name.') |
| 64 | +@click.option('-t', '--template-dir', |
| 65 | + help='Path of your custom templates directory.') |
| 66 | +@click.option('--spec', '--specification', |
| 67 | + default=False, is_flag=True, |
| 68 | + help='Generate online specification json response.') |
| 69 | +@click.option('--ui', |
| 70 | + default=False, is_flag=True, |
| 71 | + help='Generate swagger ui.') |
| 72 | +def generate(destination, swagger_doc, force=False, package=None, |
| 73 | + template_dir=None, specification=False, ui=False): |
| 74 | + |
| 75 | + package = package or destination.replace('-', '_') |
| 76 | + data = spec_load(swagger_doc) |
| 77 | + swagger = Swagger(data) |
| 78 | + generator = FlaskGenerator(swagger) |
| 79 | + generator.with_spec = specification |
| 80 | + generator.with_ui = ui |
| 81 | + template = Template() |
| 82 | + if template_dir: |
| 83 | + template.add_searchpath(template_dir) |
| 84 | + env = dict(package=package, |
| 85 | + module=swagger.module_name) |
| 86 | + |
| 87 | + if ui: |
| 88 | + ui_dest = join(destination, '%(package)s/static/swagger-ui' % env) |
| 89 | + ui_src = join(dirname(__file__), 'templates/ui') |
| 90 | + status = _copy_ui_dir(ui_dest, ui_src) |
| 91 | + click.secho('%-12s%s' % (status, ui_dest)) |
| 92 | + |
| 93 | + for code in generator.generate(): |
| 94 | + source = template.render_code(code) |
| 95 | + dest = join(destination, code.dest(env)) |
| 96 | + dest_exists = exists(dest) |
| 97 | + can_override = force or code.override |
| 98 | + statuses = { |
| 99 | + (False, False): 'generate', |
| 100 | + (False, True): 'generate', |
| 101 | + (True, False): 'skip', |
| 102 | + (True, True): 'override' |
| 103 | + } |
| 104 | + status = statuses[(dest_exists, can_override)] |
| 105 | + click.secho('%-12s' % status, nl=False) |
| 106 | + click.secho(dest) |
| 107 | + |
| 108 | + if status != 'skipped': |
| 109 | + write(dest, source) |
| 110 | + |
0 commit comments