optimise mandatory_warnings

This commit is contained in:
2015-10-29 09:03:13 +01:00
parent 64e9171ea6
commit a0de1109f7
7 changed files with 307 additions and 135 deletions

View File

@ -241,7 +241,8 @@ class SubConfig(object):
subpath = self._impl_path + '.' + name
return subpath
def getattr(self, name, force_permissive=False, validate=True):
def getattr(self, name, force_permissive=False, validate=True,
_setting_properties=undefined):
"""
attribute notation mechanism for accessing the value of an option
:param name: attribute name
@ -254,7 +255,8 @@ class SubConfig(object):
homeconfig, name = self.cfgimpl_get_home_by_path(
name, force_permissive=force_permissive)
return homeconfig.getattr(name, force_permissive=force_permissive,
validate=validate)
validate=validate,
_setting_properties=_setting_properties)
context = self._cfgimpl_get_context()
option = self.cfgimpl_get_description().__getattr__(name,
context=context)
@ -263,22 +265,26 @@ class SubConfig(object):
return self.cfgimpl_get_values()._get_cached_item(
option, path=subpath,
validate=validate,
force_permissive=force_permissive)
force_permissive=force_permissive,
setting_properties=_setting_properties)
elif isinstance(option, SymLinkOption): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt(
option._impl_getopt())
return context.getattr(path, validate=validate,
force_permissive=force_permissive)
force_permissive=force_permissive,
_setting_properties=_setting_properties)
elif option.impl_is_optiondescription():
self.cfgimpl_get_settings().validate_properties(
option, True, False, path=subpath,
force_permissive=force_permissive)
force_permissive=force_permissive,
setting_properties=_setting_properties)
return SubConfig(option, self._impl_context, subpath)
else:
return self.cfgimpl_get_values()._get_cached_item(
option, path=subpath,
validate=validate,
force_permissive=force_permissive)
force_permissive=force_permissive,
setting_properties=_setting_properties)
def find(self, bytype=None, byname=None, byvalue=undefined, type_='option',
check_properties=True, force_permissive=False):

View File

@ -115,25 +115,25 @@ class MasterSlaves(object):
def getitem(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, slave_path=undefined,
slave_value=undefined, setting_properties=undefined, settings=undefined):
slave_value=undefined, setting_properties=undefined, self_properties=undefined):
if self.is_master(opt):
return self._getmaster(values, opt, path, validate,
force_permissive, force_properties,
validate_properties, slave_path,
slave_value, settings)
slave_value, self_properties)
else:
return self._getslave(values, opt, path, validate,
force_permissive, force_properties,
validate_properties, setting_properties, settings)
validate_properties, setting_properties, self_properties)
def _getmaster(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, c_slave_path,
c_slave_value, settings):
c_slave_value, self_properties):
value = values._get_validated_value(opt, path, validate,
force_permissive,
force_properties,
validate_properties,
settings=settings)
self_properties=self_properties)
if validate is True:
masterlen = len(value)
for slave in self.getslaves(opt):
@ -148,7 +148,7 @@ class MasterSlaves(object):
False,
None, False,
None,
settings=settings)
self_properties=self_properties)
slavelen = len(slave_value)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
except ConfigError: # pragma: optional cover
@ -157,7 +157,7 @@ class MasterSlaves(object):
def _getslave(self, values, opt, path, validate, force_permissive,
force_properties, validate_properties, setting_properties,
settings):
self_properties):
"""
if master has length 0:
return []
@ -192,7 +192,7 @@ class MasterSlaves(object):
validate_properties,
None, # not undefined
with_meta=master_is_meta,
settings=settings)
self_properties=self_properties)
#if slave, had values until master's one
path = opt.impl_getpath(context)
valuelen = len(value)
@ -207,7 +207,7 @@ class MasterSlaves(object):
validate_properties=False,
with_meta=master_is_meta,
index=index,
settings=settings),
self_properties=self_properties),
setitem=False,
force=True,
validate=validate)
@ -218,7 +218,7 @@ class MasterSlaves(object):
path=path,
force_permissive=force_permissive,
force_properties=force_properties,
self_properties=setting_properties)
setting_properties=setting_properties)
return value
def setitem(self, values, opt, value, path):

