Rev 5789: Add hooks for config stacks. in file:///home/vila/src/bzr/experimental/config/

Vincent Ladeuil v.ladeuil+lp at free.fr
Wed Jun 8 16:29:36 UTC 2011


At file:///home/vila/src/bzr/experimental/config/

------------------------------------------------------------
revno: 5789
revision-id: v.ladeuil+lp at free.fr-20110608162936-nglond8qgcsvyth0
parent: v.ladeuil+lp at free.fr-20110608095148-r0rvo0qvvoebxesu
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: config-test-stats
timestamp: Wed 2011-06-08 18:29:36 +0200
message:
  Add hooks for config stacks.
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py	2011-06-01 12:31:04 +0000
+++ b/bzrlib/config.py	2011-06-08 16:29:36 +0000
@@ -65,9 +65,8 @@
 import os
 import string
 import sys
-import weakref
-
-from bzrlib import commands
+
+
 from bzrlib.decorators import needs_write_lock
 from bzrlib.lazy_import import lazy_import
 lazy_import(globals(), """
@@ -95,6 +94,8 @@
 from bzrlib.util.configobj import configobj
 """)
 from bzrlib import (
+    commands,
+    hooks,
     registry,
     )
 from bzrlib.symbol_versioning import (
@@ -159,7 +160,7 @@
         return self[section][name]
 
 
-# FIXME: Until we can guarantee that each config file is loaded once and and
+# FIXME: Until we can guarantee that each config file is loaded once and
 # only once for a given bzrlib session, we don't want to re-read the file every
 # time we query for an option so we cache the value (bad ! watch out for tests
 # needing to restore the proper value).This shouldn't be part of 2.4.0 final,
@@ -2587,6 +2588,8 @@
                 opt = None
             if opt is not None:
                 value = opt.get_default()
+        for hook in Stack.hooks['get']:
+            hook(self, name, value)
         return value
 
     def _get_mutable_section(self):
@@ -2604,17 +2607,49 @@
         """Set a new value for the option."""
         section = self._get_mutable_section()
         section.set(name, value)
+        for hook in Stack.hooks['set']:
+            hook(self, name, value)
 
     def remove(self, name):
         """Remove an existing option."""
         section = self._get_mutable_section()
         section.remove(name)
+        for hook in Stack.hooks['remove']:
+            hook(self, name)
 
     def __repr__(self):
         # Mostly for debugging use
         return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
 
 
+class StackHooks(hooks.Hooks):
+    """A dict mapping hook names and a list of callables for config stacks.
+    """
+
+    def __init__(self):
+        """Create the default hooks.
+
+        These are all empty initially, because by default nothing should get
+        notified.
+        """
+        super(StackHooks, self).__init__('bzrlib.config', 'Stack.hooks')
+        self.add_hook('get',
+                      'Invoked when a config option is read.'
+                      ' The signature is (stack, name, value).',
+                      (2, 4))
+        self.add_hook('set',
+                      'Invoked when a config option is set.'
+                      ' The signature is (stack, name, value).',
+                      (2, 4))
+        self.add_hook('remove',
+                      'Invoked when a config option is removed.'
+                      ' The signature is (stack, name).',
+                      (2, 4))
+
+# install the default hooks into the Stack class.
+Stack.hooks = StackHooks()
+
+
 class _CompatibleStack(Stack):
     """Place holder for compatibility with previous design.
 

=== modified file 'bzrlib/hooks.py'
--- a/bzrlib/hooks.py	2011-04-07 10:36:24 +0000
+++ b/bzrlib/hooks.py	2011-06-08 16:29:36 +0000
@@ -72,6 +72,7 @@
     ('bzrlib.branch', 'Branch.hooks', 'BranchHooks'),
     ('bzrlib.bzrdir', 'BzrDir.hooks', 'BzrDirHooks'),
     ('bzrlib.commands', 'Command.hooks', 'CommandHooks'),
+    ('bzrlib.config', 'Stack.hooks', 'StackHooks'),
     ('bzrlib.info', 'hooks', 'InfoHooks'),
     ('bzrlib.lock', 'Lock.hooks', 'LockHooks'),
     ('bzrlib.merge', 'Merger.hooks', 'MergeHooks'),

=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py	2011-06-01 12:31:04 +0000
+++ b/bzrlib/tests/test_config.py	2011-06-08 16:29:36 +0000
@@ -2494,10 +2494,6 @@
         conf_stack = config.Stack([conf1, conf2])
         self.assertEquals('baz', conf_stack.get('foo'))
 
-    def test_get_for_empty_stack(self):
-        conf_stack = config.Stack([])
-        self.assertEquals(None, conf_stack.get('foo'))
-
     def test_get_for_empty_section_callable(self):
         conf_stack = config.Stack([lambda : []])
         self.assertEquals(None, conf_stack.get('foo'))
@@ -2521,6 +2517,26 @@
         stack = self.get_stack(self)
 
 
+class TestStackGet(TestStackWithTransport):
+
+    def test_get_for_empty_stack(self):
+        conf = self.get_stack(self)
+        self.assertEquals(None, conf.get('foo'))
+
+    def test_get_hook(self):
+        calls = []
+        def hook(*args):
+            calls.append(args)
+        config.Stack.hooks.install_named_hook('get', hook, None)
+        self.assertLength(0, calls)
+        conf = self.get_stack(self)
+        conf.store._load_from_string('foo=bar')
+        value = conf.get('foo')
+        self.assertEquals('bar', value)
+        self.assertLength(1, calls)
+        self.assertEquals((conf, 'foo', 'bar'), calls[0])
+
+
 class TestStackSet(TestStackWithTransport):
 
     def test_simple_set(self):
@@ -2536,6 +2552,17 @@
         conf.set('foo', 'baz')
         self.assertEquals, 'baz', conf.get('foo')
 
+    def test_set_hook(self):
+        calls = []
+        def hook(*args):
+            calls.append(args)
+        config.Stack.hooks.install_named_hook('set', hook, None)
+        self.assertLength(0, calls)
+        conf = self.get_stack(self)
+        conf.set('foo', 'bar')
+        self.assertLength(1, calls)
+        self.assertEquals((conf, 'foo', 'bar'), calls[0])
+
 
 class TestStackRemove(TestStackWithTransport):
 
@@ -2551,6 +2578,18 @@
         conf = self.get_stack(self)
         self.assertRaises(KeyError, conf.remove, 'I_do_not_exist')
 
+    def test_remove_hook(self):
+        calls = []
+        def hook(*args):
+            calls.append(args)
+        config.Stack.hooks.install_named_hook('remove', hook, None)
+        self.assertLength(0, calls)
+        conf = self.get_stack(self)
+        conf.store._load_from_string('foo=bar')
+        conf.remove('foo')
+        self.assertLength(1, calls)
+        self.assertEquals((conf, 'foo'), calls[0])
+
 
 class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
 

=== modified file 'doc/en/release-notes/bzr-2.4.txt'
--- a/doc/en/release-notes/bzr-2.4.txt	2011-06-07 18:39:38 +0000
+++ b/doc/en/release-notes/bzr-2.4.txt	2011-06-08 16:29:36 +0000
@@ -20,9 +20,14 @@
 
 .. New commands, options, etc that users may wish to try out.
 
+* Hooks added for config stacks: ``get``, ``set`` and ``remove`` are called
+  when an option is repsectively read, modified or deleted.
+  (Vincent Ladeuil)
+
 * New hook server_exception in bzrlib.smart.server to catch any
-  exception caused while running bzr serve.  (Jonathan Riddell,
-  #274578)
+  exception caused while running bzr serve.
+  (Jonathan Riddell, #274578)
+
 
 Improvements
 ************



More information about the bazaar-commits mailing list