From patchwork Fri Oct 13 17:55:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [01, of, 11] configitems: allow for the registration of "generic" config item From: Boris Feld X-Patchwork-Id: 24840 Message-Id: <429c6e9c7c3a4f601db1.1507917307@FB> To: mercurial-devel@mercurial-scm.org Date: Fri, 13 Oct 2017 19:55:07 +0200 # HG changeset patch # User Boris Feld # Date 1507625355 -7200 # Tue Oct 10 10:49:15 2017 +0200 # Node ID 429c6e9c7c3a4f601db17c6553a8fcdad35708a8 # Parent 37b4375b1221e3bda055f0cbecf06b3c9510fd2c # EXP-Topic config.register.ready # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 429c6e9c7c3a 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. diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -8,6 +8,7 @@ from __future__ import absolute_import import functools +import re from . import ( encoding, @@ -33,20 +34,56 @@ :section: the official config section where to find this item, :name: the official name within the section, :default: default value for this item, - :alias: optional list of tuples as alternatives. + :alias: optional list of tuples as alternatives, + :generic: this is a generic definition, match name using regular expression. """ - def __init__(self, section, name, default=None, alias=()): + def __init__(self, section, name, default=None, alias=(), + generic=False, priority=0): self.section = section self.name = name self.default = default self.alias = list(alias) + self.generic = generic + self.priority = priority + self._re = None + if generic: + self._re = re.compile(self.name) + +class itemregister(dict): + """A specialized dictionary that can handle wild-card selection""" + + def __init__(self): + super(itemregister, self).__init__() + self._generics = set() + + def update(self, other): + super(itemregister, self).update(other) + self._generics.update(other._generics) + + def __setitem__(self, key, item): + super(itemregister, self).__setitem__(key, item) + if item.generic: + self._generics.add(item) + + def get(self, key): + if key in self: + return self[key] + + # search for a matching generic item + generics = sorted(self._generics, key=(lambda x: (x.priority, x.name))) + for item in generics: + if item._re.match(key): + return item + + # fallback to dict get + return super(itemregister, self).get(key) coreitems = {} def _register(configtable, *args, **kwargs): item = configitem(*args, **kwargs) - section = configtable.setdefault(item.section, {}) + section = configtable.setdefault(item.section, itemregister()) if item.name in section: msg = "duplicated config item registration for '%s.%s'" raise error.ProgrammingError(msg % (item.section, item.name))