Move entire app structure over to using the new config system.

This is a huge change!  This means several things.

 - From the python point of view, launching the application is a heck
   of a lot cleaner.  You just need to pass in the config file path to
   MediaGoblinApp's __init__() and whether or not this funtion should
   setup celery and you're good.
 - There are now two separate config files, separating the server
   setup from the application setup.
   - server.ini: the paste deploy config file, which configures the
     applications and server setup but *NOT* the mediagoblin application
     itself.
   - mediagoblin.ini: where you configure mediagoblin (and possibly celery)
 - Launching the application is now different.  Instead of:
     ./bin/paster serve mediagoblin.ini --reload
   We launch like:
     ./bin/paster serve server.ini --reload
This commit is contained in:
Christopher Allan Webber 2011-06-18 17:59:38 -05:00
parent d5234024b0
commit 3f5cf663c0
3 changed files with 88 additions and 73 deletions

View File

@ -18,14 +18,15 @@ import os
import urllib import urllib
import routes import routes
from paste.deploy.converters import asbool
from webob import Request, exc from webob import Request, exc
from mediagoblin import routing, util, storage, staticdirect from mediagoblin import routing, util, storage, staticdirect
from mediagoblin.config import (
read_mediagoblin_config, generate_validation_report)
from mediagoblin.db.open import setup_connection_and_db_from_config from mediagoblin.db.open import setup_connection_and_db_from_config
from mediagoblin.mg_globals import setup_globals from mediagoblin.mg_globals import setup_globals
from mediagoblin.celery_setup import setup_celery_from_config from mediagoblin.celery_setup import setup_celery_from_config
from mediagoblin.workbench import WorkbenchManager, DEFAULT_WORKBENCH_DIR from mediagoblin.workbench import WorkbenchManager
class Error(Exception): pass class Error(Exception): pass
@ -34,42 +35,101 @@ class ImproperlyConfigured(Error): pass
class MediaGoblinApp(object): class MediaGoblinApp(object):
""" """
Really basic wsgi app using routes and WebOb. WSGI application of MediaGoblin
... this is the heart of the program!
""" """
def __init__(self, connection, db, def __init__(self, config_path, setup_celery=True):
public_store, queue_store, """
staticdirector, Initialize the application based on a configuration file.
email_sender_address, email_debug_mode,
user_template_path=None, Arguments:
workbench_path=DEFAULT_WORKBENCH_DIR): - config_path: path to the configuration file we're opening.
- setup_celery: whether or not to setup celery during init.
(Note: setting 'celery_setup_elsewhere' also disables
setting up celery.)
"""
##############
# Setup config
##############
# Open and setup the config
global_config, validation_result = read_mediagoblin_config(config_path)
app_config = global_config['mediagoblin']
# report errors if necessary
validation_report = generate_validation_report(
global_config, validation_result)
if validation_report:
raise ImproperlyConfigured(validation_report)
##########################################
# Setup other connections / useful objects
##########################################
# Set up the database
self.connection, self.db = setup_connection_and_db_from_config(
app_config)
# Get the template environment # Get the template environment
self.template_loader = util.get_jinja_loader(user_template_path) self.template_loader = util.get_jinja_loader(
app_config.get('user_template_path'))
# Set up storage systems # Set up storage systems
self.public_store = public_store self.public_store = storage.storage_system_from_paste_config(
self.queue_store = queue_store app_config, 'publicstore')
self.queue_store = storage.storage_system_from_paste_config(
# Set up database app_config, 'queuestore')
self.connection = connection
self.db = db
# set up routing # set up routing
self.routing = routing.get_mapper() self.routing = routing.get_mapper()
# set up staticdirector tool # set up staticdirector tool
self.staticdirector = staticdirector if app_config.has_key('direct_remote_path'):
self.staticdirector = staticdirect.RemoteStaticDirect(
app_config['direct_remote_path'].strip())
elif app_config.has_key('direct_remote_paths'):
direct_remote_path_lines = app_config[
'direct_remote_paths'].strip().splitlines()
self.staticdirector = staticdirect.MultiRemoteStaticDirect(
dict([line.strip().split(' ', 1)
for line in direct_remote_path_lines]))
else:
raise ImproperlyConfigured(
"One of direct_remote_path or "
"direct_remote_paths must be provided")
# Setup celery, if appropriate
if setup_celery and not app_config.get('celery_setup_elsewhere'):
if os.environ.get('CELERY_ALWAYS_EAGER'):
setup_celery_from_config(
app_config, global_config,
force_celery_always_eager=True)
else:
setup_celery_from_config(app_config, global_config)
#######################################################
# Insert appropriate things into mediagoblin.mg_globals
#
# certain properties need to be accessed globally eg from # certain properties need to be accessed globally eg from
# validators, etc, which might not access to the request # validators, etc, which might not access to the request
# object. # object.
#######################################################
setup_globals( setup_globals(
email_sender_address=email_sender_address, app_config=app_config,
email_debug_mode=email_debug_mode, global_config=global_config,
db_connection=connection,
# TODO: No need to set these two up as globals, we could
# just read them out of mg_globals.app_config
email_sender_address=app_config['email_sender_address'],
email_debug_mode=app_config['email_debug_mode'],
# Actual, useful to everyone objects
db_connection=self.connection,
database=self.db, database=self.db,
public_store=self.public_store, public_store=self.public_store,
queue_store=self.queue_store, queue_store=self.queue_store,
workbench_manager=WorkbenchManager(workbench_path)) workbench_manager=WorkbenchManager(app_config['workbench_path']))
def __call__(self, environ, start_response): def __call__(self, environ, start_response):
request = Request(environ) request = Request(environ)
@ -119,45 +179,6 @@ class MediaGoblinApp(object):
def paste_app_factory(global_config, **app_config): def paste_app_factory(global_config, **app_config):
# Get the database connection mgoblin_app = MediaGoblinApp(app_config['config'])
connection, db = setup_connection_and_db_from_config(app_config)
# Set up the storage systems.
public_store = storage.storage_system_from_paste_config(
app_config, 'publicstore')
queue_store = storage.storage_system_from_paste_config(
app_config, 'queuestore')
# Set up the staticdirect system
if app_config.has_key('direct_remote_path'):
staticdirector = staticdirect.RemoteStaticDirect(
app_config['direct_remote_path'].strip())
elif app_config.has_key('direct_remote_paths'):
direct_remote_path_lines = app_config[
'direct_remote_paths'].strip().splitlines()
staticdirector = staticdirect.MultiRemoteStaticDirect(
dict([line.strip().split(' ', 1)
for line in direct_remote_path_lines]))
else:
raise ImproperlyConfigured(
"One of direct_remote_path or direct_remote_paths must be provided")
if not asbool(app_config.get('celery_setup_elsewhere')):
if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
setup_celery_from_config(
app_config, global_config,
force_celery_always_eager=True)
else:
setup_celery_from_config(app_config, global_config)
mgoblin_app = MediaGoblinApp(
connection, db,
public_store=public_store, queue_store=queue_store,
staticdirector=staticdirector,
email_sender_address=app_config.get(
'email_sender_address', 'notice@mediagoblin.example.org'),
email_debug_mode=asbool(app_config.get('email_debug_mode')),
user_template_path=app_config.get('local_templates'),
workbench_path=app_config.get('workbench_path', DEFAULT_WORKBENCH_DIR))
return mgoblin_app return mgoblin_app

View File

@ -4,7 +4,7 @@ queuestore_base_dir = string(default="%(here)s/user_dev/media/queue")
publicstore_base_dir = string(default="%(here)s/user_dev/media/public") publicstore_base_dir = string(default="%(here)s/user_dev/media/public")
# Where temporary files used in processing and etc are kept # Where temporary files used in processing and etc are kept
workbench_base_dir = string(default="%(here)s/user_dev/media/workbench") workbench_path = string(default="%(here)s/user_dev/media/workbench")
# #
publicstore_base_url = string(default="/mgoblin_media/") publicstore_base_url = string(default="/mgoblin_media/")
@ -16,7 +16,9 @@ direct_remote_path = string(default="/mgoblin_static/")
email_debug_mode = boolean(default=True) email_debug_mode = boolean(default=True)
email_sender_address = string(default="notice@mediagoblin.example.org") email_sender_address = string(default="notice@mediagoblin.example.org")
local_templates = string(default="%(here)s/user_dev/templates/") # By default not set, but you might want something like:
# "%(here)s/user_dev/templates/"
local_templates = string()
# Whether or not celery is set up via an environment variable or # Whether or not celery is set up via an environment variable or
# something else (and thus mediagoblin should not attempt to set it up # something else (and thus mediagoblin should not attempt to set it up

View File

@ -10,19 +10,11 @@ use = egg:Paste#urlmap
[app:mediagoblin] [app:mediagoblin]
use = egg:mediagoblin#app use = egg:mediagoblin#app
filter-with = beaker filter-with = beaker
queuestore_base_dir = %(here)s/user_dev/media/queue config = %(here)s/mediagoblin.ini
publicstore_base_dir = %(here)s/user_dev/media/public
publicstore_base_url = /mgoblin_media/
direct_remote_path = /mgoblin_static/
email_sender_address = "notice@mediagoblin.example.org"
# set to false to enable sending notices
email_debug_mode = true
## Uncomment this to put some user-overriding templates here
#local_templates = %(here)s/user_dev/templates/
[app:publicstore_serve] [app:publicstore_serve]
use = egg:Paste#static use = egg:Paste#static
document_root = %(here)s/user_dev/media/public document_root = %(here)s/user_dev/media/public/
[app:mediagoblin_static] [app:mediagoblin_static]
use = egg:Paste#static use = egg:Paste#static