示例#1
0
def test_default_specs(app, cli_runner):
    swagger = Swagger(app)

    result = cli_runner.invoke(generate_api_schema)

    assert result.exit_code == 0
    spec = json.loads(result.output)
    assert spec == swagger.get_apispecs(Swagger.DEFAULT_ENDPOINT)
示例#2
0
def test_get_apispecs_with_invalid_endpoint(app):
    swagger = Swagger(app)

    with app.app_context():
        with pytest.raises(RuntimeError) as e:
            bad_endpoint = "Bad endpoint"
            swagger.get_apispecs(bad_endpoint)
            assert bad_endpoint in e
示例#3
0
def test_custom_specs(app, cli_runner):
    endpoint = "custom_endpoint"
    config = dict(Swagger.DEFAULT_CONFIG)
    config["specs"][0]["endpoint"] = endpoint
    swagger = Swagger(app, config=config)

    result = cli_runner.invoke(generate_api_schema, ["-e", endpoint])

    assert result.exit_code == 0
    spec = json.loads(result.output)
    assert spec == swagger.get_apispecs(endpoint)
示例#4
0
def test_invalid_endpoint(app, cli_runner):
    endpoint = "custom_endpoint"
    config = dict(Swagger.DEFAULT_CONFIG)
    config["specs"][0]["endpoint"] = endpoint
    Swagger(app, config=config)

    result = cli_runner.invoke(generate_api_schema, ["-e", "other_endpoint"])

    assert result.exit_code == 1
    assert "other_endpoint" in result.stderr
示例#5
0
def test_definitions_is_removed_for_openapi_3(app, cli_runner):
    app.config["SWAGGER"] = {
        "openapi": "3.0.3",
    }

    Swagger(app)

    result = cli_runner.invoke(generate_api_schema)
    assert result.exit_code == 0
    assert "definitions" not in json.loads(result.output)
示例#6
0
def test_init_config(monkeypatch):
    def __init__(self, config=None, merge=False):
        self._init_config(config, merge)

    monkeypatch.setattr(Swagger, "__init__", __init__)

    # # Unspecified config will be initialized to dict()
    t = Swagger(config=None, merge=False)
    assert t.config == Swagger.DEFAULT_CONFIG

    # Empty dict passed to arguments will be overriden with default_config
    empty_dict = dict()
    t = Swagger(config=empty_dict, merge=False)
    assert t.config == Swagger.DEFAULT_CONFIG
    assert t.config is not empty_dict

    # Config will be merged
    d = {"a": 0}
    t = Swagger(config=d, merge=False)
    assert t.config is d

    # Config will be overridden
    t = Swagger(config={"a": 0}, merge=False)
    assert t.config == {"a": 0}

    # Config will be merged
    t = Swagger(config={"a": 0}, merge=True)
    assert t.config.items() > {"a": 0}.items()
    assert all(t.config[k] == v for k, v in Swagger.DEFAULT_CONFIG.items())

    # Config will be merged
    empty_dict = dict()
    t = Swagger(config=empty_dict, merge=True)
    assert t.config == Swagger.DEFAULT_CONFIG

    # keys in DEFAULT_CONFIG will be overridden
    d = {
        "specs": [{
            "endpoint": "swagger",
            "route": "/characteristics/swagger.json",
            "rule_filter": lambda rule: True,  # all in
            "model_filter": lambda tag: True,  # all in
        }],
    }
    t = Swagger(config=d, merge=True)
    assert all(t.config[k] == v for k, v in d.items())
    assert t.config["specs"] == d["specs"]
示例#7
0
def create_app():
    """create flask app"""
    app = Flask(__name__)
    app.config.from_pyfile("config.py", silent=True)
    logger.warning("database: " + app.config["MPCONTRIBS_DB"])
    app.config["USTS"] = URLSafeTimedSerializer(app.secret_key)
    app.jinja_env.globals["get_resource_as_string"] = get_resource_as_string
    app.jinja_env.lstrip_blocks = True
    app.jinja_env.trim_blocks = True

    if app.config.get("DEBUG"):
        from flask_cors import CORS

        CORS(app)  # enable for development (allow localhost)

    Compress(app)
    Logging(app)
    Marshmallow(app)
    MongoEngine(app)
    Swagger(app, template=app.config.get("TEMPLATE"))
    # NOTE: hard-code to avoid pre-generating for new deployment
    # collections = get_collections(db)
    collections = [
        "projects",
        "contributions",
        "tables",
        "structures",
        "notebooks",
    ]

    for collection in collections:
        module_path = ".".join(["mpcontribs", "api", collection, "views"])
        try:
            module = import_module(module_path)
        except ModuleNotFoundError as ex:
            logger.warning(f"API module {module_path}: {ex}")
            continue

        try:
            blueprint = getattr(module, collection)
            app.register_blueprint(blueprint, url_prefix="/" + collection)
            klass = getattr(module, collection.capitalize() + "View")
            register_class(app, klass, name=collection)
            logger.warning(f"{collection} registered")
        except AttributeError as ex:
            logger.warning(
                f"Failed to register {module_path}: {collection} {ex}")

    # TODO discover user-contributed views automatically
    # only load for main deployment
    if os.environ.get("API_PORT", "5000") == "5000":
        collection = "redox_thermo_csp"
        module_path = ".".join(["mpcontribs", "api", collection, "views"])
        try:
            module = import_module(module_path)
            blueprint = getattr(module, collection)
            app.register_blueprint(blueprint, url_prefix="/" + collection)
            logger.warning(f"{collection} registered")
        except ModuleNotFoundError as ex:
            logger.warning(f"API module {module_path}: {ex}")

    app.register_blueprint(sse, url_prefix="/stream")
    # TODO add healthcheck view/url
    logger.warning("app created.")
    return app
