Tests for mediagoblin.config functions
[mediagoblin.git] / mediagoblin / app.py
CommitLineData
8e1e744d 1# GNU MediaGoblin -- federated, autonomous media hosting
e5572c60
ML
2# Copyright (C) 2011 Free Software Foundation, Inc
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
571198c9 17import os
31a8ff42
CAW
18import urllib
19
31a8ff42 20import routes
86f9b473 21from paste.deploy.converters import asbool
b61874b2 22from webob import Request, exc
31a8ff42 23
0f18ed8f 24from mediagoblin import routing, util, storage, staticdirect
a67fec81 25from mediagoblin.db.open import setup_connection_and_db_from_config
6e7ce8d1 26from mediagoblin.mg_globals import setup_globals
5784c4e9 27from mediagoblin.celery_setup import setup_celery_from_config
a32acafa 28from mediagoblin.workbench import WorkbenchManager, DEFAULT_WORKBENCH_DIR
31a8ff42
CAW
29
30
31class Error(Exception): pass
32class ImproperlyConfigured(Error): pass
33
34
8e1e744d 35class MediaGoblinApp(object):
31a8ff42
CAW
36 """
37 Really basic wsgi app using routes and WebOb.
38 """
a67fec81 39 def __init__(self, connection, db,
5afdd7a1 40 public_store, queue_store,
582c4d5f 41 staticdirector,
29f3fb70 42 email_sender_address, email_debug_mode,
7ecc58cc
CAW
43 user_template_path=None,
44 workbench_path=DEFAULT_WORKBENCH_DIR):
5afdd7a1 45 # Get the template environment
0e0e3d9a 46 self.template_loader = util.get_jinja_loader(user_template_path)
5afdd7a1
CAW
47
48 # Set up storage systems
49 self.public_store = public_store
50 self.queue_store = queue_store
51
52 # Set up database
2b4e236a 53 self.connection = connection
a67fec81 54 self.db = db
5afdd7a1
CAW
55
56 # set up routing
0f63a944 57 self.routing = routing.get_mapper()
31a8ff42 58
582c4d5f
CAW
59 # set up staticdirector tool
60 self.staticdirector = staticdirector
2b4e236a 61
df9809c2
CAW
62 # certain properties need to be accessed globally eg from
63 # validators, etc, which might not access to the request
64 # object.
65 setup_globals(
4c093e85 66 email_sender_address=email_sender_address,
29f3fb70 67 email_debug_mode=email_debug_mode,
df9809c2
CAW
68 db_connection=connection,
69 database=self.db,
70 public_store=self.public_store,
7ecc58cc
CAW
71 queue_store=self.queue_store,
72 workbench_manager=WorkbenchManager(workbench_path))
df9809c2 73
31a8ff42
CAW
74 def __call__(self, environ, start_response):
75 request = Request(environ)
76 path_info = request.path_info
582c4d5f
CAW
77
78 ## Routing / controller loading stuff
0f63a944 79 route_match = self.routing.match(path_info)
31a8ff42
CAW
80
81 # No matching page?
82 if route_match is None:
83 # Try to do see if we have a match with a trailing slash
84 # added and if so, redirect
85 if not path_info.endswith('/') \
86 and request.method == 'GET' \
0f63a944 87 and self.routing.match(path_info + '/'):
31a8ff42
CAW
88 new_path_info = path_info + '/'
89 if request.GET:
90 new_path_info = '%s?%s' % (
91 new_path_info, urllib.urlencode(request.GET))
1bb0fdf2 92 redirect = exc.HTTPFound(location=new_path_info)
31a8ff42
CAW
93 return request.get_response(redirect)(environ, start_response)
94
95 # Okay, no matches. 404 time!
96 return exc.HTTPNotFound()(environ, start_response)
97
cb8ea0fe 98 controller = util.import_component(route_match['controller'])
31a8ff42
CAW
99 request.start_response = start_response
100
582c4d5f 101 ## Attach utilities to the request object
31a8ff42 102 request.matchdict = route_match
0f63a944 103 request.urlgen = routes.URLGenerator(self.routing, environ)
7846e406 104 # Do we really want to load this via middleware? Maybe?
14ba9383 105 request.session = request.environ['beaker.session']
0dd65945
CAW
106 # Attach self as request.app
107 # Also attach a few utilities from request.app for convenience?
108 request.app = self
0e0e3d9a
CAW
109 request.locale = util.get_locale_from_request(request)
110
111 request.template_env = util.get_jinja_env(
112 self.template_loader, request.locale)
0dd65945
CAW
113 request.db = self.db
114 request.staticdirect = self.staticdirector
31a8ff42 115
ddff7cce
CAW
116 util.setup_user_in_request(request)
117
31a8ff42
CAW
118 return controller(request)(environ, start_response)
119
120
5784c4e9 121def paste_app_factory(global_config, **app_config):
cb8ea0fe 122 # Get the database connection
a67fec81 123 connection, db = setup_connection_and_db_from_config(app_config)
73e0dbcc 124
cb8ea0fe 125 # Set up the storage systems.
5afdd7a1 126 public_store = storage.storage_system_from_paste_config(
5784c4e9 127 app_config, 'publicstore')
5afdd7a1 128 queue_store = storage.storage_system_from_paste_config(
5784c4e9 129 app_config, 'queuestore')
5afdd7a1 130
582c4d5f 131 # Set up the staticdirect system
5784c4e9 132 if app_config.has_key('direct_remote_path'):
582c4d5f 133 staticdirector = staticdirect.RemoteStaticDirect(
5784c4e9
CAW
134 app_config['direct_remote_path'].strip())
135 elif app_config.has_key('direct_remote_paths'):
136 direct_remote_path_lines = app_config[
137 'direct_remote_paths'].strip().splitlines()
582c4d5f
CAW
138 staticdirector = staticdirect.MultiRemoteStaticDirect(
139 dict([line.strip().split(' ', 1)
5784c4e9 140 for line in direct_remote_path_lines]))
582c4d5f
CAW
141 else:
142 raise ImproperlyConfigured(
143 "One of direct_remote_path or direct_remote_paths must be provided")
144
c5678c1a
CAW
145 if not asbool(app_config.get('celery_setup_elsewhere')):
146 if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
147 setup_celery_from_config(
148 app_config, global_config,
149 force_celery_always_eager=True)
150 else:
151 setup_celery_from_config(app_config, global_config)
5784c4e9 152
8e1e744d 153 mgoblin_app = MediaGoblinApp(
a67fec81 154 connection, db,
5afdd7a1 155 public_store=public_store, queue_store=queue_store,
582c4d5f 156 staticdirector=staticdirector,
29f3fb70
CAW
157 email_sender_address=app_config.get(
158 'email_sender_address', 'notice@mediagoblin.example.org'),
cd847fd3 159 email_debug_mode=asbool(app_config.get('email_debug_mode')),
7ecc58cc
CAW
160 user_template_path=app_config.get('local_templates'),
161 workbench_path=app_config.get('workbench_path', DEFAULT_WORKBENCH_DIR))
b61874b2 162
c4d71564 163 return mgoblin_app