memegen.factory   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 92
dl 0
loc 130
ccs 73
cts 73
cp 1
rs 10
c 0
b 0
f 0
wmc 9

6 Functions

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