reorganise optiondescription
This commit is contained in:
parent
c44aab67b8
commit
911af90564
|
@ -175,46 +175,45 @@ class SubConfig(object):
|
||||||
force_permissive=force_permissive,
|
force_permissive=force_permissive,
|
||||||
validate_properties=validate_properties,
|
validate_properties=validate_properties,
|
||||||
setting_properties=setting_properties)
|
setting_properties=setting_properties)
|
||||||
if isinstance(self, Exception):
|
|
||||||
return self, None
|
|
||||||
return self, path[-1]
|
return self, path[-1]
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
def __iter__(self, force_permissive=False):
|
# def __iter__(self, force_permissive=False):
|
||||||
"""Pythonesque way of parsing group's ordered options.
|
# """Pythonesque way of parsing group's ordered options.
|
||||||
iteration only on Options (not OptionDescriptions)"""
|
# iteration only on Options (not OptionDescriptions)"""
|
||||||
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_context_properties()
|
# setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_context_properties()
|
||||||
for child in self.cfgimpl_get_description().impl_getchildren(context=self._cfgimpl_get_context()):
|
# for child in self.cfgimpl_get_description().impl_getchildren(context=self._cfgimpl_get_context()):
|
||||||
if not child.impl_is_optiondescription():
|
# if not child.impl_is_optiondescription():
|
||||||
try:
|
# try:
|
||||||
name = child.impl_getname()
|
# name = child.impl_getname()
|
||||||
yield name, self.getattr(name,
|
# yield name, self.getattr(name,
|
||||||
force_permissive=force_permissive,
|
# force_permissive=force_permissive,
|
||||||
setting_properties=setting_properties)
|
# setting_properties=setting_properties)
|
||||||
except GeneratorExit: # pragma: optional cover
|
# except GeneratorExit: # pragma: optional cover
|
||||||
if sys.version_info[0] < 3:
|
# if sys.version_info[0] < 3:
|
||||||
raise StopIteration
|
# raise StopIteration
|
||||||
else:
|
# else:
|
||||||
raise GeneratorExit()
|
# raise GeneratorExit()
|
||||||
except PropertiesOptionError: # pragma: optional cover
|
# except PropertiesOptionError: # pragma: optional cover
|
||||||
pass # option with properties
|
# pass # option with properties
|
||||||
|
#
|
||||||
def iter_all(self, force_permissive=False):
|
# def iter_all(self, force_permissive=False):
|
||||||
"""A way of parsing options **and** groups.
|
# """A way of parsing options **and** groups.
|
||||||
iteration on Options and OptionDescriptions."""
|
# iteration on Options and OptionDescriptions."""
|
||||||
for child in self.cfgimpl_get_description().impl_getchildren():
|
# for child in self.cfgimpl_get_description().impl_getchildren():
|
||||||
try:
|
# try:
|
||||||
yield child.impl_getname(), self.getattr(child.impl_getname(),
|
# yield child.impl_getname(), self.getattr(child.impl_getname(),
|
||||||
force_permissive=force_permissive)
|
# force_permissive=force_permissive)
|
||||||
except GeneratorExit: # pragma: optional cover
|
# except GeneratorExit: # pragma: optional cover
|
||||||
if sys.version_info[0] < 3:
|
# if sys.version_info[0] < 3:
|
||||||
raise StopIteration
|
# raise StopIteration
|
||||||
else:
|
# else:
|
||||||
raise GeneratorExit()
|
# raise GeneratorExit()
|
||||||
except PropertiesOptionError: # pragma: optional cover
|
# except PropertiesOptionError: # pragma: optional cover
|
||||||
pass # option with properties
|
# pass # option with properties
|
||||||
|
|
||||||
def iter_groups(self,
|
def iter_groups(self,
|
||||||
|
setting_properties,
|
||||||
group_type=None,
|
group_type=None,
|
||||||
force_permissive=False):
|
force_permissive=False):
|
||||||
"""iteration on groups objects only.
|
"""iteration on groups objects only.
|
||||||
|
@ -230,7 +229,8 @@ class SubConfig(object):
|
||||||
raise TypeError(_("unknown group_type: {0}").format(group_type))
|
raise TypeError(_("unknown group_type: {0}").format(group_type))
|
||||||
context = self._cfgimpl_get_context()
|
context = self._cfgimpl_get_context()
|
||||||
setting_properties = context.cfgimpl_get_settings().get_context_properties()
|
setting_properties = context.cfgimpl_get_settings().get_context_properties()
|
||||||
for child in self.cfgimpl_get_description().impl_getchildren(context=context):
|
for child in self.cfgimpl_get_description().impl_getchildren(context=context,
|
||||||
|
setting_properties=setting_properties):
|
||||||
if child.impl_is_optiondescription():
|
if child.impl_is_optiondescription():
|
||||||
try:
|
try:
|
||||||
if group_type is None or (group_type is not None and
|
if group_type is None or (group_type is not None and
|
||||||
|
@ -249,20 +249,20 @@ class SubConfig(object):
|
||||||
pass
|
pass
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
||||||
def __str__(self):
|
# def __str__(self):
|
||||||
"Config's string representation"
|
# "Config's string representation"
|
||||||
lines = []
|
# lines = []
|
||||||
for name, grp in self.iter_groups():
|
# for name, grp in self.iter_groups():
|
||||||
lines.append("[{0}]".format(name))
|
# lines.append("[{0}]".format(name))
|
||||||
for name, value in self:
|
# for name, value in self:
|
||||||
try:
|
# try:
|
||||||
lines.append("{0} = {1}".format(name, value))
|
# lines.append("{0} = {1}".format(name, value))
|
||||||
except UnicodeEncodeError: # pragma: optional cover
|
# except UnicodeEncodeError: # pragma: optional cover
|
||||||
lines.append("{0} = {1}".format(name,
|
# lines.append("{0} = {1}".format(name,
|
||||||
value.encode(default_encoding)))
|
# value.encode(default_encoding)))
|
||||||
return '\n'.join(lines)
|
# return '\n'.join(lines)
|
||||||
|
#
|
||||||
__repr__ = __str__
|
# __repr__ = __str__
|
||||||
|
|
||||||
def _cfgimpl_get_context(self):
|
def _cfgimpl_get_context(self):
|
||||||
"""context could be None, we need to test it
|
"""context could be None, we need to test it
|
||||||
|
@ -315,8 +315,9 @@ class SubConfig(object):
|
||||||
self, name = self.cfgimpl_get_home_by_path(name,
|
self, name = self.cfgimpl_get_home_by_path(name,
|
||||||
force_permissive=force_permissive,
|
force_permissive=force_permissive,
|
||||||
setting_properties=setting_properties)
|
setting_properties=setting_properties)
|
||||||
child = self.cfgimpl_get_description().__getattr__(name,
|
child = self.cfgimpl_get_description().impl_getchild(name,
|
||||||
context=context)
|
setting_properties,
|
||||||
|
context)
|
||||||
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
|
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
|
||||||
raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover
|
raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover
|
||||||
elif child.impl_is_symlinkoption() and \
|
elif child.impl_is_symlinkoption() and \
|
||||||
|
@ -347,8 +348,9 @@ class SubConfig(object):
|
||||||
self, name = self.cfgimpl_get_home_by_path(name,
|
self, name = self.cfgimpl_get_home_by_path(name,
|
||||||
force_permissive=force_permissive,
|
force_permissive=force_permissive,
|
||||||
setting_properties=setting_properties)
|
setting_properties=setting_properties)
|
||||||
child = self.cfgimpl_get_description().__getattr__(name,
|
child = self.cfgimpl_get_description().impl_getchild(name,
|
||||||
context=context)
|
setting_properties,
|
||||||
|
context)
|
||||||
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
|
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
|
||||||
raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover
|
raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover
|
||||||
elif child.impl_is_symlinkoption() and \
|
elif child.impl_is_symlinkoption() and \
|
||||||
|
@ -408,8 +410,9 @@ class SubConfig(object):
|
||||||
setting_properties=setting_properties)
|
setting_properties=setting_properties)
|
||||||
|
|
||||||
context = self._cfgimpl_get_context()
|
context = self._cfgimpl_get_context()
|
||||||
option = self.cfgimpl_get_description().__getattr__(name,
|
option = self.cfgimpl_get_description().impl_getchild(name,
|
||||||
context=context)
|
context,
|
||||||
|
setting_properties)
|
||||||
if option.impl_is_symlinkoption() and isinstance(option, DynSymLinkOption):
|
if option.impl_is_symlinkoption() and isinstance(option, DynSymLinkOption):
|
||||||
# FIXME peuvent-il vraiment etre le 2 ?
|
# FIXME peuvent-il vraiment etre le 2 ?
|
||||||
# si non supprimer tout ces tests inutiles
|
# si non supprimer tout ces tests inutiles
|
||||||
|
@ -827,11 +830,9 @@ class _CommonConfig(SubConfig):
|
||||||
force_permissive=force_permissive,
|
force_permissive=force_permissive,
|
||||||
validate_properties=validate_properties,
|
validate_properties=validate_properties,
|
||||||
setting_properties=setting_properties)
|
setting_properties=setting_properties)
|
||||||
if isinstance(self, Exception):
|
option = self.cfgimpl_get_description().impl_getchild(path,
|
||||||
return self
|
setting_properties,
|
||||||
option = self.cfgimpl_get_description().__getattr__(path,
|
self._cfgimpl_get_context())
|
||||||
context=self._cfgimpl_get_context(),
|
|
||||||
setting_properties=setting_properties)
|
|
||||||
if not validate_properties:
|
if not validate_properties:
|
||||||
return option
|
return option
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -327,38 +327,21 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
return find_results
|
return find_results
|
||||||
return find_results
|
return find_results
|
||||||
|
|
||||||
def _getattr(self,
|
def impl_getchild(self,
|
||||||
name,
|
name,
|
||||||
setting_properties,
|
setting_properties,
|
||||||
suffix=undefined,
|
|
||||||
context=undefined,
|
context=undefined,
|
||||||
dyn=True):
|
dyn=True):
|
||||||
error = False
|
if name not in self._children[0]:
|
||||||
if suffix is not undefined:
|
|
||||||
if undefined in [suffix, context]: # pragma: no cover
|
|
||||||
raise ConfigError(_("suffix and context needed if "
|
|
||||||
"it's a dyn option"))
|
|
||||||
if name.endswith(suffix):
|
|
||||||
oname = name[:-len(suffix)]
|
|
||||||
child = self._children[1][self._children[0].index(oname)]
|
|
||||||
return self._impl_get_dynchild(child, suffix)
|
|
||||||
else:
|
|
||||||
error = True
|
|
||||||
else:
|
|
||||||
if name in self._children[0]:
|
|
||||||
child = self._children[1][self._children[0].index(name)]
|
|
||||||
if dyn and child.impl_is_dynoptiondescription():
|
|
||||||
error = True
|
|
||||||
else:
|
|
||||||
return child
|
|
||||||
else:
|
|
||||||
child = self._impl_search_dynchild(name,
|
child = self._impl_search_dynchild(name,
|
||||||
context=context,
|
context=context,
|
||||||
setting_properties=setting_properties)
|
setting_properties=setting_properties)
|
||||||
if child != []:
|
if child:
|
||||||
|
return child
|
||||||
|
else:
|
||||||
|
child = self._children[1][self._children[0].index(name)]
|
||||||
|
if not child.impl_is_dynoptiondescription():
|
||||||
return child
|
return child
|
||||||
error = True
|
|
||||||
if error:
|
|
||||||
raise AttributeError(_('unknown Option {0} '
|
raise AttributeError(_('unknown Option {0} '
|
||||||
'in OptionDescription {1}'
|
'in OptionDescription {1}'
|
||||||
'').format(name, self.impl_getname()))
|
'').format(name, self.impl_getname()))
|
||||||
|
@ -404,7 +387,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
name,
|
name,
|
||||||
context,
|
context,
|
||||||
setting_properties):
|
setting_properties):
|
||||||
ret = []
|
|
||||||
for child in self._impl_st_getchildren(only_dyn=True):
|
for child in self._impl_st_getchildren(only_dyn=True):
|
||||||
cname = child.impl_getname()
|
cname = child.impl_getname()
|
||||||
if name.startswith(cname):
|
if name.startswith(cname):
|
||||||
|
@ -414,7 +396,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
return SynDynOptionDescription(child,
|
return SynDynOptionDescription(child,
|
||||||
name,
|
name,
|
||||||
value)
|
value)
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getattr__(self,
|
def __getattr__(self,
|
||||||
name,
|
name,
|
||||||
|
@ -423,16 +404,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
if name.startswith('_'):
|
if name.startswith('_'):
|
||||||
return object.__getattribute__(self,
|
return object.__getattribute__(self,
|
||||||
name)
|
name)
|
||||||
if '.' in name:
|
|
||||||
path = name.split('.')[0]
|
|
||||||
subpath = '.'.join(name.split('.')[1:])
|
|
||||||
return self.__getattr__(path, context=context).__getattr__(subpath,
|
|
||||||
context=context,
|
|
||||||
setting_properties=setting_properties)
|
|
||||||
return self._getattr(name,
|
|
||||||
context=context,
|
|
||||||
setting_properties=setting_properties)
|
|
||||||
|
|
||||||
def _impl_get_dynchild(self,
|
def _impl_get_dynchild(self,
|
||||||
child,
|
child,
|
||||||
suffix):
|
suffix):
|
||||||
|
@ -464,7 +435,7 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not isinstance(children, list):
|
if not isinstance(children, list):
|
||||||
raise ValueError(_('children in optiondescription "{}"must be a liste').format(name))
|
raise ValueError(_('children in optiondescription "{}" must be a list').format(name))
|
||||||
super(OptionDescription, self).__init__(name,
|
super(OptionDescription, self).__init__(name,
|
||||||
doc=doc,
|
doc=doc,
|
||||||
requires=requires,
|
requires=requires,
|
||||||
|
@ -491,11 +462,10 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
raise ConflictError(_('the option\'s name "{}" start as '
|
raise ConflictError(_('the option\'s name "{}" start as '
|
||||||
'the dynoptiondescription\'s name "{}"').format(child, dynopt))
|
'the dynoptiondescription\'s name "{}"').format(child, dynopt))
|
||||||
old = child
|
old = child
|
||||||
_setattr = object.__setattr__
|
self._children = (tuple(child_names), tuple(children))
|
||||||
_setattr(self, '_children', (tuple(child_names), tuple(children)))
|
self._cache_consistencies = None
|
||||||
_setattr(self, '_cache_consistencies', None)
|
|
||||||
# the group_type is useful for filtering OptionDescriptions in a config
|
# the group_type is useful for filtering OptionDescriptions in a config
|
||||||
_setattr(self, '_group_type', groups.default)
|
self._group_type = groups.default
|
||||||
|
|
||||||
def impl_getdoc(self):
|
def impl_getdoc(self):
|
||||||
return self.impl_get_information('doc')
|
return self.impl_get_information('doc')
|
||||||
|
@ -508,8 +478,7 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
def impl_set_group_type(self,
|
def impl_set_group_type(self,
|
||||||
group_type,
|
group_type):
|
||||||
setting_properties):
|
|
||||||
"""sets a given group object to an OptionDescription
|
"""sets a given group object to an OptionDescription
|
||||||
|
|
||||||
:param group_type: an instance of `GroupType` or `MasterGroupType`
|
:param group_type: an instance of `GroupType` or `MasterGroupType`
|
||||||
|
@ -519,28 +488,12 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
raise TypeError(_('cannot change group_type if already set '
|
raise TypeError(_('cannot change group_type if already set '
|
||||||
'(old {0}, new {1})').format(self._group_type,
|
'(old {0}, new {1})').format(self._group_type,
|
||||||
group_type))
|
group_type))
|
||||||
if isinstance(group_type, groups.GroupType):
|
if not isinstance(group_type, groups.GroupType):
|
||||||
self._group_type = group_type
|
|
||||||
if isinstance(group_type, groups.MasterGroupType):
|
|
||||||
raise Exception('please use MasterSlaves object instead of OptionDescription')
|
|
||||||
children = self.impl_getchildren(setting_properties)
|
|
||||||
for child in children:
|
|
||||||
if child.impl_is_symlinkoption(): # pragma: optional cover
|
|
||||||
raise ValueError(_("master group {0} shall not have "
|
|
||||||
"a symlinkoption").format(self.impl_getname()))
|
|
||||||
if not isinstance(child, Option): # pragma: optional cover
|
|
||||||
raise ValueError(_("master group {0} shall not have "
|
|
||||||
"a subgroup").format(self.impl_getname()))
|
|
||||||
if not child.impl_is_multi(): # pragma: optional cover
|
|
||||||
raise ValueError(_("not allowed option {0} "
|
|
||||||
"in group {1}"
|
|
||||||
": this option is not a multi"
|
|
||||||
"").format(child.impl_getname(), self.impl_getname()))
|
|
||||||
#length of master change slaves length
|
|
||||||
MasterSlaves(self.impl_getname(), children)
|
|
||||||
else: # pragma: optional cover
|
|
||||||
raise ValueError(_('group_type: {0}'
|
raise ValueError(_('group_type: {0}'
|
||||||
' not allowed').format(group_type))
|
' not allowed').format(group_type))
|
||||||
|
if isinstance(group_type, groups.MasterGroupType):
|
||||||
|
raise ConfigError('please use MasterSlaves object instead of OptionDescription')
|
||||||
|
self._group_type = group_type
|
||||||
|
|
||||||
def impl_get_group_type(self):
|
def impl_get_group_type(self):
|
||||||
return self._group_type
|
return self._group_type
|
||||||
|
@ -588,7 +541,8 @@ class DynOptionDescription(OptionDescription):
|
||||||
callback,
|
callback,
|
||||||
callback_params):
|
callback_params):
|
||||||
if callback is None:
|
if callback is None:
|
||||||
raise ConfigError(_('callback is mandatory for dynoptiondescription'))
|
raise ConfigError(_('callback is mandatory for the dynoptiondescription "{}"'
|
||||||
|
'').format(self.impl_get_display_name()))
|
||||||
|
|
||||||
def _impl_get_suffixes(self,
|
def _impl_get_suffixes(self,
|
||||||
context,
|
context,
|
||||||
|
@ -599,33 +553,49 @@ class DynOptionDescription(OptionDescription):
|
||||||
callback=callback,
|
callback=callback,
|
||||||
callback_params=callback_params,
|
callback_params=callback_params,
|
||||||
setting_properties=setting_properties)
|
setting_properties=setting_properties)
|
||||||
|
if not isinstance(values, list):
|
||||||
|
raise ValueError(_('invalid suffix "{}" for option "{}", must be a list'
|
||||||
|
'').format(values,
|
||||||
|
self.impl_get_display_name()))
|
||||||
if len(values) > len(set(values)):
|
if len(values) > len(set(values)):
|
||||||
raise ConfigError(_('DynOptionDescription callback return not unique value'))
|
raise ValueError(_('DynOptionDescription callback return not unique value'))
|
||||||
for val in values:
|
for val in values:
|
||||||
if not isinstance(val, str) or re.match(NAME_REGEXP, val) is None:
|
if not isinstance(val, str) or re.match(NAME_REGEXP, val) is None:
|
||||||
raise ValueError(_("invalid suffix: {0} for option").format(val))
|
raise ValueError(_('invalid suffix "{}" for option "{}"'
|
||||||
|
'').format(val,
|
||||||
|
self.impl_get_display_name()))
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
class SynDynOptionDescription(object):
|
class SynDynOptionDescription(object):
|
||||||
__slots__ = ('_opt', '_name', '_suffix')
|
__slots__ = ('_opt',
|
||||||
|
'_name',
|
||||||
|
'_suffix')
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
opt,
|
||||||
|
name,
|
||||||
|
suffix):
|
||||||
|
|
||||||
def __init__(self, opt, name, suffix):
|
|
||||||
self._opt = opt
|
self._opt = opt
|
||||||
self._name = name
|
self._name = name
|
||||||
self._suffix = suffix
|
self._suffix = suffix
|
||||||
|
|
||||||
def __getattr__(self,
|
def __getattr__(self, name):
|
||||||
|
return getattr(self._opt, name)
|
||||||
|
|
||||||
|
def impl_getchild(self,
|
||||||
name,
|
name,
|
||||||
setting_properties=undefined,
|
|
||||||
context=undefined):
|
|
||||||
if name in dir(self._opt):
|
|
||||||
return getattr(self._opt,
|
|
||||||
name)
|
|
||||||
return self._opt._getattr(name,
|
|
||||||
setting_properties,
|
setting_properties,
|
||||||
suffix=self._suffix,
|
context):
|
||||||
context=context)
|
if name.endswith(self._suffix):
|
||||||
|
oname = name[:-len(self._suffix)]
|
||||||
|
child = self._children[1][self._children[0].index(oname)]
|
||||||
|
return self._impl_get_dynchild(child,
|
||||||
|
self._suffix)
|
||||||
|
raise AttributeError(_('unknown Option {0} '
|
||||||
|
'in SynDynOptionDescription {1}'
|
||||||
|
'').format(name, self.impl_getname()))
|
||||||
|
|
||||||
def impl_getname(self):
|
def impl_getname(self):
|
||||||
return self._name
|
return self._name
|
||||||
|
@ -636,7 +606,8 @@ class SynDynOptionDescription(object):
|
||||||
context=undefined):
|
context=undefined):
|
||||||
children = []
|
children = []
|
||||||
for child in self._opt.impl_getchildren(setting_properties):
|
for child in self._opt.impl_getchildren(setting_properties):
|
||||||
yield(self._opt._impl_get_dynchild(child, self._suffix))
|
yield(self._opt._impl_get_dynchild(child,
|
||||||
|
self._suffix))
|
||||||
|
|
||||||
def impl_getpath(self, context):
|
def impl_getpath(self, context):
|
||||||
path = self.impl_getopt().impl_getpath(context).split('.')
|
path = self.impl_getopt().impl_getpath(context).split('.')
|
||||||
|
@ -737,7 +708,7 @@ class MasterSlaves(OptionDescription):
|
||||||
c_opt = opt._opt
|
c_opt = opt._opt
|
||||||
else:
|
else:
|
||||||
c_opt = opt
|
c_opt = opt
|
||||||
return child in self._children[1]
|
return c_opt in self._children[1]
|
||||||
|
|
||||||
def reset(self,
|
def reset(self,
|
||||||
opt,
|
opt,
|
||||||
|
@ -1018,15 +989,13 @@ class MasterSlaves(OptionDescription):
|
||||||
type_,
|
type_,
|
||||||
resetted_opts)
|
resetted_opts)
|
||||||
|
|
||||||
def _getattr(self,
|
def impl_getchild(self,
|
||||||
name,
|
name,
|
||||||
setting_properties,
|
setting_properties,
|
||||||
suffix=undefined,
|
|
||||||
context=undefined,
|
context=undefined,
|
||||||
dyn=True):
|
dyn=True):
|
||||||
return super(MasterSlaves, self)._getattr(name,
|
return super(MasterSlaves, self).impl_getchild(name,
|
||||||
setting_properties,
|
setting_properties,
|
||||||
suffix,
|
|
||||||
context,
|
context,
|
||||||
dyn)
|
dyn)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue