permissive in the getattr

This commit is contained in:
gwen 2012-10-16 15:09:52 +02:00
parent b3da043190
commit a36ae7df85
4 changed files with 35 additions and 19 deletions

View File

@ -42,12 +42,13 @@ def carry_out_calculation(name, option, config):
if type(value) == tuple:
path, check_disabled = value
try:
opt_value = getattr(config, path)
#opt_value = getattr(config, path)
opt_value = config._getattr(path, permissive=True)
opt = config.unwrap_from_path(path)
except PropertiesOptionError, e:
except PropertiesOptionError, err:
if check_disabled:
continue
raise PropertiesOptionError(e)
raise PropertiesOptionError(err, err.proptype)
is_multi = opt.is_multi()
if is_multi:
if opt_value != None:

View File

@ -34,6 +34,7 @@ default_owner = 'user'
class Config(object):
"properties attribute: the name of a property enables this property"
_cfgimpl_properties = ['hidden', 'disabled']
_cfgimpl_permissive = []
"mandatory means: a mandatory option has to have a value that is not None"
_cfgimpl_mandatory = True
_cfgimpl_frozen = True
@ -100,6 +101,11 @@ class Config(object):
self._cfgimpl_values[child._name] = Config(child, parent=self)
self.override(overrides)
def cfgimpl_set_permissive(self, permissive):
if not isinstance(permissive, list):
raise TypeError('permissive must be a list')
self._cfgimpl_permissive = permissive
def cfgimpl_update(self):
"""dynamically adds `Option()` or `OptionDescription()`
"""
@ -175,7 +181,7 @@ class Config(object):
self._validate(name, getattr(self._cfgimpl_descr, name))
self.setoption(name, value, self._cfgimpl_owner)
def _validate(self, name, opt_or_descr):
def _validate(self, name, opt_or_descr, permissive=False):
"validation for the setattr and the getattr"
apply_requires(opt_or_descr, self)
if not isinstance(opt_or_descr, Option) and \
@ -185,6 +191,10 @@ class Config(object):
for proper in properties:
if not self._cfgimpl_toplevel._cfgimpl_has_property(proper):
properties.remove(proper)
if permissive:
for perm in self._cfgimpl_toplevel._cfgimpl_permissive:
if perm in properties:
properties.remove(perm)
if properties != []:
raise PropertiesOptionError("trying to access"
" to an option named: {0} with properties"
@ -200,12 +210,15 @@ class Config(object):
return False
def __getattr__(self, name):
return self._getattr(name)
def _getattr(self, name, permissive=False):
"attribute notation mechanism for accessing the value of an option"
# attribute access by passing a path,
# for instance getattr(self, "creole.general.family.adresse_ip_eth0")
if '.' in name:
homeconfig, name = self._cfgimpl_get_home_by_path(name)
return getattr(homeconfig, name)
return homeconfig._getattr(name, permissive)
opt_or_descr = getattr(self._cfgimpl_descr, name)
# symlink options
if type(opt_or_descr) == SymLinkOption:
@ -213,7 +226,7 @@ class Config(object):
if name not in self._cfgimpl_values:
raise AttributeError("%s object has no attribute %s" %
(self.__class__, name))
self._validate(name, opt_or_descr)
self._validate(name, opt_or_descr, permissive)
# special attributes
if name.startswith('_cfgimpl_'):
# if it were in __dict__ it would have been found already
@ -271,9 +284,8 @@ class Config(object):
raise MandatoryError("option: {0} is mandatory "
"and shall have a value".format(name))
# frozen and force default
if opt_or_descr.is_forced_on_freeze():
if not opt_or_descr.has_callback() and opt_or_descr.is_forced_on_freeze():
return opt_or_descr.getdefault()
return self._cfgimpl_values[name]
def unwrap_from_name(self, name):

View File

@ -7,7 +7,7 @@ class ConfigError(Exception):
class ConflictConfigError(ConfigError):
pass
class PropertiesOptionError(AttributeError):
def __init__(self, msg, proptype=None):
def __init__(self, msg, proptype):
self.proptype = proptype
super(PropertiesOptionError, self).__init__(msg)

View File

@ -22,7 +22,8 @@
# ____________________________________________________________
from tiramisu.basetype import HiddenBaseType, DisabledBaseType
from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError,
RequiresError, RequirementRecursionError, MandatoryError)
RequiresError, RequirementRecursionError, MandatoryError,
PropertiesOptionError)
from tiramisu.autolib import carry_out_calculation
requires_actions = [('hide', 'show'), ('enable', 'disable'), ('freeze', 'unfreeze')]
@ -195,8 +196,7 @@ class Option(HiddenBaseType, DisabledBaseType):
def getcallback_value(self, config):
return carry_out_calculation(self._name,
option=self,
config=config)
option=self, config=config)
def getcallback_params(self):
"if a callback has been defined, returns his arity"
@ -539,15 +539,18 @@ def apply_requires(opt, config):
"imbrication detected for option: '{0}' "
"with requirement on: '{1}'".format(path, name))
homeconfig, shortname = rootconfig._cfgimpl_get_home_by_path(name)
if shortname in homeconfig._cfgimpl_values:
value = homeconfig._cfgimpl_values[shortname]
if value == expected:
getattr(opt, action)() #.hide() or show() or...
# FIXME generic programming opt.property_launch(action, False)
matches = True
else: # option doesn't exist ! should not happen...
try:
value = homeconfig._getattr(shortname, permissive=True)
except PropertiesOptionError, err:
raise NotFoundError("required option has property error: "
"{0} {1}".format(name, err.proptype))
except Exception, err:
raise NotFoundError("required option not found: "
"{0}".format(name))
if value == expected:
getattr(opt, action)() #.hide() or show() or...
# FIXME generic programming opt.property_launch(action, False)
matches = True
# no callback has been triggered, then just reverse the action
if not matches:
getattr(opt, reverse_actions[action])()