Passed
Pull Request — main (#702)
by Juho
07:24
created

annif.create_app()   A

Complexity

Conditions 2

Size

Total Lines 35
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 20
nop 1
dl 0
loc 35
rs 9.4
c 0
b 0
f 0
1
#!/usr/bin/env python3
2
3
from __future__ import annotations
4
5
import logging
6
import os
7
import os.path
8
from typing import TYPE_CHECKING
9
10
from flask import Flask
11
12
logging.basicConfig()
13
logger = logging.getLogger("annif")
14
logger.setLevel(level=logging.INFO)
15
16
import annif.backend  # noqa
17
18
if TYPE_CHECKING:
19
    from connexion.apps.flask import FlaskApp
20
21
22
def create_flask_app(config_name: str | None = None) -> Flask:
23
    """Create a Flask app to be used by the CLI."""
24
25
    _set_tensorflow_loglevel()
26
27
    app = Flask(__name__)
28
    config_name = _get_config_name(config_name)
29
    logger.debug(f"creating flask app with configuration {config_name}")
30
    app.config.from_object(config_name)
31
    app.config.from_envvar("ANNIF_SETTINGS", silent=True)
32
    return app
33
34
35
def create_cx_app(config_name: str | None = None) -> FlaskApp:
36
    """Create a Connexion app to be used for the API."""
37
    import connexion
38
39
    # from flask_cors import CORS  # TODO Use CORSMiddleware
40
    import annif.registry
41
42
    # from annif.openapi.validation import CustomRequestBodyValidator  # TODO Re-enable
43
44
    specdir = os.path.join(os.path.dirname(__file__), "openapi")
45
    cxapp = connexion.FlaskApp(__name__, specification_dir=specdir)
46
    config_name = _get_config_name(config_name)
47
    logger.debug(f"creating connexion app with configuration {config_name}")
48
    cxapp.app.config.from_object(config_name)
49
    cxapp.app.config.from_envvar("ANNIF_SETTINGS", silent=True)
50
51
    # validator_map = {
52
    #     "body": CustomRequestBodyValidator,
53
    # }
54
    cxapp.add_api("annif.yaml")  # validator_map=validator_map)
55
56
    # add CORS support
57
    # CORS(cxapp.app)
58
59
    if cxapp.app.config["INITIALIZE_PROJECTS"]:
60
        annif.registry.initialize_projects(cxapp.app)
61
        logger.info("finished initializing projects")
62
63
    # register the views via blueprints
64
    from annif.views import bp
65
66
    cxapp.app.register_blueprint(bp)
67
68
    # return the Connexion app
69
    return cxapp
70
71
72
create_app = create_cx_app  # Alias to allow starting directly with uvicorn run
73
74
75
def _get_config_name(config_name: str | None) -> str:
76
    if config_name is None:
77
        config_name = os.environ.get("ANNIF_CONFIG")
78
    if config_name is None:
79
        if os.environ.get("FLASK_RUN_FROM_CLI") == "true":  # pragma: no cover
80
            config_name = "annif.default_config.Config"
81
        else:
82
            config_name = "annif.default_config.ProductionConfig"  # pragma: no cover
83
    return config_name
84
85
86
def _set_tensorflow_loglevel():
87
    """Set TensorFlow log level based on Annif log level (--verbosity/-v
88
    option) using an environment variable. INFO messages by TF are shown only on
89
    DEBUG (or NOTSET) level of Annif."""
90
    annif_loglevel = logger.getEffectiveLevel()
91
    tf_loglevel_mapping = {
92
        0: "0",  # NOTSET
93
        10: "0",  # DEBUG
94
        20: "1",  # INFO
95
        30: "1",  # WARNING
96
        40: "2",  # ERROR
97
        50: "3",  # CRITICAL
98
    }
99
    tf_loglevel = tf_loglevel_mapping[annif_loglevel]
100
    os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", tf_loglevel)
101