From bf0dcbe2c8445902fe1712dad591232b35475051 Mon Sep 17 00:00:00 2001 From: gwen Date: Tue, 14 Aug 2012 10:55:08 +0200 Subject: [PATCH] replace special_owner with hascallback_and_freeze --- test/test_option_owner.py | 58 ++++-------------------------------- test/test_option_type.py | 2 +- tiramisu/autolib.py | 21 ++++++------- tiramisu/config.py | 62 ++++++++++++++------------------------- tiramisu/error.py | 2 -- tiramisu/option.py | 24 +++++++-------- 6 files changed, 48 insertions(+), 121 deletions(-) diff --git a/test/test_option_owner.py b/test/test_option_owner.py index 70fb845..ac40dfd 100644 --- a/test/test_option_owner.py +++ b/test/test_option_owner.py @@ -3,7 +3,6 @@ import autopath from py.test import raises from tiramisu.config import * from tiramisu.option import * -from tiramisu.error import SpecialOwnersError def make_description(): gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') @@ -67,65 +66,20 @@ def test_override_are_default_owner(): config.gc.dummy = False assert config.gc._cfgimpl_value_owners['dummy'] == 'user' -def test_change_owner(): +def test_has_callback(): descr = make_description() # here the owner is 'default' config = Config(descr, bool=False) - # the default owner is 'user' (which is not 'default') - # Still not getting it ? read the docs - config.gc.dummy = True - assert config.gc._cfgimpl_value_owners['dummy'] == 'user' -# config.cfgimpl_set_owner('eggs') -# config.set(dummy=False) -# assert config.gc._cfgimpl_value_owners['dummy'] == 'eggs' -# config.cfgimpl_set_owner('spam') -# gcdummy = config.unwrap_from_path('gc.dummy') -# gcdummy.setowner(config.gc, 'blabla') -# assert config.gc._cfgimpl_value_owners['dummy'] == 'blabla' -# config.gc.dummy = True -# assert config.gc._cfgimpl_value_owners['dummy'] == 'spam' - + # because dummy has a callback + raises(ConflictConfigError, "config.gc.dummy = True") #____________________________________________________________ -# special owners -def test_auto_owner(): +def test_has_callback_with_setoption(): descr = make_description() config = Config(descr, bool=False) - config.gc.setoption('dummy', True, 'auto') - raises(PropertiesOptionError, "config.gc.dummy") - raises(ConflictConfigError, "config.gc.setoption('dummy', False, 'auto')") - # shall return an auto value... - #assert config.gc.dummy == 'auto_dummy_value' + raises(ConflictConfigError, "config.gc.setoption('dummy', True, 'gen_config')") def test_cannot_override_special_owners(): descr = make_description() config = Config(descr, bool=False) - config.gc.setoption('dummy', True, 'auto') - raises(SpecialOwnersError, "config.override({'gc.dummy': True})") - -# FIXME have to test the fills anyway -#def test_fill_owner(): -# "fill option" -# descr = make_description() -# config = Config(descr, bool=False) -# assert config.bool == False -# assert config.gc.dummy == False -# # 'fill' special values -# config.gc.setoption('dummy', True, 'fill') -# assert config.gc.dummy == False - -#def test_auto_fill_and_override(): -# descr = make_description() -# config = Config(descr, bool=False) -# booloption = config.unwrap_from_path('bool') -# booloption.callback = 'identical' -# booloption.setowner(config, 'auto') -# assert config.bool == 'identicalbool' -# gcdummy = config.unwrap_from_path('gc.dummy') -# gcdummy.callback = 'identical' -# gcdummy.setowner(config.gc, 'fill') -# raises(SpecialOwnersError, "config.override({'gc.dummy':True})") -# config.gc.setoption('dummy', False, 'fill') -# # value is returned -# assert config.gc.dummy == False - + raises(ConflictConfigError, "config.override({'gc.dummy': True})") diff --git a/test/test_option_type.py b/test/test_option_type.py index 3cd61c6..044451a 100644 --- a/test/test_option_type.py +++ b/test/test_option_type.py @@ -67,7 +67,7 @@ def test_freeze_one_option(): #freeze only one option conf.gc._cfgimpl_descr.dummy.freeze() assert conf.gc.dummy == False - raises(TypeError, "conf.gc.dummy = True") + raises(ConflictConfigError, "conf.gc.dummy = True") def test_frozen_value(): "setattr a frozen value at the config level" diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index d6c57a8..7c715fd 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -19,18 +19,15 @@ # the whole pypy projet is under MIT licence # ____________________________________________________________ "enables us to carry out a calculation and return an option's value" -from tiramisu.error import PropertiesOptionError, SpecialOwnersError +from tiramisu.error import PropertiesOptionError, ConflictConfigError # ____________________________________________________________ # automatic Option object -special_owners = ['auto', 'fill'] - -def special_owner_factory(name, owner, value, - callback, callback_params=None, config=None): - # in case of an 'auto' and a 'fill' without a value, - # we have to carry out a calculation - return calc_factory(name, callback, callback_params, config) - -def calc_factory(name, callback, callback_params, config): +#def special_owner_factory(name, owner, value, +# callback, callback_params=None, config=None): +# # in case of an 'auto' and a 'fill' without a value, +# # we have to carry out a calculation +# return calc_factory(name, callback, callback_params, config) +def carry_out_calculation(name, callback, callback_params, config): # FIXME we have to know the exact status of the config # not to disrupt it # config.freeze() @@ -54,7 +51,7 @@ def calc_factory(name, callback, callback_params, config): if opt_value != None: len_value = len(opt_value) if len_multi != 0 and len_multi != len_value: - raise SpecialOwnersError('unable to carry out a calculation, ' + raise ConflictConfigError('unable to carry out a calculation, ' 'option values with multi types must have same length for: ' + name) len_multi = len_value @@ -89,6 +86,6 @@ def calculate(name, callback, tcparams): except AttributeError, err: import traceback traceback.print_exc() - raise SpecialOwnersError("callback: {0} return error {1} for " + raise ConflictConfigError("callback: {0} return error {1} for " "option: {2}".format(callback, str(err), name)) diff --git a/tiramisu/config.py b/tiramisu/config.py index c4f9024..dd7c2a2 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -23,10 +23,10 @@ from copy import copy from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError, AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound, - SpecialOwnersError, MandatoryError, MethodCallError) + MandatoryError, MethodCallError) from tiramisu.option import (OptionDescription, Option, SymLinkOption, group_types, Multi, apply_requires) -from tiramisu.autolib import special_owners, special_owner_factory +from tiramisu.autolib import carry_out_calculation # ______________________________________________________________________ # generic owner. 'default' is the general config owner after init time default_owner = 'user' @@ -70,21 +70,13 @@ class Config(object): child=child) self._cfgimpl_values[child._name] = childdef self._cfgimpl_previous_values[child._name] = list(childdef) + self._cfgimpl_value_owners[child._name] = ['default' \ + for i in range(len(child.getdefault() ))] else: childdef = child.getdefault() self._cfgimpl_values[child._name] = childdef self._cfgimpl_previous_values[child._name] = childdef - if child.getcallback() is not None: - if child._is_hidden(): - self._cfgimpl_value_owners[child._name] = 'auto' - else: - self._cfgimpl_value_owners[child._name] = 'fill' - else: - if child.is_multi(): - self._cfgimpl_value_owners[child._name] = ['default' \ - for i in range(len(child.getdefault() ))] - else: - self._cfgimpl_value_owners[child._name] = 'default' + self._cfgimpl_value_owners[child._name] = 'default' elif isinstance(child, OptionDescription): self._validate_duplicates(child._children) self._cfgimpl_values[child._name] = Config(child, parent=self) @@ -113,10 +105,6 @@ class Config(object): def override(self, overrides): for name, value in overrides.iteritems(): homeconfig, name = self._cfgimpl_get_home_by_path(name) - # if there are special_owners, impossible to override - if homeconfig._cfgimpl_value_owners[name] in special_owners: - raise SpecialOwnersError("cannot override option: {0} because " - "of its special owner".format(name)) homeconfig.setoption(name, value, 'default') def cfgimpl_set_owner(self, owner): @@ -209,19 +197,17 @@ class Config(object): if name not in self._cfgimpl_values: raise AttributeError("%s object has no attribute %s" % (self.__class__, name)) - if name in self._cfgimpl_value_owners: - owner = self._cfgimpl_value_owners[name] - if owner in special_owners: + if not isinstance(opt_or_descr, OptionDescription): + # options with callbacks (fill or auto) + if opt_or_descr.has_callback(): value = self._cfgimpl_values[name] if value != None: if opt_or_descr.is_multi(): - if owner == 'fill' and None not in value: + if None not in value: return value else: - if owner == 'fill' and value != None: - return value - result = special_owner_factory(name, owner, - value=value, + return value + result = carry_out_calculation(name, callback=opt_or_descr.getcallback(), callback_params=opt_or_descr.getcallback_params(), config=self._cfgimpl_get_toplevel()) @@ -245,7 +231,7 @@ class Config(object): else: _result = result return _result - if not isinstance(opt_or_descr, OptionDescription): + # mandatory options homeconfig = self._cfgimpl_get_toplevel() mandatory = homeconfig._cfgimpl_mandatory @@ -318,23 +304,19 @@ class Config(object): else: newowner = who if type(child) != SymLinkOption: + if child.is_mandatory() and value is None: + raise MandatoryError('cannot override value to %s for ' + 'option %s' % (value, name)) if name not in self._cfgimpl_values: raise AttributeError('unknown option %s' % (name,)) - # special owners, a value with a owner *auto* cannot be changed - oldowner = self._cfgimpl_value_owners[child._name] - if oldowner == 'auto': - if who == 'auto': - raise ConflictConfigError('cannot override value to %s for ' - 'option %s' % (value, name)) - if oldowner == who: - oldvalue = getattr(self, name) - if oldvalue == value: #or who in ("default",): - return + if child.has_callback() or child.isfrozen(): + raise ConflictConfigError('cannot override value to %s for ' + 'option %s' % (value, name)) +# if oldowner == who: +# oldvalue = getattr(self, name) +# if oldvalue == value: +# return child.setoption(self, value, who) - # if the value owner is 'auto', set the option to hidden - if who == 'auto': - if not child._is_hidden(): - child.hide() if (value is None and who != 'default' and not child.is_multi()): child.setowner(self, 'default') self._cfgimpl_values[name] = copy(child.getdefault()) diff --git a/tiramisu/error.py b/tiramisu/error.py index 82dd86f..061099b 100644 --- a/tiramisu/error.py +++ b/tiramisu/error.py @@ -18,6 +18,4 @@ class RequirementRecursionError(RequiresError): pass class MandatoryError(Exception): pass -class SpecialOwnersError(Exception): - pass diff --git a/tiramisu/option.py b/tiramisu/option.py index 4cd8700..23ddc63 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -20,18 +20,17 @@ # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/ # the whole pypy projet is under MIT licence # ____________________________________________________________ -from tiramisu.autolib import special_owners from tiramisu.basetype import HiddenBaseType, DisabledBaseType from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError, - SpecialOwnersError, RequiresError, RequirementRecursionError) + RequiresError, RequirementRecursionError) available_actions = ['hide', 'show', 'enable', 'disable'] reverse_actions = {'hide': 'show', 'show': 'hide', 'disable':'enable', 'enable': 'disable'} # ____________________________________________________________ # OptionDescription authorized group_type values group_types = ['default', 'family', 'group', 'master'] +# ____________________________________________________________ # multi types - class Multi(list): "container that support items for the values of list (multi) options" def __init__(self, lst, config, child): @@ -145,11 +144,11 @@ class Option(HiddenBaseType, DisabledBaseType): def force_default(self): self._force_default_on_freeze = True + def hascallback_and_isfrozen(): + return self._frozen and self.has_callback() + def is_forced_on_freeze(self): - if self._frozen and self._force_default_on_freeze: - return True - else: - return False + return self._frozen and self._force_default_on_freeze def getdoc(self): return self.doc @@ -172,10 +171,6 @@ class Option(HiddenBaseType, DisabledBaseType): name = self._name if self._frozen: raise TypeError("trying to change a frozen option's owner: %s" % name) - if owner in special_owners: - if self.callback == None: - raise SpecialOwnersError("no callback specified for" - "option {0}".format(name)) if self.is_multi(): if not type(owner) == list: raise ConfigError("invalid owner for multi " @@ -228,13 +223,16 @@ class Option(HiddenBaseType, DisabledBaseType): def getkey(self, value): return value - + # ____________________________________________________________ def freeze(self): self._frozen = True return True def unfreeze(self): self._frozen = False + + def isfrozen(self): + return self._frozen # ____________________________________________________________ def is_multi(self): return self.multi @@ -513,8 +511,6 @@ def apply_requires(opt, config): "detected for option: '{0}' with requirement on: '{1}'".format(path, name)) homeconfig, shortname = \ rootconfig._cfgimpl_get_home_by_path(name) - # FIXME: doesn't work with 'auto' or 'fill' yet - # (copy the code from the __getattr__ if shortname in homeconfig._cfgimpl_values: value = homeconfig._cfgimpl_values[shortname] if (not inverted and value == expected) or \