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: if type(value) == tuple:
path, check_disabled = value path, check_disabled = value
try: try:
opt_value = getattr(config, path) #opt_value = getattr(config, path)
opt_value = config._getattr(path, permissive=True)
opt = config.unwrap_from_path(path) opt = config.unwrap_from_path(path)
except PropertiesOptionError, e: except PropertiesOptionError, err:
if check_disabled: if check_disabled:
continue continue
raise PropertiesOptionError(e) raise PropertiesOptionError(err, err.proptype)
is_multi = opt.is_multi() is_multi = opt.is_multi()
if is_multi: if is_multi:
if opt_value != None: if opt_value != None:

View File

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

View File

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

View File

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