Rev 6127: Introduce a stack factory registry and use it instead of the *Stack classses (now deleted). in file:///home/vila/src/bzr/bugs/832036-stack-registry/

Vincent Ladeuil v.ladeuil+lp at free.fr
Tue Sep 6 16:02:02 UTC 2011


At file:///home/vila/src/bzr/bugs/832036-stack-registry/

------------------------------------------------------------
revno: 6127
revision-id: v.ladeuil+lp at free.fr-20110906160201-9qss61wdp7rzykbl
parent: v.ladeuil+lp at free.fr-20110905160446-9aihwyfudsplk7xm
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 832036-stack-registry
timestamp: Tue 2011-09-06 18:02:01 +0200
message:
  Introduce a stack factory registry and use it instead of the *Stack classses (now deleted).
-------------- next part --------------
=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py	2011-08-17 09:27:29 +0000
+++ b/bzrlib/bzrdir.py	2011-09-06 16:02:01 +0000
@@ -2288,7 +2288,7 @@
     help='Same as 2a.')
 
 # The current format that is made on 'bzr init'.
-format_name = config.GlobalStack().get('default_format')
+format_name = config.stacks.get('bazaar')().get('default_format')
 controldir.format_registry.set_default(format_name)
 
 # XXX 2010-08-20 JRV: There is still a lot of code relying on

=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py	2011-09-05 16:04:46 +0000
+++ b/bzrlib/config.py	2011-09-06 16:02:01 +0000
@@ -414,7 +414,7 @@
             # add) the final ','
             l = [l]
         return l
-        
+
     def get_user_option_as_int_from_SI(self,  option_name,  default=None):
         """Get a generic option from a human readable size in SI units, e.g 10MB
         
@@ -452,7 +452,6 @@
             except TypeError:
                 val = default
         return val
-        
 
     def gpg_signing_command(self):
         """What program should be used to sign signatures?"""
@@ -2454,8 +2453,7 @@
 
         :param option: The option to register. Its name is used as the key.
         """
