replace special_owner with hascallback_and_freeze

This commit is contained in:
gwen 2012-08-14 10:55:08 +02:00
parent 11b2edd07d
commit bf0dcbe2c8
6 changed files with 48 additions and 121 deletions

View File

@ -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})")

View File

@ -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"

View File

@ -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))

View File

@ -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,20 +70,12 @@ 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'
elif isinstance(child, OptionDescription):
self._validate_duplicates(child._children)
@ -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,
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':
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: #or who in ("default",):
return
# 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())

View File

@ -18,6 +18,4 @@ class RequirementRecursionError(RequiresError):
pass
class MandatoryError(Exception):
pass
class SpecialOwnersError(Exception):
pass

View File

@ -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 \