From aa67ae31aa1aea2f00c35c4dc29c0fd063daee8e Mon Sep 17 00:00:00 2001 From: gwen Date: Thu, 11 Oct 2012 16:16:43 +0200 Subject: [PATCH] find method in config --- test/test_config_api.py | 22 ++++++++++++------ tiramisu/config.py | 50 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/test/test_config_api.py b/test/test_config_api.py index babd42e..3ac6457 100644 --- a/test/test_config_api.py +++ b/test/test_config_api.py @@ -17,7 +17,7 @@ def make_description(): boolop = BoolOption('boolop', 'Test boolean option op', default=True) wantref_option = BoolOption('wantref', 'Tests', default=False) wantframework_option = BoolOption('wantframework', 'Test', default=False) - + gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption, wantref_option, stroption, @@ -61,7 +61,7 @@ def test_iter_subconfig(): def test_getpaths(): descr = make_description() config = Config(descr) - + assert config.getpaths() == ['gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop'] @@ -71,7 +71,7 @@ def test_getpaths(): assert config.getpaths(include_groups=True) == [ 'gc', 'gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop'] - + assert config.getpaths(True) == descr.getpaths(True) def test_getpaths_with_hidden(): @@ -85,18 +85,18 @@ def test_getpaths_with_hidden(): wantref_option = BoolOption('wantref', 'Test requires', default=False) wantframework_option = BoolOption('wantframework', 'Test requires', default=False) - + descr = OptionDescription('tiramisu', '', [booloption, objspaceoption, wantref_option, stroption, wantframework_option, intoption, boolop]) - + config = Config(descr) result = ['objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop'] - assert config.getpaths() == result + assert config.getpaths() == result r2 = ['bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop'] assert config.getpaths(allpaths=True) == r2 - + def test_str(): descr = make_description() c = Config(descr) @@ -137,6 +137,14 @@ def test_delattr(): c.int = 45 assert c.int == 45 +def test_find_in_config(): + "finds option in config" + descr = make_description() + conf = Config(descr) + assert conf.find(byname='dummy')[0] == conf.unwrap_from_name('dummy') + assert conf.find(bytype=ChoiceOption)[0] == conf.unwrap_from_name('name') + assert conf.find(byvalue='ref')[0] == conf.unwrap_from_name('name') + #def test_validator(): # "validates the integrity of an option towards a whole configuration" # def my_validator_1(config): diff --git a/tiramisu/config.py b/tiramisu/config.py index 7881fcb..6bc6780 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -359,7 +359,6 @@ class Config(object): and sets the found option if the match is not ambiguous. :param kwargs: dict of name strings to values. """ - all_paths = [p.split(".") for p in self.getpaths(allpaths=True)] for key, value in kwargs.iteritems(): key_p = key.split('.') @@ -384,10 +383,15 @@ class Config(object): def get(self, name): """ + same as a find_first() method in a config that has identical names + that is : Returns the first item of an option named 'name' + much like the attribute access way, except that the search for the option is performed recursively in the whole configuration tree. **carefull**: very slow ! + + :returns: option value. """ paths = self.getpaths(allpaths=True) pathsvalues = [] @@ -560,6 +564,11 @@ class Config(object): def getpaths(self, include_groups=False, allpaths=False, mandatory=False): """returns a list of all paths in self, recursively, taking care of the context of properties (hidden/disabled) + + :param include_groups: if true, OptionDescription are included + :param allpaths: all the options (event the properties protected ones) + :param mandatory: includes the mandatory options + :returns: list of all paths """ paths = [] for path in self._cfgimpl_descr.getpaths(include_groups=include_groups): @@ -576,6 +585,45 @@ class Config(object): paths.append(path) return paths + def find(self, bytype=None, byname=None, byvalue=None, byattrs=None): + """ + finds an option recursively in the config + + :param bytype: Option class (BoolOption, StrOption, ...) + :param byname: filter by Option._name + :param byvalue: filter by the option's value + :param byattrs: dict of option attributes (default, callback...) + :returns: list of matching Option objects + """ + def _filter_by_name(): + if byname is not None: + pathname = path.split('.')[-1] + if pathname == byname: + yield option + def _filter_by_value(): + if byvalue is not None: + try: + value = getattr(self, path) + if value == byvalue: + yield option + except Exception, e: # a property restricts the acces to value + pass + def _filter_by_type(): + if bytype is not None: + if isinstance(option, bytype): + find_results.append(self.unwrap_from_path(path)) + find_results = [] + paths = self.getpaths(allpaths=True) + for path in paths: + option = self.unwrap_from_path(path) + if _filter_by_name() is not None: + find_results.extend(list( _filter_by_name() )) + if _filter_by_value() is not None: + find_results.extend(list( _filter_by_value() )) + if _filter_by_type() is not None: + find_results.extend(list( _filter_by_type() )) + return find_results + def make_dict(config, flatten=False): """export the whole config into a `dict` :returns: dict of Option's name (or path) and values"""