View File

@ -330,19 +330,19 @@ class Settings(object):
# properties methods
def __contains__(self, propname):
"enables the pythonic 'in' syntaxic sugar"
return propname in self._getproperties()
return propname in self._getproperties(read_write=False)
def __repr__(self):
return str(list(self._getproperties()))
return str(list(self._getproperties(read_write=False)))
def __getitem__(self, opt):
path = opt.impl_getpath(self._getcontext())
return self._getitem(opt, path)
def _getitem(self, opt, path, self_properties=undefined):
def _getitem(self, opt, path, setting_properties=undefined):
return Property(self,
self._getproperties(opt, path,
self_properties=self_properties),
setting_properties=setting_properties),
opt, path)
def __setitem__(self, opt, value): # pragma: optional cover
@ -361,41 +361,45 @@ class Settings(object):
self._getcontext().cfgimpl_reset_cache()
def _getproperties(self, opt=None, path=None,
self_properties=undefined, read_write=True):
setting_properties=undefined, read_write=True,
apply_requires=True):
"""
"""
if opt is None:
props = self._p_.getproperties(path, default_properties)
else:
if self_properties is undefined:
self_properties = self._getproperties()
if setting_properties is undefined:
setting_properties = self._getproperties(read_write=False)
if path is None: # pragma: optional cover
raise ValueError(_('if opt is not None, path should not be'
' None in _getproperties'))
is_cached = False
if 'cache' in self_properties and 'expire' in self_properties:
ntime = int(time())
else:
ntime = None
if 'cache' in self_properties and self._p_.hascache(path):
is_cached, props = self._p_.getcache(path, ntime)
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):
is_cached, props = self._p_.getcache(path, ntime)
if not is_cached:
props = copy(self._p_.getproperties(path, opt.impl_getproperties()))
props |= self.apply_requires(opt, path)
if 'cache' in self_properties:
if 'expire' in self_properties:
ntime = ntime + expires_time
self._p_.setcache(path, props, ntime)
props = self._p_.getproperties(path, opt.impl_getproperties())
if apply_requires:
props = copy(props)
props |= self.apply_requires(opt, path, setting_properties)
if 'cache' in setting_properties:
if 'expire' in setting_properties:
ntime = ntime + expires_time
self._p_.setcache(path, props, ntime)
if read_write:
return copy(props)
else:
return props
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)
props.add(propname)
self._setproperties(props, None)
if propname not in props:
props.add(propname)
self._setproperties(props, None)
def remove(self, propname):
"deletes property propname in the Config's properties attribute"
@ -422,7 +426,8 @@ class Settings(object):
#____________________________________________________________
def validate_properties(self, opt_or_descr, is_descr, is_write, path,
value=None, force_permissive=False,
force_properties=None, force_permissives=None,
force_properties=None,
setting_properties=undefined,
self_properties=undefined):
"""
validation upon the properties related to `opt_or_descr`
@ -432,8 +437,6 @@ class Settings(object):
was present
:param force_properties: set() with properties that is force to add
in global properties
:param force_permissives: set() with permissives that is force to add
in global permissives
:param is_descr: we have to know if we are in an option description,
just because the mandatory property
doesn't exist here
@ -443,25 +446,26 @@ class Settings(object):
(typically with the `frozen` property)
"""
# opt properties
if self_properties is undefined:
self_properties = self._getproperties(read_write=False)
properties = self._getproperties(opt_or_descr, path,
self_properties=self_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)
# remove opt permissive
# permissive affect option's permission with or without permissive
# global property
properties -= self._p_.getpermissive(path)
# remove global permissive if need
if force_permissive is True or 'permissive' in self_properties:
if force_permissive is True or 'permissive' in setting_properties:
properties -= self._p_.getpermissive()
if force_permissives is not None:
properties -= force_permissives
if force_properties is not None:
forced_properties = copy(self_properties)
forced_properties = copy(setting_properties)
forced_properties.update(force_properties)
else:
forced_properties = self_properties
forced_properties = setting_properties
# calc properties
properties &= forced_properties
@ -531,10 +535,16 @@ class Settings(object):
#____________________________________________________________
def _read(self, remove, append):
for prop in remove:
self.remove(prop)
for prop in append:
self.append(prop)
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)
def read_only(self):
"convenience method to freeze, hide and disable"
@ -555,7 +565,7 @@ class Settings(object):
else:
self._p_.reset_all_cache()
def apply_requires(self, opt, path):
def apply_requires(self, opt, path, setting_properties):
"""carries out the jit (just in time) requirements between options
a requirement is a tuple of this form that comes from the option's
@ -616,7 +626,8 @@ class Settings(object):
" '{0}' with requirement on: "
"'{1}'").format(path, reqpath))
try:
value = context.getattr(reqpath, force_permissive=True)
value = context.getattr(reqpath, force_permissive=True,
_setting_properties=setting_properties)
except PropertiesOptionError as err:
if not transitive:
continue

View File

@ -55,7 +55,7 @@ class Values(object):
return context
def _getvalue(self, opt, path, is_default, index=undefined,
with_meta=True, settings=undefined):
with_meta=True, self_properties=undefined):
"""actually retrieves the value
:param opt: the `option.Option()` object
@ -64,11 +64,11 @@ class Values(object):
if opt.impl_is_optiondescription(): # pragma: optional cover
raise ValueError(_('optiondescription has no value'))
if settings is undefined:
settings = self._getcontext().cfgimpl_get_settings()._getproperties(
if self_properties is undefined:
self_properties = self._getcontext().cfgimpl_get_settings()._getproperties(
opt, path, read_write=False)
force_default = 'frozen' in settings and \
'force_default_on_freeze' in settings
force_default = 'frozen' in self_properties and \
'force_default_on_freeze' in self_properties
if not is_default and not force_default:
value = self._p_.getvalue(path)
if index is not undefined:
@ -210,27 +210,37 @@ class Values(object):
def _get_cached_item(self, opt, path=None, validate=True,
force_permissive=False, force_properties=None,
validate_properties=True,
setting_properties=undefined):
setting_properties=undefined, self_properties=undefined):
untrusted_cached_properties = force_properties is None
context = self._getcontext()
if path is None:
path = opt.impl_getpath(self._getcontext())
path = opt.impl_getpath(context)
ntime = None
if setting_properties is undefined:
setting_properties = self._getcontext().cfgimpl_get_settings(
setting_properties = context.cfgimpl_get_settings(
)._getproperties(read_write=False)
settings = self._getcontext().cfgimpl_get_settings()._getproperties(
opt, path, read_write=False, self_properties=setting_properties)
if self_properties is undefined:
self_properties = context.cfgimpl_get_settings()._getproperties(
opt, path, read_write=False, setting_properties=setting_properties)
if 'cache' in setting_properties and self._p_.hascache(path):
if 'expire' in setting_properties:
ntime = int(time())
is_cached, value = self._p_.getcache(path, ntime)
if is_cached:
if opt.impl_is_multi() and not isinstance(value, Multi):
#load value so don't need to validate if is not a Multi
value = Multi(value, self.context, opt, path)
if not untrusted_cached_properties:
# revalidate properties (because not default properties)
context.cfgimpl_get_settings().validate_properties(opt, False, False, value=value,
path=path,
force_permissive=force_permissive,
force_properties=force_properties,
setting_properties=setting_properties,
self_properties=self_properties)
return value
val = self._getitem(opt, path, validate, force_permissive,
force_properties, validate_properties,
setting_properties, settings=settings)
setting_properties, self_properties=self_properties)
if 'cache' in setting_properties and validate and validate_properties \
and force_permissive is False and force_properties is None:
if 'expire' in setting_properties:
@ -242,7 +252,7 @@ class Values(object):
def _getitem(self, opt, path, validate, force_permissive, force_properties,
validate_properties, setting_properties=undefined,
settings=undefined):
self_properties=undefined):
if opt.impl_is_master_slaves():
return opt.impl_get_master_slaves().getitem(self, opt, path,
validate,
@ -250,20 +260,20 @@ class Values(object):
force_properties,
validate_properties,
setting_properties=setting_properties,
settings=settings)
self_properties=self_properties)
else:
return self._get_validated_value(opt, path, validate,
force_permissive,
force_properties,
validate_properties,
setting_properties=setting_properties,
settings=settings)
self_properties=self_properties)
def _get_validated_value(self, opt, path, validate, force_permissive,
force_properties, validate_properties,
index=undefined, submulti_index=undefined,
with_meta=True, setting_properties=undefined,
settings=undefined):
self_properties=undefined):
"""same has getitem but don't touch the cache
index is None for slave value, if value returned is not a list, just return []
"""
@ -271,12 +281,12 @@ class Values(object):
setting = context.cfgimpl_get_settings()
if setting_properties is undefined:
setting_properties = setting._getproperties(read_write=False)
if settings is undefined:
settings = setting._getproperties(opt, path, read_write=False)
if self_properties is undefined:
self_properties = setting._getproperties(opt, path, read_write=False)
is_default = self._is_default_owner(opt, path,
validate_properties=False,
validate_meta=False,
settings=settings)
self_properties=self_properties)
try:
if index is None:
gv_index = undefined
@ -284,7 +294,7 @@ class Values(object):
gv_index = index
value = self._getvalue(opt, path, is_default, index=gv_index,
with_meta=with_meta,
settings=settings)
self_properties=self_properties)
config_error = None
except ConfigError as err:
# For calculating properties, we need value (ie for mandatory
@ -329,7 +339,7 @@ class Values(object):
config_error = err
value = None
if is_default and 'force_store_value' in settings:
if is_default and 'force_store_value' in self_properties:
if isinstance(value, Multi):
item = list(value)
else:
@ -337,11 +347,18 @@ class Values(object):
self.setitem(opt, item, path, is_write=False,
force_permissive=force_permissive)
if validate_properties:
setting.validate_properties(opt, False, False, value=value,
if config_error is not None:
# should not raise PropertiesOptionError if option is
# mandatory
val_props = undefined
else:
val_props = value
setting.validate_properties(opt, False, False, value=val_props,
path=path,
force_permissive=force_permissive,
force_properties=force_properties,
self_properties=setting_properties)
setting_properties=setting_properties,
self_properties=self_properties)
if config_error is not None:
raise config_error
return value
@ -385,7 +402,7 @@ class Values(object):
setting.validate_properties(opt, False, is_write,
value=value, path=path,
force_permissive=force_permissive,
self_properties=setting_properties)
setting_properties=setting_properties)
if isinstance(value, Multi):
value = list(value)
if opt.impl_is_submulti():
@ -398,8 +415,8 @@ class Values(object):
def _is_meta(self, opt, path):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
settings = setting._getproperties(opt, path, read_write=False)
if 'frozen' in settings and 'force_default_on_freeze' in settings:
self_properties = setting._getproperties(opt, path, read_write=False)
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return False
if self._p_.getowner(path, owners.default) is not owners.default:
return False
@ -424,21 +441,21 @@ class Values(object):
def _getowner(self, opt, path, validate_properties=True,
force_permissive=False, validate_meta=undefined,
settings=undefined):
self_properties=undefined):
"""get owner of an option
"""
if not isinstance(opt, Option) and not isinstance(opt,
DynSymLinkOption):
raise ConfigError(_('owner only avalaible for an option'))
context = self._getcontext()
if settings is undefined:
settings = context.cfgimpl_get_settings()._getproperties(
if self_properties is undefined:
self_properties = context.cfgimpl_get_settings()._getproperties(
opt, path, read_write=False)
if 'frozen' in settings and 'force_default_on_freeze' in settings:
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default
if validate_properties:
self._getitem(opt, path, True, force_permissive, None, True,
settings=settings)
self_properties=self_properties)
owner = self._p_.getowner(path, owners.default)
if validate_meta is undefined:
if opt.impl_is_master_slaves('slave'):
@ -490,10 +507,10 @@ class Values(object):
validate_meta=validate_meta)
def _is_default_owner(self, opt, path, validate_properties=True,
validate_meta=True, settings=undefined):
validate_meta=True, self_properties=undefined):
return self._getowner(opt, path, validate_properties,
validate_meta=validate_meta,
settings=settings) == \
self_properties=self_properties) == \
owners.default
def reset_cache(self, only_expired):
@ -528,41 +545,72 @@ class Values(object):
raise ValueError(_("information's item"
" not found: {0}").format(key))
def mandatory_warnings(self, force_permissive=False):
def mandatory_warnings(self, force_permissive=False, validate=True):
"""convenience function to trace Options that are mandatory and
where no value has been set
:returns: generator of mandatory Option's path
:param force_permissive: do raise with permissives properties
:type force_permissive: `bool`
:param validate: validate value when calculating properties
:type validate: `bool`
:returns: generator of mandatory Option's path
"""
def _mandatory_warnings(description):
#if value in cache, properties are not calculated
_ret = []
context = self._getcontext()
setting_properties = context.cfgimpl_get_settings()._getproperties(
read_write=False)
context = self._getcontext()
settings = context.cfgimpl_get_settings()
setting_properties = context.cfgimpl_get_settings()._getproperties(
read_write=False)
def _mandatory_warnings(description, currpath=None):
if currpath is None:
currpath = []
for opt in description._impl_getchildren(context=context):
name = opt.impl_getname()
path = '.'.join(currpath + [name])
if opt.impl_is_optiondescription():
_ret.extend(_mandatory_warnings(opt))
elif isinstance(opt, SymLinkOption) and \
not isinstance(opt, DynSymLinkOption):
pass
else:
path = opt.impl_getpath(self._getcontext())
try:
self._get_cached_item(opt, path=path,
force_properties=frozenset(('mandatory',)),
force_permissive=force_permissive,
setting_properties=setting_properties)
settings.validate_properties(opt, True, False, path=path,
force_permissive=force_permissive,
setting_properties=setting_properties)
except PropertiesOptionError as err:
if err.proptype == ['mandatory']:
_ret.append(path)
return _ret
self.reset_cache(False)
pass
else:
for path in _mandatory_warnings(opt, currpath + [name]):
yield path
else:
if isinstance(opt, SymLinkOption) and \
not isinstance(opt, DynSymLinkOption):
true_opt = opt._impl_getopt()
true_path = descr.impl_get_path_by_opt(true_opt)
else:
true_opt = opt
true_path = path
#FIXME attention c'est réutilisé donc jamais complet ??
self_properties = settings._getproperties(true_opt, true_path,
read_write=False,
setting_properties=setting_properties)
if 'mandatory' in self_properties:
try:
self._get_cached_item(true_opt, path=true_path,
force_properties=frozenset(('mandatory',)),
force_permissive=force_permissive,
setting_properties=setting_properties,
self_properties=self_properties,
validate=validate)
except PropertiesOptionError as err:
if err.proptype == ['mandatory']:
yield path
except ConfigError as err:
if validate:
raise err
else:
#assume that uncalculated value is an empty value
yield path
descr = self._getcontext().cfgimpl_get_description()
ret = _mandatory_warnings(descr)
self.reset_cache(False)
return ret
for path in _mandatory_warnings(descr):
yield path
def force_cache(self):
"""parse all option to force data in cache
@ -660,7 +708,7 @@ class Multi(list):
self._validate(value, fake_context, index, True)
#assume not checking mandatory property
super(Multi, self).__setitem__(index, value)
context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
context.cfgimpl_get_values()._setvalue(self.opt, self.path, self, setting_properties=setting_properties)
#def __repr__(self, *args, **kwargs):
# return super(Multi, self).__repr__(*args, **kwargs)