-        super(OptionRegistry, self).register(option.name, option,
-                                             help=option.help)
+        super(OptionRegistry, self).register(option.name, option)
 
     def register_lazy(self, key, module_name, member_name):
         """Register a new option to be loaded on request.
@@ -3247,71 +3245,105 @@
         self.store.save()
 
 
-class GlobalStack(_CompatibleStack):
-    """Global options only stack."""
-
-    def __init__(self):
-        # Get a GlobalStore
-        gstore = GlobalStore()
-        super(GlobalStack, self).__init__([gstore.get_sections], gstore)
-
-
-class LocationStack(_CompatibleStack):
-    """Per-location options falling back to global options stack."""
-
-    def __init__(self, location):
-        """Make a new stack for a location and global configuration.
-        
-        :param location: A URL prefix to """
-        lstore = LocationStore()
-        matcher = LocationMatcher(lstore, location)
-        gstore = GlobalStore()
-        super(LocationStack, self).__init__(
-            [matcher.get_sections, gstore.get_sections], lstore)
-
-
-class BranchStack(_CompatibleStack):
-    """Per-location options falling back to branch then global options stack."""
-
-    def __init__(self, branch):
-        bstore = BranchStore(branch)
-        lstore = LocationStore()
-        matcher = LocationMatcher(lstore, branch.base)
-        gstore = GlobalStore()
-        super(BranchStack, self).__init__(
-            [matcher.get_sections, bstore.get_sections, gstore.get_sections],
-            bstore)
-        self.branch = branch
-
-
-class RemoteControlStack(_CompatibleStack):
-    """Remote control-only options stack."""
-
-    def __init__(self, bzrdir):
-        cstore = ControlStore(bzrdir)
-        super(RemoteControlStack, self).__init__(
+def global_stack():
+    """Create a stack for the global options."""
+    # Get a GlobalStore
+    gstore = GlobalStore()
+    stack = _CompatibleStack([gstore.get_sections], gstore)
+    return stack
+
+
+def location_stack(location):
+    """Create a stack for the options applying to a location.
+
+    This includes the matching sections from LocationStore and falls back to
+    the section in the GlobalStore.
+
+    :param location: A URL prefix to match sections from the LocationStore.
+    """
+    lstore = LocationStore()
+    matcher = LocationMatcher(lstore, location)
+    gstore = GlobalStore()
+    stack = _CompatibleStack([matcher.get_sections, gstore.get_sections],
+                             lstore)
+    return stack
+
+
+def branch_stack(branch):
+    """Create a stack for the branch options.
+
+    This includes the section in the BranchStore, falls back the sections in
+    LocationStore (using the branch URL) and finally to the section in the
+    GlobalStore.
+
+    :param branch: The related branch object.
+    """
+    bstore = BranchStore(branch)
+    lstore = LocationStore()
+    matcher = LocationMatcher(lstore, branch.base)
+    gstore = GlobalStore()
+    stack = _CompatibleStack(
+        [matcher.get_sections, bstore.get_sections, gstore.get_sections],
+        bstore)
+    return stack
+
+# Neeed for 'default_stack_on location' which is the only option defined in
+# 'control.conf'. This stack is not yet used in bzrdir.py -- vila 2011-09-06
+def control_only_stack(bzrdir):
+    """Create a stack for the control options *only*.
+
+    This includes only the section in the ControlStore.
+
+    :param bzrdir: The related bzrdir object.
+    """
+    cstore = ControlStore(bzrdir)
+    stack = _CompatibleStack(
             [cstore.get_sections],
             cstore)
-        self.bzrdir = bzrdir
-
-
-class RemoteBranchStack(_CompatibleStack):
-    """Remote branch-only options stack."""
-
-    def __init__(self, branch):
-        bstore = BranchStore(branch)
-        super(RemoteBranchStack, self).__init__(
+    return stack
+
+
+# Needed for 'stacked_on_location' only which use a hack that could be removed
+# when each config file is read only once. This stack is not yet used in
+# branch.py -- vila 2011-09-06
+def branch_only_stack(branch):
+    """Create a stack for the branch options *only*.
+
+    This includes only the section in the BranchStore.
+
+    :param branch: The related branch object.
+    """
+    bstore = BranchStore(branch)
+    stack = _CompatibleStack(
             [bstore.get_sections],
             bstore)
-        self.branch = branch
-
-
-class _StackRegistry(registry.Registry):
+    return stack
+
+
+class StackRegistry(registry.Registry):
     """Registry of Stack factories.
 
     This registry is queried for a given key and provides a factory that accept
     a context and build the appropriate Stack for this context.
     """
+    def get_help(self, key=None):
+        """Get the help text associated with the given key"""
+        factory = self.get(key)
+        the_help = factory.__doc__
+        if callable(the_help):
+            return the_help(self, key)
+        return the_help
+
+
+stacks = StackRegistry()
+stacks.register('bazaar', global_stack)
+stacks.register('locations', location_stack)
+stacks.register('branch', branch_stack)
+
+# Not used yet, may change in the future, don't use -- vila 2011-09-06
+stacks.register('control-only', control_only_stack)
+stacks.register('branch-only', branch_only_stack)
+
 
 class cmd_config(commands.Command):
     __doc__ = """Display, set or remove a configuration option.

=== modified file 'bzrlib/debug.py'
--- a/bzrlib/debug.py	2011-08-20 07:49:15 +0000
+++ b/bzrlib/debug.py	2011-09-06 16:02:01 +0000
@@ -32,7 +32,7 @@
 
     from bzrlib import config
 
-    c = config.GlobalStack()
+    c = config.stacks.get('bazaar')()
     for f in c.get('debug_flags'):
         debug_flags.add(f)
 

=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2011-07-25 07:11:56 +0000
+++ b/bzrlib/dirstate.py	2011-09-06 16:02:01 +0000
@@ -450,12 +450,11 @@
         self._known_hash_changes = set()
         # How many hash changed entries can we have without saving
         self._worth_saving_limit = worth_saving_limit
-        self._config_stack = config.LocationStack(urlutils.local_path_to_url(
-            path))
+        self._config_stack = config.stacks.get(
+            'locations')(urlutils.local_path_to_url(path))
 
     def __repr__(self):
