replace special_owner with hascallback_and_freeze
This commit is contained in:
parent
11b2edd07d
commit
bf0dcbe2c8
|
@ -3,7 +3,6 @@ import autopath
|
||||||
from py.test import raises
|
from py.test import raises
|
||||||
from tiramisu.config import *
|
from tiramisu.config import *
|
||||||
from tiramisu.option import *
|
from tiramisu.option import *
|
||||||
from tiramisu.error import SpecialOwnersError
|
|
||||||
|
|
||||||
def make_description():
|
def make_description():
|
||||||
gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
|
gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
|
||||||
|
@ -67,65 +66,20 @@ def test_override_are_default_owner():
|
||||||
config.gc.dummy = False
|
config.gc.dummy = False
|
||||||
assert config.gc._cfgimpl_value_owners['dummy'] == 'user'
|
assert config.gc._cfgimpl_value_owners['dummy'] == 'user'
|
||||||
|
|
||||||
def test_change_owner():
|
def test_has_callback():
|
||||||
descr = make_description()
|
descr = make_description()
|
||||||
# here the owner is 'default'
|
# here the owner is 'default'
|
||||||
config = Config(descr, bool=False)
|
config = Config(descr, bool=False)
|
||||||
# the default owner is 'user' (which is not 'default')
|
# because dummy has a callback
|
||||||
# Still not getting it ? read the docs
|
raises(ConflictConfigError, "config.gc.dummy = True")
|
||||||
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'
|
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
# special owners
|
def test_has_callback_with_setoption():
|
||||||
def test_auto_owner():
|
|
||||||
descr = make_description()
|
descr = make_description()
|
||||||
config = Config(descr, bool=False)
|
config = Config(descr, bool=False)
|
||||||
config.gc.setoption('dummy', True, 'auto')
|
raises(ConflictConfigError, "config.gc.setoption('dummy', True, 'gen_config')")
|
||||||
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'
|
|
||||||
|
|
||||||
def test_cannot_override_special_owners():
|
def test_cannot_override_special_owners():
|
||||||
descr = make_description()
|
descr = make_description()
|
||||||
config = Config(descr, bool=False)
|
config = Config(descr, bool=False)
|
||||||
config.gc.setoption('dummy', True, 'auto')
|
raises(ConflictConfigError, "config.override({'gc.dummy': True})")
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ def test_freeze_one_option():
|
||||||
#freeze only one option
|
#freeze only one option
|
||||||
conf.gc._cfgimpl_descr.dummy.freeze()
|
conf.gc._cfgimpl_descr.dummy.freeze()
|
||||||
assert conf.gc.dummy == False
|
assert conf.gc.dummy == False
|
||||||
raises(TypeError, "conf.gc.dummy = True")
|
raises(ConflictConfigError, "conf.gc.dummy = True")
|
||||||
|
|
||||||
def test_frozen_value():
|
def test_frozen_value():
|
||||||
"setattr a frozen value at the config level"
|
"setattr a frozen value at the config level"
|
||||||
|
|
|
@ -19,18 +19,15 @@
|
||||||
# the whole pypy projet is under MIT licence
|
# the whole pypy projet is under MIT licence
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
"enables us to carry out a calculation and return an option's value"
|
"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
|
# automatic Option object
|
||||||
special_owners = ['auto', 'fill']
|
#def special_owner_factory(name, owner, value,
|
||||||
|
# callback, callback_params=None, config=None):
|
||||||
def special_owner_factory(name, owner, value,
|
# # in case of an 'auto' and a 'fill' without a value,
|
||||||
callback, callback_params=None, config=None):
|
# # we have to carry out a calculation
|
||||||
# in case of an 'auto' and a 'fill' without a value,
|
# return calc_factory(name, callback, callback_params, config)
|
||||||
# we have to carry out a calculation
|
def carry_out_calculation(name, callback, callback_params, config):
|
||||||
return calc_factory(name, callback, callback_params, config)
|
|
||||||
|
|
||||||
def calc_factory(name, callback, callback_params, config):
|
|
||||||
# FIXME we have to know the exact status of the config
|
# FIXME we have to know the exact status of the config
|
||||||
# not to disrupt it
|
# not to disrupt it
|
||||||
# config.freeze()
|
# config.freeze()
|
||||||
|
@ -54,7 +51,7 @@ def calc_factory(name, callback, callback_params, config):
|
||||||
if opt_value != None:
|
if opt_value != None:
|
||||||
len_value = len(opt_value)
|
len_value = len(opt_value)
|
||||||
if len_multi != 0 and len_multi != len_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: '
|
'option values with multi types must have same length for: '
|
||||||
+ name)
|
+ name)
|
||||||
len_multi = len_value
|
len_multi = len_value
|
||||||
|
@ -89,6 +86,6 @@ def calculate(name, callback, tcparams):
|
||||||
except AttributeError, err:
|
except AttributeError, err:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
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))
|
"option: {2}".format(callback, str(err), name))
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError,
|
from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError,
|
||||||
AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound,
|
AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound,
|
||||||
SpecialOwnersError, MandatoryError, MethodCallError)
|
MandatoryError, MethodCallError)
|
||||||
from tiramisu.option import (OptionDescription, Option, SymLinkOption,
|
from tiramisu.option import (OptionDescription, Option, SymLinkOption,
|
||||||
group_types, Multi, apply_requires)
|
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
|
# generic owner. 'default' is the general config owner after init time
|
||||||
default_owner = 'user'
|
default_owner = 'user'
|
||||||
|
@ -70,21 +70,13 @@ class Config(object):
|
||||||
child=child)
|
child=child)
|
||||||
self._cfgimpl_values[child._name] = childdef
|
self._cfgimpl_values[child._name] = childdef
|
||||||
self._cfgimpl_previous_values[child._name] = list(childdef)
|
self._cfgimpl_previous_values[child._name] = list(childdef)
|
||||||
|
self._cfgimpl_value_owners[child._name] = ['default' \
|
||||||
|
for i in range(len(child.getdefault() ))]
|
||||||
else:
|
else:
|
||||||
childdef = child.getdefault()
|
childdef = child.getdefault()
|
||||||
self._cfgimpl_values[child._name] = childdef
|
self._cfgimpl_values[child._name] = childdef
|
||||||
self._cfgimpl_previous_values[child._name] = childdef
|
self._cfgimpl_previous_values[child._name] = childdef
|
||||||
if child.getcallback() is not None:
|
self._cfgimpl_value_owners[child._name] = 'default'
|
||||||
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'
|
|
||||||
elif isinstance(child, OptionDescription):
|
elif isinstance(child, OptionDescription):
|
||||||
self._validate_duplicates(child._children)
|
self._validate_duplicates(child._children)
|
||||||
self._cfgimpl_values[child._name] = Config(child, parent=self)
|
self._cfgimpl_values[child._name] = Config(child, parent=self)
|
||||||
|
@ -113,10 +105,6 @@ class Config(object):
|
||||||
def override(self, overrides):
|
def override(self, overrides):
|
||||||
for name, value in overrides.iteritems():
|
for name, value in overrides.iteritems():
|
||||||
homeconfig, name = self._cfgimpl_get_home_by_path(name)
|
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')
|
homeconfig.setoption(name, value, 'default')
|
||||||
|
|
||||||
def cfgimpl_set_owner(self, owner):
|
def cfgimpl_set_owner(self, owner):
|
||||||
|
@ -209,19 +197,17 @@ class Config(object):
|
||||||
if name not in self._cfgimpl_values:
|
if name not in self._cfgimpl_values:
|
||||||
raise AttributeError("%s object has no attribute %s" %
|
raise AttributeError("%s object has no attribute %s" %
|
||||||
(self.__class__, name))
|
(self.__class__, name))
|
||||||
if name in self._cfgimpl_value_owners:
|
if not isinstance(opt_or_descr, OptionDescription):
|
||||||
owner = self._cfgimpl_value_owners[name]
|
# options with callbacks (fill or auto)
|
||||||
if owner in special_owners:
|
if opt_or_descr.has_callback():
|
||||||
value = self._cfgimpl_values[name]
|
value = self._cfgimpl_values[name]
|
||||||
if value != None:
|
if value != None:
|
||||||
if opt_or_descr.is_multi():
|
if opt_or_descr.is_multi():
|
||||||
if owner == 'fill' and None not in value:
|
if None not in value:
|
||||||
return value
|
return value
|
||||||
else:
|
else:
|
||||||
if owner == 'fill' and value != None:
|
return value
|
||||||
return value
|
result = carry_out_calculation(name,
|
||||||
result = special_owner_factory(name, owner,
|
|
||||||
value=value,
|
|
||||||
callback=opt_or_descr.getcallback(),
|
callback=opt_or_descr.getcallback(),
|
||||||
callback_params=opt_or_descr.getcallback_params(),
|
callback_params=opt_or_descr.getcallback_params(),
|
||||||
config=self._cfgimpl_get_toplevel())
|
config=self._cfgimpl_get_toplevel())
|
||||||
|
@ -245,7 +231,7 @@ class Config(object):
|
||||||
else:
|
else:
|
||||||
_result = result
|
_result = result
|
||||||
return _result
|
return _result
|
||||||
if not isinstance(opt_or_descr, OptionDescription):
|
|
||||||
# mandatory options
|
# mandatory options
|
||||||
homeconfig = self._cfgimpl_get_toplevel()
|
homeconfig = self._cfgimpl_get_toplevel()
|
||||||
mandatory = homeconfig._cfgimpl_mandatory
|
mandatory = homeconfig._cfgimpl_mandatory
|
||||||
|
@ -318,23 +304,19 @@ class Config(object):
|
||||||
else:
|
else:
|
||||||
newowner = who
|
newowner = who
|
||||||
if type(child) != SymLinkOption:
|
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:
|
if name not in self._cfgimpl_values:
|
||||||
raise AttributeError('unknown option %s' % (name,))
|
raise AttributeError('unknown option %s' % (name,))
|
||||||
# special owners, a value with a owner *auto* cannot be changed
|
if child.has_callback() or child.isfrozen():
|
||||||
oldowner = self._cfgimpl_value_owners[child._name]
|
raise ConflictConfigError('cannot override value to %s for '
|
||||||
if oldowner == 'auto':
|
'option %s' % (value, name))
|
||||||
if who == 'auto':
|
# if oldowner == who:
|
||||||
raise ConflictConfigError('cannot override value to %s for '
|
# oldvalue = getattr(self, name)
|
||||||
'option %s' % (value, name))
|
# if oldvalue == value:
|
||||||
if oldowner == who:
|
# return
|
||||||
oldvalue = getattr(self, name)
|
|
||||||
if oldvalue == value: #or who in ("default",):
|
|
||||||
return
|
|
||||||
child.setoption(self, value, who)
|
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()):
|
if (value is None and who != 'default' and not child.is_multi()):
|
||||||
child.setowner(self, 'default')
|
child.setowner(self, 'default')
|
||||||
self._cfgimpl_values[name] = copy(child.getdefault())
|
self._cfgimpl_values[name] = copy(child.getdefault())
|
||||||
|
|
|
@ -18,6 +18,4 @@ class RequirementRecursionError(RequiresError):
|
||||||
pass
|
pass
|
||||||
class MandatoryError(Exception):
|
class MandatoryError(Exception):
|
||||||
pass
|
pass
|
||||||
class SpecialOwnersError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
|
@ -20,18 +20,17 @@
|
||||||
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||||
# the whole pypy projet is under MIT licence
|
# the whole pypy projet is under MIT licence
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from tiramisu.autolib import special_owners
|
|
||||||
from tiramisu.basetype import HiddenBaseType, DisabledBaseType
|
from tiramisu.basetype import HiddenBaseType, DisabledBaseType
|
||||||
from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError,
|
from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError,
|
||||||
SpecialOwnersError, RequiresError, RequirementRecursionError)
|
RequiresError, RequirementRecursionError)
|
||||||
available_actions = ['hide', 'show', 'enable', 'disable']
|
available_actions = ['hide', 'show', 'enable', 'disable']
|
||||||
reverse_actions = {'hide': 'show', 'show': 'hide',
|
reverse_actions = {'hide': 'show', 'show': 'hide',
|
||||||
'disable':'enable', 'enable': 'disable'}
|
'disable':'enable', 'enable': 'disable'}
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
# OptionDescription authorized group_type values
|
# OptionDescription authorized group_type values
|
||||||
group_types = ['default', 'family', 'group', 'master']
|
group_types = ['default', 'family', 'group', 'master']
|
||||||
|
# ____________________________________________________________
|
||||||
# multi types
|
# multi types
|
||||||
|
|
||||||
class Multi(list):
|
class Multi(list):
|
||||||
"container that support items for the values of list (multi) options"
|
"container that support items for the values of list (multi) options"
|
||||||
def __init__(self, lst, config, child):
|
def __init__(self, lst, config, child):
|
||||||
|
@ -145,11 +144,11 @@ class Option(HiddenBaseType, DisabledBaseType):
|
||||||
def force_default(self):
|
def force_default(self):
|
||||||
self._force_default_on_freeze = True
|
self._force_default_on_freeze = True
|
||||||
|
|
||||||
|
def hascallback_and_isfrozen():
|
||||||
|
return self._frozen and self.has_callback()
|
||||||
|
|
||||||
def is_forced_on_freeze(self):
|
def is_forced_on_freeze(self):
|
||||||
if self._frozen and self._force_default_on_freeze:
|
return self._frozen and self._force_default_on_freeze
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def getdoc(self):
|
def getdoc(self):
|
||||||
return self.doc
|
return self.doc
|
||||||
|
@ -172,10 +171,6 @@ class Option(HiddenBaseType, DisabledBaseType):
|
||||||
name = self._name
|
name = self._name
|
||||||
if self._frozen:
|
if self._frozen:
|
||||||
raise TypeError("trying to change a frozen option's owner: %s" % name)
|
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 self.is_multi():
|
||||||
if not type(owner) == list:
|
if not type(owner) == list:
|
||||||
raise ConfigError("invalid owner for multi "
|
raise ConfigError("invalid owner for multi "
|
||||||
|
@ -228,13 +223,16 @@ class Option(HiddenBaseType, DisabledBaseType):
|
||||||
|
|
||||||
def getkey(self, value):
|
def getkey(self, value):
|
||||||
return value
|
return value
|
||||||
|
# ____________________________________________________________
|
||||||
def freeze(self):
|
def freeze(self):
|
||||||
self._frozen = True
|
self._frozen = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def unfreeze(self):
|
def unfreeze(self):
|
||||||
self._frozen = False
|
self._frozen = False
|
||||||
|
|
||||||
|
def isfrozen(self):
|
||||||
|
return self._frozen
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
def is_multi(self):
|
def is_multi(self):
|
||||||
return self.multi
|
return self.multi
|
||||||
|
@ -513,8 +511,6 @@ def apply_requires(opt, config):
|
||||||
"detected for option: '{0}' with requirement on: '{1}'".format(path, name))
|
"detected for option: '{0}' with requirement on: '{1}'".format(path, name))
|
||||||
homeconfig, shortname = \
|
homeconfig, shortname = \
|
||||||
rootconfig._cfgimpl_get_home_by_path(name)
|
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:
|
if shortname in homeconfig._cfgimpl_values:
|
||||||
value = homeconfig._cfgimpl_values[shortname]
|
value = homeconfig._cfgimpl_values[shortname]
|
||||||
if (not inverted and value == expected) or \
|
if (not inverted and value == expected) or \
|
||||||
|
|
Loading…
Reference in New Issue