consistencies can make a warning instead of raises

for that, you have to set something like:
  a.impl_add_consistency('not_equal', b, warnings_only=True)

warning product now adapted message
This commit is contained in:
Emmanuel Garette 2014-03-12 21:56:53 +01:00
parent d7b04ebed0
commit ff802b46e5
5 changed files with 391 additions and 282 deletions

View File

@ -5,7 +5,8 @@ from tiramisu.setting import owners, groups
from tiramisu.config import Config
from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
BroadcastOption, SymLinkOption, OptionDescription
from tiramisu.error import ConfigError
from tiramisu.error import ConfigError, ValueWarning
import warnings
def test_consistency():
@ -19,6 +20,19 @@ def test_consistency():
raises(ConfigError, "a.impl_add_consistency('not_equal', 'a')")
def test_consistency_warnings_only():
a = IntOption('a', '')
b = IntOption('b', '')
od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', b, warnings_only=True)
c = Config(od)
c.a = 1
warnings.simplefilter("always", ValueWarning)
with warnings.catch_warnings(record=True) as w:
c.b = 1
assert w != []
def test_consistency_not_equal():
a = IntOption('a', '')
b = IntOption('b', '')

View File

@ -88,7 +88,7 @@ def test_validator_warning():
cfg.opt2 = 'val'
assert len(w) == 1
assert w[0].message.opt == opt2
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt2', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('opt2', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.opt3.append('val')
@ -98,7 +98,7 @@ def test_validator_warning():
cfg.opt3.append('val1')
assert len(w) == 1
assert w[0].message.opt == opt3
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt3', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('opt3', 'error')
raises(ValueError, "cfg.opt2 = 1")
#
with warnings.catch_warnings(record=True) as w:
@ -106,9 +106,9 @@ def test_validator_warning():
cfg.opt3.append('val')
assert len(w) == 2
assert w[0].message.opt == opt2
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt2', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('opt2', 'error')
assert w[1].message.opt == opt3
assert str(w[1].message) == _('invalid value for option {0}: {1}').format('opt3', 'error')
assert str(w[1].message) == _("warning on the value of the option {0}: {1}").format('opt3', 'error')
def test_validator_warning_master_slave():
@ -128,29 +128,29 @@ def test_validator_warning_master_slave():
cfg.ip_admin_eth0.netmask_admin_eth0 = ['val1']
assert len(w) == 1
assert w[0].message.opt == netmask_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('netmask_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('netmask_admin_eth0', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.ip_admin_eth0.ip_admin_eth0 = ['val']
assert len(w) == 1
assert w[0].message.opt == ip_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.ip_admin_eth0.ip_admin_eth0 = ['val', 'val1', 'val1']
assert len(w) == 1
assert w[0].message.opt == ip_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.ip_admin_eth0.ip_admin_eth0 = ['val1', 'val', 'val1']
assert len(w) == 1
assert w[0].message.opt == ip_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')
#
warnings.resetwarnings()
with warnings.catch_warnings(record=True) as w:
cfg.ip_admin_eth0.ip_admin_eth0 = ['val1', 'val1', 'val']
assert len(w) == 1
assert w[0].message.opt == ip_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')

View File

@ -336,7 +336,7 @@ class Option(BaseOption):
self._consistencies = None
def _launch_consistency(self, func, option, value, context, index,
all_cons_opts):
all_cons_opts, warnings_only):
"""Launch consistency now
:param func: function name, this name should start with _cons_
@ -351,6 +351,8 @@ class Option(BaseOption):
:type index: `int`
:param all_cons_opts: all options concerne by this consistency
:type all_cons_opts: `list` of `tiramisu.option.Option`
:param warnings_only: specific raise error for warning
:type warnings_only: `boolean`
"""
if context is not None:
descr = context.cfgimpl_get_description()
@ -379,7 +381,7 @@ class Option(BaseOption):
except IndexError:
#so return if no value
return
getattr(self, func)(all_cons_opts, all_cons_vals)
getattr(self, func)(all_cons_opts, all_cons_vals, warnings_only)
def impl_validate(self, value, context=None, validate=True,
force_index=None):
@ -422,22 +424,31 @@ class Option(BaseOption):
except ValueError as err:
raise ValueError(_('invalid value for option {0}: {1}'
'').format(self._name, err))
error = None
warning = None
try:
# valid with self._validator
val_validator(_value)
# if not context launch consistency validation
# if context launch consistency validation
if context is not None:
descr._valid_consistency(self, _value, context, _index)
self._second_level_validation(_value)
except ValueError as err:
msg = _("invalid value for option {0}: {1}").format(
self._name, err)
descr._valid_consistency(self, _value, context, _index,
self._warnings_only)
self._second_level_validation(_value, self._warnings_only)
except ValueError as error:
if self._warnings_only:
warnings.warn_explicit(ValueWarning(msg, self),
ValueWarning,
self.__class__.__name__, 0)
else:
raise ValueError(msg)
warning = error
error = None
except ValueWarning as warning:
pass
if warning:
msg = _("warning on the value of the option {0}: {1}").format(
self._name, warning)
warnings.warn_explicit(ValueWarning(msg, self),
ValueWarning,
self.__class__.__name__, 0)
elif error:
raise ValueError(_("invalid value for option {0}: {1}").format(
self._name, error))
# generic calculation
if context is not None:
@ -490,7 +501,7 @@ class Option(BaseOption):
def impl_is_multi(self):
return self._multi
def impl_add_consistency(self, func, *other_opts):
def impl_add_consistency(self, func, *other_opts, **params):
"""Add consistency means that value will be validate with other_opts
option's values.
@ -498,16 +509,18 @@ class Option(BaseOption):
:type func: `str`
:param other_opts: options used to validate value
:type other_opts: `list` of `tiramisu.option.Option`
:param params: extra params (only warnings_only are allowed)
"""
if self._consistencies is None:
self._consistencies = []
warnings_only = params.get('warnings_only', False)
for opt in other_opts:
if not isinstance(opt, Option):
raise ConfigError(_('consistency should be set with an option'))
raise ConfigError(_('consistency must be set with an option'))
if self is opt:
raise ConfigError(_('cannot add consistency with itself'))
if self.impl_is_multi() != opt.impl_is_multi():
raise ConfigError(_('every options in consistency should be '
raise ConfigError(_('every options in consistency must be '
'multi or none'))
func = '_cons_{0}'.format(func)
all_cons_opts = tuple([self] + list(other_opts))
@ -516,19 +529,23 @@ class Option(BaseOption):
if self.impl_is_multi():
for idx, val in enumerate(value):
self._launch_consistency(func, self, val, None,
idx, all_cons_opts)
idx, all_cons_opts, warnings_only)
else:
self._launch_consistency(func, self, value, None,
None, all_cons_opts)
self._consistencies.append((func, all_cons_opts))
None, all_cons_opts, warnings_only)
self._consistencies.append((func, all_cons_opts, params))
self.impl_validate(self.impl_getdefault())
def _cons_not_equal(self, opts, vals):
def _cons_not_equal(self, opts, vals, warnings_only):
for idx_inf, val_inf in enumerate(vals):
for idx_sup, val_sup in enumerate(vals[idx_inf + 1:]):
if val_inf == val_sup is not None:
raise ValueError(_("same value for {0} and {1}").format(
opts[idx_inf]._name, opts[idx_inf + idx_sup + 1]._name))
if warnings_only:
msg = _("same value for {0} and {1}, should be different")
else:
msg = _("same value for {0} and {1}, must be different")
raise ValueError(msg.format(opts[idx_inf]._name,
opts[idx_inf + idx_sup + 1]._name))
def _impl_convert_callbacks(self, descr, load=False):
if not load and self._callback is None:
@ -592,14 +609,14 @@ class Option(BaseOption):
values.append(descr.impl_get_opt_by_path(obj))
else:
values.append(descr.impl_get_path_by_opt(obj))
new_value.append((consistency[0], tuple(values)))
new_value.append((consistency[0], tuple(values), consistency[2]))
if load:
del(self._state_consistencies)
self._consistencies = new_value
else:
self._state_consistencies = new_value
def _second_level_validation(self, value):
def _second_level_validation(self, value, warnings_only):
pass
@ -777,24 +794,36 @@ class IPOption(Option):
except ValueError:
raise ValueError(_('invalid IP'))
def _second_level_validation(self, value):
def _second_level_validation(self, value, warnings_only):
ip = IP('{0}/32'.format(value))
if not self._allow_reserved and ip.iptype() == 'RESERVED':
raise ValueError(_("invalid IP, mustn't not be in reserved class"))
if warnings_only:
msg = _("IP shouldn't be in reserved class")
else:
msg = _("invalid IP, mustn't be in reserved class")
raise ValueError(msg)
if self._private_only and not ip.iptype() == 'PRIVATE':
raise ValueError(_("invalid IP, must be in private class"))
if warnings_only:
msg = _("IP should be in private class")
else:
msg = _("invalid IP, must be in private class")
raise ValueError(msg)
def _cons_in_network(self, opts, vals):
def _cons_in_network(self, opts, vals, warnings_only):
if len(vals) != 3:
raise ConfigError(_('invalid len for vals'))
if None in vals:
return
ip, network, netmask = vals
if IP(ip) not in IP('{0}/{1}'.format(network, netmask)):
raise ValueError(_('invalid IP {0} ({1}) with network {2} '
'({3}) and netmask {4} ({5})').format(
ip, opts[0]._name, network,
opts[1]._name, netmask, opts[2]._name))
if warnings_only:
msg = _('IP {0} ({1}) not in network {2} ({3}) with netmask {4}'
' ({5})')
else:
msg = _('invalid IP {0} ({1}) not in network {2} ({3}) with '
'netmask {4} ({5})')
raise ValueError(msg.format(ip, opts[0]._name, network,
opts[1]._name, netmask, opts[2]._name))
class PortOption(Option):
@ -884,10 +913,14 @@ class NetworkOption(Option):
except ValueError:
raise ValueError(_('invalid network address'))
def _second_level_validation(self, value):
def _second_level_validation(self, value, warnings_only):
ip = IP(value)
if ip.iptype() == 'RESERVED':
raise ValueError(_("invalid network address, must not be in reserved class"))
if warnings_only:
msg = _("network address shouldn't be in reserved class")
else:
msg = _("invalid network address, mustn't be in reserved class")
raise ValueError(msg)
class NetmaskOption(Option):
@ -901,19 +934,20 @@ class NetmaskOption(Option):
except ValueError:
raise ValueError(_('invalid netmask address'))
def _cons_network_netmask(self, opts, vals):
def _cons_network_netmask(self, opts, vals, warnings_only):
#opts must be (netmask, network) options
if None in vals:
return
self.__cons_netmask(opts, vals[0], vals[1], False)
self.__cons_netmask(opts, vals[0], vals[1], False, warnings_only)
def _cons_ip_netmask(self, opts, vals):
def _cons_ip_netmask(self, opts, vals, warnings_only):
#opts must be (netmask, ip) options
if None in vals:
return
self.__cons_netmask(opts, vals[0], vals[1], True)
self.__cons_netmask(opts, vals[0], vals[1], True, warnings_only)
def __cons_netmask(self, opts, val_netmask, val_ipnetwork, make_net):
def __cons_netmask(self, opts, val_netmask, val_ipnetwork, make_net,
warnings_only):
if len(opts) != 2:
raise ConfigError(_('invalid len for opts'))
msg = None
@ -950,7 +984,7 @@ class BroadcastOption(Option):
except ValueError:
raise ValueError(_('invalid broadcast address'))
def _cons_broadcast(self, opts, vals):
def _cons_broadcast(self, opts, vals, warnings_only):
if len(vals) != 3:
raise ConfigError(_('invalid len for vals'))
if None in vals:
@ -1047,7 +1081,7 @@ class EmailOption(DomainnameOption):
try:
username, domain = splitted
except ValueError:
raise ValueError(_('invalid email address, should contains one @'
raise ValueError(_('invalid email address, must contains one @'
))
if not self.username_re.search(username):
raise ValueError(_('invalid username in email address'))
@ -1063,7 +1097,7 @@ class URLOption(DomainnameOption):
def _validate(self, value):
match = self.proto_re.search(value)
if not match:
raise ValueError(_('invalid url, should start with http:// or '
raise ValueError(_('invalid url, must start with http:// or '
'https://'))
value = value[len(match.group(0)):]
# get domain/files
@ -1088,7 +1122,7 @@ class URLOption(DomainnameOption):
super(URLOption, self)._validate(domain)
# validate file
if files is not None and files != '' and not self.path_re.search(files):
raise ValueError(_('invalid url, should ends with filename'))
raise ValueError(_('invalid url, must ends with filename'))
class UsernameOption(Option):
@ -1217,11 +1251,12 @@ class OptionDescription(BaseOption):
if not force_no_consistencies and \
option._consistencies is not None:
for consistency in option._consistencies:
func, all_cons_opts = consistency
func, all_cons_opts, params = consistency
for opt in all_cons_opts:
_consistencies.setdefault(opt,
[]).append((func,
all_cons_opts))
all_cons_opts,
params))
else:
_currpath.append(attr)
option.impl_build_cache(cache_path,
@ -1311,18 +1346,29 @@ class OptionDescription(BaseOption):
def impl_get_group_type(self):
return self._group_type
def _valid_consistency(self, option, value, context, index):
def _valid_consistency(self, option, value, context, index, warnings_only):
if self._cache_consistencies is None:
return True
#consistencies is something like [('_cons_not_equal', (opt1, opt2))]
consistencies = self._cache_consistencies.get(option)
if consistencies is not None:
for func, all_cons_opts in consistencies:
for func, all_cons_opts, params in consistencies:
if not warnings_only:
l_warnings_only = params.get('warnings_only', False)
else:
l_warnings_only = warnings_only
#all_cons_opts[0] is the option where func is set
all_cons_opts[0]._launch_consistency(func, option,
value,
context, index,
all_cons_opts)
try:
all_cons_opts[0]._launch_consistency(func, option,
value,
context, index,
all_cons_opts,
l_warnings_only)
except ValueError as err:
if l_warnings_only:
raise ValueWarning(err.message, option)
else:
raise err
def _impl_getstate(self, descr=None):
"""enables us to export into a dict
@ -1432,7 +1478,7 @@ def validate_requires_arg(requires, name):
'must be an option in option {0}').format(name))
if option.impl_is_multi():
raise ValueError(_('malformed requirements option {0} '
'should not be a multi').format(name))
'must not be a multi').format(name))
if expected is not None:
try:
option._validate(expected)
@ -1467,17 +1513,17 @@ def validate_requires_arg(requires, name):
def validate_callback(callback, callback_params, type_):
if type(callback) != FunctionType:
raise ValueError(_('{0} should be a function').format(type_))
raise ValueError(_('{0} must be a function').format(type_))
if callback_params is not None:
if not isinstance(callback_params, dict):
raise ValueError(_('{0}_params should be a dict').format(type_))
raise ValueError(_('{0}_params must be a dict').format(type_))
for key, callbacks in callback_params.items():
if key != '' and len(callbacks) != 1:
raise ValueError(_('{0}_params with key {1} should not have '
'length different to 1').format(type_,
raise ValueError(_("{0}_params with key {1} mustn't have "
"length different to 1").format(type_,
key))
if not isinstance(callbacks, tuple):
raise ValueError(_('{0}_params should be tuple for key "{1}"'
raise ValueError(_('{0}_params must be tuple for key "{1}"'
).format(type_, key))
for callbk in callbacks:
if isinstance(callbk, tuple):
@ -1486,11 +1532,11 @@ def validate_callback(callback, callback_params, type_):
raise ValueError(_('validator not support tuple'))
if not isinstance(option, Option) and not \
isinstance(option, SymLinkOption):
raise ValueError(_('{0}_params should have an option '
raise ValueError(_('{0}_params must have an option '
'not a {0} for first argument'
).format(type_, type(option)))
if force_permissive not in [True, False]:
raise ValueError(_('{0}_params should have a boolean'
raise ValueError(_('{0}_params must have a boolean'
' not a {0} for second argument'
).format(type_, type(
force_permissive)))

View File

@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Tiramisu\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-03-11 18:51+CET\n"
"POT-Creation-Date: 2014-03-12 21:49+CET\n"
"PO-Revision-Date: \n"
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
"Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
@ -130,264 +130,289 @@ msgstr ""
"params définis pour une fonction callback mais par de callback encore "
"définis pour l'option {0}"
#: tiramisu/option.py:423 tiramisu/option.py:433
#: tiramisu/option.py:425 tiramisu/option.py:450
msgid "invalid value for option {0}: {1}"
msgstr "valeur invalide pour l'option {0} : {1}"
#: tiramisu/option.py:450
#: tiramisu/option.py:444
msgid "warning on the value of the option {0}: {1}"
msgstr "avertissement sur la valeur de l'option {0} : {1}"
#: tiramisu/option.py:461
msgid "invalid value {0} for option {1} which must be a list"
msgstr "valeur invalide pour l'option {0} : {1} laquelle doit être une liste"
#: tiramisu/option.py:506
msgid "consistency should be set with an option"
#: tiramisu/option.py:519
msgid "consistency must be set with an option"
msgstr "consistency doit être configuré avec une option"
#: tiramisu/option.py:508
#: tiramisu/option.py:521
msgid "cannot add consistency with itself"
msgstr "ne peut ajouter une consistency avec lui même"
#: tiramisu/option.py:510
msgid "every options in consistency should be multi or none"
#: tiramisu/option.py:523
msgid "every options in consistency must be multi or none"
msgstr ""
"toutes les options d'une consistency devrait être multi ou ne pas l'être"
"toutes les options d'une consistency doivent être multi ou ne pas l'être"
#: tiramisu/option.py:530
msgid "same value for {0} and {1}"
msgstr "même valeur pour {0} et {1}"
#: tiramisu/option.py:544
msgid "same value for {0} and {1}, should be different"
msgstr "même valeur pour {0} et {1}, devrait être différent"
#: tiramisu/option.py:623
#: tiramisu/option.py:546
msgid "same value for {0} and {1}, must be different"
msgstr "même valeur pour {0} et {1}, doit être différent"
#: tiramisu/option.py:640
msgid "values must be a tuple for {0}"
msgstr "values doit être un tuple pour {0}"
#: tiramisu/option.py:626
#: tiramisu/option.py:643
msgid "open_values must be a boolean for {0}"
msgstr "open_values doit être un booléen pour {0}"
#: tiramisu/option.py:648
#: tiramisu/option.py:665
msgid "value {0} is not permitted, only {1} is allowed"
msgstr "valeur {0} n'est pas permis, seules {1} sont autorisées"
#: tiramisu/option.py:660
#: tiramisu/option.py:677
msgid "invalid boolean"
msgstr "booléen invalide"
#: tiramisu/option.py:670
#: tiramisu/option.py:687
msgid "invalid integer"
msgstr "nombre invalide"
#: tiramisu/option.py:680
#: tiramisu/option.py:697
msgid "invalid float"
msgstr "invalide nombre flottan"
#: tiramisu/option.py:690
#: tiramisu/option.py:707
msgid "invalid string"
msgstr "invalide caractère"
#: tiramisu/option.py:707
#: tiramisu/option.py:724
msgid "invalid unicode"
msgstr "invalide unicode"
#: tiramisu/option.py:719
#: tiramisu/option.py:736
msgid "malformed symlinkoption must be an option for symlink {0}"
msgstr "symlinkoption mal formé, doit être une option pour symlink {0}"
#: tiramisu/option.py:770 tiramisu/option.py:773 tiramisu/option.py:778
#: tiramisu/option.py:787 tiramisu/option.py:790 tiramisu/option.py:795
msgid "invalid IP"
msgstr "adresse IP invalide"
#: tiramisu/option.py:783
msgid "invalid IP, mustn't not be in reserved class"
msgstr "adresse IP invalide, ne doit pas être d'une classe reservée"
#: tiramisu/option.py:801
msgid "IP shouldn't be in reserved class"
msgstr "l'adresse IP ne devrait pas être d'une classe réservée"
#: tiramisu/option.py:785
#: tiramisu/option.py:803
msgid "invalid IP, mustn't be in reserved class"
msgstr "adresse IP invalide, ne doit pas être dans une classe réservée"
#: tiramisu/option.py:807
msgid "IP should be in private class"
msgstr "l'adresse IP devrait être dans une classe privée"
#: tiramisu/option.py:809
msgid "invalid IP, must be in private class"
msgstr "adresse IP invalide, doit être dans la classe privée"
#: tiramisu/option.py:789 tiramisu/option.py:955
#: tiramisu/option.py:814 tiramisu/option.py:989
msgid "invalid len for vals"
msgstr "longueur invalide pour vals"
#: tiramisu/option.py:794
msgid "invalid IP {0} ({1}) with network {2} ({3}) and netmask {4} ({5})"
msgstr "IP invalide {0} ({1}) avec le réseau {2} ({3}) et le masque {4} ({5})"
#: tiramisu/option.py:820
msgid "IP {0} ({1}) not in network {2} ({3}) with netmask {4} ({5})"
msgstr "IP {0} ({1}) pas dans le réseau {2} ({3}) avec le masque {4} ({5})"
#: tiramisu/option.py:835
#: tiramisu/option.py:823
msgid "invalid IP {0} ({1}) not in network {2} ({3}) with netmask {4} ({5})"
msgstr ""
"IP invalide {0} ({1}) pas dans le réseau {2} ({3}) avec le masque {4} ({5})"
#: tiramisu/option.py:864
msgid "inconsistency in allowed range"
msgstr "inconsistence dans la plage autorisée"
#: tiramisu/option.py:840
#: tiramisu/option.py:869
msgid "max value is empty"
msgstr "la valeur maximum est vide"
#: tiramisu/option.py:857
#: tiramisu/option.py:886
msgid "invalid port, range must have two values only"
msgstr "port invalide, une plage doit avoir deux valeurs seulement"
#: tiramisu/option.py:860
#: tiramisu/option.py:889
msgid "invalid port, first port in range must be smaller than the second one"
msgstr ""
"port invalide, le premier port d'une plage doit être plus petit que le second"
#: tiramisu/option.py:869
#: tiramisu/option.py:898
msgid "invalid port"
msgstr "port invalide"
#: tiramisu/option.py:871
#: tiramisu/option.py:900
msgid "invalid port, must be an between {0} and {1}"
msgstr "port invalide, port doit être entre {0} et {1}"
#: tiramisu/option.py:885
#: tiramisu/option.py:914
msgid "invalid network address"
msgstr "adresse réseau invalide"
#: tiramisu/option.py:890
msgid "invalid network address, must not be in reserved class"
msgstr "adresse réseau invalide, ne doit pas être dans la classe reservée"
#: tiramisu/option.py:920
msgid "network address shouldn't be in reserved class"
msgstr "l'adresse réseau ne devait pas être dans la classe réservée"
#: tiramisu/option.py:902
#: tiramisu/option.py:922
msgid "invalid network address, mustn't be in reserved class"
msgstr "adresse réseau invalide, ne doit pas être dans la classe réservée"
#: tiramisu/option.py:935
msgid "invalid netmask address"
msgstr "masque de sous-réseau invalide"
#: tiramisu/option.py:918
#: tiramisu/option.py:952
msgid "invalid len for opts"
msgstr "longueur invalide pour opts"
#: tiramisu/option.py:932
#: tiramisu/option.py:966
msgid "invalid IP {0} ({1}) with netmask {2}, this IP is a network"
msgstr "IP invalide {0} ({1}) avec masque {2}, cette IP est un réseau"
#: tiramisu/option.py:937
#: tiramisu/option.py:971
msgid "invalid network {0} ({1}) with netmask {2}"
msgstr "réseau invalide {0} ({1}) avec masque {2}"
#: tiramisu/option.py:951
#: tiramisu/option.py:985
msgid "invalid broadcast address"
msgstr "adresse de broadcast invalide"
#: tiramisu/option.py:960
#: tiramisu/option.py:994
msgid ""
"invalid broadcast {0} ({1}) with network {2} ({3}) and netmask {4} ({5})"
msgstr ""
"Broadcast invalide {0} ({1}) avec le réseau {2} ({3}) et le masque {4} ({5})"
#: tiramisu/option.py:982
#: tiramisu/option.py:1016
msgid "unknown type_ {0} for hostname"
msgstr "type_ inconnu {0} pour le nom d'hôte"
#: tiramisu/option.py:985
#: tiramisu/option.py:1019
msgid "allow_ip must be a boolean"
msgstr "allow_ip doit être un booléen"
#: tiramisu/option.py:987
#: tiramisu/option.py:1021
msgid "allow_without_dot must be a boolean"
msgstr "allow_without_dot doit être un booléen"
#: tiramisu/option.py:1031
#: tiramisu/option.py:1065
msgid "invalid domainname, must have dot"
msgstr "nom de domaine invalide, doit avoir un point"
#: tiramisu/option.py:1033
#: tiramisu/option.py:1067
msgid "invalid domainname's length (max 255)"
msgstr "longueur du nom de domaine invalide (maximum {1})"
#: tiramisu/option.py:1035
#: tiramisu/option.py:1069
msgid "invalid domainname's length (min 2)"
msgstr "longueur du nom de domaine invalide (minimum 2)"
#: tiramisu/option.py:1037
#: tiramisu/option.py:1071
msgid "invalid domainname"
msgstr "nom de domaine invalide"
#: tiramisu/option.py:1050
msgid "invalid email address, should contains one @"
msgstr "adresse email invalide, devrait contenir un @"
#: tiramisu/option.py:1084
msgid "invalid email address, must contains one @"
msgstr "adresse email invalide, doit contenir un @"
#: tiramisu/option.py:1053
#: tiramisu/option.py:1087
msgid "invalid username in email address"
msgstr "nom d'utilisateur invalide dans une adresse email"
#: tiramisu/option.py:1066
msgid "invalid url, should start with http:// or https://"
msgstr "URL invalide, devrait démarré avec http:// ou https://"
#: tiramisu/option.py:1100
msgid "invalid url, must start with http:// or https://"
msgstr "URL invalide, doit démarrer avec http:// ou https://"
#: tiramisu/option.py:1085
#: tiramisu/option.py:1119
msgid "invalid url, port must be an between 0 and 65536"
msgstr "URL invalide, port doit être entre 0 et 65536"
#: tiramisu/option.py:1091
msgid "invalid url, should ends with filename"
msgstr "URL invalide, devrait finir avec un nom de fichier"
#: tiramisu/option.py:1125
msgid "invalid url, must ends with filename"
msgstr "URL invalide, doit finir avec un nom de fichier"
#: tiramisu/option.py:1103
#: tiramisu/option.py:1137
msgid "invalid username"
msgstr "utilisateur invalide"
#: tiramisu/option.py:1114
#: tiramisu/option.py:1148
msgid "invalid filename"
msgstr "nom de fichier invalide"
#: tiramisu/option.py:1141
#: tiramisu/option.py:1175
msgid "duplicate option name: {0}"
msgstr "nom de l'option dupliqué : {0}"
#: tiramisu/option.py:1159
#: tiramisu/option.py:1193
msgid "unknown Option {0} in OptionDescription {1}"
msgstr "Option {0} inconnue pour l'OptionDescription {1}"
#: tiramisu/option.py:1210
#: tiramisu/option.py:1244
msgid "duplicate option: {0}"
msgstr "option dupliquée : {0}"
#: tiramisu/option.py:1240
#: tiramisu/option.py:1275
msgid "consistency with option {0} which is not in Config"
msgstr "consistency avec l'option {0} qui n'est pas dans une Config"
#: tiramisu/option.py:1248
#: tiramisu/option.py:1283
msgid "no option for path {0}"
msgstr "pas d'option pour le chemin {0}"
#: tiramisu/option.py:1254
#: tiramisu/option.py:1289
msgid "no option {0} found"
msgstr "pas d'option {0} trouvée"
#: tiramisu/option.py:1264
#: tiramisu/option.py:1299
msgid "cannot change group_type if already set (old {0}, new {1})"
msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1})"
#: tiramisu/option.py:1276
#: tiramisu/option.py:1311
msgid "master group {0} shall not have a subgroup"
msgstr "groupe maître {0} ne doit pas avoir de sous-groupe"
#: tiramisu/option.py:1279
#: tiramisu/option.py:1314
msgid "master group {0} shall not have a symlinkoption"
msgstr "groupe maître {0} ne doit pas avoir de symlinkoption"
#: tiramisu/option.py:1282
#: tiramisu/option.py:1317
msgid "not allowed option {0} in group {1}: this option is not a multi"
msgstr ""
"option non autorisée {0} dans le groupe {1} : cette option n'est pas une "
"multi"
#: tiramisu/option.py:1292
#: tiramisu/option.py:1327
msgid "master group with wrong master name for {0}"
msgstr "le groupe maître avec un nom de maître érroné pour {0}"
#: tiramisu/option.py:1300
#: tiramisu/option.py:1335
msgid "callback of master's option shall not refered a slave's ones"
msgstr ""
"callback d'une variable maitre ne devrait pas référencer des variables "
"esclaves"
#: tiramisu/option.py:1308
#: tiramisu/option.py:1343
msgid "group_type: {0} not allowed"
msgstr "group_type : {0} non autorisé"
#: tiramisu/option.py:1397
#: tiramisu/option.py:1443
msgid "malformed requirements type for option: {0}, must be a dict"
msgstr ""
"type requirements malformé pour l'option : {0}, doit être un dictionnaire"
#: tiramisu/option.py:1414
#: tiramisu/option.py:1460
msgid ""
"malformed requirements for option: {0} require must have option, expected "
"and action keys"
@ -395,68 +420,68 @@ msgstr ""
"requirements malformé pour l'option : {0} l'exigence doit avoir les clefs "
"option, expected et action"
#: tiramisu/option.py:1419
#: tiramisu/option.py:1465
msgid "malformed requirements for option: {0} inverse must be boolean"
msgstr ""
"requirements mal formés pour l'option : {0} inverse doit être un booléen"
#: tiramisu/option.py:1423
#: tiramisu/option.py:1469
msgid "malformed requirements for option: {0} transitive must be boolean"
msgstr ""
"requirements mal formés pour l'option : {0} transitive doit être booléen"
#: tiramisu/option.py:1427
#: tiramisu/option.py:1473
msgid "malformed requirements for option: {0} same_action must be boolean"
msgstr ""
"requirements mal formés pour l'option : {0} same_action doit être un booléen"
#: tiramisu/option.py:1431
#: tiramisu/option.py:1477
msgid "malformed requirements must be an option in option {0}"
msgstr "requirements mal formés doit être une option dans l'option {0}"
#: tiramisu/option.py:1434
msgid "malformed requirements option {0} should not be a multi"
#: tiramisu/option.py:1480
msgid "malformed requirements option {0} must not be a multi"
msgstr "requirements mal formés l'option {0} ne doit pas être une multi"
#: tiramisu/option.py:1440
#: tiramisu/option.py:1486
msgid ""
"malformed requirements second argument must be valid for option {0}: {1}"
msgstr ""
"requirements mal formés deuxième argument doit être valide pour l'option "
"{0} : {1}"
#: tiramisu/option.py:1445
#: tiramisu/option.py:1491
msgid "inconsistency in action types for option: {0} action: {1}"
msgstr "incohérence dans les types action pour l'option : {0} action {1}"
#: tiramisu/option.py:1470
msgid "{0} should be a function"
#: tiramisu/option.py:1516
msgid "{0} must be a function"
msgstr "{0} doit être une fonction"
#: tiramisu/option.py:1473
msgid "{0}_params should be a dict"
msgstr "{0}_params devrait être un dict"
#: tiramisu/option.py:1519
msgid "{0}_params must be a dict"
msgstr "{0}_params doit être un dict"
#: tiramisu/option.py:1476
msgid "{0}_params with key {1} should not have length different to 1"
#: tiramisu/option.py:1522
msgid "{0}_params with key {1} mustn't have length different to 1"
msgstr ""
"{0}_params avec la clef {1} devrait ne pas avoir une longueur différent de 1"
"{0}_params avec la clef {1} ne doit pas avoir une longueur différent de 1"
#: tiramisu/option.py:1480
msgid "{0}_params should be tuple for key \"{1}\""
msgstr "{0}_params devrait être un tuple pour la clef \"{1}\""
#: tiramisu/option.py:1526
msgid "{0}_params must be tuple for key \"{1}\""
msgstr "{0}_params doit être un tuple pour la clef \"{1}\""
#: tiramisu/option.py:1486
#: tiramisu/option.py:1532
msgid "validator not support tuple"
msgstr "validator n'accepte pas de tuple"
#: tiramisu/option.py:1489
msgid "{0}_params should have an option not a {0} for first argument"
msgstr "{0}_params devrait avoir une option pas un {0} pour premier argument"
#: tiramisu/option.py:1535
msgid "{0}_params must have an option not a {0} for first argument"
msgstr "{0}_params doit avoir une option pas un {0} pour premier argument"
#: tiramisu/option.py:1493
msgid "{0}_params should have a boolean not a {0} for second argument"
msgstr "{0}_params devrait avoir un boolean pas un {0} pour second argument"
#: tiramisu/option.py:1539
msgid "{0}_params must have a boolean not a {0} for second argument"
msgstr "{0}_params doit avoir un booléen pas un {0} pour second argument"
#: tiramisu/setting.py:116
msgid "can't rebind {0}"

View File

@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2014-03-11 18:51+CET\n"
"POT-Creation-Date: 2014-03-12 21:49+CET\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -120,312 +120,336 @@ msgstr ""
msgid "params defined for a callback function but no callback defined yet for option {0}"
msgstr ""
#: tiramisu/option.py:423 tiramisu/option.py:433
#: tiramisu/option.py:425 tiramisu/option.py:450
msgid "invalid value for option {0}: {1}"
msgstr ""
#: tiramisu/option.py:450
#: tiramisu/option.py:444
msgid "warning on the value of the option {0}: {1}"
msgstr ""
#: tiramisu/option.py:461
msgid "invalid value {0} for option {1} which must be a list"
msgstr ""
#: tiramisu/option.py:506
msgid "consistency should be set with an option"
#: tiramisu/option.py:519
msgid "consistency must be set with an option"
msgstr ""
#: tiramisu/option.py:508
#: tiramisu/option.py:521
msgid "cannot add consistency with itself"
msgstr ""
#: tiramisu/option.py:510
msgid "every options in consistency should be multi or none"
#: tiramisu/option.py:523
msgid "every options in consistency must be multi or none"
msgstr ""
#: tiramisu/option.py:530
msgid "same value for {0} and {1}"
#: tiramisu/option.py:544
msgid "same value for {0} and {1}, should be different"
msgstr ""
#: tiramisu/option.py:623
#: tiramisu/option.py:546
msgid "same value for {0} and {1}, must be different"
msgstr ""
#: tiramisu/option.py:640
msgid "values must be a tuple for {0}"
msgstr ""
#: tiramisu/option.py:626
#: tiramisu/option.py:643
msgid "open_values must be a boolean for {0}"
msgstr ""
#: tiramisu/option.py:648
#: tiramisu/option.py:665
msgid "value {0} is not permitted, only {1} is allowed"
msgstr ""
#: tiramisu/option.py:660
#: tiramisu/option.py:677
msgid "invalid boolean"
msgstr ""
#: tiramisu/option.py:670
#: tiramisu/option.py:687
msgid "invalid integer"
msgstr ""
#: tiramisu/option.py:680
#: tiramisu/option.py:697
msgid "invalid float"
msgstr ""
#: tiramisu/option.py:690
#: tiramisu/option.py:707
msgid "invalid string"
msgstr ""
#: tiramisu/option.py:707
#: tiramisu/option.py:724
msgid "invalid unicode"
msgstr ""
#: tiramisu/option.py:719
#: tiramisu/option.py:736
msgid "malformed symlinkoption must be an option for symlink {0}"
msgstr ""
#: tiramisu/option.py:770 tiramisu/option.py:773 tiramisu/option.py:778
#: tiramisu/option.py:787 tiramisu/option.py:790 tiramisu/option.py:795
msgid "invalid IP"
msgstr ""
#: tiramisu/option.py:783
msgid "invalid IP, mustn't not be in reserved class"
#: tiramisu/option.py:801
msgid "IP shouldn't be in reserved class"
msgstr ""
#: tiramisu/option.py:785
#: tiramisu/option.py:803
msgid "invalid IP, mustn't be in reserved class"
msgstr ""
#: tiramisu/option.py:807
msgid "IP should be in private class"
msgstr ""
#: tiramisu/option.py:809
msgid "invalid IP, must be in private class"
msgstr ""
#: tiramisu/option.py:789 tiramisu/option.py:955
#: tiramisu/option.py:814 tiramisu/option.py:989
msgid "invalid len for vals"
msgstr ""
#: tiramisu/option.py:794
msgid "invalid IP {0} ({1}) with network {2} ({3}) and netmask {4} ({5})"
#: tiramisu/option.py:820
msgid "IP {0} ({1}) not in network {2} ({3}) with netmask {4} ({5})"
msgstr ""
#: tiramisu/option.py:835
#: tiramisu/option.py:823
msgid "invalid IP {0} ({1}) not in network {2} ({3}) with netmask {4} ({5})"
msgstr ""
#: tiramisu/option.py:864
msgid "inconsistency in allowed range"
msgstr ""
#: tiramisu/option.py:840
#: tiramisu/option.py:869
msgid "max value is empty"
msgstr ""
#: tiramisu/option.py:857
#: tiramisu/option.py:886
msgid "invalid port, range must have two values only"
msgstr ""
#: tiramisu/option.py:860
#: tiramisu/option.py:889
msgid "invalid port, first port in range must be smaller than the second one"
msgstr ""
#: tiramisu/option.py:869
#: tiramisu/option.py:898
msgid "invalid port"
msgstr ""
#: tiramisu/option.py:871
#: tiramisu/option.py:900
msgid "invalid port, must be an between {0} and {1}"
msgstr ""
#: tiramisu/option.py:885
#: tiramisu/option.py:914
msgid "invalid network address"
msgstr ""
#: tiramisu/option.py:890
msgid "invalid network address, must not be in reserved class"
#: tiramisu/option.py:920
msgid "network address shouldn't be in reserved class"
msgstr ""
#: tiramisu/option.py:902
#: tiramisu/option.py:922
msgid "invalid network address, mustn't be in reserved class"
msgstr ""
#: tiramisu/option.py:935
msgid "invalid netmask address"
msgstr ""
#: tiramisu/option.py:918
#: tiramisu/option.py:952
msgid "invalid len for opts"
msgstr ""
#: tiramisu/option.py:932
#: tiramisu/option.py:966
msgid "invalid IP {0} ({1}) with netmask {2}, this IP is a network"
msgstr ""
#: tiramisu/option.py:937
#: tiramisu/option.py:971
msgid "invalid network {0} ({1}) with netmask {2}"
msgstr ""
#: tiramisu/option.py:951
#: tiramisu/option.py:985
msgid "invalid broadcast address"
msgstr ""
#: tiramisu/option.py:960
#: tiramisu/option.py:994
msgid "invalid broadcast {0} ({1}) with network {2} ({3}) and netmask {4} ({5})"
msgstr ""
#: tiramisu/option.py:982
#: tiramisu/option.py:1016
msgid "unknown type_ {0} for hostname"
msgstr ""
#: tiramisu/option.py:985
#: tiramisu/option.py:1019
msgid "allow_ip must be a boolean"
msgstr ""
#: tiramisu/option.py:987
#: tiramisu/option.py:1021
msgid "allow_without_dot must be a boolean"
msgstr ""
#: tiramisu/option.py:1031
#: tiramisu/option.py:1065
msgid "invalid domainname, must have dot"
msgstr ""
#: tiramisu/option.py:1033
#: tiramisu/option.py:1067
msgid "invalid domainname's length (max 255)"
msgstr ""
#: tiramisu/option.py:1035
#: tiramisu/option.py:1069
msgid "invalid domainname's length (min 2)"
msgstr ""
#: tiramisu/option.py:1037
#: tiramisu/option.py:1071
msgid "invalid domainname"
msgstr ""
#: tiramisu/option.py:1050
msgid "invalid email address, should contains one @"
#: tiramisu/option.py:1084
msgid "invalid email address, must contains one @"
msgstr ""
#: tiramisu/option.py:1053
#: tiramisu/option.py:1087
msgid "invalid username in email address"
msgstr ""
#: tiramisu/option.py:1066
msgid "invalid url, should start with http:// or https://"
#: tiramisu/option.py:1100
msgid "invalid url, must start with http:// or https://"
msgstr ""
#: tiramisu/option.py:1085
#: tiramisu/option.py:1119
msgid "invalid url, port must be an between 0 and 65536"
msgstr ""
#: tiramisu/option.py:1091
msgid "invalid url, should ends with filename"
#: tiramisu/option.py:1125
msgid "invalid url, must ends with filename"
msgstr ""
#: tiramisu/option.py:1103
#: tiramisu/option.py:1137
msgid "invalid username"
msgstr ""
#: tiramisu/option.py:1114
#: tiramisu/option.py:1148
msgid "invalid filename"
msgstr ""
#: tiramisu/option.py:1141
#: tiramisu/option.py:1175
msgid "duplicate option name: {0}"
msgstr ""
#: tiramisu/option.py:1159
#: tiramisu/option.py:1193
msgid "unknown Option {0} in OptionDescription {1}"
msgstr ""
#: tiramisu/option.py:1210
#: tiramisu/option.py:1244
msgid "duplicate option: {0}"
msgstr ""
#: tiramisu/option.py:1240
#: tiramisu/option.py:1275
msgid "consistency with option {0} which is not in Config"
msgstr ""
#: tiramisu/option.py:1248
#: tiramisu/option.py:1283
msgid "no option for path {0}"
msgstr ""
#: tiramisu/option.py:1254
#: tiramisu/option.py:1289
msgid "no option {0} found"
msgstr ""
#: tiramisu/option.py:1264
#: tiramisu/option.py:1299
msgid "cannot change group_type if already set (old {0}, new {1})"
msgstr ""
#: tiramisu/option.py:1276
#: tiramisu/option.py:1311
msgid "master group {0} shall not have a subgroup"
msgstr ""
#: tiramisu/option.py:1279
#: tiramisu/option.py:1314
msgid "master group {0} shall not have a symlinkoption"
msgstr ""
#: tiramisu/option.py:1282
#: tiramisu/option.py:1317
msgid "not allowed option {0} in group {1}: this option is not a multi"
msgstr ""
#: tiramisu/option.py:1292
#: tiramisu/option.py:1327
msgid "master group with wrong master name for {0}"
msgstr ""
#: tiramisu/option.py:1300
#: tiramisu/option.py:1335
msgid "callback of master's option shall not refered a slave's ones"
msgstr ""
#: tiramisu/option.py:1308
#: tiramisu/option.py:1343
msgid "group_type: {0} not allowed"
msgstr ""
#: tiramisu/option.py:1397
#: tiramisu/option.py:1443
msgid "malformed requirements type for option: {0}, must be a dict"
msgstr ""
#: tiramisu/option.py:1414
#: tiramisu/option.py:1460
msgid "malformed requirements for option: {0} require must have option, expected and action keys"
msgstr ""
#: tiramisu/option.py:1419
#: tiramisu/option.py:1465
msgid "malformed requirements for option: {0} inverse must be boolean"
msgstr ""
#: tiramisu/option.py:1423
#: tiramisu/option.py:1469
msgid "malformed requirements for option: {0} transitive must be boolean"
msgstr ""
#: tiramisu/option.py:1427
#: tiramisu/option.py:1473
msgid "malformed requirements for option: {0} same_action must be boolean"
msgstr ""
#: tiramisu/option.py:1431
#: tiramisu/option.py:1477
msgid "malformed requirements must be an option in option {0}"
msgstr ""
#: tiramisu/option.py:1434
msgid "malformed requirements option {0} should not be a multi"
msgstr ""
#: tiramisu/option.py:1440
msgid "malformed requirements second argument must be valid for option {0}: {1}"
msgstr ""
#: tiramisu/option.py:1445
msgid "inconsistency in action types for option: {0} action: {1}"
msgstr ""
#: tiramisu/option.py:1470
msgid "{0} should be a function"
msgstr ""
#: tiramisu/option.py:1473
msgid "{0}_params should be a dict"
msgstr ""
#: tiramisu/option.py:1476
msgid "{0}_params with key {1} should not have length different to 1"
msgstr ""
#: tiramisu/option.py:1480
msgid "{0}_params should be tuple for key \"{1}\""
msgid "malformed requirements option {0} must not be a multi"
msgstr ""
#: tiramisu/option.py:1486
msgid "malformed requirements second argument must be valid for option {0}: {1}"
msgstr ""
#: tiramisu/option.py:1491
msgid "inconsistency in action types for option: {0} action: {1}"
msgstr ""
#: tiramisu/option.py:1516
msgid "{0} must be a function"
msgstr ""
#: tiramisu/option.py:1519
msgid "{0}_params must be a dict"
msgstr ""
#: tiramisu/option.py:1522
msgid "{0}_params with key {1} mustn't have length different to 1"
msgstr ""
#: tiramisu/option.py:1526
msgid "{0}_params must be tuple for key \"{1}\""
msgstr ""
#: tiramisu/option.py:1532
msgid "validator not support tuple"
msgstr ""
#: tiramisu/option.py:1489
msgid "{0}_params should have an option not a {0} for first argument"
#: tiramisu/option.py:1535
msgid "{0}_params must have an option not a {0} for first argument"
msgstr ""
#: tiramisu/option.py:1493
msgid "{0}_params should have a boolean not a {0} for second argument"
#: tiramisu/option.py:1539
msgid "{0}_params must have a boolean not a {0} for second argument"
msgstr ""
#: tiramisu/setting.py:116