-        return "%s(%r)" % \
-            (self.__class__.__name__, self._filename)
+        return "%s(%r)" % (self.__class__.__name__, self._filename)
 
     def _mark_modified(self, hash_changed_entries=None, header_modified=False):
         """Mark this dirstate as modified.

=== modified file 'bzrlib/i18n.py'
--- a/bzrlib/i18n.py	2011-08-31 10:56:58 +0000
+++ b/bzrlib/i18n.py	2011-09-06 16:02:01 +0000
@@ -136,7 +136,7 @@
 def _get_current_locale():
     if not os.environ.get('LANGUAGE'):
         from bzrlib import config
-        lang = config.GlobalStack().get('language')
+        lang = config.stacks.get('bazaar')().get('language')
         if lang:
             os.environ['LANGUAGE'] = lang
             return lang

=== modified file 'bzrlib/lockdir.py'
--- a/bzrlib/lockdir.py	2011-08-12 12:11:44 +0000
+++ b/bzrlib/lockdir.py	2011-09-06 16:02:01 +0000
@@ -708,7 +708,7 @@
         # XXX: This really should also use the locationconfig at least, but
         # that seems a bit hard to hook up at the moment. -- mbp 20110329
         # FIXME: The above is still true ;) -- vila 20110811
-        return config.GlobalStack()
+        return config.stacks.get('bazaar')()
 
 
 class LockHeldInfo(object):

=== modified file 'bzrlib/msgeditor.py'
--- a/bzrlib/msgeditor.py	2011-07-23 16:33:38 +0000
+++ b/bzrlib/msgeditor.py	2011-09-06 16:02:01 +0000
@@ -41,7 +41,7 @@
     except KeyError:
         pass
 
-    e = config.GlobalStack().get('editor')
+    e = config.stacks.get('bazaar')().get('editor')
     if e is not None:
         yield e, config.config_filename()
 

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2011-08-24 23:55:03 +0000
+++ b/bzrlib/osutils.py	2011-09-06 16:02:01 +0000
@@ -986,7 +986,7 @@
 def report_extension_load_failures():
     if not _extension_load_failures:
         return
-    if config.GlobalStack().get('ignore_missing_extensions'):
+    if config.stacks.get('bazaar')().get('ignore_missing_extensions'):
         return
     # the warnings framework should by default show this only once
     from bzrlib.trace import warning

=== modified file 'bzrlib/repofmt/pack_repo.py'
--- a/bzrlib/repofmt/pack_repo.py	2011-07-25 07:51:35 +0000
+++ b/bzrlib/repofmt/pack_repo.py	2011-09-06 16:02:01 +0000
@@ -831,7 +831,7 @@
                 set(all_combined).difference([combined_idx]))
         # resumed packs
         self._resumed_packs = []
-        self.config_stack = config.LocationStack(self.transport.base)
+        self.config_stack = config.stacks.get('locations')(self.transport.base)
 
     def __repr__(self):
         return '%s(%r)' % (self.__class__.__name__, self.repo)

=== modified file 'bzrlib/tests/per_workingtree/test_workingtree.py'
--- a/bzrlib/tests/per_workingtree/test_workingtree.py	2011-08-31 22:52:43 +0000
+++ b/bzrlib/tests/per_workingtree/test_workingtree.py	2011-09-06 16:02:01 +0000
@@ -1161,7 +1161,7 @@
 
     def test_set_in_branch(self):
         wt = self.make_wt_with_worth_saving_limit()
-        conf = config.BranchStack(wt.branch)
+        conf = config.stacks.get('branch')(wt.branch)
         conf.set('bzr.workingtree.worth_saving_limit', '20')
         self.assertEqual(20, wt._worth_saving_limit())
         ds = wt.current_dirstate()
@@ -1169,7 +1169,7 @@
 
     def test_invalid(self):
         wt = self.make_wt_with_worth_saving_limit()
-        conf = config.BranchStack(wt.branch)
+        conf = config.stacks.get('branch')(wt.branch)
         conf.set('bzr.workingtree.worth_saving_limit', 'a')
         # If the config entry is invalid, default to 10
         warnings = []

=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py	2011-09-05 16:04:46 +0000
+++ b/bzrlib/tests/test_config.py	2011-09-06 16:02:01 +0000
@@ -132,15 +132,15 @@
 
 
 config.test_stack_builder_registry.register(
-    'bazaar', lambda test: config.GlobalStack())
+    'bazaar', lambda test: config.stacks.get('bazaar')())
 config.test_stack_builder_registry.register(
-    'location', lambda test: config.LocationStack('.'))
+    'location', lambda test: config.stacks.get('locations')('.'))
 
 
 def build_branch_stack(test):
     build_backing_branch(test, 'branch')
     b = branch.Branch.open('branch')
-    return config.BranchStack(b)
+    return config.stacks.get('branch')(b)
 config.test_stack_builder_registry.register('branch', build_branch_stack)
 
 
@@ -151,7 +151,7 @@
      server_class) = transport_remote.get_test_permutations()[0]
     build_backing_branch(test, 'branch', transport_class, server_class)
     b = branch.Branch.open(test.get_url('branch'))
-    return config.RemoteBranchStack(b)
+    return config.stacks.get('branch')(b)
 config.test_stack_builder_registry.register('remote_branch',
                                             build_remote_branch_stack)
 
@@ -164,7 +164,7 @@
     # creating a dedicated helper to create only the bzrdir
     build_backing_branch(test, 'branch', transport_class, server_class)
     b = branch.Branch.open(test.get_url('branch'))
-    return config.RemoteControlStack(b.bzrdir)
+    return config.stacks.get('control-only')(b.bzrdir)
 config.test_stack_builder_registry.register('remote_control',
                                             build_remote_control_stack)
 
@@ -2530,7 +2530,6 @@
 
     def test_help_is_set(self):
         option_help = self.registry.get_help(self.option_name)
-        self.assertNotEquals(None, option_help)
         # Come on, think about the user, he really wants to know what the
         # option is about
         self.assertIsNot(None, option_help)
@@ -3184,7 +3183,7 @@
 
     def setUp(self):
         super(TestStackRegistry, self).setUp()
-        self.registry = config._StackRegistry()
+        self.registry = config.StackRegistry()
 
     def test_register_remove(self):
         self.registry.register('test', config.Stack)
@@ -3208,8 +3207,25 @@
         self.assertIs(self.lazy_stack, self.registry.get('test'))
 
 
-# register override
-# get_all
+class TestRegisteredStacks(tests.TestCase):
+
+    scenarios = [(key, {'stack_name': key, 'stack_factory': factory})
+                 for key, factory in config.stacks.iteritems()]
+
+    def setUp(self):
+        super(TestRegisteredStacks, self).setUp()
+        self.registry = config.stacks
+
+    def test_factory_callable(self):
+        self.assertTrue(callable(self.stack_factory))
+
+    def test_help_is_set(self):
+        stack_help = self.registry.get_help(self.stack_name)
+        # Come on, think about the user, he really wants to know what the
+        # stack is about
+        self.assertIsNot(None, stack_help)
+        self.assertNotEquals('', stack_help)
+
 
 class TestStackGet(tests.TestCase):
 
@@ -3520,7 +3536,7 @@
             string = ''
         # Since we don't save the config we won't strictly require to inherit
         # from TestCaseInTempDir, but an error occurs so quickly...
-        c = config.LocationStack(location)
+        c = config.stacks.get('locations')(location)
         c.store._load_from_string(string)
         return c
 

=== modified file 'bzrlib/tests/test_debug.py'
--- a/bzrlib/tests/test_debug.py	2011-08-12 16:25:56 +0000
+++ b/bzrlib/tests/test_debug.py	2011-09-06 16:02:01 +0000
@@ -33,7 +33,7 @@
         self.assertDebugFlags(['hpss'], 'debug_flags = hpss\n')
 
     def assertDebugFlags(self, expected_flags, conf_bytes):
-        conf = config.GlobalStack()
+        conf = config.stacks.get('bazaar')()
         conf.store._load_from_string(conf_bytes)
         conf.store.save()
         self.overrideAttr(debug, 'debug_flags', set())

=== modified file 'bzrlib/ui/__init__.py'
--- a/bzrlib/ui/__init__.py	2011-08-08 15:57:57 +0000
+++ b/bzrlib/ui/__init__.py	2011-09-06 16:02:01 +0000
@@ -248,7 +248,7 @@
         """
         # XXX: is the caller supposed to close the resulting object?
         if encoding is None:
-            encoding = config.GlobalStack().get('output_encoding')
+            encoding = config.stacks.get('bazaar')().get('output_encoding')
         if encoding is None:
             encoding = osutils.get_terminal_encoding(trace=True)
         if encoding_type is None:

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2011-08-12 14:47:42 +0000
+++ b/bzrlib/workingtree_4.py	2011-09-06 16:02:01 +0000
@@ -251,7 +251,7 @@
         :return: an integer. -1 means never save.
         """
         # FIXME: We want a WorkingTreeStack here -- vila 20110812
-        conf = config.BranchStack(self.branch)
+        conf = config.stacks.get('branch')(self.branch)
         return conf.get('bzr.workingtree.worth_saving_limit')
 
     def filter_unversioned_files(self, paths):



More information about the bazaar-commits mailing list