memegen.factory.create_app()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nop 1
dl 0
loc 12
rs 9.95
c 0
b 0
f 0
1
import os
2
3
from flask import request, current_app
4
from flask_api import FlaskAPI
5
from flask_api.exceptions import APIException, NotFound
6
import bugsnag
7
from bugsnag.flask import handle_exceptions
8
import log
9
10
from . import extensions
11
from . import services
12
from . import stores
13
from . import routes
14
15
16
class TemplateNotFound(NotFound):
17
    detail = "Template not found."
18
19
20
class InvalidMaskedCode(NotFound):
21
    detail = "Masked URL does not match any image."
22
23
24
class FilenameTooLong(APIException):
25
    status_code = 414
26
    detail = "Filename too long."
27
28
29
class InvalidImageLink(APIException):
30
    status_code = 415
31
    detail = "Unsupported image type."
32
33
34
def create_app(config):
35
    app = FlaskAPI(__name__)
36
    app.config.from_object(config)
37
38
    configure_exceptions(app)
39
    configure_logging(app)
40
41
    register_extensions(app)
42
    register_services(app)
43
    register_blueprints(app)
44
45
    return app
46
47
48
def configure_exceptions(app):
49
    if app.config['BUGSNAG_API_KEY']:  # pragma: no cover
50
        bugsnag.configure(
51
            api_key=app.config['BUGSNAG_API_KEY'],
52
            project_root=app.config['ROOT'],
53
        )
54
        handle_exceptions(app)
55
56
57
def configure_logging(app):
58
    log.init(level=app.config['LOG_LEVEL'])
59
    log.silence('requests', 'werkzeug', 'yorm', allow_warning=True)
60
    log.silence('PIL', allow_info=True)
61
62
63
def register_extensions(app):
64
    extensions.cors.init_app(app, methods=['GET', 'OPTIONS'],
65
                             allow_headers='*')
66
    extensions.cache.init_app(app)
67
68
69
def register_services(app):
70
    exceptions = services.Exceptions(
71
        TemplateNotFound,
72
        InvalidMaskedCode,
73
        FilenameTooLong,
74
        InvalidImageLink,
75
    )
76
77
    templates_root = os.path.join(app.config['ROOT'], 'data', 'templates')
78
    template_store = stores.template.TemplateStore(templates_root)
79
80
    fonts_root = os.path.join(app.config['ROOT'], 'data', 'fonts')
81
    font_store = stores.font.FontStore(fonts_root)
82
83
    images_root = os.path.join(app.config['ROOT'], 'data', 'images')
84
    image_store = stores.image.ImageStore(images_root, app.config)
85
86
    app.link_service = services.link.LinkService(
87
        exceptions=exceptions,
88
        template_store=template_store,
89
    )
90
    app.template_service = services.template.TemplateService(
91
        exceptions=exceptions,
92
        template_store=template_store,
93
    )
94
    app.font_service = services.font.FontService(
95
        exceptions=exceptions,
96
        font_store=font_store
97
    )
98
    app.image_service = services.image.ImageService(
99
        exceptions=exceptions,
100
        template_store=template_store,
101
        font_store=font_store,
102
        image_store=image_store,
103
    )
104
105
    def log_request(response=None):
106
        if current_app.debug:
107
            status = response.status_code if response else ''
108
            log.info(f"{request.method}: {request.full_path} - {status}")
109
110
        return response
111
112
    app.before_request(log_request)
113
    app.after_request(log_request)
114
115
116
def register_blueprints(app):
117
    app.register_blueprint(routes.api_aliases.blueprint)
118
    app.register_blueprint(routes.api_fonts.blueprint)
119
    app.register_blueprint(routes.api_legacy.blueprint)
120
    app.register_blueprint(routes.api_links.blueprint)
121
    app.register_blueprint(routes.api_root.blueprint)
122
    app.register_blueprint(routes.api_search.blueprint)
123
    app.register_blueprint(routes.api_templates.blueprint)
124
    app.register_blueprint(routes.custom.blueprint)
125
    app.register_blueprint(routes.examples.blueprint)
126
    app.register_blueprint(routes.image.blueprint)
127
    app.register_blueprint(routes.index.blueprint)
128
    app.register_blueprint(routes.latest.blueprint)
129
    app.register_blueprint(routes.static.blueprint)
130