예제 #1
0
def create_app():
    Flask.response_class = JsonResponse
    app = Flask(__name__)
    app.config['CLASSIFIER_BASE_PATH'] = app.instance_path
    app.config.from_object('inspire_classifier.config')
    docs = FlaskApiSpec(app)

    @app.route("/api/health")
    def date():
        """Basic endpoint that returns the date, used to check if everything is up and working."""
        now = datetime.datetime.now()
        return jsonify(now)

    docs.register(date)

    @app.route("/api/predict/coreness", methods=["POST"])
    @use_kwargs({
        'title': fields.Str(required=True),
        'abstract': fields.Str(required=True)
    })
    @marshal_with(serializers.ClassifierOutputSerializer)
    def core_classifier(**kwargs):
        """Endpoint for the CORE classifier."""

        return predict_coreness(kwargs['title'], kwargs['abstract'])

    docs.register(core_classifier)

    return app

    @app.errorhandler(404)
    def page_not_found(e):
        return {"errors": [str(e)]}, 404
예제 #2
0
def build_routes(app):
    """Register routes to given app instance."""
    app.config.update({
        'APISPEC_SPEC':
        APISpec(
            title=SERVICE_NAME,
            openapi_version=OPENAPI_VERSION,
            version=API_VERSION,
            plugins=[MarshmallowPlugin()],
        ),
        'APISPEC_SWAGGER_URL':
        API_SPEC_URL,
    })
    app.register_blueprint(cache_blueprint)
    app.register_blueprint(dataset_blueprint)

    swaggerui_blueprint = get_swaggerui_blueprint(
        SWAGGER_URL, API_SPEC_URL, config={'app_name': 'Renku Service'})
    app.register_blueprint(swaggerui_blueprint, url_prefix=SWAGGER_URL)

    docs = FlaskApiSpec(app)

    docs.register(upload_file_view, blueprint=CACHE_BLUEPRINT_TAG)
    docs.register(list_uploaded_files_view, blueprint=CACHE_BLUEPRINT_TAG)
    docs.register(project_clone, blueprint=CACHE_BLUEPRINT_TAG)
    docs.register(list_projects_view, blueprint=CACHE_BLUEPRINT_TAG)

    docs.register(create_dataset_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(add_file_to_dataset_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(list_datasets_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(list_dataset_files_view, blueprint=DATASET_BLUEPRINT_TAG)
예제 #3
0
def register_blueprints(app: Flask):
    """Register Flask blueprints."""
    app.config.update({"APISPEC_SPEC": APISPEC_SPEC})
    docs = FlaskApiSpec(app)

    from blueprints.images import images_bp
    from blueprints.images import routes as image_routes

    image_routes.set_routes(app, images_bp, docs)
예제 #4
0
def register_blueprints(app: Flask):
    """ Register Flask blueprints. """
    app.config.update({"APISPEC_SPEC": APISPEC_SPEC})
    docs = FlaskApiSpec(app)

    # example blueprint
    from blueprints.example import example_bp
    from blueprints.example import routes as example_routes

    example_routes.set_routes(app, example_bp, docs)
예제 #5
0
def init_app(app):
    """Register API resources on the provided Flask application."""
    def register(path, resource):
        app.add_url_rule(path, view_func=resource.as_view(resource.__name__))
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            docs.register(resource, endpoint=resource.__name__)

    docs = FlaskApiSpec(app)
    register("/models", Models)
    register("/models/<int:id>", IndvModel)
예제 #6
0
def create_app():
    app = Flask(__name__)
    app.config['PROPAGATE_EXCEPTIONS'] = True
    docs = FlaskApiSpec(app)

    app.add_url_rule('/data/<path:folder>/chunks',
                     view_func=DataResource.as_view('DataResource'))
    docs.register(DataResource, endpoint='DataResource')

    app.add_url_rule('/status', view_func=Status.as_view('Status'))
    docs.register(Status, endpoint='Status')

    return app
예제 #7
0
 def __init__(self, app):
     app.config.update({
         'APISPEC_SPEC': APISpec(
             title='KodeSmil Flask',
             version='v1',
             openapi_version="3.0.2",
             info=dict(description='KodeSmil microservices API'),
             plugins=[MarshmallowPlugin()],
         ),
         'APISPEC_SWAGGER_UI_URL': '/docs/',
     })
     self.docs = FlaskApiSpec(app)
     self._initialize()
예제 #8
0
def register_blueprints(app):
    app.register_blueprint(blueprints_blueprint,
                           url_prefix=API_BASE_URL + 'blueprints')
    app.register_blueprint(jobs_blueprint, url_prefix=API_BASE_URL + 'jobs')
    app.register_blueprint(operations_blueprint,
                           url_prefix=API_BASE_URL + 'operations')

    # Swagger
    docs = FlaskApiSpec(app)

    from .jobs.routes import get_job

    docs.register(get_job, blueprint="jobs")
예제 #9
0
    def __init__(self, app, url, **config):
        app.config.update({
            'APISPEC_SPEC':
            APISpec(**config,
                    plugins=[MarshmallowPlugin()],
                    **self.__default_security_schema()),
            'APISPEC_SWAGGER_UI_URL':
            url,
            'APISPEC_SWAGGER_URL':
            url + '.json'
        })

        self.app = app
        self.doc = FlaskApiSpec(app)
        self.__register_security_schema()
예제 #10
0
def build_routes(app):
    """Register routes to given app instance."""
    app.config.update({
        "APISPEC_SPEC":
        APISpec(
            title=SERVICE_NAME,
            openapi_version=OPENAPI_VERSION,
            version=API_VERSION,
            plugins=[MarshmallowPlugin()],
        ),
        "APISPEC_SWAGGER_URL":
        API_SPEC_URL,
    })
    app.register_blueprint(cache_blueprint)
    app.register_blueprint(dataset_blueprint)
    app.register_blueprint(jobs_blueprint)
    app.register_blueprint(templates_blueprint)
    app.register_blueprint(version_blueprint)

    swaggerui_blueprint = get_swaggerui_blueprint(
        SWAGGER_URL, API_SPEC_URL, config={"app_name": "Renku Service"})
    app.register_blueprint(swaggerui_blueprint, url_prefix=SWAGGER_URL)

    docs = FlaskApiSpec(app)

    docs.register(version, blueprint=VERSION_BLUEPRINT_TAG)

    docs.register(list_uploaded_files_view, blueprint=CACHE_BLUEPRINT_TAG)
    docs.register(upload_file_view, blueprint=CACHE_BLUEPRINT_TAG)
    docs.register(project_clone_view, blueprint=CACHE_BLUEPRINT_TAG)
    docs.register(list_projects_view, blueprint=CACHE_BLUEPRINT_TAG)
    docs.register(migrate_project_view, blueprint=CACHE_BLUEPRINT_TAG)
    docs.register(migration_check_project_view, blueprint=CACHE_BLUEPRINT_TAG)

    docs.register(list_datasets_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(list_dataset_files_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(add_file_to_dataset_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(create_dataset_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(import_dataset_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(edit_dataset_view, blueprint=DATASET_BLUEPRINT_TAG)
    docs.register(unlink_file_view, blueprint=DATASET_BLUEPRINT_TAG)

    docs.register(list_jobs, blueprint=JOBS_BLUEPRINT_TAG)

    docs.register(read_manifest_from_template,
                  blueprint=TEMPLATES_BLUEPRINT_TAG)
    docs.register(create_project_from_template,
                  blueprint=TEMPLATES_BLUEPRINT_TAG)
예제 #11
0
def _register_openapi(app):
    from ursh.schemas import TokenSchema, URLSchema
    with app.app_context():
        spec = APISpec(
            openapi_version='3.0.2',
            title='ursh - URL Shortener',
            version='2.0',
            plugins=(
                FlaskPlugin(),
                MarshmallowPlugin(),
            ),
        )
        spec.components.schema('Token', schema=TokenSchema)
        spec.components.schema('URL', schema=URLSchema)
        app.config['APISPEC_SPEC'] = spec
        apispec = FlaskApiSpec(app)
        apispec.register_existing_resources()
예제 #12
0
def create_app(env_name):

    app = Flask(__name__)
    app.config.from_object(app_config[env_name])

    bcrypt.init_app(app)
    db.init_app(app)

    app.register_blueprint(user_blueprint, url_prefix='/garden/v1/users')
    app.register_blueprint(device_blueprint, url_prefix='/garden/v1/devices')

    docs = FlaskApiSpec(app)
    docs.register(devices.create, blueprint=device_blueprint)

    @app.route('/', methods=['GET'])
    def index():
        return 'blah blah blah'

    return app
예제 #13
0
 def __init__(self):
     app = Flask(__name__)
     add_flask_profiler(app)
     with app.app_context():
         log.info(
             f"starting {settings.APP_NAME} server on {settings.API.SERVER}"
         )
     CORS(app)
     self.app = app
     self.docs = FlaskApiSpec(app)
     self.lineProfiler = line_profiler()
     log.info(
         f"starting {settings.APP_NAME} mongo connector {settings.MONGO}")
     self.mongo = MongoConnector(settings.MONGO)
     log.info(
         f"starting {settings.APP_NAME} postgres connector {settings.POSTGRES}"
     )
     self.postgres = Postgres(settings.POSTGRES)
     """
         When worker fork's the parent process, the db engine & connection pool is included in that.
         But, the db connections should not be shared across processes, so we tell the engine
         to dispose of all existing connections, which will cause new ones to be opened in the child
         processes as needed.
         More info:
         https://docs.sqlalchemy.org/en/latest/core/pooling.html#using-connection-pools-with-multiprocessing
     """
     with app.app_context():
         self.postgres.get_engine().dispose()
     log.info(
         f"starting {settings.APP_NAME} redis connector {settings.REDIS}")
     self.redis = RedisConnector(settings.REDIS)
     log.info(
         f"starting {settings.APP_NAME} rq dashboard at http://"
         f"{settings.API.SERVER.url}:{settings.API.SERVER.port}{settings.API.VERSION}{settings.APP_NAME}/rq"
     )
     app.config["RQ_DASHBOARD_REDIS_URL"] = settings.REDIS.url
     log.info(f"starting {settings.APP_NAME} redis job queues")
     self.redisJobQueues = RedisJobQueues(self.redis.get_redis_conn())
     log.info(f"starting {settings.APP_NAME} redis job queues")
     self.redisJobQueues = RedisJobQueues(self.redis.get_redis_conn())
     log.info(
         f"started {settings.APP_NAME} server on {settings.API.SERVER}")
예제 #14
0
def create_app():
    app = Flask(__name__)
    app.config.from_object('config.Config')
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    app.config.update({
        'APISPEC_TITLE': 'Pylerplate',
        'APISPEC_VERSION': 'Pylerplate',
        'APISPEC_SWAGGER_URL': '/swagger/',
        'APISPEC_SWAGGER_UI_URL': None,
    })

    app.__docs__ = FlaskApiSpec(app)
    initialize_extensions(app)
    register_handlers(app)
    CORS(app)

    register_routes(app)

    return app
예제 #15
0
def init_app(app: Flask):
    global FileField

    docs = FlaskApiSpec(document_options=False)
    ma = MarshmallowPlugin()
    spec = APISpec(
        title=app.config.get("APISPEC_TITLE", "API Docs"),
        version=app.config.get("APISPEC_VERSION", "v1"),
        openapi_version=app.config.get("APISPEC_OAS_VERSION", "2.0"),
        plugins=[ma],
        securityDefinitions=app.config.get("APISPEC_SECURITY_DEFINITIONS", {}),
    )

    @ma.map_to_openapi_type("file", None)
    class FileField(fields.Raw):
        pass

    app.config.update({"APISPEC_SPEC": spec})
    docs.init_app(app)
    app.extensions["apispec"] = docs
예제 #16
0
def register_spec(app):
    app.config.update({
        "APISPEC_SPEC":
        APISpec(
            title="Flask VRFs API",
            version="0.0.1",
            openapi_version="2.0",
            plugins=[MarshmallowPlugin()],
        ),
        "APISPEC_SWAGGER_URL":
        "/api/docs/apispec.json",
        "APISPEC_SWAGGER_UI_URL":
        "/api/docs",
    })
    docs = FlaskApiSpec(app)
    from app.api.vrf.views import Vrf

    docs.register(Vrf, blueprint="api")
    from app.api.vrfs.views import Vrfs

    docs.register(Vrfs, blueprint="api")
예제 #17
0
def main():
    app = Flask('MySchemaApp')
    docs = FlaskApiSpec(app)

    parser = argparse.ArgumentParser()
    parser.add_argument('-x', dest='xvalue', type=str, help='the x value', default='hello')
    parser.add_argument('-y', dest='yvalue', type=int, help='the y value', default=10)

    MySchema = parser_to_schema(parser, 'MySchema')
    my_schema = MySchema()

    
    @docs.register
    @app.route('/api')
    @use_kwargs(MySchema, locations=['query'])
    def handler(**kwargs):
        obj = my_schema.load(kwargs)
        print('recv args: {}'.format(kwargs))
        print('recv obj: {}'.format(obj))
        return my_schema.dump(obj)

    return app
예제 #18
0
import os
from flask import Flask
from flask_mongoengine import MongoEngine
from flask_restful import Api
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from flask_apispec import FlaskApiSpec
from celery import Celery
from .tasks import make_celery
from .config import configs

env = os.environ.get("FLASK_ENV", "development")
db = MongoEngine()
rest_api = Api()
docs = FlaskApiSpec()
celery = Celery(
    __name__, broker=configs[env].CELERY_BROKER_URL, backend=configs[env].CELERY_RESULT_BACKEND
)


def create_app(test_config=None):
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_object(configs[env])
    app.config.update({
            'APISPEC_SPEC': APISpec(
                title='openforms',
                version='v1',
                openapi_version='2.0',
                plugins=[MarshmallowPlugin()],
            ),
            'APISPEC_SWAGGER_URL': '/swagger/',
from . import settings
from .middlewares import (
    HTTPMethodOverrideMiddleware, )
from .extensions import (
    Webpack, )
from . import commands

db = SQLAlchemy()
ds_client = None
cache = Cache()
user_datastore = None
security = None
mail = Mail()
babel = Babel()
marshmallow = Marshmallow()
api_spec = FlaskApiSpec()


def create_app(config_object=settings):
    app = Flask(__name__)
    app.config.from_object(config_object)

    global ds_client
    ds_client = datastore.Client()

    register_extensions(app)
    register_middlewares(app)
    register_commands(app)
    init_security(app)
    register_blueprints(app)
예제 #20
0
파일: server.py 프로젝트: joskid/http-api
def create_app(
    name: str = __name__,
    mode: ServerModes = ServerModes.NORMAL,
    options: Optional[Dict[str, bool]] = None,
) -> Flask:
    """ Create the server istance for Flask application """

    if PRODUCTION and TESTING and not FORCE_PRODUCTION_TESTS:  # pragma: no cover
        print_and_exit("Unable to execute tests in production")

    # TERM is not catched by Flask
    # https://github.com/docker/compose/issues/4199#issuecomment-426109482
    # signal.signal(signal.SIGTERM, teardown_handler)
    # SIGINT is registered as STOPSIGNAL in Dockerfile
    signal.signal(signal.SIGINT, teardown_handler)

    # Flask app instance
    # template_folder = template dir for output in HTML
    microservice = Flask(
        name, template_folder=os.path.join(ABS_RESTAPI_PATH, "templates")
    )

    # CORS
    if not PRODUCTION:
        cors = CORS(
            allow_headers=[
                "Content-Type",
                "Authorization",
                "X-Requested-With",
                "x-upload-content-length",
                "x-upload-content-type",
                "content-range",
            ],
            supports_credentials=["true"],
            methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
        )

        cors.init_app(microservice)
        log.debug("CORS Injected")

    # Flask configuration from config file
    microservice.config.from_object(config)
    log.debug("Flask app configured")

    if PRODUCTION:
        log.info("Production server mode is ON")

    endpoints_loader = EndpointsLoader()
    mem.configuration = endpoints_loader.load_configuration()

    mem.initializer = Meta.get_class("initialization", "Initializer")
    if not mem.initializer:  # pragma: no cover
        print_and_exit("Invalid Initializer class")

    mem.customizer = Meta.get_instance("customization", "Customizer")
    if not mem.customizer:  # pragma: no cover
        print_and_exit("Invalid Customizer class")

    if not isinstance(mem.customizer, BaseCustomizer):  # pragma: no cover
        print_and_exit("Invalid Customizer class, it should inherit BaseCustomizer")

    Connector.init_app(app=microservice, worker_mode=(mode == ServerModes.WORKER))

    # Initialize reading of all files
    mem.geo_reader = geolite2.reader()
    # when to close??
    # geolite2.close()

    if mode == ServerModes.INIT:
        Connector.project_init(options=options)

    if mode == ServerModes.DESTROY:
        Connector.project_clean()

    # Restful plugin with endpoint mapping (skipped in INIT|DESTROY|WORKER modes)
    if mode == ServerModes.NORMAL:

        logging.getLogger("werkzeug").setLevel(logging.ERROR)
        # ignore warning messages from apispec
        warnings.filterwarnings(
            "ignore", message="Multiple schemas resolved to the name "
        )
        mem.cache = Cache.get_instance(microservice)

        endpoints_loader.load_endpoints()
        mem.authenticated_endpoints = endpoints_loader.authenticated_endpoints
        mem.private_endpoints = endpoints_loader.private_endpoints

        # Triggering automatic mapping of REST endpoints
        rest_api = Api(catch_all_404s=True)

        for endpoint in endpoints_loader.endpoints:
            # Create the restful resource with it;
            # this method is from RESTful plugin
            rest_api.add_resource(endpoint.cls, *endpoint.uris)

        # HERE all endpoints will be registered by using FlaskRestful
        rest_api.init_app(microservice)

        # APISpec configuration
        api_url = get_backend_url()
        scheme, host = api_url.rstrip("/").split("://")

        spec = APISpec(
            title=get_project_configuration(
                "project.title", default="Your application name"
            ),
            version=get_project_configuration("project.version", default="0.0.1"),
            openapi_version="2.0",
            # OpenApi 3 not working with FlaskApiSpec
            # -> Duplicate parameter with name body and location body
            # https://github.com/jmcarp/flask-apispec/issues/170
            # Find other warning like this by searching:
            # **FASTAPI**
            # openapi_version="3.0.2",
            plugins=[MarshmallowPlugin()],
            host=host,
            schemes=[scheme],
            tags=endpoints_loader.tags,
        )
        # OpenAPI 3 changed the definition of the security level.
        # Some changes needed here?
        api_key_scheme = {"type": "apiKey", "in": "header", "name": "Authorization"}
        spec.components.security_scheme("Bearer", api_key_scheme)

        microservice.config.update(
            {
                "APISPEC_SPEC": spec,
                # 'APISPEC_SWAGGER_URL': '/api/swagger',
                "APISPEC_SWAGGER_URL": None,
                # 'APISPEC_SWAGGER_UI_URL': '/api/swagger-ui',
                # Disable Swagger-UI
                "APISPEC_SWAGGER_UI_URL": None,
            }
        )

        mem.docs = FlaskApiSpec(microservice)

        # Clean app routes
        ignore_verbs = {"HEAD", "OPTIONS"}

        for rule in microservice.url_map.iter_rules():

            endpoint = microservice.view_functions[rule.endpoint]
            if not hasattr(endpoint, "view_class"):
                continue

            newmethods = ignore_verbs.copy()
            rulename = str(rule)

            for verb in rule.methods - ignore_verbs:
                method = verb.lower()
                if method in endpoints_loader.uri2methods[rulename]:
                    # remove from flask mapping
                    # to allow 405 response
                    newmethods.add(verb)

            rule.methods = newmethods

        # Register swagger. Note: after method mapping cleaning
        with microservice.app_context():
            for endpoint in endpoints_loader.endpoints:
                try:
                    mem.docs.register(endpoint.cls)
                except TypeError as e:  # pragma: no cover
                    print(e)
                    log.error("Cannot register {}: {}", endpoint.cls.__name__, e)

    # marshmallow errors handler
    microservice.register_error_handler(422, handle_marshmallow_errors)

    # Logging responses
    microservice.after_request(handle_response)

    if SENTRY_URL is not None:  # pragma: no cover

        if PRODUCTION:
            sentry_sdk.init(
                dsn=SENTRY_URL,
                # already catched by handle_marshmallow_errors
                ignore_errors=[werkzeug.exceptions.UnprocessableEntity],
                integrations=[FlaskIntegration()],
            )
            log.info("Enabled Sentry {}", SENTRY_URL)
        else:
            # Could be enabled in print mode
            # sentry_sdk.init(transport=print)
            log.info("Skipping Sentry, only enabled in PRODUCTION mode")

    log.info("Boot completed")

    return microservice
예제 #21
0
import marshmallow

from flask_apispec import FlaskApiSpec, marshal_with, MethodResource


class Api:
    """
    Holds a version of the API with documentation and allows routes to
    register.
    """
    def __init__(self, prefix=""):
        self.prefix = prefix
        self._deferred_routes = []

    def register(self, path, aMethodResource):
        self._deferred_routes.append((
            "/{0}/{1}".format(self.prefix, path.lstrip("/")),
            aMethodResource.as_view(name=aMethodResource.__module__ + "_" +
                                    aMethodResource.__name__.lower()),
        ))

    def init_app(self, app):
        for deferred in self._deferred_routes:
            app.add_url_rule(deferred[0], view_func=deferred[1])
            specs.register(deferred[1])


specs = FlaskApiSpec()
api_v1 = Api(prefix="v0.1")
예제 #22
0
        spec.register(cls)

        return cls
    return wrapper


app.config.update({
    'APISPEC_SPEC': APISpec(
        title='Flask-apispec user API',
        version='1.0',
        plugins=(MarshmallowPlugin(), ),
    ),
    'APISPEC_SWAGGER_URL': '/swagger.json',
})

spec = FlaskApiSpec(app)


class UserSchema(Schema):
    id = ma_fields.Integer()
    name = ma_fields.String()

    class Meta:
        strict = True


class LoginSchema(Schema):
    logged_user = ma_fields.String()


@route(app, spec, '/user')
예제 #23
0
APP.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
APP.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
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
})

API = Api(APP)
db.init_app(APP)
DOCS = FlaskApiSpec(APP)


@APP.before_first_request
def create_table():
    '''Takes in a number n, returns the square of n'''
    db.create_all()


class AwesomeResponseSchema(Schema):
    '''Takes in a number n, returns the square of n'''

    message = fields.Str(default='Success')


class AwesomeRequestSchema(Schema):
예제 #24
0
파일: apispec.py 프로젝트: zelsaddr/zemfrog
"""
Reference: https://github.com/tiangolo/full-stack-flask-couchdb/tree/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/api/api_v1
"""

from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from flask.app import Flask
from flask_apispec import FlaskApiSpec

docs = FlaskApiSpec(document_options=False)


def init_app(app: Flask):
    app.config.update(
        {
            "APISPEC_SPEC": APISpec(
                title=app.config.get("APISPEC_TITLE", "API Docs"),
                version=app.config.get("APISPEC_VERSION", "v1"),
                openapi_version=app.config.get("APISPEC_OAS_VERSION", "2.0"),
                plugins=[MarshmallowPlugin()],
                securityDefinitions=app.config.get("APISPEC_SECURITY_DEFINITIONS", {}),
            ),
        }
    )
    docs.init_app(app)
예제 #25
0
def init_swagger(app):
    docs = FlaskApiSpec(app)
    docs.register(UsersController)
    docs.register(UserController)
    return docs
예제 #26
0
파일: rest.py 프로젝트: nbedi/openFEC
api.add_resource(
    filings.FilingsView,
    '/committee/<committee_id>/filings/',
    '/candidate/<candidate_id>/filings/',
)
api.add_resource(filings.FilingsList, '/filings/')

api.add_resource(download.DownloadView, '/download/<path:path>/')

app.config.update({
    'APISPEC_SWAGGER_URL': None,
    'APISPEC_SWAGGER_UI_URL': None,
    'APISPEC_SPEC': spec.spec,
})
apidoc = FlaskApiSpec(app)

apidoc.register(search.CandidateNameSearch, blueprint='v1')
apidoc.register(search.CommitteeNameSearch, blueprint='v1')
apidoc.register(candidates.CandidateView, blueprint='v1')
apidoc.register(candidates.CandidateList, blueprint='v1')
apidoc.register(candidates.CandidateSearch, blueprint='v1')
apidoc.register(candidates.CandidateHistoryView, blueprint='v1')
apidoc.register(committees.CommitteeView, blueprint='v1')
apidoc.register(committees.CommitteeList, blueprint='v1')
apidoc.register(committees.CommitteeHistoryView, blueprint='v1')
apidoc.register(reports.ReportsView, blueprint='v1')
apidoc.register(totals.TotalsView, blueprint='v1')
apidoc.register(sched_a.ScheduleAView, blueprint='v1')
apidoc.register(sched_b.ScheduleBView, blueprint='v1')
apidoc.register(sched_e.ScheduleEView, blueprint='v1')
예제 #27
0
from flask import Flask, redirect
from flask_apispec import FlaskApiSpec
from .skin_detect import *
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
import cv2
from flask import jsonify

app = Flask(__name__)

docs = FlaskApiSpec(app)

app.add_url_rule('/skin_detect',
                 view_func=ImageEndPoint.as_view('skin_detect'))

docs.register(ImageEndPoint, endpoint="skin_detect")

import skin_detector

UPLOAD_FOLDER = './uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER


def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

    APISpec(
        title='Test Chassis Service',
        version='1.0.0-b1',
        openapi_version="2.0",
        # openapi_version="3.0.2",
        plugins=[MarshmallowPlugin()],
        info=dict(description=
                  "Handles common resources shared by the entire architecture",
                  license={
                      "name": "Apache 2.0",
                      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
                  })),
    'APISPEC_SWAGGER_URL':
    '/swagger/',
})
docs = FlaskApiSpec(flask_test_app)
docs.register(TestApiList)
docs.register(TestApi)
docs.register(TestCountryList)
docs.register(TestCountryApi)

flask_test_app.register_error_handler(422, validation_error_handler)


@flask_test_app.errorhandler(InvalidTokenError)
def unauthorized(error):
    flask_test_app.logger.error("Authorization error: %s", error)
    return {
        "message":
        "You are not authorized to perform this request. "
        "Ensure you have a valid credentials before trying again"
예제 #29
0
def fd_app(cache_dir):
    """ API app for FreeDiscovery """

    if not os.path.exists(cache_dir):
        raise ValueError('Cache_dir {} does not exist!'.format(cache_dir))
    app = Flask('freediscovery_api')
    app.url_map.strict_slashes = False
    app.config.update({
        'APISPEC_SPEC':
        APISpec(title='FreeDiscovery',
                version='v0',
                plugins=['apispec.ext.marshmallow']),
        'APISPEC_SWAGGER_URL':
        '/openapi-specs.json',
        'APISPEC_SWAGGER_UI_URL':
        '/swagger-ui.html'
    })

    app.test_client_class = TestClient

    docs = FlaskApiSpec(app)

    #app.config['DEBUG'] = False

    ## Actually setup the Api resource routing here
    for resource_el, url in [
        (ExampleDatasetApi, "/example-dataset/<name>"),
        (FeaturesApi, "/feature-extraction"),
        (FeaturesApiElement, '/feature-extraction/<dsid>'),
        (FeaturesApiElementMappingNested,
         '/feature-extraction/<dsid>/id-mapping'),
        (EmailParserApi, "/email-parser"),
        (EmailParserApiElement, '/email-parser/<dsid>'),
        (EmailParserApiElementIndex, '/email-parser/<dsid>/index'),
        (ModelsApi, '/categorization/'),
        (ModelsApiElement, '/categorization/<mid>'),
        (ModelsApiPredict, '/categorization/<mid>/predict'),
        (LsiApi, '/lsi/'),
        (LsiApiElement, '/lsi/<mid>'),
        (KmeanClusteringApi, '/clustering/k-mean/'),
        (BirchClusteringApi, '/clustering/birch'),
        (WardHCClusteringApi, '/clustering/ward_hc'),
        (DBSCANClusteringApi, '/clustering/dbscan'),
        (ClusteringApiElement, '/clustering/<method>/<mid>'),
        (DupDetectionApi, '/duplicate-detection/'),
        (DupDetectionApiElement, '/duplicate-detection/<mid>'),
        (MetricsCategorizationApiElement, '/metrics/categorization'),
        (MetricsClusteringApiElement, '/metrics/clustering'),
        (MetricsDupDetectionApiElement, '/metrics/duplicate-detection'),
        (EmailThreadingApi, '/email-threading/'),
        (EmailThreadingApiElement, '/email-threading/<mid>'),
        (SearchApi, '/search/'),
        (CustomStopWordsApi, '/stop-words/'),
        (CustomStopWordsLoadApi, '/stop-words/<name>'),
            #(CatchAll                       , "/<url>")
    ]:
        # monkeypatching, not great
        resource_el._cache_dir = cache_dir
        resource_el.methods = ['GET', 'POST', 'DELETE']
        #api.add_resource(resource_el, '/api/v0' + url, strict_slashes=False)

        ressource_name = resource_el.__name__
        app.add_url_rule('/api/v0' + url,
                         view_func=resource_el.as_view(ressource_name))
        if ressource_name not in ["EmailThreadingApi"]:
            # the above two cases fail due to recursion limit
            docs.register(resource_el, endpoint=ressource_name)

    @app.errorhandler(500)
    def handle_error(error):
        #response = jsonify(error.to_dict())
        response = jsonify({'messages': str(error)})
        response.status_code = 500
        return response

    @app.errorhandler(404)
    def handle_404_error(error):
        response = jsonify({"messages": str(error)})
        response.status_code = 404
        return response

    @app.errorhandler(400)
    def handle_400_error(error):
        response = jsonify({"messages": str(error)})
        response.status_code = 400
        return response

    @app.errorhandler(422)
    def handle_422_error(error):
        # marshmallow error
        response = jsonify(error.data)
        response.status_code = 422
        return response

    return app
예제 #30
0
def create_app(
    name: str = __name__,
    mode: ServerModes = ServerModes.NORMAL,
    options: Optional[Dict[str, bool]] = None,
) -> Flask:
    """Create the server istance for Flask application"""

    if PRODUCTION and TESTING and not FORCE_PRODUCTION_TESTS:  # pragma: no cover
        print_and_exit("Unable to execute tests in production")

    # TERM is not catched by Flask
    # https://github.com/docker/compose/issues/4199#issuecomment-426109482
    # signal.signal(signal.SIGTERM, teardown_handler)
    # SIGINT is registered as STOPSIGNAL in Dockerfile
    signal.signal(signal.SIGINT, teardown_handler)

    # Flask app instance
    # template_folder = template dir for output in HTML
    flask_app = Flask(name, template_folder=str(ABS_RESTAPI_PATH.joinpath("templates")))

    # CORS
    if not PRODUCTION:

        if TESTING:
            cors_origin = "*"
        else:  # pragma: no cover
            cors_origin = get_frontend_url()
            # Beware, this only works because get_frontend_url never append a port
            cors_origin += ":*"

        CORS(
            flask_app,
            allow_headers=[
                "Content-Type",
                "Authorization",
                "X-Requested-With",
                "x-upload-content-length",
                "x-upload-content-type",
                "content-range",
            ],
            supports_credentials=["true"],
            methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
            resources={r"*": {"origins": cors_origin}},
        )

        log.debug("CORS Enabled")

    # Flask configuration from config file
    flask_app.config.from_object(config)
    flask_app.json_encoder = ExtendedJSONEncoder

    # Used to force flask to avoid json sorting and ensure that
    # the output to reflect the order of field in the Marshmallow schema
    flask_app.config["JSON_SORT_KEYS"] = False

    log.debug("Flask app configured")

    if PRODUCTION:
        log.info("Production server mode is ON")

    endpoints_loader = EndpointsLoader()

    if HOST_TYPE == DOCS:  # pragma: no cover
        log.critical("Creating mocked configuration")
        mem.configuration = {}

        log.critical("Loading Mocked Initializer and Customizer classes")
        from restapi.mocks import Customizer, Initializer

        mem.initializer = Initializer
        mem.customizer = Customizer()

    else:

        mem.configuration = endpoints_loader.load_configuration()
        mem.initializer = Meta.get_class("initialization", "Initializer")
        if not mem.initializer:  # pragma: no cover
            print_and_exit("Invalid Initializer class")

        customizer = Meta.get_class("customization", "Customizer")
        if not customizer:  # pragma: no cover
            print_and_exit("Invalid Customizer class")
        mem.customizer = customizer()

    if not isinstance(mem.customizer, BaseCustomizer):  # pragma: no cover
        print_and_exit("Invalid Customizer class, it should inherit BaseCustomizer")

    Connector.init_app(app=flask_app, worker_mode=(mode == ServerModes.WORKER))

    # Initialize reading of all files
    mem.geo_reader = geolite2.reader()
    # when to close??
    # geolite2.close()

    if mode == ServerModes.INIT:
        Connector.project_init(options=options)

    if mode == ServerModes.DESTROY:
        Connector.project_clean()

    # Restful plugin with endpoint mapping (skipped in INIT|DESTROY|WORKER modes)
    if mode == ServerModes.NORMAL:

        logging.getLogger("werkzeug").setLevel(logging.ERROR)

        # warnings levels:
        # default  # Warn once per call location
        # error    # Convert to exceptions
        # always   # Warn every time
        # module   # Warn once per calling module
        # once     # Warn once per Python process
        # ignore   # Never warn

        # Types of warnings:
        # Warning: This is the base class of all warning category classes
        # UserWarning: The default category for warn().
        # DeprecationWarning: Base category for warnings about deprecated features when
        #                     those warnings are intended for other Python developers
        # SyntaxWarning: Base category for warnings about dubious syntactic features.
        # RuntimeWarning: Base category for warnings about dubious runtime features.
        # FutureWarning: Base category for warnings about deprecated features when those
        #                warnings are intended for end users
        # PendingDeprecationWarning: Base category for warnings about features that will
        #                            be deprecated in the future (ignored by default).
        # ImportWarning: Base category for warnings triggered during the process of
        #                importing a module
        # UnicodeWarning: Base category for warnings related to Unicode.
        # BytesWarning: Base category for warnings related to bytes and bytearray.
        # ResourceWarning: Base category for warnings related to resource usage

        if TESTING:
            warnings.simplefilter("always", Warning)
            warnings.simplefilter("error", UserWarning)
            warnings.simplefilter("error", DeprecationWarning)
            warnings.simplefilter("error", SyntaxWarning)
            warnings.simplefilter("error", RuntimeWarning)
            warnings.simplefilter("error", FutureWarning)
            # warnings about features that will be deprecated in the future
            warnings.simplefilter("default", PendingDeprecationWarning)
            warnings.simplefilter("error", ImportWarning)
            warnings.simplefilter("error", UnicodeWarning)
            warnings.simplefilter("error", BytesWarning)
            # Can't set this an error due to false positives with downloads
            # a lot of issues like: https://github.com/pallets/flask/issues/2468
            warnings.simplefilter("always", ResourceWarning)
            warnings.simplefilter("default", Neo4jExperimentalWarning)

            # Remove me in a near future, this is due to hypothesis with pytest 7
            # https://github.com/HypothesisWorks/hypothesis/issues/3222
            warnings.filterwarnings(
                "ignore", message="A private pytest class or function was used."
            )

        elif PRODUCTION:  # pragma: no cover
            warnings.simplefilter("ignore", Warning)
            warnings.simplefilter("always", UserWarning)
            warnings.simplefilter("default", DeprecationWarning)
            warnings.simplefilter("ignore", SyntaxWarning)
            warnings.simplefilter("ignore", RuntimeWarning)
            warnings.simplefilter("ignore", FutureWarning)
            warnings.simplefilter("ignore", PendingDeprecationWarning)
            warnings.simplefilter("ignore", ImportWarning)
            warnings.simplefilter("ignore", UnicodeWarning)
            warnings.simplefilter("ignore", BytesWarning)
            warnings.simplefilter("ignore", ResourceWarning)
            # even if ignore it is raised once
            # because of the imports executed before setting this to ignore
            warnings.simplefilter("ignore", Neo4jExperimentalWarning)
        else:  # pragma: no cover
            warnings.simplefilter("default", Warning)
            warnings.simplefilter("always", UserWarning)
            warnings.simplefilter("always", DeprecationWarning)
            warnings.simplefilter("default", SyntaxWarning)
            warnings.simplefilter("default", RuntimeWarning)
            warnings.simplefilter("always", FutureWarning)
            warnings.simplefilter("default", PendingDeprecationWarning)
            warnings.simplefilter("default", ImportWarning)
            warnings.simplefilter("default", UnicodeWarning)
            warnings.simplefilter("default", BytesWarning)
            warnings.simplefilter("always", ResourceWarning)
            # even if ignore it is raised once
            # because of the imports executed before setting this to ignore
            warnings.simplefilter("ignore", Neo4jExperimentalWarning)

        # ignore warning messages from apispec
        warnings.filterwarnings(
            "ignore", message="Multiple schemas resolved to the name "
        )

        # ignore warning messages on flask socket after teardown
        warnings.filterwarnings("ignore", message="unclosed <socket.socket")

        # from flask_caching 1.10.1 with python 3.10 on core tests...
        # try to remove this once upgraded flask_caching in a near future
        warnings.filterwarnings(
            "ignore",
            message="_SixMetaPathImporter.find_spec",
        )

        # Raised from sentry_sdk 1.5.11 with python 3.10 events
        warnings.filterwarnings(
            "ignore",
            message="SelectableGroups dict interface is deprecated. Use select.",
        )

        mem.cache = Cache.get_instance(flask_app)

        endpoints_loader.load_endpoints()
        mem.authenticated_endpoints = endpoints_loader.authenticated_endpoints
        mem.private_endpoints = endpoints_loader.private_endpoints

        for endpoint in endpoints_loader.endpoints:
            ename = endpoint.cls.__name__.lower()
            endpoint_view = endpoint.cls.as_view(ename)
            for url in endpoint.uris:
                flask_app.add_url_rule(url, view_func=endpoint_view)

        # APISpec configuration
        api_url = get_backend_url()
        scheme, host = api_url.rstrip("/").split("://")

        spec = APISpec(
            title=get_project_configuration(
                "project.title", default="Your application name"
            ),
            version=get_project_configuration("project.version", default="0.0.1"),
            openapi_version="2.0",
            # OpenApi 3 not working with FlaskApiSpec
            # -> Duplicate parameter with name body and location body
            # https://github.com/jmcarp/flask-apispec/issues/170
            # Find other warning like this by searching:
            # **FASTAPI**
            # openapi_version="3.0.2",
            plugins=[MarshmallowPlugin()],
            host=host,
            schemes=[scheme],
            tags=endpoints_loader.tags,
        )
        # OpenAPI 3 changed the definition of the security level.
        # Some changes needed here?

        if Env.get_bool("AUTH_ENABLE"):
            api_key_scheme = {"type": "apiKey", "in": "header", "name": "Authorization"}
            spec.components.security_scheme("Bearer", api_key_scheme)

        flask_app.config.update(
            {
                "APISPEC_SPEC": spec,
                # 'APISPEC_SWAGGER_URL': '/api/swagger',
                "APISPEC_SWAGGER_URL": None,
                # 'APISPEC_SWAGGER_UI_URL': '/api/swagger-ui',
                # Disable Swagger-UI
                "APISPEC_SWAGGER_UI_URL": None,
            }
        )

        mem.docs = FlaskApiSpec(flask_app)

        # Clean app routes
        ignore_verbs = {"HEAD", "OPTIONS"}

        for rule in flask_app.url_map.iter_rules():

            view_function = flask_app.view_functions[rule.endpoint]
            if not hasattr(view_function, "view_class"):
                continue

            newmethods = ignore_verbs.copy()
            rulename = str(rule)

            if rule.methods:
                for verb in rule.methods - ignore_verbs:
                    method = verb.lower()
                    if method in endpoints_loader.uri2methods[rulename]:
                        # remove from flask mapping
                        # to allow 405 response
                        newmethods.add(verb)

            rule.methods = newmethods

        # Register swagger. Note: after method mapping cleaning
        with flask_app.app_context():
            for endpoint in endpoints_loader.endpoints:
                try:
                    mem.docs.register(endpoint.cls)
                except TypeError as e:  # pragma: no cover
                    print(e)
                    log.error("Cannot register {}: {}", endpoint.cls.__name__, e)

    # marshmallow errors handler
    # Can't get the typing to work with flask 2.1
    flask_app.register_error_handler(422, handle_marshmallow_errors)  # type: ignore
    flask_app.register_error_handler(400, handle_http_errors)  # type: ignore
    flask_app.register_error_handler(404, handle_http_errors)  # type: ignore
    flask_app.register_error_handler(405, handle_http_errors)  # type: ignore
    flask_app.register_error_handler(500, handle_http_errors)  # type: ignore

    # flask_app.before_request(inspect_request)
    # Logging responses
    # Can't get the typing to work with flask 2.1
    flask_app.after_request(handle_response)  # type: ignore

    if SENTRY_URL is not None:  # pragma: no cover

        if PRODUCTION:
            sentry_sdk_init(
                dsn=SENTRY_URL,
                # already catched by handle_marshmallow_errors
                ignore_errors=[werkzeug.exceptions.UnprocessableEntity],
                integrations=[FlaskIntegration()],
            )
            log.info("Enabled Sentry {}", SENTRY_URL)
        else:
            # Could be enabled in print mode
            # sentry_sdk_init(transport=print)
            log.info("Skipping Sentry, only enabled in PRODUCTION mode")

    log.info("Boot completed")
    if PRODUCTION and not TESTING and name == MAIN_SERVER_NAME:  # pragma: no cover
        save_event_log(
            event=Events.server_startup,
            payload={"server": name},
            user=None,
            target=None,
        )

    return flask_app