def build_openapi_spec(publish): """Creates an OpenAPI definition of Flask application, check conformity of generated definition against OpenAPI 2.0 specification and writes it into a file.""" package = __title__ desc = __api_description__ ver = __version__ # Create OpenAPI specification object spec = APISpec(title=package, version=ver, info=dict(description=desc), plugins=('apispec.ext.flask', 'apispec.ext.marshmallow')) # Add marshmallow schemas to the specification here # spec.definition('Example', schema=Example_schema) # Collect OpenAPI docstrings from Flask endpoints for key in current_app.view_functions: if key != 'static' and key != 'get_openapi_spec': spec.add_path(view=current_app.view_functions[key]) spec_json = json.dumps(spec.to_dict(), indent=2, separators=(',', ': '), sort_keys=True) # Output spec to JSON file with click.open_file(__output_path__, mode='w+', encoding=None, errors='strict', lazy=False, atomic=False) as output_file: output_file.write(spec_json) click.echo( click.style('OpenAPI specification written to {}'.format( output_file.name), fg='green')) # Check that generated spec passes validation. Done after writing to file # in order to give user easy way to access the possible erroneous spec. with open(os.path.join(os.getcwd(), __output_path__)) as output_file: validate_json(json.load(output_file), 'schemas/v2.0/schema.json') click.echo( click.style('OpenAPI specification validated successfully', fg='green')) if publish: copy_openapi_specs(__output_path__, 'reana-workflow-controller') return spec.to_dict()
def get_json(app: Chalice, route_functions: dict, route_prefix: str, version="1.0.0"): spec = APISpec( title=app.app_name, version=version, openapi_version="3.0.2", plugins=[generate_plugin(app)(), MarshmallowPlugin()], servers=[{ "url": f"/{route_prefix}", "description": f"Host on /" }], ) fn_list = {[fn_name.view_name for fn_name in r.values()][0] for path, r in app.routes.items()} for fn_name in [ fn_name for fn_name in fn_list if fn_name in route_functions ]: try: spec.path(view=route_functions[fn_name]) except (TypeError, KeyError, ValueError) as e: logging.warning(f"Error parsing docstring: {e}") return json.dumps(spec.to_dict())
def get_specification(self): spec = APISpec( title=self.__class__.__name__, version='1.0.0', plugins=( 'apispec.ext.flask', 'apispec.ext.marshmallow', ), ) class PetSchema(Schema): id = fields.Int() name = fields.Str() app = Flask(__name__) @app.route('/random') def random_pet(): """A cute furry animal endpoint. --- get: description: Get a random pet responses: 200: description: A pet to be returned schema: PetSchema """ return jsonify({}) # Register entities and paths spec.definition('Pet', schema=PetSchema) with app.test_request_context(): spec.add_path(view=random_pet) return json.dumps(spec.to_dict(), indent=4)
def api_spec(request): """ Serve the spec to explorer """ spec = APISpec( title="Some API", version="1.0.0", openapi_version="2.0", plugins=[MarshmallowPlugin()], ) # using marshmallow plugin here spec.components.schema("FooBodySchema", schema=validation.FooBodySchema) spec.components.schema("BarBodySchema", schema=validation.BarBodySchema(many=True)) # register API security scheme api_auth_scheme = {"type": "apiKey", "in": "header", "name": "Authorization"} spec.components.security_scheme("APIKeyHeader", api_auth_scheme) # inspect the `foo_route` and generate operations from docstring add_pyramid_paths(spec, "users", request=request) # inspection supports filtering via pyramid add_view predicate arguments add_pyramid_paths(spec, "bar_route", request=request) my_spec = spec.to_dict() # you can further mutate the spec dict to include things like security definitions return my_spec
def test_oauth2_authentication_documentation(): app = Starlette() plugin = StarlettePlugin(app) spec = APISpec( title="Test API", version="0.0.1", openapi_version="2.0", plugins=[plugin] ) document_oauth2_authentication( spec, authorization_url="http://test", flow="implicit", scopes={"scope1": "Description of scope1", "scope2": "Description of scope2"}, ) assert spec.to_dict() == { "info": {"title": "Test API", "version": "0.0.1"}, "paths": {}, "securityDefinitions": { "oauth2": { "authorizationUrl": "http://test", "flow": "implicit", "scopes": { "scope1": "Description of " "scope1", "scope2": "Description of " "scope2", }, "type": "oauth2", } }, "swagger": "2.0", }
def update_api_docs() -> None: """Regenerate the openapi.json file in docs""" superset_dir = os.path.abspath(os.path.dirname(__file__)) openapi_json = os.path.join( superset_dir, "..", "docs", "src", "resources", "openapi.json" ) api_version = "v1" version_found = False api_spec = APISpec( title=current_app.appbuilder.app_name, version=api_version, openapi_version="3.0.2", info=dict(description=current_app.appbuilder.app_name), plugins=[MarshmallowPlugin(schema_name_resolver=resolver)], servers=[{"url": "http://localhost:8088"}], ) for base_api in current_app.appbuilder.baseviews: if isinstance(base_api, BaseApi) and base_api.version == api_version: base_api.add_api_spec(api_spec) version_found = True if version_found: click.secho("Generating openapi.json", fg="green") with open(openapi_json, "w") as outfile: json.dump(api_spec.to_dict(), outfile, sort_keys=True, indent=2) else: click.secho("API version not found", err=True)
class Spec: def __init__(self, api, title, version): self.obj = API_Spec(title=title, version=version, openapi_version='2.0', produces=['application/json'], consumes=['application/json'], tags=rc_tags, plugins=[Falcon_Plugin(api), Marshmallow_Plugin(schema_name_resolver=self.__schema_name_resolver)]) def get(self): return self.obj def write(self): path = Path(__file__).parent / '../swagger/schema.yaml' with path.open('w') as file: file.write(self.obj.to_yaml()) path = Path(__file__).parent / '../swagger/schema.json' with path.open('w') as file: file.write(dumps(self.obj.to_dict(), indent=2)) @staticmethod def __schema_name_resolver(schema): if is_str(schema): ref = schema else: ref = schema.__class__.__name__ return ref.replace('_Schema', '')
def test_with_exception_handlers_in_app_without_status_code_but_yaml_docstring( ): async def handle_exception(request: Request, exc: HTTPException): """ required: - message properties: message: type: string description: Description of the error. example: This is a description of the error. type: object """ pass # pragma: no cover app = Starlette(exception_handlers={HTTPException: handle_exception}) spec = APISpec( title="Test API", version="0.0.1", openapi_version="2.0", plugins=[StarlettePlugin(app)], ) assert spec.to_dict() == { "info": { "title": "Test API", "version": "0.0.1" }, "paths": {}, "swagger": "2.0", }
def update_api_docs() -> None: """Regenerate the openapi.json file in docs""" from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin from flask_appbuilder.api import BaseApi from os import path superset_dir = path.abspath(path.dirname(__file__)) openapi_json = path.join(superset_dir, "..", "docs", "src", "resources", "openapi.json") api_version = "v1" version_found = False api_spec = APISpec( title=current_app.appbuilder.app_name, version=api_version, openapi_version="3.0.2", info=dict(description=current_app.appbuilder.app_name), plugins=[MarshmallowPlugin()], servers=[{ "url": "/api/{}".format(api_version) }], ) for base_api in current_app.appbuilder.baseviews: if isinstance(base_api, BaseApi) and base_api.version == api_version: base_api.add_api_spec(api_spec) version_found = True if version_found: click.secho("Generating openapi.json", fg="green") with open(openapi_json, "w") as outfile: json.dump(api_spec.to_dict(), outfile, sort_keys=True, indent=2) else: click.secho("API version not found", err=True)
def generate_swagger_file(handlers, file_location): """Automatically generates Swagger spec file based on RequestHandler docstrings and saves it to the specified file_location. """ # Starting to generate Swagger spec file. All the relevant # information can be found from here https://apispec.readthedocs.io/ spec = APISpec( title="Car Brand API", version="1.0.0", openapi_version="3.0.2", info=dict(description="Documentation for the Car Brand API"), plugins=[TornadoPlugin(), MarshmallowPlugin()], servers=[ { "url": "http://localhost:8888/", "description": "Local environment", }, ], ) # Looping through all the handlers and trying to register them. # Handlers without docstring will raise errors. That's why we # are catching them silently. for handler in handlers: try: spec.path(urlspec=handler) except APISpecError: pass # Write the Swagger file into specified location. with open(file_location, "w", encoding="utf-8") as file: json.dump(spec.to_dict(), file, ensure_ascii=False, indent=4)
def get_spec(): """ Produce the OpenAPIv3 spec document. :rtype: dict """ spec = APISpec( title="rest-demo-api", version=__version__, openapi_version="3.0.2", plugins=[FlaskPlugin(), MarshmallowPlugin()], ) app = get_app() # Useful for debugging # print(app.view_functions) spec.path("/authors", view=app.view_functions["authors"], app=app) spec.path("/authors/{author_id}", view=app.view_functions["author"], app=app) spec.path("/authors/{author_id}/quotes", view=app.view_functions["authorquotes"], app=app) spec.path("/quotes", view=app.view_functions["quotes"], app=app) spec.path("/quotes/{quote_id}", view=app.view_functions["quote"], app=app) return spec.to_dict()
class SwaggerResource: def __init__(self): from meerkat.configurations.app.settings import Props from meerkat.configurations.app.main import app from meerkat.configurations.app.main import container # todo: should be moved to env vars self.spec = APISpec(title='meerkat', version='1.0.0', openapi_version='2.0', plugins=[ FalconPlugin(app), MarshmallowPlugin(), ]) injector = container.get(Props.DI_PROVIDER).get_injector() self.spec.components.schema('Health', schema=injector.get(HealthSchema)) self.spec.path(resource=injector.get(HealthCheck)) self.spec.components.schema('Post', schema=injector.get(PostSchema)) self.spec.path(resource=injector.get(PostCollection)) self.spec.path(resource=injector.get(Post)) def on_get(self, req: Request, resp: Response): resp.status = falcon.HTTP_200 resp.body = json.dumps(self.spec.to_dict(), ensure_ascii=False)
def generate_swagger( app: web.Application, title=DEFAULT_TITLE, version=DEFAULT_VERSION, host=DEFAULT_HOST, schemes=DEFAULT_SCHEMES, definitions_path=DEFAULT_DEFINITIONS_PATH, **options ): if host is not None: options["host"] = host if schemes is not None: options["schemes"] = schemes spec = APISpec( title=title, version=version, plugins=("apispec.ext.marshmallow",), **options ) if definitions_path is not None: definitions = importlib.import_module(definitions_path) for name, schema in definitions.__dict__.items(): # type: str, Schema if name.endswith("Schema") and len(name) > len("Schema"): spec.definition(name, schema=schema) resources = app.router._resources for resource in resources: url = resource.canonical name = resource.name for route in resource._routes: method = route.method if method == "HEAD": continue handler = route._handler try: handler_spec = handler.swagger_spec except AttributeError: handler_spec = {} if "excluded" in handler_spec: continue try: handler_spec["summary"] = get_summary(handler.__doc__) handler_spec["description"] = handler.__doc__ except KeyError: pass parameters = get_parameters(url, handler, spec) if parameters: handler_spec["parameters"] = parameters handler_spec["operationId"] = name spec.add_path(url, operations={method.lower(): handler_spec}) return spec.to_dict()
def oas_schema(self, pkg): spec = APISpec( title=pkg.meta["name"].capitalize(), version=pkg.meta["version"], openapi_version=self.config["oas_version"], plugins=[MarshmallowPlugin()], ) for ctrl in pkg.controllers: if not isinstance(ctrl, BaseHttpController): continue routes = {} for func, handler in ctrl.handlers: if not handler.status: warnings.warn(f"No @returns for {func}, cannot generate OAS3 schema for this handler") break abspath = handler.path_full method = handler.method.lower() if abspath not in routes: routes[abspath] = {} if method not in routes[abspath]: routes[abspath][method] = dict( responses={}, parameters=[] ) route = routes[abspath][method] responses = route["responses"] parameters = route["parameters"] for location, schema_cls in handler.schemas: if location == "response": if not schema_cls: content = {} else: content = {"application/json": {"schema": schema_cls}} responses[handler.status] = dict( description=None, content=content ) elif location in ["path", "query", "header"]: if not schema_cls: continue parameters.append({ "in": location, "schema": schema_cls }) spec.path(handler.path_full, operations=routes[abspath]) return spec.to_dict()
def test_definition_autogeneration(app, routes): spec = APISpec( title='test api', version='0.1.0', plugins=('apispec.ext.marshmallow', 'flask_resty.spec')) spec.add_path(view=routes['fooList']) assert 'FooSchema' in spec.to_dict()['definitions']
def test_tagging(app, routes): spec = APISpec( title='test api', version='0.1.0', plugins=('apispec.ext.marshmallow', 'flask_resty.spec')) spec.add_path(view=routes['fooList']) assert 'FooSchema' in spec.to_dict()['paths']['/foos']['get']['tags']
def test_with_exception_handlers_in_app_with_status_code_in_yaml_docstring(): async def handle_exception(request: Request, exc: HTTPException): """ 400: required: - message properties: message: type: string description: Description of the error. example: This is a description of the error. type: object """ pass # pragma: no cover app = Starlette(exception_handlers={HTTPException: handle_exception}) spec = APISpec( title="Test API", version="0.0.1", openapi_version="2.0", plugins=[StarlettePlugin(app)], ) assert spec.to_dict() == { "definitions": { "Error400": { "properties": { "message": { "description": "Description " "of " "the " "error.", "example": "This is a " "description " "of the " "error.", "type": "string", } }, "required": ["message"], "type": "object", } }, "info": { "title": "Test API", "version": "0.0.1" }, "paths": {}, "responses": { 400: { "schema": { "$ref": "#/definitions/Error400" } } }, "swagger": "2.0", }
def test_definition_autogeneration(views): spec = APISpec( title='test api', version='0.1.0', plugins=(FlaskRestyPlugin(), ), ) spec.add_path(view=views['foo_list']) assert 'FooSchema' in spec.to_dict()['definitions']
def test_definition_autogeneration(views): spec = APISpec( title='test api', version='0.1.0', plugins=('apispec.ext.marshmallow', 'flask_resty.spec'), ) spec.add_path(view=views['foo_list']) assert 'FooSchema' in spec.to_dict()['definitions']
def test_tagging(views): spec = APISpec( title='test api', version='0.1.0', plugins=('apispec.ext.marshmallow', 'flask_resty.spec'), ) spec.add_path(view=views['foo_list']) assert 'FooSchema' in spec.to_dict()['paths']['/foos']['get']['tags']
def test_tagging(views): spec = APISpec( title='test api', version='0.1.0', plugins=(FlaskRestyPlugin(), ), ) spec.add_path(view=views['foo_list']) assert 'FooSchema' in spec.to_dict()['paths']['/foos']['get']['tags']
class AiohttpApiSpec: def __init__(self, url='/api/docs/api-docs', **kwargs): self.spec = APISpec(**kwargs) if 'apispec.ext.marshmallow' not in self.spec.plugins: self.spec.setup_plugin('apispec.ext.marshmallow') self.url = url def swagger_dict(self): return self.spec.to_dict() def register(self, app: web.Application): for route in app.router.routes(): view = route.handler method = route.method.lower() if hasattr(view, '__apispec__') and view.__apispec__['docked'].get( method) is not True: url_path = get_path(route) if url_path: if not view.__apispec__['docked'].get('parameters'): view.__apispec__['parameters'].extend({ "in": "path", "name": path_key, "required": True, "type": "string" } for path_key in get_path_keys(url_path) if path_key) view.__apispec__['docked']['parameters'] = True self._update_paths(view.__apispec__, method, url_path) view.__apispec__['docked'][method] = True app['swagger_dict'] = self.spec.to_dict() def swagger_handler(request): return web.json_response(request.app['swagger_dict']) app.router.add_routes([web.get(self.url, swagger_handler)]) def _update_paths(self, data: dict, method, url_path): operations = copy.deepcopy(data) operations.pop('docked', None) if method in PATHS: self.spec.add_path( Path(path=url_path, operations={method: operations}))
class APISpecExt: """Very simple and small extension to use apispec with this API as a flask extension """ def __init__(self, app=None, **kwargs): self.spec = None if app is not None: self.init_app(app, **kwargs) def init_app(self, app, **kwargs): app.config.setdefault("APISPEC_TITLE", "enki_api") app.config.setdefault("APISPEC_VERSION", "4.0.0") app.config.setdefault("OPENAPI_VERSION", "3.0.3") app.config.setdefault("SWAGGER_JSON_URL", "/swagger.json") app.config.setdefault("SWAGGER_UI_URL", "/documentation") app.config.setdefault("SWAGGER_URL_PREFIX", None) self.spec = APISpec( title=app.config["APISPEC_TITLE"], version=app.config["APISPEC_VERSION"], openapi_version=app.config["OPENAPI_VERSION"], plugins=[FlaskRestfulPlugin(), MarshmallowPlugin(), DisableOptionsOperationPlugin()], **kwargs ) blueprint = Blueprint( "swagger", __name__, template_folder="./templates", url_prefix=app.config["SWAGGER_URL_PREFIX"], ) blueprint.add_url_rule( app.config["SWAGGER_JSON_URL"], "swagger_json", self.swagger_json ) blueprint.add_url_rule( app.config["SWAGGER_UI_URL"], "swagger_ui", self.swagger_ui ) blueprint.add_url_rule( "/redoc", "redoc_ui", self.redoc_ui ) app.register_blueprint(blueprint) def swagger_json(self): return jsonify(self.spec.to_dict()) def swagger_ui(self): return render_template("swagger.j2") def redoc_ui(self): return render_template("redoc.html")
def parameters_json_schema(cls) -> Any: """ Return configuration parameters as OpenAPI. """ spec = APISpec( title="Database Parameters", version="1.0.0", openapi_version="3.0.2", plugins=[MarshmallowPlugin()], ) spec.components.schema(cls.__name__, schema=cls.parameters_schema) return spec.to_dict()["components"]["schemas"][cls.__name__]
def swagger_json(hug_api): spec = APISpec(title=settings.TITLE, description=settings.DESCRIPTION, version=settings.VERSION, plugins=('apispec.ext.marshmallow', ), schemes=settings.SCHEMES, host=settings.HOST) if settings.DEFINITIONS_PATH is not None: definitions = importlib.import_module(settings.DEFINITIONS_PATH) for name, schema in definitions.__dict__.items(): # type: str, Schema if name.endswith('Schema') and len(name) > len('Schema'): spec.definition(name, schema=schema) routes = hug_api.http.routes[''] for url, route in routes.items(): for method, versioned_interfaces in route.items(): for versions, interface in versioned_interfaces.items(): methods_data = {} documentation = interface.documentation() methods_data['content_type'] = documentation['outputs'][ 'content_type'] try: methods_data['summary'] = get_summary( documentation['usage']) methods_data['description'] = documentation['usage'] except KeyError: pass parameters = get_parameters(url, interface, spec) if parameters: methods_data['parameters'] = parameters responses = get_operation(interface, spec, settings.USE_DEFAULT_RESPONSE) if responses: methods_data['responses'] = responses if not isinstance(versions, collections.Iterable): versions = [versions] for version in versions: versioned_url = '/v{}{}'.format(version, url) if version else url spec.add_path(versioned_url, operations={method.lower(): methods_data}) return spec.to_dict()
def convert(self, yaml=False, references=True, ignorespec=None, **options): spec = APISpec(title=self.info.get('title'), version=self.info.get('version'), openapi_version=self.openapi, plugins=[MultiOperationBuilderPlugin(references)], **options) for requestitem in self.postman_collection.get_requestitems(): spec.path(path=requestitem.get_request().path, operations=Operation(requestitem, ignorespec=ignorespec).get()) return spec.to_yaml() if yaml else spec.to_dict()
def test_path_summary(): app = Starlette() plugin = StarlettePlugin(app) spec = APISpec(title="Test API", version="0.0.1", openapi_version="2.0", plugins=[plugin]) @app.route("/test") def test_endpoint(request): """This is the expected summary""" pass # pragma: no cover @app.route("/test_with_doc") def test_endpoint_with_doc(request): """ This is the expected summary 2 --- responses: 200: description: "ok" """ pass # pragma: no cover for endpoint in plugin.endpoints(): spec.path(endpoint.path, endpoint=endpoint) assert spec.to_dict() == { "info": { "title": "Test API", "version": "0.0.1" }, "paths": { "/test": { "get": { "operationId": "get_test_endpoint", "summary": "This is the expected summary", } }, "/test_with_doc": { "get": { "summary": "This is the expected summary 2", "operationId": "get_test_endpoint_with_doc", "responses": { "200": { "description": "ok" } }, } }, }, "swagger": "2.0", }
def spec(app, schemas, routes): spec = APISpec( title='test api', version='0.1.0', plugins=('apispec.ext.marshmallow', 'flask_resty.spec')) spec.definition('Foo', schema=schemas['foo']) spec.add_path(view=routes['fooList']) spec.add_path(view=routes['foo']) spec.add_path(view=routes['bar']) return spec.to_dict()
def create_spec(registry, zone=None, merge=None): title = registry.settings.get("openapi.title", "Untitled") version = registry.settings.get("openapi.version", "0.0.0") name_resolver = DottedNameResolver() MarshmallowPlugin = name_resolver.maybe_resolve( registry.settings.get("openapi.plugin", "apispec.ext.marshmallow.MarshmallowPlugin")) marshmallow_plugin = MarshmallowPlugin( schema_name_resolver=schema_name_resolver) spec = APISpec( title=title, version=version, openapi_version="3.0.2", plugins=[marshmallow_plugin], ) for path, operations in list_paths(registry.introspector): final_ops = dict() for method, view in operations.items(): if zone is not None and zone != view.get("api_zone"): continue summary, descr, user_op = split_docstring(view["callable"].__doc__) op = { "responses": dict(), "parameters": [], } if summary: op["summary"] = summary if descr: op["description"] = descr set_url_params(spec, op, view) if "validate" in view: if method == "get": set_query_params(spec, op, view) else: set_request_body(spec, op, view) if "marshal" in view: set_response_body(spec, op, view) set_tag(spec, op, view) final_op = utils.deepupdate(op, user_op) final_op = utils.deepupdate(final_op, view.get("api_spec", dict())) # We are required to have some response, so make one up. if not final_op["responses"]: final_op["responses"]["200"] = { "description": "", } final_ops[method] = final_op spec.path(path, operations=final_ops) json = spec.to_dict() return _perform_merges(json, merge, registry.settings.get("openapi.merge"))
def test_resolve_schema_dict_auto_reference_return_none( self, schema, deprecated_interface): # this resolver return None def resolver(schema): return None if deprecated_interface: spec = APISpec( title='Test auto-reference', version='0.1', description='Test auto-reference', plugins=('apispec.ext.marshmallow', ), schema_name_resolver=resolver, ) else: spec = APISpec( title='Test auto-reference', version='0.1', description='Test auto-reference', plugins=(MarshmallowPlugin(schema_name_resolver=resolver, ), ), ) assert {} == spec._definitions spec.definition('analysis', schema=schema) spec.add_path( '/test', operations={ 'get': { 'responses': { '200': { 'schema': { '$ref': '#/definitions/analysis', }, }, }, }, }, ) # Other shemas not yet referenced assert 1 == len(spec._definitions) spec_dict = spec.to_dict() assert spec_dict.get('definitions') assert 'analysis' in spec_dict['definitions'] # Inspect/Read objects will not auto reference because resolver func # return None json.dumps(spec_dict) # Other shema still not referenced assert 1 == len(spec._definitions)
def specs_view(self, *args, **kwargs): specs = APISpec(title=self.name, version=self.version, basePath=self.url_prefix, host=request.host, plugins=[MarshmallowPlugin()]) for resource in self.resources: resource.update_specs(specs) specs = specs.to_dict() if isinstance(self.specs, dict): specs.update(self.specs) return specs
def spec(schemas, views): spec = APISpec( title='test api', version='0.1.0', plugins=('apispec.ext.marshmallow', 'flask_resty.spec'), ) spec.definition('Foo', schema=schemas['foo']) spec.add_path(view=views['foo_list']) spec.add_path(view=views['foo']) spec.add_path(view=views['bar']) return spec.to_dict()
def spec(schemas, views): spec = APISpec( title='test api', version='0.1.0', plugins=(FlaskRestyPlugin(), ), ) spec.definition('Foo', schema=schemas['foo']) spec.add_path(view=views['foo_list']) spec.add_path(view=views['foo']) spec.add_path(view=views['foo_baz']) spec.add_path(view=views['bar']) return spec.to_dict()
def api_spec(request): spec = APISpec( title='Some API', version='1.0.0', openapi_version='2.0', plugins=[ MarshmallowPlugin() ], ) # inspect the `foo_route` and generate operations from docstring add_pyramid_paths(spec, 'api_object', request=request) add_pyramid_paths(spec, 'api_object_relation', request=request) return spec.to_dict()
def get_specification(self): spec = APISpec( title=self.__class__.__name__, version='1.0.0', plugins=( 'apispec.ext.flask', 'apispec.ext.marshmallow', ), ) class PetParameter(Schema): pet_id = fields.Int() class PetSchema(Schema): id = fields.Int() name = fields.Str() app = Flask(__name__) @app.route('/pets/<int:pet_id>') def get_pet(pet_id): """A cute furry animal endpoint. --- get: description: Get a random pet parameters: - in: path schema: PetParameter responses: 200: description: A pet to be returned schema: PetSchema """ return jsonify({}) # Register entities and paths spec.definition('Pet', schema=PetSchema) spec.definition('PetParameter', schema=PetParameter, required=True) with app.test_request_context(): spec.add_path(view=get_pet) specification_as_string = json.dumps(spec.to_dict(), indent=4) # Kludge! I was unable to do this via `apispec` specification_as_string = specification_as_string.replace('"required": false,', '"required": true,') return specification_as_string
def generate_specs(module_name): module = import_service_module(module_name) service_name = ''.split('.')[-1] ctx = module.app.test_request_context() ctx.push() spec = APISpec( title=service_name, version='1.0.0', plugins=('apispec.ext.marshmallow', 'flask_resty.spec')) schemas = get_subclasses(module.schemas, Schema) for schema in schemas: spec.definition(prettify_schema_name(schema), schema=schema) for view in get_subclasses(module.views, ApiView): try: spec.add_path(view=view, tag=True) except KeyError: pass # means that the view is not registered. move along return json.dumps(spec.to_dict(), indent=2)
def api_spec(self): """ OpenApi 2.0 spec --- get: tags: - "OpenApi 2.0 spec" summary: "Return openapi spec purposes" description: "" operationId: "api_spec" consumes: - "application/json" produces: - "application/json" parameters: responses: 200: description: "Success" """ spec = APISpec( title="Channelstream API", version="0.7.0", openapi_version="2.0.0", plugins=(MarshmallowPlugin(),), ) spec.components.schema("ConnectBody", schema=schemas.ConnectBodySchema) spec.components.schema("SubscribeBody", schema=schemas.SubscribeBodySchema) spec.components.schema("UnsubscribeBody", schema=schemas.UnsubscribeBodySchema) spec.components.schema("UserStateBody", schema=schemas.UserStateBodySchema) spec.components.schema( "MessagesBody", schema=schemas.MessageBodySchema(many=True) ) spec.components.schema("MessageBody", schema=schemas.MessageBodySchema()) spec.components.schema( "MessageEditBody", schema=schemas.MessageEditBodySchema(many=True) ) spec.components.schema( "MessagesDeleteBody", schema=schemas.MessagesDeleteBodySchema(many=True) ) spec.components.schema("DisconnectBody", schema=schemas.DisconnectBodySchema) spec.components.schema("ChannelConfigBody", schema=schemas.ChannelConfigSchema) spec.components.schema("ChannelInfoBody", schema=schemas.ChannelInfoBodySchema) # api add_pyramid_paths(spec, "connect", request=self.request) add_pyramid_paths(spec, "subscribe", request=self.request) add_pyramid_paths(spec, "unsubscribe", request=self.request) add_pyramid_paths(spec, "user_state", request=self.request) add_pyramid_paths(spec, "message", request=self.request) add_pyramid_paths(spec, "channel_config", request=self.request) add_pyramid_paths(spec, "info", request=self.request) add_pyramid_paths(spec, "api_listen", request=self.request) add_pyramid_paths(spec, "api_listen_ws", request=self.request) add_pyramid_paths(spec, "api_disconnect", request=self.request) add_pyramid_paths(spec, "admin_json", request=self.request) spec_dict = spec.to_dict() spec_dict["securityDefinitions"] = { "APIKeyHeader": { "type": "apiKey", "name": "X-Channelstream-Secret", "in": "header", } } return spec_dict