1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2014 Team tiramisu (see AUTHORS for all contributors)
5 # This program is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Lesser General Public License as published by the
7 # Free Software Foundation, either version 3 of the License, or (at your
8 # option) any later version.
10 # This program is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 # The original `Config` design model is unproudly borrowed from
19 # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
20 # the whole pypy projet is under MIT licence
21 # ____________________________________________________________
22 from tiramisu.i18n import _
23 from tiramisu.setting import log
24 from tiramisu.error import SlaveError, ConfigError
25 from .baseoption import SymLinkOption, Option
28 class MasterSlaves(object):
29 __slots__ = ('master', 'slaves')
31 def __init__(self, name, childs):
32 #if master (same name has group) is set
33 #for collect all slaves
37 if isinstance(child, SymLinkOption):
38 raise ValueError(_("master group {0} shall not have "
39 "a symlinkoption").format(name))
40 if not isinstance(child, Option):
41 raise ValueError(_("master group {0} shall not have "
42 "a subgroup").format(name))
43 if not child.impl_is_multi():
44 raise ValueError(_("not allowed option {0} "
46 ": this option is not a multi"
47 "").format(child._name, name))
48 if child._name == name:
52 if self.master is None:
53 raise ValueError(_('master group with wrong'
54 ' master name for {0}'
56 if self.master._callback is not None and self.master._callback[1] is not None:
57 for key, callbacks in self.master._callback[1].items():
58 for callbk in callbacks:
59 if isinstance(callbk, tuple):
60 if callbk[0] in slaves:
61 raise ValueError(_("callback of master's option shall "
62 "not refered a slave's ones"))
63 #everything is ok, store references
64 self.slaves = tuple(slaves)
66 child._master_slaves = self
68 def is_master(self, opt):
69 return opt == self.master
71 def in_same_group(self, opt):
72 return opt == self.master or opt in self.slaves
74 def reset(self, values):
75 for slave in self.slaves:
78 def pop(self, values, index):
79 #FIXME pas test de meta ...
80 for slave in self.slaves:
81 if not values.is_default_owner(slave, validate_properties=False,
83 values._get_cached_item(slave, validate=False,
84 validate_properties=False
85 ).pop(index, force=True)
88 def getitem(self, values, opt, path, validate, force_permissive,
89 force_properties, validate_properties):
90 if opt == self.master:
91 value = values._get_validated_value(opt, path, validate,
96 masterlen = len(value)
97 for slave in self.slaves:
99 slave_path = values._get_opt_path(slave)
100 slave_value = values._get_validated_value(slave,
105 None) # not undefined
106 slavelen = len(slave_value)
107 self.validate_slave_length(masterlen, slavelen, slave._name)
112 value = values._get_validated_value(opt, path, validate,
116 None) # not undefined
117 return self.get_slave_value(values, opt, value, validate, validate_properties)
119 def setitem(self, values, opt, value, path):
120 if opt == self.master:
121 masterlen = len(value)
122 for slave in self.slaves:
123 slave_path = values._get_opt_path(slave)
124 slave_value = values._get_validated_value(slave,
129 None) # not undefined
130 slavelen = len(slave_value)
131 self.validate_slave_length(masterlen, slavelen, slave._name)
133 self.validate_slave_length(self.get_length(values), len(value),
134 opt._name, setitem=True)
136 def get_length(self, values, validate=True):
137 masterp = values._get_opt_path(self.master)
138 return len(self.getitem(values, self.master, masterp, validate, False,
141 def validate_slave_length(self, masterlen, valuelen, name, setitem=False):
142 if valuelen > masterlen or (valuelen < masterlen and setitem):
143 log.debug('validate_slave_length: masterlen: {0}, valuelen: {1}, '
144 'setitem: {2}'.format(masterlen, valuelen, setitem))
145 raise SlaveError(_("invalid len for the slave: {0}"
146 " which has {1} as master").format(
147 name, self.master._name))
149 def get_slave_value(self, values, opt, value, validate=True,
150 validate_properties=True):
152 if master has length 0:
154 if master has length bigger than 0:
158 list same length as master: return list
159 list is smaller than master: return list + None
160 list is greater than master: raise SlaveError
161 if has default value:
162 list same length as master: return list
163 list is smaller than master: return list + None
164 list is greater than master: raise SlaveError
165 if has default_multi value:
166 return default_multi * master's length
168 list same length as master: return list
169 list is smaller than master: return list + None
170 list is greater than master: raise SlaveError
172 #if slave, had values until master's one
173 masterlen = self.get_length(values, validate)
174 valuelen = len(value)
176 self.validate_slave_length(masterlen, valuelen, opt._name)
177 path = values._get_opt_path(opt)
178 if valuelen < masterlen:
179 for num in range(0, masterlen - valuelen):
180 index = valuelen + num
181 value.append(values._get_validated_value(opt, path, True,