diff options
-rw-r--r-- | openapi/generate_openapi.py | 140 |
1 files changed, 72 insertions, 68 deletions
diff --git a/openapi/generate_openapi.py b/openapi/generate_openapi.py index 2f206a2d..2a898f0e 100644 --- a/openapi/generate_openapi.py +++ b/openapi/generate_openapi.py @@ -23,12 +23,12 @@ def get_req_body_elems(obj, elems): right = obj.property.name if left == 'req.body' and right not in elems: elems.append(right) - return f'{left}.{right}' + return '{}.{}'.format(left, right) elif obj.type == 'VariableDeclaration': for s in obj.declarations: get_req_body_elems(s, elems) elif obj.type == 'VariableDeclarator': - if obj.id.type == "ObjectPattern": + if obj.id.type == 'ObjectPattern': # get_req_body_elems() can't be called directly here: # const {isAdmin, isNoComments, isCommentOnly} = req.body; right = get_req_body_elems(obj.init, elems) @@ -158,12 +158,14 @@ class EntryPoint(object): def error(self, message): if self._raw_doc is None: - sys.stderr.write(f'in {self.schema.name},\n') - sys.stderr.write(f'{message}\n') + sys.stderr.write('in {},\n'.format(self.schema.name)) + sys.stderr.write('{}\n'.format(message)) return - sys.stderr.write(f'in {self.schema.name}, lines {self._raw_doc.loc.start.line}-{self._raw_doc.loc.end.line}\n') - sys.stderr.write(f'{self._raw_doc.value}\n') - sys.stderr.write(f'{message}\n') + sys.stderr.write('in {}, lines {}-{}\n'.format(self.schema.name, + self._raw_doc.loc.start.line, + self._raw_doc.loc.end.line)) + sys.stderr.write('{}\n'.format(self._raw_doc.value)) + sys.stderr.write('{}\n'.format(message)) @property def doc(self): @@ -233,7 +235,7 @@ class EntryPoint(object): if name.startswith('{'): param_type = name.strip('{}') if param_type not in ['string', 'number', 'boolean', 'integer', 'array', 'file']: - self.error(f'Warning, unknown type {param_type}\n allowed values: string, number, boolean, integer, array, file') + self.error('Warning, unknown type {}\n allowed values: string, number, boolean, integer, array, file'.format(param_type)) try: name, desc = desc.split(maxsplit=1) except ValueError: @@ -246,7 +248,7 @@ class EntryPoint(object): # we should not have 2 identical parameter names if tag in params: - self.error(f'Warning, overwriting parameter {name}') + self.error('Warning, overwriting parameter {}'.format(name)) params[name] = (param_type, optional, desc) @@ -276,7 +278,7 @@ class EntryPoint(object): # we should not have 2 identical tags but @param or @tag if tag in self._doc: - self.error(f'Warning, overwriting tag {tag}') + self.error('Warning, overwriting tag {}'.format(tag)) self._doc[tag] = data @@ -299,7 +301,7 @@ class EntryPoint(object): current_data = '' line = data else: - self.error(f'Unknown tag {tag}, ignoring') + self.error('Unknown tag {}, ignoring'.format(tag)) current_data += line + '\n' @@ -321,24 +323,24 @@ class EntryPoint(object): def print_openapi_param(self, name, indent): ptype, poptional, pdesc = self.doc_param(name) if pdesc is not None: - print(f'{" " * indent}description: |') - print(f'{" " * (indent + 2)}{pdesc}') + print('{}description: |'.format(' ' * indent)) + print('{}{}'.format(' ' * (indent + 2), pdesc)) else: - print(f'{" " * indent}description: the {name} value') + print('{}description: the {} value'.format(' ' * indent, name)) if ptype is not None: - print(f'{" " * indent}type: {ptype}') + print('{}type: {}'.format(' ' * indent, ptype)) else: - print(f'{" " * indent}type: string') + print('{}type: string'.format(' ' * indent)) if poptional: - print(f'{" " * indent}required: false') + print('{}required: false'.format(' ' * indent)) else: - print(f'{" " * indent}required: true') + print('{}required: true'.format(' ' * indent)) @property def operationId(self): if 'operation' in self._doc: return self._doc['operation'] - return f'{self.method_name}_{self.reduced_function_name}' + return '{}_{}'.format(self.method_name, self.reduced_function_name) @property def description(self): @@ -363,49 +365,49 @@ class EntryPoint(object): def print_openapi_return(self, obj, indent): if isinstance(obj, dict): - print(f'{" " * indent}type: object') - print(f'{" " * indent}properties:') + print('{}type: object'.format(' ' * indent)) + print('{}properties:'.format(' ' * indent)) for k, v in obj.items(): - print(f'{" " * (indent + 2)}{k}:') + print('{}{}:'.format(' ' * (indent + 2), k)) self.print_openapi_return(v, indent + 4) elif isinstance(obj, list): if len(obj) > 1: self.error('Error while parsing @return tag, an array should have only one type') - print(f'{" " * indent}type: array') - print(f'{" " * indent}items:') + print('{}type: array'.format(' ' * indent)) + print('{}items:'.format(' ' * indent)) self.print_openapi_return(obj[0], indent + 2) elif isinstance(obj, str) or isinstance(obj, unicode): rtype = 'type: ' + obj if obj == self.schema.name: - rtype = f'$ref: "#/definitions/{obj}"' - print(f'{" " * indent}{rtype}') + rtype = '$ref: "#/definitions/{}"'.format(obj) + print('{}{}'.format(' ' * indent, rtype)) def print_openapi(self): parameters = [token[1:-2] if token.endswith('Id') else token[1:] for token in self.path.split('/') if token.startswith(':')] - print(f' {self.method_name}:') + print(' {}:'.format(self.method_name)) - print(f' operationId: {self.operationId}') + print(' operationId: {}'.format(self.operationId)) if self.summary is not None: - print(f' summary: {self.summary}') + print(' summary: {}'.format(self.summary)) if self.description is not None: - print(f' description: |') + print(' description: |') for line in self.description.split('\n'): if line.strip(): - print(f' {line}') + print(' {}'.format(line)) else: print('') if len(self.tags) > 0: - print(f' tags:') + print(' tags:') for tag in self.tags: - print(f' - {tag}') + print(' - {}'.format(tag)) # export the parameters if self.method_name in ('post', 'put'): @@ -416,14 +418,14 @@ class EntryPoint(object): print(' parameters:') if self.method_name in ('post', 'put'): for f in self.body_params: - print(f''' - name: {f} - in: formData''') + print(''' - name: {} + in: formData'''.format(f)) self.print_openapi_param(f, 10) for p in parameters: if p in self.body_params: self.error(' '.join((p, self.path, self.method_name))) - print(f''' - name: {p} - in: path''') + print(''' - name: {} + in: path'''.format(p)) self.print_openapi_param(p, 10) print(''' produces: - application/json @@ -485,7 +487,9 @@ class SchemaProperty(object): return def __repr__(self): - return f'SchemaProperty({self.name}{"*" if self.required else ""}, {self.doc})' + return 'SchemaProperty({}{}, {})'.format(self.name, + '*' if self.required else '', + self.doc) def print_openapi(self, indent, current_schema, required_properties): schema_name = self.schema.name @@ -501,11 +505,11 @@ class SchemaProperty(object): if required_properties is not None and required_properties: print(' required:') for f in required_properties: - print(f' - {f}') + print(' - {}'.format(f)) required_properties.clear() - print(f''' {subschema}: - type: object''') + print(''' {}: + type: object'''.format(subschema)) return current_schema subschema = name.split('.')[0] @@ -516,23 +520,23 @@ class SchemaProperty(object): if required_properties is not None and required_properties: print(' required:') for f in required_properties: - print(f' - {f}') + print(' - {}'.format(f)) required_properties.clear() - print(f''' {schema_name}: + print(''' {}: type: object - properties:''') + properties:'''.format(schema_name)) if required_properties is not None and self.required: required_properties.append(name) - print(f'{" "*indent}{name}:') + print('{}{}:'.format(' ' * indent, name)) if self.doc is not None: - print(f'{" "*indent} description: |') + print('{} description: |'.format(' ' * indent)) for line in self.doc: if line.strip(): - print(f'{" "*indent} {line}') + print('{} {}'.format(' ' * indent, line)) else: print('') @@ -540,31 +544,31 @@ class SchemaProperty(object): if ptype in ('enum', 'date'): ptype = 'string' if ptype != 'object': - print(f'{" "*indent} type: {ptype}') + print('{} type: {}'.format(' ' * indent, ptype)) if self.type == 'array': - print(f'{" "*indent} items:') + print('{} items:'.format(' ' * indent)) for elem in self.elements: if elem == 'object': - print(f'{" "*indent} $ref: "#/definitions/{schema_name + name.capitalize()}"') + print('{} $ref: "#/definitions/{}"'.format(' ' * indent, schema_name + name.capitalize())) else: - print(f'{" "*indent} type: {elem}') + print('{} type: {}'.format(' ' * indent, elem)) if not self.required: - print(f'{" "*indent} x-nullable: true') + print('{} x-nullable: true'.format(' ' * indent)) elif self.type == 'object': if self.blackbox: - print(f'{" "*indent} type: object') + print('{} type: object'.format(' ' * indent)) else: - print(f'{" "*indent} $ref: "#/definitions/{schema_name + name.capitalize()}"') + print('{} $ref: "#/definitions/{}"'.format(' ' * indent, schema_name + name.capitalize())) elif self.type == 'enum': - print(f'{" "*indent} enum:') + print('{} enum:'.format(' ' * indent)) for enum in self.enum: - print(f'{" "*indent} - {enum}') + print('{} - {}'.format(' ' * indent, enum)) if '.' not in self.name and not self.required: - print(f'{" "*indent} x-nullable: true') + print('{} x-nullable: true'.format(' ' * indent)) return schema_name @@ -620,10 +624,10 @@ class Schemas(object): if self.fields is None: return - print(f' {self.name}:') + print(' {}:'.format(self.name)) print(' type: object') if self.doc is not None: - print(f' description: {self.doc}') + print(' description: {}'.format(self.doc)) print(' properties:') @@ -636,7 +640,7 @@ class Schemas(object): if required_properties: print(' required:') for f in required_properties: - print(f' - {f}') + print(' - {}'.format(f)) # then print the references current = None @@ -648,7 +652,7 @@ class Schemas(object): if required_properties: print(' required:') for f in required_properties: - print(f' - {f}') + print(' - {}'.format(f)) required_properties = [] # then print the references in the references @@ -658,7 +662,7 @@ class Schemas(object): if required_properties: print(' required:') for f in required_properties: - print(f' - {f}') + print(' - {}'.format(f)) def parse_schemas(schemas_dir): @@ -731,10 +735,10 @@ def parse_schemas(schemas_dir): def generate_openapi(schemas, entry_points, version): - print(f'''swagger: '2.0' + print('''swagger: '2.0' info: title: Wekan REST API - version: {version} + version: {0} description: | The REST API allows you to control and extend Wekan with ease. @@ -866,7 +870,7 @@ paths: default: description: | Error in registration -''') +'''.format(version)) # GET and POST on the same path are valid, we need to reshuffle the paths # with the path as the sorting key @@ -880,7 +884,7 @@ paths: sorted_paths.sort() for path in sorted_paths: - print(f' {methods[path][0].url}:') + print(' {}:'.format(methods[path][0].url)) for ep in methods[path]: ep.print_openapi() @@ -897,9 +901,9 @@ paths: def main(): parser = argparse.ArgumentParser(description='Generate an OpenAPI 2.0 from the given JS schemas.') script_dir = os.path.dirname(os.path.realpath(__file__)) - parser.add_argument('--release', default=f'git-master', nargs=1, + parser.add_argument('--release', default='git-master', nargs=1, help='the current version of the API, can be retrieved by running `git describe --tags --abbrev=0`') - parser.add_argument('dir', default=f'{script_dir}/../models', nargs='?', + parser.add_argument('dir', default='{}/../models'.format(script_dir), nargs='?', help='the directory where to look for schemas') args = parser.parse_args() |