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