replace special_owner with hascallback_and_freeze
This commit is contained in:
parent
11b2edd07d
commit
bf0dcbe2c8
6 changed files with 48 additions and 121 deletions
|
@ -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})")
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -18,6 +18,4 @@ class RequirementRecursionError(RequiresError):
|
|||
pass
|
||||
class MandatoryError(Exception):
|
||||
pass
|
||||
class SpecialOwnersError(Exception):
|
||||
pass
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
Loading…
Reference in a new issue