From c461d30194efdfb3fbea2f64b3e502d640b7350f Mon Sep 17 00:00:00 2001 From: John MacKenzie Date: Fri, 14 Dec 2012 11:12:05 -0600 Subject: [PATCH] --settings_module Option Allow logan apps to accept a --settings_module option that takes a dotted string representing an import path (e.g. my_module.settings). This value eventually gets run through __import__ and makes it possible to look up the module object by __name__ in sys.modules while loading the config for the logan app. --- logan/importer.py | 25 +++++++++++++++---------- logan/runner.py | 38 ++++++++++++++++++++++++++------------ logan/settings.py | 19 +++++++++++-------- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/logan/importer.py b/logan/importer.py index 318c24c..64b003e 100644 --- a/logan/importer.py +++ b/logan/importer.py @@ -7,34 +7,35 @@ """ import sys +import os from django.utils.importlib import import_module from logan.settings import load_settings, create_module installed = False -def install(name, config_path, default_settings, **kwargs): +def install(name, config_path_or_settings_mod, default_settings, **kwargs): global installed if installed: # TODO: reinstall return - sys.meta_path.append(LoganImporter(name, config_path, default_settings, **kwargs)) + sys.meta_path.append(LoganImporter(name, config_path_or_settings_mod, default_settings, **kwargs)) installed = True class LoganImporter(object): - def __init__(self, name, config_path, default_settings=None, allow_extras=True, callback=None): + def __init__(self, name, config_path_or_settings_mod, default_settings=None, allow_extras=True, callback=None): self.name = name - self.config_path = config_path + self.config_path_or_settings_mod = config_path_or_settings_mod self.default_settings = default_settings self.allow_extras = allow_extras self.callback = callback self.validate() def __repr__(self): - return "<%s for '%s' (%s)>" % (type(self), self.name, self.config_path) + return "<%s for '%s' (%s)>" % (type(self), self.name, self.config_path_or_settings_mod) def validate(self): # if self.name is None: @@ -47,7 +48,7 @@ def find_module(self, fullname, path=None): return LoganLoader( name=self.name, - config_path=self.config_path, + config_path_or_settings_mod=self.config_path_or_settings_mod, default_settings=self.default_settings, allow_extras=self.allow_extras, callback=self.callback, @@ -55,9 +56,9 @@ def find_module(self, fullname, path=None): class LoganLoader(object): - def __init__(self, name, config_path, default_settings=None, allow_extras=True, callback=None): + def __init__(self, name, config_path_or_settings_mod, default_settings=None, allow_extras=True, callback=None): self.name = name - self.config_path = config_path + self.config_path_or_settings_mod = config_path_or_settings_mod self.default_settings = default_settings self.allow_extras = allow_extras self.callback = callback @@ -75,13 +76,17 @@ def load_module(self, fullname): settings_mod = create_module(self.name) # Django doesn't play too nice without the config file living as a real file, so let's fake it. - settings_mod.__file__ = self.config_path + if os.path.exists(self.config_path_or_settings_mod): + settings_mod.__file__ = self.config_path_or_settings_mod + else: + settings_mod.__file__ = self.config_path_or_settings_mod.replace( + '.', os.sep) + '.py' # install the default settings for this app load_settings(default_settings_mod, allow_extras=self.allow_extras, settings=settings_mod) # install the custom settings for this app - load_settings(self.config_path, allow_extras=self.allow_extras, settings=settings_mod) + load_settings(self.config_path_or_settings_mod, allow_extras=self.allow_extras, settings=settings_mod) if self.callback: self.callback(settings_mod) diff --git a/logan/runner.py b/logan/runner.py index ab97e65..9de110c 100644 --- a/logan/runner.py +++ b/logan/runner.py @@ -48,7 +48,8 @@ def parse_args(args): def configure_app(config_path=None, project=None, default_config_path=None, default_settings=None, settings_initializer=None, settings_envvar=None, initializer=None, - allow_extras=True, config_module_name=None, runner_name=None): + allow_extras=True, config_module_name=None, runner_name=None, + settings_module=None): """ :param project: should represent the canonical name for the project, generally the same name it assigned in distutils. @@ -77,15 +78,20 @@ def configure_app(config_path=None, project=None, default_config_path=None, defa else: default_config_path = os.path.normpath(os.path.abspath(os.path.expanduser(default_config_path))) - if not config_path: - config_path = default_config_path + if settings_module: + config_path_or_settings_mod = settings_module + else: + if not config_path: + config_path = default_config_path + + config_path = os.path.expanduser(config_path) - config_path = os.path.expanduser(config_path) + if not os.path.exists(config_path): + if runner_name: + raise ValueError("Configuration file does not exist. Use '%s init' to initialize the file." % (runner_name,)) + raise ValueError("Configuration file does not exist at %r" % (config_path,)) - if not os.path.exists(config_path): - if runner_name: - raise ValueError("Configuration file does not exist. Use '%s init' to initialize the file." % (runner_name,)) - raise ValueError("Configuration file does not exist at %r" % (config_path,)) + config_path_or_settings_mod = config_path os.environ['DJANGO_SETTINGS_MODULE'] = config_module_name @@ -99,8 +105,8 @@ def settings_callback(settings): 'settings': settings, }) - importer.install(config_module_name, config_path, default_settings, - allow_extras=allow_extras, callback=settings_callback) + importer.install(config_module_name, config_path_or_settings_mod, + default_settings, allow_extras=allow_extras, callback=settings_callback) def run_app(**kwargs): @@ -144,13 +150,21 @@ def run_app(**kwargs): return - parser.add_option('--config', metavar='CONFIG', default=default_config_path) + parser.add_option('--config', metavar='CONFIG', default=None) + parser.add_option('--settings_module', metavar='SETTINGS_MODULE', + default=None) (options, logan_args) = parser.parse_args(args) config_path = options.config + settings_module = options.settings_module + + if config_path and settings_module: + raise ValueError('Only one of --settings_module or --config can be ' + 'passed to sentry.') - configure_app(config_path=config_path, **kwargs) + configure_app(config_path=config_path, settings_module=settings_module, + **kwargs) management.execute_from_command_line([runner_name, command] + command_args) diff --git a/logan/settings.py b/logan/settings.py index cec470a..f641438 100644 --- a/logan/settings.py +++ b/logan/settings.py @@ -43,15 +43,18 @@ def create_module(name, install=True): def load_settings(mod_or_filename, silent=False, allow_extras=True, settings=_settings): if isinstance(mod_or_filename, basestring): - conf = create_module('temp_config', install=False) - conf.__file__ = mod_or_filename try: - execfile(mod_or_filename, conf.__dict__) - except IOError, e: - if silent and e.errno in (errno.ENOENT, errno.EISDIR): - return settings - e.strerror = 'Unable to load configuration file (%s)' % e.strerror - raise + conf = __import__(mod_or_filename, globals(), locals(), ['*'], -1) + except ImportError: + conf = create_module('temp_config', install=False) + conf.__file__ = mod_or_filename + try: + execfile(mod_or_filename, conf.__dict__) + except IOError, e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return settings + e.strerror = 'Unable to load configuration file (%s)' % e.strerror + raise else: conf = mod_or_filename