From 3f5cf663c0c8c2c06c9185af82b5f75423fce7f3 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 18 Jun 2011 17:59:38 -0500 Subject: [PATCH] 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 --- mediagoblin/app.py | 145 +++++++++++++++++++--------------- mediagoblin/config_spec.ini | 6 +- mediagoblin.ini => server.ini | 12 +-- 3 files changed, 89 insertions(+), 74 deletions(-) rename mediagoblin.ini => server.ini (60%) diff --git a/mediagoblin/app.py b/mediagoblin/app.py index a1c6b512..da1aba47 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -18,14 +18,15 @@ import os import urllib import routes -from paste.deploy.converters import asbool from webob import Request, exc 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.mg_globals import setup_globals 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 @@ -34,42 +35,101 @@ class ImproperlyConfigured(Error): pass 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, - public_store, queue_store, - staticdirector, - email_sender_address, email_debug_mode, - user_template_path=None, - workbench_path=DEFAULT_WORKBENCH_DIR): + def __init__(self, config_path, setup_celery=True): + """ + Initialize the application based on a configuration file. + + Arguments: + - 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 - 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 - self.public_store = public_store - self.queue_store = queue_store - - # Set up database - self.connection = connection - self.db = db + self.public_store = storage.storage_system_from_paste_config( + app_config, 'publicstore') + self.queue_store = storage.storage_system_from_paste_config( + app_config, 'queuestore') # set up routing self.routing = routing.get_mapper() # 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 # validators, etc, which might not access to the request # object. + ####################################################### + setup_globals( - email_sender_address=email_sender_address, - email_debug_mode=email_debug_mode, - db_connection=connection, + app_config=app_config, + global_config=global_config, + + # 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, public_store=self.public_store, queue_store=self.queue_store, - workbench_manager=WorkbenchManager(workbench_path)) + workbench_manager=WorkbenchManager(app_config['workbench_path'])) def __call__(self, environ, start_response): request = Request(environ) @@ -119,45 +179,6 @@ class MediaGoblinApp(object): def paste_app_factory(global_config, **app_config): - # Get the database connection - 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)) + mgoblin_app = MediaGoblinApp(app_config['config']) return mgoblin_app diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index 2e782101..52e3fdfd 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -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") # 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/") @@ -16,7 +16,9 @@ direct_remote_path = string(default="/mgoblin_static/") email_debug_mode = boolean(default=True) 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 # something else (and thus mediagoblin should not attempt to set it up diff --git a/mediagoblin.ini b/server.ini similarity index 60% rename from mediagoblin.ini rename to server.ini index b85f22ea..73fbe8e8 100644 --- a/mediagoblin.ini +++ b/server.ini @@ -10,19 +10,11 @@ use = egg:Paste#urlmap [app:mediagoblin] use = egg:mediagoblin#app filter-with = beaker -queuestore_base_dir = %(here)s/user_dev/media/queue -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/ +config = %(here)s/mediagoblin.ini [app:publicstore_serve] use = egg:Paste#static -document_root = %(here)s/user_dev/media/public +document_root = %(here)s/user_dev/media/public/ [app:mediagoblin_static] use = egg:Paste#static -- 2.25.1