tiramisu/tiramisu/option/masterslave.py

198 lines
7.9 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"master slave support"
2018-01-26 07:33:47 +01:00
# Copyright (C) 2014-2018 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# The original `Config` design model is unproudly borrowed from
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence
# ____________________________________________________________
import weakref
from itertools import chain
from ..i18n import _
2018-08-02 22:35:40 +02:00
from ..setting import groups, undefined, OptionBag
from .optiondescription import OptionDescription
from .option import Option
from ..error import SlaveError, PropertiesOptionError
from ..function import ParamOption
class MasterSlaves(OptionDescription):
__slots__ = ('master', 'slaves')
def __init__(self,
name,
doc,
children,
requires=None,
properties=None):
super(MasterSlaves, self).__init__(name,
doc,
children,
requires=requires,
properties=properties)
self._group_type = groups.master
slaves = []
2018-04-09 21:37:49 +02:00
if len(children) < 2:
2018-04-11 18:32:13 +02:00
raise ValueError(_('a master and a slave are mandatories in masterslaves "{}"').format(name))
master = children[0]
for idx, child in enumerate(children):
if child.impl_is_symlinkoption(): # pragma: optional cover
2018-04-11 18:32:13 +02:00
raise ValueError(_('masterslaves "{0}" shall not have '
2017-12-02 22:53:57 +01:00
"a symlinkoption").format(self.impl_get_display_name()))
if not isinstance(child, Option): # pragma: optional cover
2018-04-11 18:32:13 +02:00
raise ValueError(_('masterslaves "{0}" shall not have '
2017-12-02 22:53:57 +01:00
'a subgroup').format(self.impl_get_display_name()))
if not child.impl_is_multi(): # pragma: optional cover
2018-04-11 18:32:13 +02:00
raise ValueError(_('only multi option allowed in masterslaves "{0}" but option '
2018-04-09 21:37:49 +02:00
'"{1}" is not a multi').format(self.impl_get_display_name(),
child.impl_get_display_name()))
if idx != 0 and child.impl_getdefault() != []:
raise ValueError(_('not allowed default value for option "{0}" '
2018-04-11 18:32:13 +02:00
'in masterslaves "{1}"'
2017-12-02 22:53:57 +01:00
'').format(child.impl_get_display_name(),
self.impl_get_display_name()))
# no empty property for save
if idx != 0:
properties = list(child._properties)
properties.remove('empty')
2017-12-30 18:31:56 +01:00
child._properties = frozenset(properties)
2017-12-02 22:53:57 +01:00
slaves.append(child)
child._add_dependency(self)
child._master_slaves = weakref.ref(self)
callback, callback_params = master.impl_get_callback()
if callback is not None and callback_params != None:
for callbk in chain(callback_params.args, callback_params.kwargs.values()):
if isinstance(callbk, ParamOption):
if callbk.option in slaves:
raise ValueError(_("callback of master's option shall "
"not refered a slave's ones"))
def is_master(self, opt):
master = self._children[0][0]
return opt.impl_getname() == master or (opt.impl_is_dynsymlinkoption() and
opt._opt.impl_getname() == master)
2017-12-02 22:53:57 +01:00
def getmaster(self):
return self._children[1][0]
2017-12-02 22:53:57 +01:00
def getslaves(self):
for slave in self._children[1][1:]:
yield slave
def in_same_group(self, opt):
if opt.impl_is_dynsymlinkoption():
c_opt = opt._opt
else:
c_opt = opt
return c_opt in self._children[1]
def reset(self,
values,
2018-08-01 08:37:58 +02:00
option_bag,
2017-12-19 23:11:45 +01:00
_commit=True):
2018-08-02 22:35:40 +02:00
config_bag = option_bag.config_bag.copy()
2018-08-17 23:11:25 +02:00
config_bag.remove_validation()
2017-12-02 22:53:57 +01:00
for slave in self.getslaves():
slave_path = slave.impl_getpath(values._getcontext())
2018-08-01 08:37:58 +02:00
soption_bag = OptionBag()
soption_bag.set_option(slave,
slave_path,
None,
config_bag)
values.reset(soption_bag,
2017-12-19 23:11:45 +01:00
_commit=_commit)
def pop(self,
values,
index,
2018-08-01 08:37:58 +02:00
option_bag,
2017-12-02 22:53:57 +01:00
slaves=undefined):
2017-12-02 22:53:57 +01:00
context = values._getcontext()
if slaves is undefined:
slaves = self.getslaves()
2018-08-02 22:35:40 +02:00
config_bag = option_bag.config_bag.copy()
2018-08-17 23:11:25 +02:00
config_bag.remove_validation()
2017-12-02 22:53:57 +01:00
for slave in slaves:
slave_path = slave.impl_getpath(context)
slavelen = values._p_.get_max_length(slave_path)
2018-08-01 08:37:58 +02:00
soption_bag = OptionBag()
soption_bag.set_option(slave,
slave_path,
index,
config_bag)
# do not check force_default_on_freeze
2018-08-02 22:35:40 +02:00
soption_bag.properties = set()
2018-08-01 08:37:58 +02:00
if not values.is_default_owner(soption_bag,
2017-12-19 23:11:45 +01:00
validate_meta=False):
if slavelen > index:
values._p_.resetvalue_index(slave_path,
index)
if slavelen > index + 1:
for idx in range(index + 1, slavelen):
2018-06-09 18:59:40 +02:00
if values._p_.hasvalue(slave_path, idx):
values._p_.reduce_index(slave_path,
idx)
def reset_cache(self,
path,
2018-04-03 21:15:58 +02:00
values,
settings,
resetted_opts):
2018-04-09 21:37:49 +02:00
master = self.getmaster()
slaves = self.getslaves()
self._reset_cache(master,
slaves,
values,
settings,
resetted_opts)
def _reset_cache(self,
master,
slaves,
values,
settings,
resetted_opts):
2018-04-03 21:15:58 +02:00
context = values._getcontext()
2018-04-09 21:37:49 +02:00
mpath = master.impl_getpath(context)
master.reset_cache(mpath,
values,
settings,
None)
for slave in slaves:
spath = slave.impl_getpath(context)
2018-04-09 21:37:49 +02:00
slave.reset_cache(spath,
2018-04-03 21:15:58 +02:00
values,
settings,
2018-04-09 21:37:49 +02:00
None)
resetted_opts.append(spath)
def impl_validate_value(self,
option,
value,
context):
if option.impl_is_master_slaves('master') and isinstance(value, list):
if len(value) < context._impl_length:
2018-01-01 21:32:39 +01:00
raise SlaveError(_('cannot reduce length of the master "{}"'
'').format(option.impl_get_display_name()))
2017-12-02 22:53:57 +01:00
2018-03-24 22:37:48 +01:00
def impl_is_master_slaves(self, *args, **kwargs):
2017-12-02 22:53:57 +01:00
return True