refactor
This commit is contained in:
@ -106,7 +106,8 @@ rw_append = set(['frozen', 'disabled', 'validator', 'hidden'])
|
||||
rw_remove = set(['permissive', 'everything_frozen', 'mandatory', 'empty'])
|
||||
|
||||
|
||||
forbidden_set_properties = set(['force_store_value'])
|
||||
forbidden_set_properties = frozenset(['force_store_value'])
|
||||
forbidden_set_permissives = frozenset(['frozen', 'force_default_on_freeze'])
|
||||
|
||||
|
||||
log = getLogger('tiramisu')
|
||||
@ -124,15 +125,16 @@ class _NameSpace(object):
|
||||
when attribute is added, we cannot delete it
|
||||
"""
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name in self.__dict__: # pragma: optional cover
|
||||
def __setattr__(self,
|
||||
name,
|
||||
value):
|
||||
if name in self.__dict__:
|
||||
raise ConstError(_("can't rebind {0}").format(name))
|
||||
self.__dict__[name] = value
|
||||
|
||||
def __delattr__(self, name): # pragma: optional cover
|
||||
if name in self.__dict__:
|
||||
raise ConstError(_("can't unbind {0}").format(name))
|
||||
raise ValueError(name)
|
||||
def __delattr__(self,
|
||||
name):
|
||||
raise ConstError(_("can't unbind {0}").format(name))
|
||||
|
||||
|
||||
class GroupModule(_NameSpace):
|
||||
@ -168,69 +170,44 @@ class OwnerModule(_NameSpace):
|
||||
"""groups that are default (typically 'default')"""
|
||||
pass
|
||||
|
||||
|
||||
class MultiTypeModule(_NameSpace):
|
||||
"namespace for the master/slaves"
|
||||
class MultiType(str):
|
||||
pass
|
||||
|
||||
class DefaultMultiType(MultiType):
|
||||
pass
|
||||
|
||||
class MasterMultiType(MultiType):
|
||||
pass
|
||||
|
||||
class SlaveMultiType(MultiType):
|
||||
pass
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
def populate_groups():
|
||||
"""populates the available groups in the appropriate namespaces
|
||||
|
||||
groups.default
|
||||
default group set when creating a new optiondescription
|
||||
|
||||
groups.master
|
||||
master group is a special optiondescription, all suboptions should be
|
||||
multi option and all values should have same length, to find master's
|
||||
option, the optiondescription's name should be same than de master's
|
||||
option
|
||||
|
||||
groups.family
|
||||
example of group, no special behavior with this group's type
|
||||
"""
|
||||
groups.default = groups.DefaultGroupType('default')
|
||||
groups.master = groups.MasterGroupType('master')
|
||||
groups.family = groups.GroupType('family')
|
||||
|
||||
|
||||
def populate_owners():
|
||||
"""populates the available owners in the appropriate namespaces
|
||||
|
||||
default
|
||||
is the config owner after init time
|
||||
|
||||
user
|
||||
is the generic is the generic owner
|
||||
"""
|
||||
setattr(owners, 'default', owners.DefaultOwner('default'))
|
||||
setattr(owners, 'user', owners.Owner('user'))
|
||||
setattr(owners, 'forced', owners.Owner('forced'))
|
||||
|
||||
def addowner(name):
|
||||
def addowner(self, name):
|
||||
"""
|
||||
:param name: the name of the new owner
|
||||
"""
|
||||
setattr(owners, name, owners.Owner(name))
|
||||
setattr(owners, 'addowner', addowner)
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
# populate groups and owners with default attributes
|
||||
# populate groups
|
||||
groups = GroupModule()
|
||||
populate_groups()
|
||||
"""groups.default
|
||||
default group set when creating a new optiondescription"""
|
||||
groups.default = groups.DefaultGroupType('default')
|
||||
|
||||
"""groups.master
|
||||
master group is a special optiondescription, all suboptions should be
|
||||
multi option and all values should have same length, to find master's
|
||||
option, the optiondescription's name should be same than de master's
|
||||
option"""
|
||||
groups.master = groups.MasterGroupType('master')
|
||||
|
||||
""" groups.family
|
||||
example of group, no special behavior with this group's type"""
|
||||
groups.family = groups.GroupType('family')
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
# populate owners with default attributes
|
||||
owners = OwnerModule()
|
||||
populate_owners()
|
||||
"""default
|
||||
is the config owner after init time"""
|
||||
owners.default = owners.DefaultOwner('default')
|
||||
"""user
|
||||
is the generic is the generic owner"""
|
||||
owners.user = owners.Owner('user')
|
||||
"""forced
|
||||
special owner when value is forced"""
|
||||
owners.forced = owners.Owner('forced')
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
@ -241,73 +218,6 @@ class Undefined(object):
|
||||
undefined = Undefined()
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Property(object):
|
||||
"a property is responsible of the option's value access rules"
|
||||
__slots__ = ('_setting', '_properties', '_opt', '_path')
|
||||
|
||||
def __init__(self, setting, prop, opt=None, path=None):
|
||||
self._opt = opt
|
||||
self._path = path
|
||||
self._setting = setting
|
||||
self._properties = prop
|
||||
|
||||
def append(self, propname):
|
||||
"""Appends a property named propname
|
||||
|
||||
:param propname: a predefined or user defined property name
|
||||
:type propname: string
|
||||
"""
|
||||
self._append(propname)
|
||||
|
||||
def _append(self, propname, save=True):
|
||||
if self._opt is not None and self._opt.impl_getrequires() is not None \
|
||||
and propname in getattr(self._opt, '_calc_properties', static_set): # pragma: optional cover
|
||||
raise ValueError(_('cannot append {0} property for option {1}: '
|
||||
'this property is calculated').format(
|
||||
propname, self._opt.impl_getname()))
|
||||
if propname in forbidden_set_properties:
|
||||
raise ConfigError(_('cannot add those properties: {0}').format(propname))
|
||||
self._properties.add(propname)
|
||||
if save:
|
||||
self._setting.setproperties(self._properties, self._opt, self._path, force=True)
|
||||
|
||||
def remove(self, propname):
|
||||
"""Removes a property named propname
|
||||
|
||||
:param propname: a predefined or user defined property name
|
||||
:type propname: string
|
||||
"""
|
||||
if propname in self._properties:
|
||||
self._properties.remove(propname)
|
||||
self._setting.setproperties(self._properties, self._opt, self._path)
|
||||
|
||||
def extend(self, propnames):
|
||||
"""Extends properties to the existing properties
|
||||
|
||||
:param propnames: an iterable made of property names
|
||||
:type propnames: iterable of string
|
||||
"""
|
||||
for propname in propnames:
|
||||
self._append(propname, save=False)
|
||||
self._setting.setproperties(self._properties, self._opt, self._path)
|
||||
|
||||
def reset(self):
|
||||
"""resets the properties (does not **clear** the properties,
|
||||
default properties are still present)
|
||||
"""
|
||||
self._setting.reset(_path=self._path)
|
||||
|
||||
def __contains__(self, propname):
|
||||
return propname in self._properties
|
||||
|
||||
def __repr__(self):
|
||||
return str(list(self._properties))
|
||||
|
||||
def get(self):
|
||||
return tuple(self._properties)
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
class Settings(object):
|
||||
"``config.Config()``'s configuration options settings"
|
||||
@ -341,321 +251,89 @@ class Settings(object):
|
||||
return context
|
||||
|
||||
#____________________________________________________________
|
||||
# properties methods
|
||||
def __contains__(self, propname):
|
||||
"enables the pythonic 'in' syntaxic sugar"
|
||||
return propname in self._getproperties(read_write=False)
|
||||
# get properties and permissive methods
|
||||
|
||||
def __repr__(self):
|
||||
return str(list(self._getproperties(read_write=False)))
|
||||
|
||||
def __getitem__(self, opt):
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
return self.getproperties(opt, path)
|
||||
def get_context_properties(self):
|
||||
ntime = int(time())
|
||||
if self._p_.hascache(None,
|
||||
None):
|
||||
is_cached, props = self._p_.getcache(None,
|
||||
ntime,
|
||||
None)
|
||||
else:
|
||||
is_cached = False
|
||||
if not is_cached or 'cache' not in props:
|
||||
meta = self._getcontext().cfgimpl_get_meta()
|
||||
if meta is None:
|
||||
props = self._p_.getproperties(None,
|
||||
default_properties)
|
||||
else:
|
||||
props = meta.cfgimpl_get_settings().get_context_properties()
|
||||
if 'cache' in props:
|
||||
if 'expire' in props:
|
||||
ntime = ntime + expires_time
|
||||
else:
|
||||
ntime = None
|
||||
self._p_.setcache(None, props, ntime, None)
|
||||
return props
|
||||
|
||||
def getproperties(self,
|
||||
opt,
|
||||
path,
|
||||
setting_properties=undefined,
|
||||
setting_properties,
|
||||
index=None,
|
||||
obj=True):
|
||||
"""get properties for a specified option
|
||||
"""
|
||||
properties = self._getproperties(opt,
|
||||
path,
|
||||
index=index,
|
||||
setting_properties=setting_properties)
|
||||
if obj:
|
||||
return Property(self, properties, opt, path)
|
||||
return properties
|
||||
|
||||
def get_context_properties(self):
|
||||
return self._getproperties()
|
||||
|
||||
def __setitem__(self, opt, value): # pragma: optional cover
|
||||
raise ValueError(_('you should only append/remove properties'))
|
||||
|
||||
def reset(self, opt=None, _path=None, all_properties=False):
|
||||
if all_properties and (_path or opt): # pragma: optional cover
|
||||
raise ValueError(_('opt and all_properties must not be set '
|
||||
'together in reset'))
|
||||
if all_properties:
|
||||
self._p_.reset_all_properties()
|
||||
else:
|
||||
if opt is not None and _path is None:
|
||||
_path = opt.impl_getpath(self._getcontext())
|
||||
self._p_.delproperties(_path)
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path, only=('settings', 'values'))
|
||||
|
||||
def _getproperties(self,
|
||||
opt=None,
|
||||
path=None,
|
||||
setting_properties=undefined,
|
||||
read_write=True,
|
||||
apply_requires=True,
|
||||
index=None):
|
||||
apply_requires=True):
|
||||
"""
|
||||
"""
|
||||
if opt is None:
|
||||
ntime = int(time())
|
||||
if self._p_.hascache(path, index):
|
||||
is_cached, props = self._p_.getcache(path, ntime, None)
|
||||
else:
|
||||
is_cached = False
|
||||
if not is_cached or 'cache' not in props:
|
||||
meta = self._getcontext().cfgimpl_get_meta()
|
||||
if meta is None:
|
||||
props = self._p_.getproperties(path, default_properties)
|
||||
else:
|
||||
props = meta.cfgimpl_get_settings()._getproperties()
|
||||
if 'cache' in props:
|
||||
if 'expire' in props:
|
||||
ntime = ntime + expires_time
|
||||
else:
|
||||
ntime = None
|
||||
self._p_.setcache(path, props, ntime, None)
|
||||
else:
|
||||
if path is None: # pragma: optional cover
|
||||
raise ValueError(_('if opt is not None, path should not be'
|
||||
' None in _getproperties'))
|
||||
if setting_properties is undefined:
|
||||
setting_properties = self._getproperties(read_write=False)
|
||||
is_cached = False
|
||||
is_cached = False
|
||||
|
||||
if apply_requires:
|
||||
if 'cache' in setting_properties and 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
else:
|
||||
ntime = None
|
||||
if 'cache' in setting_properties and self._p_.hascache(path, index):
|
||||
is_cached, props = self._p_.getcache(path, ntime, index)
|
||||
if not is_cached:
|
||||
props = self._p_.getproperties(path, opt.impl_getproperties())
|
||||
if not opt.impl_is_optiondescription() and opt.impl_is_multi() and \
|
||||
not opt.impl_is_master_slaves('slave'):
|
||||
props.add('empty')
|
||||
if apply_requires:
|
||||
requires = self.apply_requires(opt, path, setting_properties, index, False)
|
||||
if requires != set([]):
|
||||
props = copy(props)
|
||||
props |= requires
|
||||
if 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path, props, ntime, index)
|
||||
if read_write:
|
||||
props = copy(props)
|
||||
return props
|
||||
|
||||
def append(self, propname):
|
||||
"puts property propname in the Config's properties attribute"
|
||||
props = self._p_.getproperties(None, default_properties)
|
||||
if propname not in props:
|
||||
props.add(propname)
|
||||
self.setproperties(props, None, None)
|
||||
|
||||
def remove(self, propname):
|
||||
"deletes property propname in the Config's properties attribute"
|
||||
props = self._p_.getproperties(None, default_properties)
|
||||
if propname in props:
|
||||
props.remove(propname)
|
||||
self.setproperties(props, None, None)
|
||||
|
||||
def extend(self, propnames):
|
||||
for propname in propnames:
|
||||
self.append(propname)
|
||||
|
||||
def _setproperties(self, properties, opt, path, force=False):
|
||||
"""just for compatibility
|
||||
"""
|
||||
self.setproperties(properties, opt, path, force)
|
||||
|
||||
def setproperties(self, properties, opt, path, force=False):
|
||||
"""save properties for specified path
|
||||
(never save properties if same has option properties)
|
||||
"""
|
||||
if self._getcontext().cfgimpl_get_meta() is not None:
|
||||
raise ConfigError(_('cannot change global property with metaconfig'))
|
||||
if not force:
|
||||
forbidden_properties = forbidden_set_properties & properties
|
||||
if forbidden_properties:
|
||||
raise ConfigError(_('cannot add those properties: {0}').format(
|
||||
' '.join(forbidden_properties)))
|
||||
self._p_.setproperties(path, properties)
|
||||
#values too because of slave values could have a PropertiesOptionError has value
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties',))
|
||||
|
||||
def getpermissive(self, setting_properties, path=None):
|
||||
if 'cache' in setting_properties and 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
else:
|
||||
ntime = None
|
||||
if 'cache' in setting_properties and self._pp_.hascache(path, None):
|
||||
is_cached, perm = self._pp_.getcache(path, ntime, None)
|
||||
else:
|
||||
is_cached = False
|
||||
if not is_cached:
|
||||
if path is not None:
|
||||
perm = self._pp_.getpermissive(path)
|
||||
else:
|
||||
perm = self._pp_.getpermissive()
|
||||
if 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = ntime + expires_time
|
||||
self._pp_.setcache(path, perm, ntime, None)
|
||||
return perm
|
||||
|
||||
#____________________________________________________________
|
||||
def validate_properties(self, opt_or_descr, is_descr, check_frozen, path,
|
||||
value=None, force_permissive=False,
|
||||
setting_properties=undefined,
|
||||
self_properties=undefined,
|
||||
index=None, debug=False):
|
||||
"""
|
||||
validation upon the properties related to `opt_or_descr`
|
||||
|
||||
:param opt_or_descr: an option or an option description object
|
||||
:param force_permissive: behaves as if the permissive property
|
||||
was present
|
||||
:param is_descr: we have to know if we are in an option description,
|
||||
just because the mandatory property
|
||||
doesn't exist here
|
||||
|
||||
:param check_frozen: in the validation process, an option is to be modified,
|
||||
the behavior can be different
|
||||
(typically with the `frozen` property)
|
||||
"""
|
||||
# opt properties
|
||||
if setting_properties is undefined:
|
||||
setting_properties = self._getproperties(read_write=False)
|
||||
if self_properties is not undefined:
|
||||
properties = copy(self_properties)
|
||||
else:
|
||||
properties = self._getproperties(opt_or_descr, path,
|
||||
setting_properties=setting_properties,
|
||||
index=index)
|
||||
# calc properties
|
||||
properties &= setting_properties
|
||||
if not is_descr:
|
||||
#mandatory
|
||||
if 'mandatory' in properties and \
|
||||
not self._getcontext().cfgimpl_get_values()._isempty(
|
||||
opt_or_descr, value, index=index):
|
||||
properties.remove('mandatory')
|
||||
elif 'empty' in properties and \
|
||||
'empty' in setting_properties and \
|
||||
self._getcontext().cfgimpl_get_values()._isempty(
|
||||
opt_or_descr, value, force_allow_empty_list=True, index=index):
|
||||
properties.add('mandatory')
|
||||
# should return 'frozen' only when tried to modify a value
|
||||
if check_frozen and 'everything_frozen' in setting_properties:
|
||||
properties.add('frozen')
|
||||
elif 'frozen' in properties and not check_frozen:
|
||||
properties.remove('frozen')
|
||||
if 'empty' in properties:
|
||||
properties.remove('empty')
|
||||
|
||||
# remove permissive properties
|
||||
if properties != frozenset():
|
||||
# remove opt permissive
|
||||
# permissive affect option's permission with or without permissive
|
||||
# global property
|
||||
properties -= self.getpermissive(setting_properties, path)
|
||||
# remove global permissive if need
|
||||
if force_permissive is True or 'permissive' in setting_properties:
|
||||
properties -= self.getpermissive(setting_properties)
|
||||
|
||||
# at this point an option should not remain in properties
|
||||
if properties != frozenset():
|
||||
props = list(properties)
|
||||
datas = {'opt': opt_or_descr, 'path': path, 'setting_properties': setting_properties,
|
||||
'index': index, 'debug': True}
|
||||
if is_descr:
|
||||
opt_type = 'optiondescription'
|
||||
else:
|
||||
opt_type = 'option'
|
||||
if 'frozen' in properties:
|
||||
raise PropertiesOptionError(_('cannot change the value for '
|
||||
'option "{0}" this option is'
|
||||
' frozen').format(
|
||||
opt_or_descr.impl_getname()),
|
||||
props,
|
||||
self,
|
||||
datas,
|
||||
opt_type)
|
||||
else:
|
||||
if len(props) == 1:
|
||||
prop_msg = _('property')
|
||||
else:
|
||||
prop_msg = _('properties')
|
||||
raise PropertiesOptionError(_('cannot access to {0} "{1}" '
|
||||
'because has {2} {3}'
|
||||
'').format(opt_type,
|
||||
opt_or_descr.impl_get_display_name(),
|
||||
prop_msg,
|
||||
display_list(props)),
|
||||
props,
|
||||
self,
|
||||
datas,
|
||||
opt_type)
|
||||
|
||||
def setpermissive(self, permissive, opt=None, path=None):
|
||||
"""
|
||||
enables us to put the permissives in the storage
|
||||
|
||||
:param path: the option's path
|
||||
:param type: str
|
||||
:param opt: if an option object is set, the path is extracted.
|
||||
it is better (faster) to set the path parameter
|
||||
instead of passing a :class:`tiramisu.option.Option()` object.
|
||||
"""
|
||||
if opt is not None and path is None:
|
||||
path = opt.impl_getpath(self._getcontext())
|
||||
if not isinstance(permissive, tuple): # pragma: optional cover
|
||||
raise TypeError(_('permissive must be a tuple'))
|
||||
self._pp_.setpermissive(path, permissive)
|
||||
setting_properties = self._getproperties(read_write=False)
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt, path=path, only=('properties', 'values'))
|
||||
if 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = int(time()) + expires_time
|
||||
if apply_requires:
|
||||
if 'cache' in setting_properties and 'expire' in setting_properties:
|
||||
ntime = int(time())
|
||||
else:
|
||||
ntime = None
|
||||
self._pp_.setcache(path, set(permissive), ntime, None)
|
||||
if 'cache' in setting_properties and self._p_.hascache(path,
|
||||
index):
|
||||
is_cached, props = self._p_.getcache(path,
|
||||
ntime,
|
||||
index)
|
||||
if not is_cached:
|
||||
props = self._p_.getproperties(path,
|
||||
opt.impl_getproperties())
|
||||
if apply_requires:
|
||||
requires = self.apply_requires(opt,
|
||||
path,
|
||||
setting_properties,
|
||||
index,
|
||||
False)
|
||||
#FIXME devrait etre un frozenset!
|
||||
if requires != set([]):
|
||||
props = copy(props)
|
||||
props |= requires
|
||||
|
||||
#____________________________________________________________
|
||||
def setowner(self, owner):
|
||||
":param owner: sets the default value for owner at the Config level"
|
||||
if not isinstance(owner, owners.Owner): # pragma: optional cover
|
||||
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
|
||||
self._owner = owner
|
||||
#FIXME qu'est ce qui se passe si pas de owner ??
|
||||
props -= self.getpermissive(path)
|
||||
if apply_requires and 'cache' in setting_properties:
|
||||
if 'expire' in setting_properties:
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path,
|
||||
props,
|
||||
ntime,
|
||||
index)
|
||||
return props
|
||||
|
||||
def getowner(self):
|
||||
return self._owner
|
||||
def get_context_permissive(self):
|
||||
return self.getpermissive(None)
|
||||
|
||||
#____________________________________________________________
|
||||
def _read(self, remove, append):
|
||||
props = self._p_.getproperties(None, default_properties)
|
||||
modified = False
|
||||
if remove & props != set([]):
|
||||
props = props - remove
|
||||
modified = True
|
||||
if append & props != append:
|
||||
props = props | append
|
||||
modified = True
|
||||
if modified:
|
||||
self.setproperties(props, None, None)
|
||||
def getpermissive(self,
|
||||
path):
|
||||
return self._pp_.getpermissive(path)
|
||||
|
||||
def read_only(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(ro_remove, ro_append)
|
||||
|
||||
def read_write(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(rw_remove, rw_append)
|
||||
|
||||
def apply_requires(self, opt, path, setting_properties, index, debug):
|
||||
def apply_requires(self,
|
||||
opt,
|
||||
path,
|
||||
setting_properties,
|
||||
index,
|
||||
debug):
|
||||
"""carries out the jit (just in time) requirements between options
|
||||
|
||||
a requirement is a tuple of this form that comes from the option's
|
||||
@ -735,16 +413,16 @@ class Settings(object):
|
||||
idx = None
|
||||
try:
|
||||
value = context.getattr(reqpath,
|
||||
setting_properties,
|
||||
force_permissive=True,
|
||||
_setting_properties=setting_properties,
|
||||
index=idx)
|
||||
except PropertiesOptionError as err:
|
||||
if not transitive:
|
||||
if all_properties is None:
|
||||
all_properties = []
|
||||
for requires in opt.impl_getrequires():
|
||||
for require in requires:
|
||||
all_properties.append(require[1])
|
||||
for requires_ in opt.impl_getrequires():
|
||||
for require_ in requires_:
|
||||
all_properties.append(require_[1])
|
||||
if not set(err.proptype) - set(all_properties):
|
||||
continue
|
||||
properties = err.proptype
|
||||
@ -794,8 +472,228 @@ class Settings(object):
|
||||
break
|
||||
return calc_properties
|
||||
|
||||
#____________________________________________________________
|
||||
# set methods
|
||||
def set_context_properties(self, properties):
|
||||
self.setproperties(None, None, properties)
|
||||
|
||||
def setproperties(self,
|
||||
opt,
|
||||
path,
|
||||
properties):
|
||||
# force=False):
|
||||
"""save properties for specified path
|
||||
(never save properties if same has option properties)
|
||||
"""
|
||||
if self._getcontext().cfgimpl_get_meta() is not None:
|
||||
raise ConfigError(_('cannot change global property with metaconfig'))
|
||||
#if not force:
|
||||
forbidden_properties = forbidden_set_properties & properties
|
||||
if forbidden_properties:
|
||||
raise ConfigError(_('cannot add those properties: {0}').format(
|
||||
' '.join(forbidden_properties)))
|
||||
if not isinstance(properties, frozenset):
|
||||
raise TypeError(_('properties must be a frozenset'))
|
||||
self._p_.setproperties(path,
|
||||
properties)
|
||||
#values too because of slave values could have a PropertiesOptionError has value
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt,
|
||||
path=path)
|
||||
|
||||
def set_context_permissive(self, permissive):
|
||||
self.setpermissive(None, None, permissive)
|
||||
|
||||
def setpermissive(self,
|
||||
opt,
|
||||
path,
|
||||
permissives):
|
||||
"""
|
||||
enables us to put the permissives in the storage
|
||||
|
||||
:param path: the option's path
|
||||
:param type: str
|
||||
:param opt: if an option object is set, the path is extracted.
|
||||
it is better (faster) to set the path parameter
|
||||
instead of passing a :class:`tiramisu.option.Option()` object.
|
||||
"""
|
||||
if not isinstance(permissives, frozenset):
|
||||
raise TypeError(_('permissive must be a frozenset'))
|
||||
forbidden_permissives = forbidden_set_permissives & permissives
|
||||
if forbidden_permissives:
|
||||
raise ConfigError(_('cannot add those permissives: {0}').format(
|
||||
' '.join(forbidden_permissives)))
|
||||
self._pp_.setpermissive(path, permissives)
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt,
|
||||
path=path)
|
||||
|
||||
#____________________________________________________________
|
||||
# reset methods
|
||||
|
||||
def reset(self, opt=None, _path=None, all_properties=False):
|
||||
if all_properties and (_path or opt): # pragma: optional cover
|
||||
raise ValueError(_('opt and all_properties must not be set '
|
||||
'together in reset'))
|
||||
if all_properties:
|
||||
self._p_.reset_all_properties()
|
||||
else:
|
||||
if opt is not None and _path is None:
|
||||
_path = opt.impl_getpath(self._getcontext())
|
||||
self._p_.delproperties(_path)
|
||||
self._getcontext().cfgimpl_reset_cache(opt=opt,
|
||||
path=_path)
|
||||
|
||||
#____________________________________________________________
|
||||
# validate properties
|
||||
|
||||
def validate_properties(self,
|
||||
opt_or_descr,
|
||||
is_descr,
|
||||
check_frozen,
|
||||
path,
|
||||
value=None,
|
||||
force_permissive=False,
|
||||
setting_properties=undefined,
|
||||
self_properties=undefined,
|
||||
index=None,
|
||||
debug=False):
|
||||
"""
|
||||
validation upon the properties related to `opt_or_descr`
|
||||
|
||||
:param opt_or_descr: an option or an option description object
|
||||
:param force_permissive: behaves as if the permissive property
|
||||
was present
|
||||
:param is_descr: we have to know if we are in an option description,
|
||||
just because the mandatory property
|
||||
doesn't exist here
|
||||
|
||||
:param check_frozen: in the validation process, an option is to be modified,
|
||||
the behavior can be different
|
||||
(typically with the `frozen` property)
|
||||
"""
|
||||
# opt properties
|
||||
if self_properties is not undefined:
|
||||
if not isinstance(self_properties, frozenset):
|
||||
raise Exception('pouet')
|
||||
properties = self_properties
|
||||
else:
|
||||
properties = self.getproperties(opt_or_descr,
|
||||
path,
|
||||
setting_properties=setting_properties,
|
||||
index=index)
|
||||
# calc properties
|
||||
properties &= setting_properties
|
||||
if not is_descr:
|
||||
#mandatory
|
||||
if 'mandatory' in properties and \
|
||||
not self._getcontext().cfgimpl_get_values().isempty(opt_or_descr,
|
||||
value,
|
||||
index=index):
|
||||
properties.remove('mandatory')
|
||||
elif 'empty' in properties and \
|
||||
'empty' in setting_properties and \
|
||||
self._getcontext().cfgimpl_get_values().isempty(opt_or_descr,
|
||||
value,
|
||||
force_allow_empty_list=True,
|
||||
index=index):
|
||||
properties.add('mandatory')
|
||||
# should return 'frozen' only when tried to modify a value
|
||||
if check_frozen and 'everything_frozen' in setting_properties:
|
||||
properties.add('frozen')
|
||||
elif 'frozen' in properties and not check_frozen:
|
||||
properties.remove('frozen')
|
||||
if 'empty' in properties:
|
||||
properties.remove('empty')
|
||||
|
||||
# remove permissive properties
|
||||
if properties != frozenset() and (force_permissive is True or
|
||||
'permissive' in setting_properties):
|
||||
# remove global permissive if need
|
||||
properties -= self.get_context_permissive()
|
||||
|
||||
# at this point an option should not remain in properties
|
||||
if properties != frozenset():
|
||||
props = list(properties)
|
||||
datas = {'opt': opt_or_descr,
|
||||
'path': path,
|
||||
'setting_properties': setting_properties,
|
||||
'index': index,
|
||||
'debug': True}
|
||||
if is_descr:
|
||||
opt_type = 'optiondescription'
|
||||
else:
|
||||
opt_type = 'option'
|
||||
if 'frozen' in properties:
|
||||
raise PropertiesOptionError(_('cannot change the value for '
|
||||
'option "{0}" this option is'
|
||||
' frozen').format(
|
||||
opt_or_descr.impl_getname()),
|
||||
props,
|
||||
self,
|
||||
datas,
|
||||
opt_type)
|
||||
else:
|
||||
if len(props) == 1:
|
||||
prop_msg = _('property')
|
||||
else:
|
||||
prop_msg = _('properties')
|
||||
raise PropertiesOptionError(_('cannot access to {0} "{1}" '
|
||||
'because has {2} {3}'
|
||||
'').format(opt_type,
|
||||
opt_or_descr.impl_get_display_name(),
|
||||
prop_msg,
|
||||
display_list(props)),
|
||||
props,
|
||||
self,
|
||||
datas,
|
||||
opt_type)
|
||||
|
||||
#____________________________________________________________
|
||||
# read only/read write
|
||||
|
||||
def _read(self,
|
||||
remove,
|
||||
append):
|
||||
props = self._p_.getproperties(None,
|
||||
default_properties)
|
||||
modified = False
|
||||
if remove & props != set([]):
|
||||
props = props - remove
|
||||
modified = True
|
||||
if append & props != append:
|
||||
props = props | append
|
||||
modified = True
|
||||
if modified:
|
||||
self.set_context_properties(frozenset(props))
|
||||
|
||||
def read_only(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(ro_remove,
|
||||
ro_append)
|
||||
|
||||
def read_write(self):
|
||||
"convenience method to freeze, hide and disable"
|
||||
self._read(rw_remove,
|
||||
rw_append)
|
||||
|
||||
#____________________________________________________________
|
||||
# get modified properties/permissives
|
||||
|
||||
def get_modified_properties(self):
|
||||
return self._p_.get_modified_properties()
|
||||
|
||||
def get_modified_permissives(self):
|
||||
return self._pp_.get_modified_permissives()
|
||||
|
||||
#____________________________________________________________
|
||||
# default owner methods
|
||||
|
||||
def setowner(self,
|
||||
owner):
|
||||
":param owner: sets the default value for owner at the Config level"
|
||||
if not isinstance(owner,
|
||||
owners.Owner): # pragma: optional cover
|
||||
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
|
||||
self._owner = owner
|
||||
|
||||
def getowner(self):
|
||||
return self._owner
|
||||
|
Reference in New Issue
Block a user