# Initialize core objects

app = Flask(__name__)
app.config.from_object("config")

cache = Cache(app)
cors = CORS(app)
db = SQLAlchemy(app)
jwt = JWTManager(app)
limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["100 per minute", "5 per second"],
)
mail = Mail(app)
swagger = Swagger(app)
storage = Minio(app)
rq = RQ(app)

# -- Handler
from app.handlers import (http_handler, jwt_handler, log_handler)

# Comment above code when change database systems
if not os.path.exists("db.sqlite"):
    db.create_all()

# -- Controllers
from app.controllers import (auth_controller, file_controller,
                             homepage_controller, mail_controller,
                             user_controller)
示例#9
0
def test_get_apispecs_with_valid_endpoint(app):
    swagger = Swagger(app)

    with app.app_context():
        assert swagger.get_apispecs(Swagger.DEFAULT_ENDPOINT)
示例#10
0
def create_app():
    """create flask app"""
    app = Flask(__name__)
    app.config.from_pyfile("config.py", silent=True)
    app.config["USTS"] = URLSafeTimedSerializer(app.secret_key)
    app.jinja_env.globals["get_resource_as_string"] = get_resource_as_string
    app.jinja_env.lstrip_blocks = True
    app.jinja_env.trim_blocks = True
    app.config["TEMPLATE"]["schemes"] = ["http"] if app.debug else ["https"]
    MPCONTRIBS_API_HOST = os.environ["MPCONTRIBS_API_HOST"]
    logger.info("database: " + app.config["MPCONTRIBS_DB"])

    if app.debug:
        from flask_cors import CORS

        CORS(app)  # enable for development (allow localhost)

    Compress(app)
    Marshmallow(app)
    MongoEngine(app)
    Swagger(app, template=app.config.get("TEMPLATE"))
    setattr(app, "kernels", get_kernels())

    # NOTE: hard-code to avoid pre-generating for new deployment
    # collections = get_collections(db)
    collections = [
        "projects",
        "contributions",
        "tables",
        "attachments",
        "structures",
        "notebooks",
    ]

    for collection in collections:
        module_path = ".".join(["mpcontribs", "api", collection, "views"])
        try:
            module = import_module(module_path)
        except ModuleNotFoundError as ex:
            logger.error(f"API module {module_path}: {ex}")
            continue

        try:
            blueprint = getattr(module, collection)
            app.register_blueprint(blueprint, url_prefix="/" + collection)
            klass = getattr(module, collection.capitalize() + "View")
            register_class(app, klass, name=collection)
            logger.info(f"{collection} registered")
        except AttributeError as ex:
            logger.error(
                f"Failed to register {module_path}: {collection} {ex}")

    if app.kernels:
        from mpcontribs.api.notebooks.views import rq, make
        rq.init_app(app)

        if is_gunicorn:
            setattr(app, "cron_job_id",
                    f"auto-notebooks-build_{MPCONTRIBS_API_HOST}")
            make.cron('*/3 * * * *', app.cron_job_id)
            logger.info(f"CRONJOB {app.cron_job_id} added.")

    def healthcheck():
        # TODO run mpcontribs-api in next-gen task on different port so this won't be needed
        # spams logs with expected 500 errors
        if not app.debug and not app.kernels:
            return "KERNEL GATEWAY NOT AVAILABLE", 500

        return "OK"

    if is_gunicorn:
        app.register_blueprint(sse, url_prefix="/stream")
        app.add_url_rule("/healthcheck", view_func=healthcheck)
        #app.register_blueprint(rq_dashboard.blueprint, url_prefix="/rq")

        #dashboard.config.init_from(file="dashboard.cfg")
        #dashboard.config.version = app.config["VERSION"]
        #dashboard.config.table_prefix = f"fmd_{MPCONTRIBS_API_HOST}"
        #db_password = os.environ["POSTGRES_DB_PASSWORD"]
        #db_host = os.environ["POSTGRES_DB_HOST"]
        #dashboard.config.database_name = f"postgresql://*****:*****@{db_host}/kong"
        #dashboard.bind(app)

    logger.info("app created.")
    return app