comparison mercurial/configitems.py @ 35445:181d913b17e6

configitems: allow for the registration of "generic" config item Some section can contains arbitrary keys (eg: color, alias, extensions). We add a way to register some generic config items for them. This is necessary to get all the config registered. We use a regular expression because some sub- attributes (eg: hooks.xxx.priority) can define default value on their own.
author Boris Feld <boris.feld@octobus.net>
date Tue, 10 Oct 2017 10:49:15 +0200
parents 8bea493e7297
children 6de7842290b2
comparison
equal deleted inserted replaced
35444:eb586ed5d8ce 35445:181d913b17e6
6 # GNU General Public License version 2 or any later version. 6 # GNU General Public License version 2 or any later version.
7 7
8 from __future__ import absolute_import 8 from __future__ import absolute_import
9 9
10 import functools 10 import functools
11 import re
11 12
12 from . import ( 13 from . import (
13 encoding, 14 encoding,
14 error, 15 error,
15 ) 16 )
31 """represent a known config item 32 """represent a known config item
32 33
33 :section: the official config section where to find this item, 34 :section: the official config section where to find this item,
34 :name: the official name within the section, 35 :name: the official name within the section,
35 :default: default value for this item, 36 :default: default value for this item,
36 :alias: optional list of tuples as alternatives. 37 :alias: optional list of tuples as alternatives,
38 :generic: this is a generic definition, match name using regular expression.
37 """ 39 """
38 40
39 def __init__(self, section, name, default=None, alias=()): 41 def __init__(self, section, name, default=None, alias=(),
42 generic=False, priority=0):
40 self.section = section 43 self.section = section
41 self.name = name 44 self.name = name
42 self.default = default 45 self.default = default
43 self.alias = list(alias) 46 self.alias = list(alias)
47 self.generic = generic
48 self.priority = priority
49 self._re = None
50 if generic:
51 self._re = re.compile(self.name)
52
53 class itemregister(dict):
54 """A specialized dictionary that can handle wild-card selection"""
55
56 def __init__(self):
57 super(itemregister, self).__init__()
58 self._generics = set()
59
60 def update(self, other):
61 super(itemregister, self).update(other)
62 self._generics.update(other._generics)
63
64 def __setitem__(self, key, item):
65 super(itemregister, self).__setitem__(key, item)
66 if item.generic:
67 self._generics.add(item)
68
69 def get(self, key):
70 if key in self:
71 return self[key]
72
73 # search for a matching generic item
74 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
75 for item in generics:
76 if item._re.match(key):
77 return item
78
79 # fallback to dict get
80 return super(itemregister, self).get(key)
44 81
45 coreitems = {} 82 coreitems = {}
46 83
47 def _register(configtable, *args, **kwargs): 84 def _register(configtable, *args, **kwargs):
48 item = configitem(*args, **kwargs) 85 item = configitem(*args, **kwargs)
49 section = configtable.setdefault(item.section, {}) 86 section = configtable.setdefault(item.section, itemregister())
50 if item.name in section: 87 if item.name in section:
51 msg = "duplicated config item registration for '%s.%s'" 88 msg = "duplicated config item registration for '%s.%s'"
52 raise error.ProgrammingError(msg % (item.section, item.name)) 89 raise error.ProgrammingError(msg % (item.section, item.name))
53 section[item.name] = item 90 section[item.name] = item
54 91