1
# -*-  coding: utf-8 -*-
2
"""
3
    __init__.py
4
"""
5
6
from flask import Flask, request, jsonify, render_template, make_response, g
7
import os
8
import logging
9
from logging.handlers import RotatingFileHandler
10
11
from classes.database import db
12
from config import DefaultConfig
13
from classes import views
14
#from classes import models
15
from classes import oauth
16
17
__all__ = ['create_app', 'getDBInstance']
18
19
DEFAULT_APP_NAME = __name__
20
21
DEFAULT_MODULES = (
22
    (views.frontend, ''),
23
    (views.api, '/api'),
24
    (views.user, '/users'),
25
    (views.context, '/contexts'),
26
    (views.sweet, '/sweets'),
27
    (views.app, '/apps'),
28
    (views.Oauth, '/oauth')
29
)
30
31
32
def create_app(config=None, app_name=None, modules=None):
33
34
    if app_name is None:
35
        app_name = DEFAULT_APP_NAME
36
37
    if modules is None:
38
        modules = DEFAULT_MODULES
39
40
    app = Flask(app_name)
41
42
    configure_app(app, config)
43
44
    configure_logging(app)
45
    configure_errorhandlers(app)
46
    configure_extensions(app)
47
    #configure_beforehandlers(app)
48
    configure_modules(app, modules)
49
50
    return app
51
52
53
def configure_app(app, config):
54
55
    app.config.from_object(DefaultConfig())
56
57
    if config is not None:
58
        app.config.from_object(config)
59
60
    app.config.from_envvar('APP_CONFIG', silent=True)
61
62
63
def configure_modules(app, modules):
64
    for module, url_prefix in modules:
65
        app.register_module(module, url_prefix=url_prefix)
66
67
68
def configure_extensions(app):
69
    db.init_app(app)
70
    db.app = app
71
    oauth.init_app(app)
72
73
# return the current db instance
74
# TODO: is this needed so much?
75
def getDBInstance():
76
    return db
77
78
79
def configure_errorhandlers(app):
80
81
    if app.testing:
82
        return
83
84
    # TODO: with all these request can we send back the respective HTTP status
85
    # codes instead of 200?
86
    @app.errorhandler(404)
87
    def not_found(error):
88
        response = make_response()
89
        response.status_code = 404
90
91
        if request.is_xhr:
92
            response.data = jsonify(error=error)
93
        else:
94
            response.data = render_template('errors/404.html')
95
96
        return response
97
98
    @app.errorhandler(403)
99
    def forbidden(error):
100
        response = make_response()
101
        response.status_code = 403
102
103
        if request.is_xhr:
104
            response.data = jsonify(error=error)
105
        else:
106
            response.data = render_template('errors/403.html')
107
108
        return response
109
110
    @app.errorhandler(401)
111
    def unauthorized(error):
112
        response = make_response()
113
        response.status_code = 401
114
115
        if request.is_xhr:
116
            response.data = jsonify(error=error)
117
        else:
118
            response.data = render_template('errors/401.html')
119
120
        return response
121
122
    @app.errorhandler(400)
123
    def bad_request(error):
124
        response = make_response()
125
        response.status_code = 400
126
127
        # Check if we have any custom error messages
128
        #if g.error:
129
        #    print 'g.error:'
130
        #    print g.error
131
        #    error = g.error
132
133
        if request.is_xhr:
134
            response.data = jsonify(error=error)
135
        else:
136
            response.data = render_template('errors/400.html', error=error)
137
138
        return response
139
140
    @app.errorhandler(500)
141
    def server_error(error):
142
        response = make_response()
143
        response.status_code = 500
144
145
        if request.is_xhr:
146
            response.data = jsonify(error=error)
147
        else:
148
            response.data = render_template('errors/500.html')
149
150
        return response
151
152
153
def configure_logging(app):
154
155
    formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s '
156
                                  '[in %(pathname)s:%(lineno)d]')
157
158
    # Also error can be sent out via email. So we can also have a SMTPHandler?
159
    log_file = os.path.join(os.path.dirname(__file__), '..',
160
                            app.config['LOG_FILE'])
161
162
    max_size = 1024 * 1024 * 20  # Max Size for a log file: 20MB
163
    log_handler = RotatingFileHandler(log_file, maxBytes=max_size,
164
                                      backupCount=10)
165
166
    if app.config.has_key('LOG_LEVEL'):
167
        log_level = app.config['LOG_LEVEL'] or 'ERROR'
168
    else:
169
        log_level = 'ERROR'
170
171
    log_handler.setLevel(log_level)
172
    log_handler.setFormatter(formatter)
173
174
    app.logger.addHandler(log_handler)