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 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 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 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 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)
from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin from marshmallow import Schema, fields, validate from utils import make_parameter, make_request_body, make_response specification = APISpec( title="Orders API", version="1.0.0", openapi_version="3.0.3", plugins=[MarshmallowPlugin()], **{ "info": {"description": "API that allows you to manage orders for CoffeeMesh"}, "servers": [ {"url": "https://coffeemesh.com", "description": "main production server"}, { "url": "https://coffeemesh-staging.com", "description": "staging server for testing purposes only", }, ], } ) class OrderItem(Schema): product = fields.String(required=True) size = fields.String( required=True, validate=validate.OneOf(["small", "medium", "big"]) ) quantity = fields.Integer(default=1, validate=validate.Range(1, min_inclusive=True))
class DefaultConfig(object): SERVICE_NAME = os.getenv("SERVICE_NAME", "Cornflow") SECRET_KEY = os.getenv("SECRET_KEY") SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL", "sqlite:///cornflow.db") AIRFLOW_URL = os.getenv("AIRFLOW_URL") AIRFLOW_USER = os.getenv("AIRFLOW_USER") AIRFLOW_PWD = os.getenv("AIRFLOW_PWD") AUTH_TYPE = int(os.getenv("AUTH_TYPE", AUTH_DB)) DEFAULT_ROLE = int(os.getenv("DEFAULT_ROLE", PLANNER_ROLE)) CORS_ORIGINS = os.getenv("CORS_ORIGINS", "*") SQLALCHEMY_TRACK_MODIFICATIONS = True DEBUG = True TESTING = True LOG_LEVEL = int(os.getenv("LOG_LEVEL", 30)) SIGNUP_ACTIVATED = int(os.getenv("SIGNUP_ACTIVATED", 1)) # Open deployment (all dags accessible to all users) OPEN_DEPLOYMENT = os.getenv("OPEN_DEPLOYMENT", 1) # Planner users can access objects of other users (1) or not(0). USER_ACCESS_ALL_OBJECTS = os.getenv("USER_ACCESS_ALL_OBJECTS", 0) # LDAP configuration LDAP_HOST = os.getenv("LDAP_HOST", "ldap://openldap:389") LDAP_BIND_DN = os.getenv("LDAP_BIND_DN", "cn=admin,dc=example,dc=org") LDAP_BIND_PASSWORD = os.getenv("LDAP_BIND_PASSWORD", "admin") LDAP_USERNAME_ATTRIBUTE = os.getenv("LDAP_USERNAME_ATTRIBUTE", "cn") LDAP_USER_BASE = os.getenv("LDAP_USER_BASE", "ou=users,dc=example,dc=org") LDAP_EMAIL_ATTRIBUTE = os.getenv("LDAP_EMAIL_ATTRIBUTE", "mail") LDAP_USER_OBJECT_CLASS = os.getenv("LDAP_USER_OBJECT_CLASS", "inetOrgPerson") LDAP_GROUP_OBJECT_CLASS = os.getenv("LDAP_GROUP_OBJECT_CLASS", "posixGroup") LDAP_GROUP_ATTRIBUTE = os.getenv("LDAP_GROUP_ATTRIBUTE", "cn") LDAP_GROUP_BASE = os.getenv("LDAP_GROUP_BASE", "ou=groups,dc=example,dc=org") LDAP_GROUP_TO_ROLE_SERVICE = os.getenv("LDAP_GROUP_TO_ROLE_SERVICE", "service") LDAP_GROUP_TO_ROLE_ADMIN = os.getenv("LDAP_GROUP_TO_ROLE_ADMIN", "administrators") LDAP_GROUP_TO_ROLE_VIEWER = os.getenv("LDAP_GROUP_TO_ROLE_VIEWER", "viewers") LDAP_GROUP_TO_ROLE_PLANNER = os.getenv("LDAP_GROUP_TO_ROLE_PLANNER", "planners") LDAP_PROTOCOL_VERSION = int(os.getenv("LDAP_PROTOCOL_VERSION", 3)) LDAP_USE_TLS = os.getenv("LDAP_USE_TLS", "False") # OpenID login -> Default Azure OID_PROVIDER = os.getenv("OID_PROVIDER", 0) OID_CLIENT_ID = os.getenv("OID_CLIENT_ID") OID_TENANT_ID = os.getenv("OID_TENANT_ID") OID_ISSUER = os.getenv("OID_ISSUER") # APISPEC: APISPEC_SPEC = APISpec( title="Cornflow API docs", version="v1", plugins=[MarshmallowPlugin()], openapi_version="2.0.0", ) APISPEC_SWAGGER_URL = "/swagger/" APISPEC_SWAGGER_UI_URL = "/swagger-ui/" # compress config COMPRESS_REGISTER = False # Email server SERVICE_EMAIL_ADDRESS = os.getenv("SERVICE_EMAIL_ADDRESS", None) SERVICE_EMAIL_PASSWORD = os.getenv("SERVICE_EMAIL_PASSWORD", None) SERVICE_EMAIL_SERVER = os.getenv("SERVICE_EMAIL_SERVER", None) SERVICE_EMAIL_PORT = os.getenv("SERVICE_EMAIL_PORT", None)
def test_openapi_tools_validate_v2(): ma_plugin = MarshmallowPlugin() spec = APISpec( title='Pets', version='0.1', plugins=(ma_plugin, ), openapi_version='2.0', ) openapi = ma_plugin.openapi spec.definition('Category', schema=CategorySchema) spec.definition('Pet', schema=PetSchema, extra_fields={'discriminator': 'name'}) spec.add_path( view=None, path='/category/{category_id}', operations={ 'get': { 'parameters': [ { 'name': 'q', 'in': 'query', 'type': 'string' }, { 'name': 'category_id', 'in': 'path', 'required': True, 'type': 'string' }, openapi.field2parameter( field=fields.List( fields.Str(), validate=validate.OneOf(['freddie', 'roger']), location='querystring', ), name='body', use_refs=False, ), ] + openapi.schema2parameters(PageSchema, default_in='query'), 'responses': { 200: { 'schema': PetSchema, 'description': 'A pet', }, }, }, 'post': { 'parameters': ([{ 'name': 'category_id', 'in': 'path', 'required': True, 'type': 'string' }] + openapi.schema2parameters(CategorySchema, default_in='body')), 'responses': { 201: { 'schema': PetSchema, 'description': 'A pet', }, }, }, }, ) try: utils.validate_spec(spec) except exceptions.OpenAPIError as error: pytest.fail(str(error))
class AiohttpApiSpec: def __init__(self, url="/api/docs/swagger.json", app=None, request_data_name="data", swagger_path=None, static_path='/static/swagger', error_callback=None, in_place=False, prefix='', schema_name_resolver=resolver, **kwargs): self.plugin = MarshmallowPlugin( schema_name_resolver=schema_name_resolver) self.spec = APISpec(plugins=(self.plugin, ), openapi_version="2.0", **kwargs) self.url = url self.swagger_path = swagger_path self.static_path = static_path self._registered = False self._request_data_name = request_data_name self.error_callback = error_callback self.prefix = prefix if app is not None: self.register(app, in_place) def swagger_dict(self): """ Returns swagger spec representation in JSON format """ return self.spec.to_dict() def register(self, app: web.Application, in_place: bool = False): """ Creates spec based on registered app routes and registers needed view """ if self._registered is True: return None app["_apispec_request_data_name"] = self._request_data_name if self.error_callback: parser.error_callback = self.error_callback app["_apispec_parser"] = parser if in_place: self._register(app) else: async def doc_routes(app_): self._register(app_) app.on_startup.append(doc_routes) self._registered = True if self.url is not None: async def swagger_handler(request): return web.json_response(request.app["swagger_dict"]) app.router.add_route("GET", self.url, swagger_handler, name="swagger.spec") if self.swagger_path is not None: self._add_swagger_web_page(app, self.static_path, self.swagger_path) def _add_swagger_web_page(self, app: web.Application, static_path: str, view_path: str): static_files = Path(__file__).parent / "static" app.router.add_static(static_path, static_files) with open(str(static_files / "index.html")) as swg_tmp: tmp = Template(swg_tmp.read()).render(path=self.url, static=static_path) async def swagger_view(_): return web.Response(text=tmp, content_type="text/html") app.router.add_route("GET", view_path, swagger_view, name="swagger.docs") def _register(self, app: web.Application): for route in app.router.routes(): if issubclass_py37fix(route.handler, web.View) and route.method == METH_ANY: for attr in dir(route.handler): if attr.upper() in METH_ALL: view = getattr(route.handler, attr) method = attr self._register_route(route, method, view) else: method = route.method.lower() view = route.handler self._register_route(route, method, view) app["swagger_dict"] = self.swagger_dict() def _register_route(self, route: web.AbstractRoute, method: str, view: _AiohttpView): if not hasattr(view, "__apispec__"): return None url_path = get_path(route) if not url_path: return None self._update_paths(view.__apispec__, method, self.prefix + url_path) def _update_paths(self, data: dict, method: str, url_path: str): if method not in VALID_METHODS_OPENAPI_V2: return None for schema in data.pop("schemas", []): parameters = self.plugin.converter.schema2parameters( schema["schema"], **schema["options"]) data["parameters"].extend(parameters) existing = [p["name"] for p in data["parameters"] if p["in"] == "path"] data["parameters"].extend({ "in": "path", "name": path_key, "required": True, "type": "string" } for path_key in get_path_keys(url_path) if path_key not in existing) if "responses" in data: responses = {} for code, actual_params in data["responses"].items(): if "schema" in actual_params: raw_parameters = self.plugin.converter.schema2parameters( actual_params["schema"], required=actual_params.get("required", False), )[0] updated_params = { k: v for k, v in raw_parameters.items() if k in VALID_RESPONSE_FIELDS } updated_params['schema'] = actual_params["schema"] for extra_info in ("description", "headers", "examples"): if extra_info in actual_params: updated_params[extra_info] = actual_params[ extra_info] responses[code] = updated_params else: responses[code] = actual_params data["responses"] = responses operations = copy.deepcopy(data) self.spec.path(path=url_path, operations={method: operations})
def spec(self): return APISpec( title='Validation', version='0.1', plugins=['apispec.ext.marshmallow'], )
# -*- coding: utf-8 -*- from apispec import APISpec from marshmallow import Schema, fields __all__ = ['spec'] spec = APISpec( title='mypackage', version='0.0.1', info=dict( description='${description}' ), plugins=['apispec.ext.marshmallow'] ) class PersonSchema(Schema): age = fields.Int() name = fields.String() spec.definition('Person', schema=PersonSchema) spec.add_path( path='/randomPerson', operations=dict( get=dict( responses={ '${op.responses().success().code()}': {
# Copyright European Organization for Nuclear Research (CERN) since 2012 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from apispec import APISpec from apispec_webframeworks.flask import FlaskPlugin from rucio.vcsversion import VERSION_INFO from rucio.web.rest.flaskapi.v1.main import application spec = APISpec( title="Rucio", version=VERSION_INFO['version'], openapi_version="3.0.2", plugins=[FlaskPlugin()], ) with application.test_request_context(): for view_func in application.view_functions.values(): spec.path(view=view_func) print(spec.to_yaml())
from apispec.ext.marshmallow import MarshmallowPlugin from apispec_webframeworks.flask import FlaskPlugin from marshmallow import Schema, fields import os service_url = os.getenv("SERVICE_URL", "http://localhost") spec = APISpec( title="TimO Auswertung API", version="1.0.0", openapi_version="3.0.2", info=dict(description="TimO Auswertung API", version="1.0.0-oas3", contact=dict(email="*****@*****.**"), license=dict( name="Apache 2.0", url='http://www.apache.org/licenses/LICENSE-2.0.html')), servers=[dict(description="This API instance", url=service_url)], tags=[ dict(name="TimO Auswertung", description="Endpoints related to TimO Auswertung") ], plugins=[FlaskPlugin(), MarshmallowPlugin()], ) # class DemoParameter(Schema): # gist_id = fields.Int() # class DemoSchema(Schema): # id = fields.Int() # content = fields.Str()
class WRAPISpec(object): RE_URL = re.compile(r'<(?:[^:<>]+:)?([^<>]+)>') tags = [ { 'name': 'Auth', 'description': 'Auth and Login API' }, { 'name': 'Users', 'description': 'User API' }, { 'name': 'Collections', 'description': 'Collection API' }, { 'name': 'Recordings', 'description': 'Recording Sessions Management API' }, { 'name': 'Lists', 'description': 'List API' }, { 'name': 'Bookmarks', 'description': 'Bookmarks API' }, { 'name': 'Browsers', 'description': 'Browser API' }, { 'name': 'External Archives', 'description': 'External Archives Info API' }, { 'name': 'Cookies', 'description': 'Cookie Handling' }, { 'name': 'Bug Reporting', 'description': 'Bug Reporting API' }, { 'name': 'Admin', 'description': 'Admin API' }, { 'name': 'Stats', 'description': 'Stats API' }, ] string_params = { 'user': '******', 'username': '******', 'coll': 'Collection Slug', 'coll_name': 'Collection Slug', 'rec': 'Session Id', 'reqid': 'Remote Browser Request Id', 'new_coll_name': 'New Collection Name', 'list': 'List Id', 'list_id': 'List Id', 'bid': 'Bookmark Id', 'title': 'Title', 'desc': 'Description', 'url': 'Archived Url', 'timestamp': 'Archived at Timestamp', 'browser': 'Browser Used', 'page_id': 'Page Id', 'upload_id': 'Upload Id', } opt_bool_params = { 'public': 'Publicly Accessible', 'include_recordings': 'Include Recording Sessions in response', 'include_lists': 'Include all lists in response', 'include_pages': 'Include pages in response', 'include_bookmarks': 'Include bookmarks in response', 'public_index': 'Publicly Accessible Collection Index', } custom_params = { 'before_id': { 'type': 'string', 'description': 'Insert Before this Id', }, 'order': { 'type': 'array', 'items': { 'type': 'string' }, 'description': 'an array of existing ids in new order' } } all_responses = {} @classmethod def bottle_path_to_openapi(cls, path): path_vars = cls.RE_URL.findall(path) path = cls.RE_URL.sub(r'{\1}', path) return path, path_vars def __init__(self, api_root): self.api_root = api_root self.api_map = defaultdict(dict) self.funcs = defaultdict(dict) self.curr_tag = '' self.spec = APISpec(title='Webrecorder', version='1.0.0', openapi_version='3.0.0', info=dict(description='Webrecorder API'), plugins=[]) self.err_400 = self.make_err_response('Invalid Request Param') self.err_404 = self.make_err_response('Object Not Found') self.err_403 = self.make_err_response('Invalid Authorization') self.any_obj = self.make_any_response() def set_curr_tag(self, tag): self.curr_tag = tag def add_route(self, route): if route.rule.startswith(self.api_root): path, path_vars = self.bottle_path_to_openapi(route.rule) self.api_map[path][route.method.lower()] = route.callback self.funcs[route.callback]['path'] = path, self.funcs[route.callback]['path_params'] = self.make_params( path_vars, 'path') if self.curr_tag: self.funcs[route.callback]['tags'] = [self.curr_tag] def get_param(self, name): if name in self.string_params: param = { 'description': self.string_params[name], 'required': True, 'schema': { 'type': 'string' }, 'name': name } elif name in self.opt_bool_params: param = { 'description': self.opt_bool_params[name], 'required': False, 'schema': { 'type': 'boolean' }, 'name': name } elif name in self.custom_params: param = self.custom_params[name].copy() param['name'] = name else: raise AssertionError('Param {0} not found'.format(name)) return param def get_req_param(self, name): if name in self.string_params: return {'type': 'string', 'description': self.string_params[name]} elif name in self.opt_bool_params: return { 'type': 'boolean', 'description': self.opt_bool_params[name] } elif name in self.custom_params: return self.custom_params[name] raise AssertionError('Param {0} not found'.format(name)) def make_params(self, params, param_type): objs = [] for param in params: obj = self.get_param(param) obj['in'] = param_type objs.append(obj) return objs def add_func(self, func, kwargs): query = kwargs.get('query') if query: self.funcs[func]['query_params'] = self.make_params(query, 'query') req = kwargs.get('req') if req: self.funcs[func]['request'] = self.get_request( req, kwargs.get('req_desc')) def get_request(self, req_props, req_desc=None): properties = {} schema = None # make array out of props if isinstance(req_props, dict): if req_props.get('type') == 'array': obj_type = 'array' prop_list = req_props['item_type'] assert (prop_list) else: obj_type = 'object' prop_list = req_props if not schema: for prop in prop_list: properties[prop] = self.get_req_param(prop) schema = {'type': 'object', 'properties': properties} # wrap schema in array if obj_type == 'array': schema = {'type': 'array', 'items': schema} request = {'content': {'application/json': {'schema': schema}}} if req_desc: request['description'] = req_desc return request def build_api_spec(self): for name, routes in self.api_map.items(): ops = {} for method, callback in routes.items(): info = self.funcs[callback] # combine path params and query params, if any params = info.get('path_params', []) + info.get( 'query_params', []) api = {'parameters': params} # for POST and PUT, generate requestBody if method == 'post' or method == 'put': request = info.get('request') if request: api['requestBody'] = request else: # otherwise, ensure no request body! assert 'request' not in info # set tags, if any if 'tags' in info: api['tags'] = info['tags'] api['responses'] = self.get_responses(None) ops[method] = api self.spec.add_path(path=name, operations=ops) for tag in self.tags: self.spec.add_tag(tag) def get_responses(self, obj_type): response_obj = self.all_responses.get(obj_type) or self.any_obj obj = {'400': self.err_400, '404': self.err_404, '200': response_obj} return obj def make_err_response(self, msg): obj = { 'description': msg, 'content': { 'application/json': { 'schema': { 'type': 'object', 'properties': { 'error': { 'type': 'string' } } } } } } return obj def make_any_response(self): obj = { 'description': 'Any Object', 'content': { 'application/json': { 'schema': { 'type': 'object', 'additionalProperties': True } } } } return obj def get_api_spec_yaml(self): return self.spec.to_yaml()
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
class WRAPISpec(object): RE_URL = re.compile(r'<(?:[^:<>]+:)?([^<>]+)>') tags = [ { 'name': 'WASAPI (Downloads)', 'description': 'Download WARC files API (conforms to WASAPI spec)' }, { 'name': 'Auth', 'description': 'Auth and Login API' }, { 'name': 'Users', 'description': 'User API' }, { 'name': 'Collections', 'description': 'Collection API' }, { 'name': 'doi', 'description': 'DOI API' }, { 'name': 'Recordings', 'description': 'Recording Sessions Management API' }, { 'name': 'Lists', 'description': 'List API' }, { 'name': 'Bookmarks', 'description': 'Bookmarks API' }, { 'name': 'Uploads', 'description': 'Upload WARC or HAR files API' }, { 'name': 'Add External Records', 'description': 'Add External WARC Records API' }, { 'name': 'Browsers', 'description': 'Browser API' }, { 'name': 'External Archives', 'description': 'External Archives Info API' }, { 'name': 'Cookies', 'description': 'Cookie Handling' }, { 'name': 'Bug Reporting', 'description': 'Bug Reporting API' }, { 'name': 'Admin', 'description': 'Admin API', }, { 'name': 'Stats', 'description': 'Stats API', }, { 'name': 'Automation', 'description': 'Automation API', }, { 'name': 'Behaviors', 'description': 'Behaviors API' }, ] # only include these groups when logged in as admin admin_tags = ['Admin', 'Stats', 'Automation'] string_params = { 'user': '******', 'username': '******', 'coll': 'Collection Slug', 'coll_name': 'Collection Slug', 'collection': 'Collection Slug', 'doi': 'DOI Slug', 'rec': 'Session Id', 'reqid': 'Remote Browser Request Id', 'new_coll_name': 'New Collection Name', 'list': 'List Id', 'list_id': 'List Id', 'bid': 'Bookmark Id', 'autoid': 'Automation Id', 'title': 'Title', 'desc': 'Description', 'url': 'Archived Url', 'timestamp': 'Archived at Timestamp', 'browser': 'Browser Used', 'page_id': 'Page Id', 'upload_id': 'Upload Id', 'filename': 'File Name', } opt_bool_params = { 'public': 'Publicly Accessible', 'include_recordings': 'Include Recording Sessions in response', 'include_lists': 'Include all lists in response', 'include_pages': 'Include pages in response', 'include_bookmarks': 'Include bookmarks in response', 'public_index': 'Publicly Accessible Collection Index', } custom_params = { 'before_id': { 'type': 'string', 'description': 'Insert Before this Id', }, 'order': { 'type': 'array', 'items': { 'type': 'string' }, 'description': 'an array of existing ids in new order' } } all_responses = { 'wasapi_list': { 'description': 'WASAPI response for list of WARC files available for download', 'content': { 'application/json': { 'schema': { 'type': 'object', 'properties': { 'files': { 'type': 'array', 'items': { 'type': 'object', 'properties': { 'content-type': { 'type': 'string' }, 'filetype': { 'type': 'string' }, 'filename': { 'type': 'string', }, 'size': { 'type': 'integer' }, 'recording': { 'type': 'string' }, 'recording_date': { 'type': 'string' }, 'collection': { 'type': 'string' }, 'checksums': { 'type': 'object' }, 'locations': { 'type': 'array', 'items': { 'type': 'string' } }, 'is_active': { 'type': 'boolean' }, } } }, 'include-extra': { 'type': 'boolean' } } } } } }, 'wasapi_download': { 'description': 'WARC file', 'content': { 'application/warc': { 'schema': { 'type': 'string', 'format': 'binary', 'example': 'WARC/1.0\r\nWARC-Type: response\r\n...', } } } } } @classmethod def bottle_path_to_openapi(cls, path): path_vars = cls.RE_URL.findall(path) path = cls.RE_URL.sub(r'{\1}', path) return path, path_vars def __init__(self, api_root): self.api_root = api_root self.api_map = defaultdict(dict) self.funcs = defaultdict(dict) self.curr_tag = '' self.spec = APISpec( title='Webrecorder', version='1.0.0', openapi_version='3.0.0', info=dict( description= 'Webrecorder API. This API includes all features available and in use by the frontend.' ), plugins=[]) self.admin_spec = APISpec( title='Webrecorder', version='1.0.0', openapi_version='3.0.0', info=dict( description= 'Webrecorder API (including Admin). This API includes all features available in Webrecorder, including admin and stats APIs.' ), plugins=[]) self.err_400 = self.make_err_response('Invalid Request Param') self.err_404 = self.make_err_response('Object Not Found') self.err_403 = self.make_err_response('Invalid Authorization') self.any_obj = self.make_any_response() def set_curr_tag(self, tag): self.curr_tag = tag def add_route(self, route): if route.rule.startswith(self.api_root): path, path_vars = self.bottle_path_to_openapi(route.rule) self.api_map[path][route.method.lower()] = route.callback self.funcs[route.callback]['path'] = path, self.funcs[route.callback]['path_params'] = self.make_params( path_vars, 'path') if self.curr_tag: self.funcs[route.callback]['tags'] = [self.curr_tag] def get_param(self, name): """Returns the open api description of the supplied query parameter name :param str name: The name of the query parameter :return: A dictionary containing the :rtype: dict """ optional = name.startswith('?') if optional: name = name[1:] if name in self.string_params: param = { 'description': self.string_params[name], 'required': not optional, 'schema': { 'type': 'string' }, 'name': name } elif name in self.opt_bool_params: param = { 'description': self.opt_bool_params[name], 'required': False, 'schema': { 'type': 'boolean' }, 'name': name } elif name in self.custom_params: param = self.custom_params[name].copy() param['name'] = name else: raise AssertionError('Param {0} not found'.format(name)) return param def get_req_param(self, name): if name in self.string_params: return {'type': 'string', 'description': self.string_params[name]} elif name in self.opt_bool_params: return { 'type': 'boolean', 'description': self.opt_bool_params[name] } elif name in self.custom_params: return self.custom_params[name] raise AssertionError('Param {0} not found'.format(name)) def make_params(self, params, param_type): objs = [] for param in params: obj = self.get_param(param) obj['in'] = param_type objs.append(obj) return objs def add_func(self, func, kwargs): query = kwargs.get('query') if query: self.funcs[func]['query_params'] = self.make_params(query, 'query') req = kwargs.get('req') if req: self.funcs[func]['request'] = self.get_request( req, kwargs.get('req_desc')) resp = kwargs.get('resp') if resp: self.funcs[func]['resp'] = resp def get_request(self, req_props, req_desc=None): properties = {} schema = None # make array out of props if isinstance(req_props, dict): if req_props.get('type') == 'array': obj_type = 'array' prop_list = req_props['item_type'] assert (prop_list) else: obj_type = 'object' prop_list = req_props if not schema: for prop in prop_list: properties[prop] = self.get_req_param(prop) schema = {'type': 'object', 'properties': properties} # wrap schema in array if obj_type == 'array': schema = {'type': 'array', 'items': schema} request = {'content': {'application/json': {'schema': schema}}} if req_desc: request['description'] = req_desc return request def build_api_spec(self): for name, routes in self.api_map.items(): ops = {} for method, callback in routes.items(): info = self.funcs[callback] # combine path params and query params, if any params = info.get('path_params', []) + info.get( 'query_params', []) api = {'parameters': params} # for POST and PUT, generate requestBody if method == 'post' or method == 'put': request = info.get('request') if request: api['requestBody'] = request else: # otherwise, ensure no request body! assert 'request' not in info # set tags, if any if 'tags' in info: api['tags'] = info['tags'] is_admin = info['tags'][0] in self.admin_tags api['responses'] = self.get_responses(info.get('resp', None)) ops[method] = api if not is_admin: self.spec.add_path(path=name, operations=ops) self.admin_spec.add_path(path=name, operations=ops) for tag in self.tags: self.admin_spec.add_tag(tag) if tag['name'] not in self.admin_tags: self.spec.add_tag(tag) else: print('skip', tag) def get_responses(self, obj_type): response_obj = self.all_responses.get(obj_type) or self.any_obj obj = {'400': self.err_400, '404': self.err_404, '200': response_obj} return obj def make_err_response(self, msg): obj = { 'description': msg, 'content': { 'application/json': { 'schema': { 'type': 'object', 'properties': { 'error': { 'type': 'string' } } } } } } return obj def make_any_response(self): obj = { 'description': 'Any Object', 'content': { 'application/json': { 'schema': { 'type': 'object', 'additionalProperties': True } } } } return obj def get_api_spec_yaml(self, use_admin=False): """Returns the api specification as a yaml string :return: The api specification as a yaml string :rtype: str """ return self.spec.to_yaml( ) if not use_admin else self.admin_spec.to_yaml() def get_api_spec_dict(self, use_admin=False): """Returns the api specification as a dictionary :return: The api specification as a dictionary :rtype: dict """ return self.spec.to_dict( ) if not use_admin else self.admin_spec.to_dict()
# Setup API docs and Swagger from .core import app from .auth import add_auth_to_swagger from apispec import APISpec from flask_apispec.extension import FlaskApiSpec from webargs import fields from apispec.ext.marshmallow import MarshmallowPlugin file_plugin = MarshmallowPlugin() spec = APISpec(title='neuroscout', version='v1', plugins=[file_plugin], openapi_version='2.0') app.config.update({'APISPEC_SPEC': spec}) add_auth_to_swagger(spec) docs = FlaskApiSpec(app) @file_plugin.map_to_openapi_type('file', None) class FileField(fields.Raw): pass
from arcor2.source.logic import program_src # , get_logic_from_source from arcor2.source.utils import derived_resources_class, global_action_points_class, global_actions_class PORT = int(os.getenv("ARCOR2_BUILD_PORT", 5008)) SERVICE_NAME = "ARCOR2 Build Service" logger = logging.getLogger("build") ch = logging.StreamHandler() ch.setFormatter(logger_formatter()) logger.setLevel(logging.INFO) logger.addHandler(ch) # Create an APISpec spec = APISpec( title=SERVICE_NAME, version=arcor2.version(), openapi_version="3.0.2", plugins=[FlaskPlugin()], ) app = Flask(__name__) CORS(app) def _publish(project_id: str, package_name: str): with tempfile.TemporaryDirectory() as tmpdirname: try: project = ps.get_project(project_id) scene = ps.get_scene(project.scene_id)
migrate = Migrate(directory="./api/migrations") spec = APISpec( title="Large app - APIv1", description="## Our API", version="v1", swagger="2.0", openapi_version="2.0", plugins=[MarshmallowPlugin()], securityDefinitions={ "httpBasic": { "type": "basic", "description": ( "Authorization providing access to the " "backend. Currently only standard Basic " "Authentication is supported" ), }, "auth0": { "type": "oauth2", "flow": "implicit", "authorizationUrl": ( "https://trueenergy.eu.auth0.com/authorize" "?audience=apiv2.auth0.do.trnrg.co" ), }, }, ) def create_app():
from flask import Flask from flask_restful import Resource, Api from apispec import APISpec from marshmallow import Schema, fields from apispec.ext.marshmallow import MarshmallowPlugin from flask_apispec.extension import FlaskApiSpec from flask_apispec.views import MethodResource from flask_apispec import marshal_with, doc, use_kwargs app = Flask(__name__) # Flask app instance initiated api = Api(app) # Flask restful wraps Flask app around it. app.config.update({ 'APISPEC_SPEC': APISpec(title='Awesome Project', version='v1', plugins=[MarshmallowPlugin()], openapi_version='2.0.0'), 'APISPEC_SWAGGER_URL': '/swagger/', # URI to access API Doc JSON 'APISPEC_SWAGGER_UI_URL': '/swagger-ui/' # URI to access UI of API Doc }) docs = FlaskApiSpec(app) class AwesomeResponseSchema(Schema): message = fields.Str(default='Success') class AwesomeRequestSchema(Schema): api_type = fields.String(required=True,
from apispec_webframeworks.flask import FlaskPlugin from flask_base.utils import ( function_args, http_path, find_schemas, http_methods, ) from py_tools.format import dumps, loads mm_plugin = MarshmallowPlugin() flask_plugin = FlaskPlugin() api_spec = APISpec( title="", version="1.0.0", openapi_version="2.0", plugins=(mm_plugin, flask_plugin), ) def generate_swagger(cls): def update_nested(orig_dict, new_dict): """Update nested dictionary""" for key, value in new_dict.items(): if isinstance(value, Mapping): tmp = update_nested(orig_dict.get(key, {}), value) orig_dict[key] = tmp elif isinstance(value, list): orig_dict[key] = orig_dict.get(key, []) + value else: orig_dict[key] = new_dict[key]
return "" formatted = [] lines = docstring.expandtabs().splitlines() for line in lines: if line == "": formatted.append("\n\n") else: formatted.append(line.strip()) return " ".join(formatted).strip() TAGS = [ { "name": "Example", "description": format_docstring(docs.COVID_TAG) }, ] APISPEC_SPEC = APISpec( title="COVID Contact Tracing API", version="v1", info={"description": format_docstring(docs.API_DESCRIPTION)}, plugins=[MarshmallowPlugin()], produces=["application/json"], openapi_version="2.0.0", tags=TAGS, )
def create_app(script_info=None): # instantiate the app app = Flask( __name__, template_folder='templates', static_folder='static' ) # sys.modules[__name__]._current_app = app # set config app_settings = os.getenv("FLASK_APP_CONFIG", "qctrl_api.config.DevelopmentConfig") app.config.from_object(app_settings) app.config.update({ 'APISPEC_SPEC': APISpec( title='Q-CTRL API', info=qdict( # description=open('API.md').read(), ), basePath="/api", version=__version__, plugins=[ # FlaskPlugin(), MarshmallowPlugin(), ], ), }) _app_logger.info("FlaskConfig: {}".format(app.config)) # Register custom error handler so we can see what is exactly failing at validation. app.errorhandler(422)(handle_unprocessable_entity) app.errorhandler(ValidationError)(handle_validation_error) # Add spec handler to app so we don't need to pass it around separately. app.docs = FlaskApiSpec(app) # set up extensions # login_manager.init_app(app) # bcrypt.init_app(app) toolbar.init_app(app) # bootstrap.init_app(app) db.init_app(app) # migrate.init_app(app, db) # CORS Plugin init CORS(app) # # flask login # from project.server.models import User # login_manager.login_view = 'user.login' # login_manager.login_message_category = 'danger' # @login_manager.user_loader # def load_user(user_id): # return User.query.filter(User.id == int(user_id)).first() # # error handlers # @app.errorhandler(401) # def unauthorized_page(error): # return render_template('errors/401.html'), 401 # @app.errorhandler(403) # def forbidden_page(error): # return render_template('errors/403.html'), 403 # @app.errorhandler(404) # def page_not_found(error): # return render_template('errors/404.html'), 404 # @app.errorhandler(500) # def server_error_page(error): # return render_template('errors/500.html'), 500 # shell context for flask cli @app.shell_context_processor def ctx(): return { "app": app, } return app
def test_openapi_tools_validate_v3(): ma_plugin = MarshmallowPlugin() spec = APISpec( title='Pets', version='0.1', plugins=(ma_plugin, ), openapi_version='3.0.0', ) #openapi = ma_plugin.openapi spec.definition('Category', schema=CategorySchema) spec.definition('Pet', schema=PetSchemaV3) spec.add_path( view=None, path='/category/{category_id}', operations={ 'get': { 'parameters': [ { 'name': 'q', 'in': 'query', 'schema': { 'type': 'string' }, }, { 'name': 'category_id', 'in': 'path', 'required': True, 'schema': { 'type': 'string' }, }, ], # + openapi.schema2parameters(PageSchema, default_in='query'), 'responses': { 200: { 'description': 'success', 'content': { 'application/json': { 'schema': PetSchemaV3, }, }, }, }, }, 'post': { 'parameters': ([ { 'name': 'category_id', 'in': 'path', 'required': True, 'schema': { 'type': 'string' }, }, ]), 'requestBody': { 'content': { 'application/json': { 'schema': CategorySchema, }, }, }, 'responses': { 201: { 'description': 'created', 'content': { 'application/json': { 'schema': PetSchemaV3, }, }, }, }, }, }, ) try: utils.validate_spec(spec) except exceptions.OpenAPIError as error: pytest.fail(str(error))
class AiohttpApiSpec: def __init__( self, url="/api/docs/api-docs", app=None, request_data_name="data", **kwargs ): warnings.warn( "'AiohttpApiSpec' will be removed since '1.0.0' version" " of 'aiohttp-apispec', use 'setup_aiohttp_apispec' instead", PendingDeprecationWarning, ) self.spec = APISpec(**kwargs) if "apispec.ext.marshmallow" not in self.spec.plugins: self.spec.setup_plugin("apispec.ext.marshmallow") self.url = url self._registered = False self._request_data_name = request_data_name if app is not None: self.register(app) def swagger_dict(self): return self.spec.to_dict() def register(self, app: web.Application): if self._registered is True: return None app["_apispec_request_data_name"] = self._request_data_name async def doc_routes(app_): self._register(app_) app.on_startup.append(doc_routes) self._registered = True def swagger_handler(request): return web.json_response(request.app["swagger_dict"]) app.router.add_routes([web.get(self.url, swagger_handler)]) def _register(self, app: web.Application): for route in app.router.routes(): if issubclass_py37fix(route.handler, web.View) and route.method == METH_ANY: for attr in dir(route.handler): if attr.upper() in METH_ALL: view = getattr(route.handler, attr) method = attr self._register_route(route, method, view) else: method = route.method.lower() view = route.handler self._register_route(route, method, view) app["swagger_dict"] = self.swagger_dict() def _register_route(self, route: web.RouteDef, method, view): if not hasattr(view, "__apispec__"): return None url_path = get_path(route) if not url_path: return None view.__apispec__["parameters"].extend( {"in": "path", "name": path_key, "required": True, "type": "string"} for path_key in get_path_keys(url_path) ) self._update_paths(view.__apispec__, method, url_path) def _update_paths(self, data: dict, method: str, url_path: str): operations = copy.deepcopy(data) if method in PATHS: self.spec.add_path(Path(path=url_path, operations={method: operations}))
from apispec import APISpec from starlette.applications import Starlette from starlette.endpoints import HTTPEndpoint from starlette.testclient import TestClient from starlette_apispec import APISpecSchemaGenerator app = Starlette() schemas = APISpecSchemaGenerator( APISpec( title="Example API", version="1.0", openapi_version="3.0.0", info={"description": "explanation of the api purpose"}, ) ) @app.websocket_route("/ws") def ws(session): """ws""" pass # pragma: no cover @app.route("/users", methods=["GET", "HEAD"]) def list_users(request): """ responses:
from starlette_apispec import APISpecSchemaGenerator # type: ignore import sys sys.path.insert(1, '..') sys.path.insert(2, '.') from twigator.db.connection import MongoConnection from twigator.db.aggregations import get_tweet_count, get_top_hashtags, get_top_twitters from twigator.db.queries import get_last_tweets, get_tweet_by_id, get_author_by_id SCHEMAS = APISpecSchemaGenerator( APISpec( title="Tweet query API", version="1.0", openapi_version="3.0.0", info={ "description": "Aggregate tweets and provide RESTful access to DB" }, )) APP = Starlette(debug=True) class ResponseBuilder: """ Starlette Response builder. Uses UJSONResponse underneath. """ def __init__(self) -> None: self.__response: dict = {}
from apispec import APISpec from apispec_webframeworks.flask import FlaskPlugin import tempfile from geometry_service.database import db from ._version import __version__ from .api.doc_components import add_components from .loggers import logger # OpenAPI documentation logger.debug('Initializing OpenAPI specification.') spec = APISpec( title="Geometry API", version=__version__, info=dict(description=__doc__, contact={"email": "*****@*****.**"}), externalDocs={ "description": "GitHub", "url": "https://github.com/OpertusMundi/geometry-service" }, openapi_version="3.0.2", plugins=[FlaskPlugin()], ) logger.debug('Adding OpenAPI specification components.') add_components(spec) # Check environment variables if os.getenv('DATABASE_URI') is None: logger.fatal('Environment variable not set [variable="DATABASE_URI"]') sys.exit(1) if os.getenv('SECRET_KEY') is None: logger.fatal('Environment variable not set [variable="SECRET_KEY"]') sys.exit(1)
from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin TESTING = True DEBUG = True MONGO_DBS = ['test1', 'test2'] MONGODB_SETTINGS = [{ 'alias': db, 'db': db, 'host': 'mongo' } for db in MONGO_DBS] APISPEC_SPEC = APISpec(title="My API", version='v1', plugins=[MarshmallowPlugin()], openapi_version='2.0')
cors = CORS(allow_all_origins=['http://localhost:3000']) app = falcon.API( middleware=[TokenAuthenticator(), cors.middleware, Iface_watch(), prom]) app.add_route('/', DefaultRouteHandler()) app.add_route('/fast-serve', FastServe()) app.add_route('/login', IctrlProtonLogin()) app.add_route('/signup', IctrlProtonSignup()) app.add_route('/metrics', prom) app.add_route('/proton-prom', RedirectToProm()) app.add_route('/proton-grafana', RedirectToGrafana()) # Open API Specs spec = APISpec( title='PROTON STACK', version='1.0.0', openapi_version='2.0', plugins=[ FalconPlugin(app), ], ) # OPEN API specs will be generated during runtime. with open('{}/mic/iface/openApi/specs.json'.format(ProtonConfig().ROOT_DIR), 'w+') as sjf: sjf.write(json.dumps(spec.to_dict())) with open('{}/mic/iface/openApi/specs.yaml'.format(ProtonConfig().ROOT_DIR), 'w+') as syf: syf.write(spec.to_yaml())
responses: 200: description: A pet to be returned schema: PetSchema """ pet = get_random_pet() # returns JSON resp.media = pet # create instance of resource random_pet_resource = RandomPetResource() # pass into `add_route` for Falcon app.add_route("/random", random_pet_resource) # Create an APISpec spec = APISpec( title='Swagger Petstore', version='1.0.0', openapi_version='2.0', plugins=[ FalconPlugin(app), MarshmallowPlugin(), ], ) # Register entities and paths spec.components.schema('Category', schema=CategorySchema) spec.components.schema('Pet', schema=PetSchema) # pass created resource into `path` for APISpec spec.path(resource=random_pet_resource)
class GenerateApiSpec(ffd.ApplicationService): _context_map: ffd.ContextMap = None def __init__(self): self._schemas = [] def __call__(self, tag: str = None, **kwargs): try: from apispec import APISpec from docstring_parser import parse except ModuleNotFoundError: raise ffd.MissingDependency( 'This feature requires "apispec" and "docstring_parser"') self._spec = APISpec( title='Testing Spec', version='1.0.0', openapi_version='3.0.2', ) for context in self._context_map.contexts: prefix = f'/{inflection.dasherize(context.name)}' for endpoint in context.endpoints: if isinstance(endpoint, ffd.HttpEndpoint): if tag is not None and tag not in endpoint.tags: continue docstring = parse(endpoint.service.__call__.__doc__) short_description = docstring.short_description \ if docstring.short_description != 'Call self as a function.' else None path = endpoint.route if not path.startswith(prefix): path = f'{prefix}{path}' request_body = self._request_body(endpoint) method = endpoint.method.lower() operations = {method: {}} if request_body is not None: operations[method]['requestBody'] = request_body self._spec.path(path=path, operations=operations, parameters=self._parameter_list(endpoint)) print(json.dumps(self._spec.to_dict(), indent=2)) def _parameter_list(self, endpoint: ffd.HttpEndpoint): ret = [] if inspect.isclass(endpoint.service) and issubclass( endpoint.service, ffd.AggregateRoot): if endpoint.method.lower() == 'post': return [{ 'name': field_.name, 'in': 'TODO', 'description': 'TODO', 'required': 'required' in field_.metadata and field_.metadata['required'] is True, 'schema': { 'type': field_.type, } } for field_ in list( filter(lambda f: not f.name.startswith('_'), fields(endpoint.service)))] def _request_body(self, endpoint: ffd.HttpEndpoint): if not inspect.isclass(endpoint.service): return None if endpoint.method.lower() in ('post', 'put', 'patch'): return { 'required': True, 'content': { 'application/json': { 'schema': { '$ref': f'#/components/schemas/{self._add_schema(endpoint.service)}' } } } } def _add_schema(self, cls: typing.Union[Type[ffd.ValueObject], Type[ffd.ApplicationService]]): try: if cls.__name__ in self._schemas: return cls.__name__ except AttributeError: pass if issubclass(cls, ffd.ValueObject): return self._add_entity_schema(cls) elif issubclass(cls, ffd.ApplicationService): return self._add_service_body_schema(cls) def _add_service_body_schema(self, cls: Type[ffd.ApplicationService]): props = {} signature = inspect.signature(cls.__call__) hints = typing.get_type_hints(cls.__call__) for name, param in signature.parameters.items(): if name == 'self' or param.kind in ( inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD): continue try: type_ = hints[name] except KeyError: type_ = str self._handle_type(name, type_, props) self._spec.components.schema(cls.__name__, {'properties': props}) self._schemas.append(cls.__name__) return cls.__name__ def _add_entity_schema(self, cls: Type[ffd.ValueObject]): props = {} hints = typing.get_type_hints(cls) if not is_dataclass(cls): return None for field_ in fields(cls): if field_.name.startswith('_'): continue type_ = hints[field_.name] self._handle_type(field_.name, type_, props) self._spec.components.schema(cls.__name__, {'properties': props}) self._schemas.append(cls.__name__) return cls.__name__ def _handle_type(self, name: str, type_: type, props: dict): if inspect.isclass(type_) and issubclass( type_, (ffd.Entity, ffd.ValueObject)): props[name] = { 'type': { 'schema': { '$ref': f'#/components/schemas/{self._add_schema(type_)}' } } } elif ffd.is_type_hint(type_) and ffd.get_origin(type_) is typing.List: t = ffd.get_args(type_)[0] props[name] = { 'type': 'array', 'items': { '$ref': f'#/components/schemas/{self._add_schema(t)}' } } elif ffd.is_type_hint(type_) and ffd.get_origin(type_) is typing.Union: args = ffd.get_args(type_) if args[1] is None: props[name] = self._map_type(args[0]) props[name].update({'required': False}) elif ffd.is_type_hint(type_) and ffd.get_origin(type_) is typing.Dict: props[name] = {'type': 'object'} else: props[name] = self._map_type(type_) def _map_type(self, type_: type): if type_ is str or type_ == 'str': return {'type': 'string'} elif type_ is int or type_ == 'int': return {'type': 'integer'} elif type_ is float or type_ == 'float': return {'type': 'number'} elif type_ is bool or type_ == 'bool': return {'type': 'boolean'} elif type_ is list or type_ == 'list': return {'type': 'array'} elif type_ is dict or type_ == 'dict': return {'type': 'object'} elif type_ is datetime or type_ == 'datetime': return {'type': 'string', 'format': 'date-time'} elif type_ is date or type_ == 'date': return {'type': 'string', 'format': 'date'} raise Exception(f"Don't know how to handle type: {type_}")
API_DESCRIPTION = """ This is the documentation for the BubBug http service, the platform for Bugzilla Machine Learning projects. # Introduction This service can be used to classify a given bug using a pre-trained model. You can classify a single bug or a batch of bugs. The classification happens in the background so you need to call back the service for getting the results. """ spec = APISpec( title="Bugbug", version=get_bugbug_version(), openapi_version="3.0.2", info=dict(description=API_DESCRIPTION), plugins=[FlaskPlugin(), MarshmallowPlugin()], security=[{ "api_key": [] }], ) application = Flask(__name__) redis_url = os.environ.get("REDIS_URL", "redis://localhost/0") redis_conn = Redis.from_url(redis_url) # Kill jobs which don't finish within 12 minutes. JOB_TIMEOUT = 12 * 60 # Kill Bugzilla jobs which don't finish within 5 minutes. BUGZILLA_JOB_TIMEOUT = 5 * 60 # Remove jobs from the queue if they haven't started within 7 minutes. QUEUE_TIMEOUT = 7 * 60
def spec(): return APISpec(title='Swagger Petstore', version='1.0.0', description=description, plugins=['apispec.ext.marshmallow'])
from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin spec = APISpec( title="SAM apispec", version="0.0.1", openapi_version="3.0.3", plugins=[MarshmallowPlugin()], )
from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin from apispec_webframeworks.flask import FlaskPlugin from flask import Flask from libtrustbridge.utils.specs import register_specs from intergov.apis.common.errors import handlers from intergov.apis.message import message, index from intergov.apis.message.conf import Config spec = APISpec( title="Message API", version="1.0.0", openapi_version="3.0.2", plugins=[ FlaskPlugin(), MarshmallowPlugin(), ], ) def create_app(config_object=None): """ FLASK_ENV=development FLASK_APP=message_api.app flask run --port=5001 """ if config_object is None: config_object = Config app = Flask(__name__) app.config.from_object(config_object) SENTRY_DSN = app.config.get("SENTRY_DSN") if SENTRY_DSN:
if getenv('OUTPUT_DIR') is None: raise OutputDirNotSet('Environment variable OUTPUT_DIR is not set.') FILE_NOT_FOUND_MESSAGE = "File not found" # Logging mainLogger, accountLogger = getLoggers() # OpenAPI documentation spec = APISpec( title="Clustering and Outlier Detection API", version=getenv('VERSION'), info=dict(description="", contact={"email": ""}), externalDocs={ "description": "GitHub", "url": "https://github.com/OpertusMundi/clustering-outliers-service" }, openapi_version="3.0.2", plugins=[FlaskPlugin()], ) # Initialize app app = Flask(__name__, instance_relative_config=True, instance_path=getenv('INSTANCE_PATH')) environment = getenv('FLASK_ENV') if environment == 'testing' or environment == 'development': secret_key = environment else: secret_key = getenv('SECRET_KEY') or open(getenv('SECRET_KEY_FILE')).read()