From 42624eb74546893ddb1459c8d1f67e12ff1f4eb4 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Fri, 17 May 2013 19:05:16 -0700 Subject: [PATCH] use lazy config loader in confit This lets you, for example, import beets in a library or the REPL and use it immediately without calling "beets.config.read()" first. --- beets/__init__.py | 2 +- beets/ui/__init__.py | 9 ++------- beets/util/confit.py | 33 +++++++++++++++++++++++++++++++++ test/_common.py | 1 + test/test_ui.py | 2 +- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/beets/__init__.py b/beets/__init__.py index ebc3eedcd..151b46994 100644 --- a/beets/__init__.py +++ b/beets/__init__.py @@ -20,4 +20,4 @@ from beets.util import confit Library = beets.library.Library -config = confit.Configuration('beets', __name__, False) +config = confit.LazyConfig('beets', __name__) diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index 9e92ce4a4..099ea4cc3 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -689,18 +689,13 @@ class SubcommandsOptionParser(optparse.OptionParser): # The root parser and its main function. -def _raw_main(args, load_config=True): +def _raw_main(args): """A helper function for `main` without top-level exception handling. """ - # Load global configuration files. - if load_config: - config.read() - # Temporary: Migrate from 1.0-style configuration. from beets.ui import migrate - if load_config: - migrate.automigrate() + migrate.automigrate() # Get the default subcommands. from beets.ui.commands import default_commands diff --git a/beets/util/confit.py b/beets/util/confit.py index b7af4ea40..6a787ce3c 100644 --- a/beets/util/confit.py +++ b/beets/util/confit.py @@ -677,3 +677,36 @@ class Configuration(RootView): if not os.path.isdir(appdir): os.makedirs(appdir) return appdir + +class LazyConfig(Configuration): + """A Configuration at reads files on demand when it is first + accessed. This is appropriate for using as a global config object at + the module level. + """ + def __init__(self, appname, modname=None): + super(LazyConfig, self).__init__(appname, modname, False) + self._materialized = False # Have we read the files yet? + self._lazy_prefix = [] # Pre-materialization calls to set(). + self._lazy_suffix = [] # Calls to add(). + + def resolve(self): + if not self._materialized: + self._materialized = True + self.read() + self.sources += self._lazy_suffix + self.sources[:0] = self._lazy_prefix + return super(LazyConfig, self).resolve() + + def add(self, value): + super(LazyConfig, self).add(value) + if not self._materialized: + # Buffer additions to end. + self._lazy_suffix += self.sources + del self.sources[:] + + def set(self, value): + super(LazyConfig, self).set(value) + if not self._materialized: + # Buffer additions to beginning. + self._lazy_prefix[:0] = self.sources + del self.sources[:] diff --git a/test/_common.py b/test/_common.py index 864813766..0a2f8595b 100644 --- a/test/_common.py +++ b/test/_common.py @@ -92,6 +92,7 @@ class TestCase(unittest.TestCase): def setUp(self): # A "clean" source list including only the defaults. beets.config.sources = [] + beets.config._materialized = True beets.config.read(user=False, defaults=True) # Direct paths to a temporary directory. Tests can also use this diff --git a/test/test_ui.py b/test/test_ui.py index 0a286d125..c9d57a466 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -478,7 +478,7 @@ class ConfigTest(_common.TestCase): if config_yaml: config_data = yaml.load(config_yaml, Loader=confit.Loader) config.set(config_data) - ui._raw_main(args + ['test'], False) + ui._raw_main(args + ['test']) def test_paths_section_respected(self): def func(lib, opts, args):