Rev 5558: Implement a simple interpolation mechanism. in file:///home/vila/src/bzr/experimental/config/

Vincent Ladeuil v.ladeuil+lp at free.fr
Fri Feb 4 15:48:32 UTC 2011


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

------------------------------------------------------------
revno: 5558
revision-id: v.ladeuil+lp at free.fr-20110204154832-l0d43q84i15fg32x
parent: v.ladeuil+lp at free.fr-20110203103909-lgp491y9s2t1tj83
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: interpolate
timestamp: Fri 2011-02-04 16:48:32 +0100
message:
  Implement a simple interpolation mechanism.
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py	2011-02-03 10:39:09 +0000
+++ b/bzrlib/config.py	2011-02-04 15:48:32 +0000
@@ -146,30 +146,48 @@
 
     option_ref_re = None
 
-    def interpolate(self, string, env=None):
+    def interpolate(self, string, env=None, ref_stack=None):
+        if ref_stack is None:
+            # What references are currently resolved (to detect loops)
+            ref_stack = []
         if self.option_ref_re is None:
             # We want to match the most embedded reference first (i.e. for
             # '{{foo}}' we will get '{foo}',
             # for '{bar{baz}}' we will get '{baz}'
             self.option_ref_re = re.compile('({[^{}]+})')
-        while True:
-            found = self.option_ref_re.search(string)
-            if found is None:
-                # No more references, interpolation is done
-                break
-            ref = found.group()
-            name = ref[1:-1]
-            if env is not None and name in env:
-                # Special case, values provided in env takes precedence over
-                # anything else
-                value = env[name]
+        result = string
+        is_ref = False
+        chunks = []
+        import pdb; pdb.set_trace()
+        # Split will isolate refs so that every other chunk is a ref
+        for chunk in self.option_ref_re.split(result):
+            if not is_ref:
+                chunks.append(chunk)
+                is_ref = True
             else:
-                # FIXME: This is a limited implementation, what we really need
-                # is a way to query the bzr config for the value of an option,
-                # respecting the scope rules -- vila 20101222
-                value = self[name]
-            string = string.replace(ref, value)
-        return string
+                name = chunk[1:-1]
+                if name in ref_stack:
+                    raise errors.InterpolationLoop(string, ref_stack)
+                ref_stack.append(name)
+                value = self._interpolate_option(name, env, ref_stack)
+                raw_chunks.append(value)
+                ref_stack.pop()
+                is_ref = False
+        result = ''.join(chunks)
+        return result
+
+    def _interpolate_option(self, name, env, ref_stack):
+        if env is not None and name in env:
+            # Special case, values provided in env takes precedence over
+            # anything else
+            value = env[name]
+        else:
+            # FIXME: This is a limited implementation, what we really need
+            # is a way to query the bzr config for the value of an option,
+            # respecting the scope rules -- vila 20101222
+            value = self[name]
+        return self.interpolate(value, env, ref_stack)
+
 
 class Config(object):
     """A configuration policy - what username, editor, gpg needs etc."""

=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py	2011-02-03 10:39:09 +0000
+++ b/bzrlib/errors.py	2011-02-04 15:48:32 +0000
@@ -3222,10 +3222,10 @@
         self.branch_url = branch_url
 
 # FIXME: I would prefer to define the config related exception classes in
-# config.py but the lazy import mechanism proscribe this -- vila 20101222
+# config.py but the lazy import mechanism proscribes this -- vila 20101222
 class InterpolationLoop(BzrError):
 
-    _fmt = 'Loop involving %(refs)s while evaluating %(string)s.'
+    _fmt = 'Loop involving %(refs)r while evaluating <%(string)s>.'
 
     def __init__(self, string, refs):
         self.string = string

=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py	2011-02-03 10:39:09 +0000
+++ b/bzrlib/tests/test_config.py	2011-02-04 15:48:32 +0000
@@ -376,7 +376,7 @@
         self.assertInterpolate('xxx', c, '{{bar}}')
 
     def test_simple_loop(self):
-        c = self.get_config('foo=food')
+        c = self.get_config('foo={foo}')
         self.assertRaises(errors.InterpolationLoop, c.interpolate, '{foo}')
 
 



More information about the bazaar-commits mailing list