Edgewall Software

Ticket #1051: trac-global-config-4.diff

File trac-global-config-4.diff, 8.5 KB (added by trac-form@…, 7 years ago)

After some feedback from cmlenz, this version seems to be quite unobtrusive

  • setup.py

     
    3535         htdocs_dir = os.path.join(self.prefix, 'share', 'trac', 'htdocs') 
    3636         wiki_dir = os.path.join(self.prefix, 'share', 'trac', 'wiki-default') 
    3737         macros_dir = os.path.join(self.prefix, 'share', 'trac', 'wiki-macros') 
     38         config_dir = os.path.join(self.prefix, 'share', 'trac', 'conf') 
    3839         f = open(_p('trac/siteconfig.py'),'w') 
    3940         f.write(""" 
    4041# PLEASE DO NOT EDIT THIS FILE! 
     
    4445__default_htdocs_dir__ = %(htdocs)r 
    4546__default_wiki_dir__ = %(wiki)r 
    4647__default_macros_dir__ = %(macros)r 
     48__default_config_dir__ = %(config)r 
    4749 
    4850""" % {'trac':PACKAGE, 'ver':VERSION, 'templates':_p(templates_dir), 
    49        'htdocs':_p(htdocs_dir), 'wiki':_p(wiki_dir), 'macros':_p(macros_dir)}) 
     51       'htdocs':_p(htdocs_dir), 'wiki':_p(wiki_dir), 'macros':_p(macros_dir), 
     52       'config':_p(config_dir)}) 
    5053         f.close() 
    5154 
    5255         # Run actual install 
  • trac/config.py

     
    1717from __future__ import generators 
    1818 
    1919from ConfigParser import ConfigParser 
    20 import os.path 
     20import os.path, sys 
    2121 
     22def default_dir(name): 
     23    try: 
     24        from trac import siteconfig 
     25        return getattr(siteconfig, '__default_%s_dir__' % name) 
     26    except ImportError: 
     27        # This is not a regular install with a generated siteconfig.py file, 
     28        # so try to figure out the directory based on common setups 
     29        import os.path, sys 
     30        special_dirs = {'wiki': 'wiki-default', 'macros': 'wiki-macros'} 
     31        dirname = special_dirs.get(name, name) 
    2232 
     33        # First assume we're being executing directly form the source directory 
     34        import trac 
     35        path = os.path.join(os.path.split(os.path.dirname(trac.__file__))[0], 
     36                            dirname) 
     37        if not os.path.isdir(path): 
     38            # Not being executed from the source directory, so assume the 
     39            # default installation prefix 
     40            path = os.path.join(sys.prefix, 'share', 'trac', dirname) 
     41 
     42        return path 
     43 
    2344class Configuration: 
    2445    """ 
    2546    Thin layer over ConfigParser from the Python standard library. 
     
    2849    when the file has changed. 
    2950    """ 
    3051 
    31     def __init__(self, filename): 
     52    def __init__(self, filename, site_filename = os.path.join(default_dir('config'), 'trac.ini')): 
    3253        self.filename = filename 
     54        self.site_filename = site_filename 
    3355        self.parser = ConfigParser() 
     56        self.site_parser = ConfigParser() 
    3457        self.__defaults = {} 
    3558        self.__lastmtime = 0 
     59        self.__lastsitemtime = 0 
    3660        self.parse_if_needed() 
    3761 
    3862    def get(self, section, name, default=None): 
     
    4367        return self.parser.get(section, name) 
    4468 
    4569    def setdefault(self, section, name, value): 
    46         self.__defaults[(section, name)] = value 
     70        if (section, name) not in self.__defaults: 
     71            self.__defaults[(section, name)] = value 
    4772 
    4873    def set(self, section, name, value): 
    4974        """ 
     
    5580        return self.parser.set(section, name, value) 
    5681 
    5782    def options(self, section): 
    58         if not self.parser.has_section(section): 
    59             return [] 
    60         try: 
    61             return self.parser.items(section) 
    62         except AttributeError: 
    63             options = [] 
     83        options = [] 
     84        if self.parser.has_section(section): 
    6485            for option in self.parser.options(section): 
    6586                options.append((option, self.parser.get(section, option))) 
    66             return options 
     87        for option, value in self.__defaults.iteritems(): 
     88            if option[0] == section: 
     89                if not [exists for exists in options if exists[0] == option[1]]: 
     90                    options.append((option[1], value)) 
     91        return options 
    6792 
    6893    def __contains__(self, name): 
    6994        return self.parser.has_section(name) 
     
    81106        self.parser.write(open(self.filename, 'w')) 
    82107 
    83108    def parse_if_needed(self): 
     109        if self.site_filename: 
     110            try: 
     111                modtime = os.path.getmtime(self.site_filename) 
     112                if modtime > self.__lastsitemtime: 
     113                    self.site_parser.readfp(open(self.site_filename)) 
     114                    # Import global configuration into __defaults 
     115                    for section in self.site_parser.sections(): 
     116                        for option in self.site_parser.options(section): 
     117                            self.__defaults[(section, option)] = self.site_parser.get(section, option) 
     118                    self.__lastsitemtime = modtime 
     119            except (IOError, OSError): 
     120                pass 
    84121        if not self.filename: 
    85122            return 
    86123        modtime = os.path.getmtime(self.filename) 
    87124        if modtime > self.__lastmtime: 
    88125            self.parser.readfp(open(self.filename)) 
    89126            self.__lastmtime = modtime 
    90  
    91  
    92 def default_dir(name): 
    93     try: 
    94         from trac import siteconfig 
    95         return getattr(siteconfig, '__default_%s_dir__' % name) 
    96     except ImportError: 
    97         # This is not a regular install with a generated siteconfig.py file, 
    98         # so try to figure out the directory based on common setups 
    99         import os.path, sys 
    100         special_dirs = {'wiki': 'wiki-default', 'macros': 'wiki-macros'} 
    101         dirname = special_dirs.get(name, name) 
    102  
    103         # First assume we're being executing directly form the source directory 
    104         import trac 
    105         path = os.path.join(os.path.split(os.path.dirname(trac.__file__))[0], 
    106                             dirname) 
    107         if not os.path.isdir(path): 
    108             # Not being executed from the source directory, so assume the 
    109             # default installation prefix 
    110             path = os.path.join(sys.prefix, 'share', 'trac', dirname) 
    111  
    112         return path 
  • trac/tests/config.py

     
    3333        os.remove(self.filename) 
    3434 
    3535    def test_default(self): 
    36         config = Configuration(self.filename) 
     36        config = Configuration(self.filename, None) 
    3737        self.assertEquals('', config.get('a', 'option')) 
    3838        self.assertEquals('value', config.get('a', 'option', 'value')) 
    3939 
     
    4545        configfile.writelines(['[a]\n', 'option = x\n', '\n']) 
    4646        configfile.close() 
    4747 
    48         config = Configuration(self.filename) 
     48        config = Configuration(self.filename, None) 
    4949        self.assertEquals('x', config.get('a', 'option')) 
    5050        self.assertEquals('x', config.get('a', 'option', 'y')) 
    5151 
     
    5353        configfile = open(self.filename, 'w') 
    5454        configfile.close() 
    5555 
    56         config = Configuration(self.filename) 
     56        config = Configuration(self.filename, None) 
    5757        config.set('a', 'option', 'x') 
    5858        self.assertEquals('x', config.get('a', 'option')) 
    5959        config.save() 
     
    6969                               '[b]\n', 'option = y\n']) 
    7070        configfile.close() 
    7171 
    72         config = Configuration(self.filename) 
     72        config = Configuration(self.filename, None) 
    7373        self.assertEquals(['a', 'b'], config.sections()) 
    7474 
    7575    def test_options(self): 
     
    7878                               '[b]\n', 'option = y\n']) 
    7979        configfile.close() 
    8080 
    81         config = Configuration(self.filename) 
     81        config = Configuration(self.filename, None) 
    8282        self.assertEquals(('option', 'x'), iter(config.options('a')).next()) 
    8383        self.assertEquals(('option', 'y'), iter(config.options('b')).next()) 
    8484        self.assertRaises(StopIteration, iter(config.options('c')).next) 
     
    8888        configfile.writelines(['[a]\n', 'option = x\n', '\n']) 
    8989        configfile.close() 
    9090 
    91         config = Configuration(self.filename) 
     91        config = Configuration(self.filename, None) 
    9292        self.assertEquals('x', config.get('a', 'option')) 
    9393        time.sleep(1) # needed because of low mtime granularity 
    9494 
  • trac/test.py

     
    125125        self.db = InMemoryDatabase() 
    126126 
    127127        from trac.config import Configuration 
    128         self.config = Configuration(None) 
     128        self.config = Configuration(None, None) 
    129129 
    130130        from trac.log import logger_factory 
    131131        self.log = logger_factory('test')