Commits

Odd Simon Simonsen committed ef6227e

0.11.5dev: Exposing `config.getpath()` that has so far been hidden in `Section`. It also properly enables adding `PathOption` on components, and handles path calculation relative to project `trac.ini` if no chained config file contains the option. Tests included.

Fixes #8358.

Comments (0)

Files changed (2)

         self.parser = ConfigParser()
         self._old_sections = {}
         self.parent = None
+        self._base_filename = None
         self._lastmtime = 0
         self._sections = {}
         self.parse_if_needed()
         """
         return self[section].getlist(name, default, sep, keep_empty)
 
+    def getpath(self, section, name, default=''):
+        """Return a configuration value as an absolute path.
+        
+        Relative paths are made absolute relative to the location of the file
+        the option is read from. A value read from defaults use location of
+        first configuration file as base.
+
+        Valid default input is a string. Returns a string as correct path.
+        
+        (enabled since Trac 0.11.5)
+        """
+        return self[section].getpath(name, default)
+
     def set(self, section, name, value):
         """Change a configuration value.
         
                                         filename)
             if not self.parent or self.parent.filename != filename:
                 self.parent = Configuration(filename)
+                self.parent._base_filename = self._base_filename \
+                                                or self.filename
                 changed = True
             else:
                 changed |= self.parent.parse_if_needed()
         elif self.config.parent:
             return self.config.parent[self.name].getpath(name, default)
         else:
-            return default
+            base = self.config._base_filename or self.config.filename
+            path_opt = Option.registry.get((self.name, name), None)
+            path = path_opt and path_opt.default or default
+            if path and not os.path.isabs(path):
+                path = os.path.join(os.path.dirname(base), path)
+            return path
 
     def options(self):
         """Return `(name, value)` tuples for every option in the section."""

trac/tests/config.py

 
         self.assertEquals(2, config.getint('a', 'option'))
 
+    def test_default_path(self):
+        config = self._read()
+        class Foo(object):
+            option_a = PathOption('a', 'opt1', 'file.ini')
+            option_b = PathOption('a', 'opt2', '/somewhere/file.ini')
+        self.assertEquals('file.ini', config.get('a', 'opt1'))
+        self.assertNotEquals('file.ini', config.getpath('a', 'opt1'))
+        self.assertTrue(config.getpath('a', 'opt1').startswith('/'))
+        self.assertEquals('/somewhere/file.ini', config.getpath('a', 'opt2'))
+        self.assertEquals('/none.ini', config.getpath('a', 'opt3', '/none.ini'))
+        self.assertNotEquals('none.ini', config.getpath('a', 'opt3', 'none.ini'))
+
     def test_read_and_get(self):
         self._write(['[a]', 'option = x'])
         config = self._read()
         self.assertEquals(['', 'bar', 'baz'],
                           config.getlist('a', 'option', keep_empty=True))
 
+    def test_getpath(self):
+        config = self._read()
+        config.set('a', 'path_a', '/somewhere/file.txt')
+        config.set('a', 'path_b', 'file.txt')
+        config.set('a', 'path_c', './file.txt')
+        self.assertEquals('/somewhere/file.txt', config.getpath('a', 'path_a'))
+        self.assertNotEquals('file.txt', config.getpath('a', 'path_b'))
+        self.assertEquals(config.getpath('a', 'path_b'),
+                          config.getpath('a', 'path_c'))
+
     def test_set_and_save(self):
         config = self._read()
         config.set('b', 'option0', 'y')