add gettext support

This commit is contained in:
Emmanuel Garette 2013-04-13 23:09:05 +02:00
parent 9c2dcc164c
commit 9644dd3661
4 changed files with 111 additions and 102 deletions

View File

@ -26,6 +26,7 @@ from tiramisu.error import (PropertiesOptionError, NotFoundError,
from tiramisu.option import OptionDescription, Option, SymLinkOption
from tiramisu.setting import groups, Setting, apply_requires
from tiramisu.value import Values
from tiramisu.i18n import _
class SubConfig(object):
@ -85,7 +86,7 @@ class SubConfig(object):
"validation for the setattr and the getattr"
if not isinstance(opt_or_descr, Option) and \
not isinstance(opt_or_descr, OptionDescription):
raise TypeError('Unexpected object: {0}'.format(repr(opt_or_descr)))
raise TypeError(_('Unexpected object: {0}').format(repr(opt_or_descr)))
properties = set(self.cfgimpl_get_settings().get_properties(opt_or_descr))
#remove this properties, those properties are validate in value/setting
properties = properties - set(['mandatory', 'frozen'])
@ -96,9 +97,9 @@ class SubConfig(object):
properties = properties - set(self.cfgimpl_get_settings().get_permissive(opt_or_descr))
properties = list(properties)
if properties != []:
raise PropertiesOptionError("trying to access"
raise PropertiesOptionError(_("trying to access"
" to an option named: {0} with properties"
" {1}".format(name, str(properties)),
" {1}").format(name, str(properties)),
properties)
def __getattr__(self, name):
@ -131,10 +132,10 @@ class SubConfig(object):
if isinstance(opt_or_descr, OptionDescription):
children = self.cfgimpl_get_description()._children
if opt_or_descr not in children[1]:
raise AttributeError("{0} with name {1} object has "
"no attribute {2}".format(self.__class__,
opt_or_descr._name,
name))
raise AttributeError(_("{0} with name {1} object has "
"no attribute {2}").format(self.__class__,
opt_or_descr._name,
name))
return SubConfig(opt_or_descr, self._cfgimpl_context)
# special attributes
if name.startswith('_cfgimpl_'):
@ -153,16 +154,16 @@ class SubConfig(object):
apply_requires(child, self)
#needed to ?
if child not in self._cfgimpl_descr._children[1]:
raise AttributeError('unknown option %s' % (name))
raise AttributeError(_('unknown option {}').format(name))
if setting.has_property('everything_frozen'):
raise TypeError("cannot set a value to the option {} if the whole "
"config has been frozen".format(name))
raise TypeError(_("cannot set a value to the option {} if the whole "
"config has been frozen").format(name))
if setting.has_property('frozen') and setting.has_property('frozen',
child, is_apply_req=False):
raise TypeError('cannot change the value to %s for '
'option %s this option is frozen' % (str(value), name))
raise TypeError(_('cannot change the value to {} for '
'option {} this option is frozen').format(str(value), name))
self.cfgimpl_get_values()[child] = value
def cfgimpl_get_home_by_path(self, path, force_permissive=False, force_properties=None):
@ -226,7 +227,7 @@ class SubConfig(object):
"""
if group_type is not None:
if not isinstance(group_type, groups.GroupType):
raise TypeError("Unknown group_type: {0}".format(group_type))
raise TypeError(_("Unknown group_type: {0}").format(group_type))
for child in self._cfgimpl_descr._children[1]:
if isinstance(child, OptionDescription):
try:
@ -320,7 +321,7 @@ class SubConfig(object):
if _currpath is None:
_currpath = []
if withoption is None and withvalue is not None:
raise ValueError("make_dict can't filtering with value without option")
raise ValueError(_("make_dict can't filtering with value without option"))
if withoption is not None:
mypath = self.getpath()
for path in self.cfgimpl_get_context()._find(bytype=Option,
@ -339,8 +340,8 @@ class SubConfig(object):
else:
tmypath = mypath + '.'
if not path.startswith(tmypath):
raise Exception('unexpected path {}, '
'should start with {}'.format(path, mypath))
raise Exception(_('unexpected path {}, '
'should start with {}').format(path, mypath))
path = path[len(tmypath):]
self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten)
#withoption can be set to None below !
@ -428,11 +429,11 @@ class Config(SubConfig):
homeconfig.setoption(name, child, value)
elif len(candidates) > 1:
raise AmbigousOptionError(
'more than one option that ends with %s' % (key, ))
_('more than one option that ends with {}').format(key))
else:
raise NoMatchingOptionFound(
'there is no option that matches %s'
' or the option is hidden or disabled' % (key, ))
_('there is no option that matches {}'
' or the option is hidden or disabled').format(key))
def getpath(self):
return None
@ -483,7 +484,7 @@ class Config(SubConfig):
# return False
# return False
if type_ not in ('option', 'path', 'value'):
raise ValueError('unknown type_ type {} for _find'.format(type_))
raise ValueError(_('unknown type_ type {} for _find').format(type_))
find_results = []
opts, paths = self.cfgimpl_get_description()._cache_paths
for index in range(0, len(paths)):
@ -517,7 +518,7 @@ class Config(SubConfig):
else:
find_results.append(retval)
if find_results == []:
raise NotFoundError("no option found in config with these criteria")
raise NotFoundError(_("no option found in config with these criteria"))
else:
return find_results

6
tiramisu/i18n.py Normal file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import gettext
gettext.translation('tiramisu', fallback=True)
_ = gettext.gettext

View File

@ -28,6 +28,7 @@ from IPy import IP
from tiramisu.error import (ConfigError, NotFoundError, ConflictConfigError,
RequiresError, ValidateError)
from tiramisu.setting import groups, multitypes
from tiramisu.i18n import _
name_regexp = re.compile(r'^\d+')
@ -36,7 +37,7 @@ def valid_name(name):
try:
name = str(name)
except:
raise ValueError("not a valid string name")
raise ValueError(_('not a valid string name'))
if re.match(name_regexp, name) is None:
return True
else:
@ -67,7 +68,7 @@ class BaseInformation(object):
elif default is not None:
return default
else:
raise ValueError("Information's item not found: {0}".format(key))
raise ValueError(_("Information's item not found: {0}").format(key))
class Option(BaseInformation):
@ -103,7 +104,7 @@ class Option(BaseInformation):
:param validator_args: the validator's parameters
"""
if not valid_name(name):
raise NameError("invalid name: {0} for option".format(name))
raise NameError(_("invalid name: {0} for option").format(name))
self._name = name
self._informations = {}
self.set_information('doc', doc)
@ -113,24 +114,24 @@ class Option(BaseInformation):
self._consistency = None
if validator is not None:
if type(validator) != FunctionType:
raise TypeError("validator must be a function")
raise TypeError(_("validator must be a function"))
if validator_args is None:
validator_args = {}
self._validator = (validator, validator_args)
else:
self._validator = None
if not self._multi and default_multi is not None:
raise ConfigError("a default_multi is set whereas multi is False"
" in option: {0}".format(name))
raise ConfigError(_("a default_multi is set whereas multi is False"
" in option: {0}").format(name))
if default_multi is not None and not self._validate(default_multi):
raise ConfigError("invalid default_multi value {0} "
"for option {1}".format(str(default_multi), name))
raise ConfigError(_("invalid default_multi value {0} "
"for option {1}").format(str(default_multi), name))
if callback is not None and (default is not None or default_multi is not None):
raise ConfigError("defaut values not allowed if option: {0} "
"is calculated".format(name))
raise ConfigError(_("defaut values not allowed if option: {0} "
"is calculated").format(name))
if callback is None and callback_params is not None:
raise ConfigError("params defined for a callback function but "
"no callback defined yet for option {0}".format(name))
raise ConfigError(_("params defined for a callback function but "
"no callback defined yet for option {0}").format(name))
if callback is not None:
self._callback = (callback, callback_params)
else:
@ -143,21 +144,21 @@ class Option(BaseInformation):
# "for option {1} : not list type"
# "".format(str(default), name))
if not self.validate(default):
raise ValidateError("invalid default value {0} "
raise ValidateError(_("invalid default value {0} "
"for option {1}"
"".format(str(default), name))
"").format(str(default), name))
self._multitype = multitypes.default
self._default_multi = default_multi
else:
if default is not None and not self.validate(default):
raise ValidateError("invalid default value {0} "
"for option {1}".format(str(default), name))
raise ValidateError(_("invalid default value {0} "
"for option {1}").format(str(default), name))
self._default = default
if properties is None:
properties = ()
if not isinstance(properties, tuple):
raise ConfigError('invalid properties type {0} for {1},'
' must be a tuple'.format(type(properties), self._name))
raise ConfigError(_('invalid properties type {0} for {1},'
' must be a tuple').format(type(properties), self._name))
self._properties = properties # 'hidden', 'disabled'...
def validate(self, value, context=None, validate=True):
@ -183,9 +184,9 @@ class Option(BaseInformation):
return cons.valid_consistency(self, value, context, None)
else:
if not isinstance(value, list):
raise ValidateError("invalid value {0} "
raise ValidateError(_("invalid value {0} "
"for option {1} which must be a list"
"".format(value, self._name))
"").format(value, self._name))
for index in range(0, len(value)):
val = value[index]
# None allows the reset of the value
@ -268,11 +269,11 @@ class ChoiceOption(Option):
callback_params=None, open_values=False, validator=None,
validator_args=None, properties=()):
if not isinstance(values, tuple):
raise ConfigError('values must be a tuple for {0}'.format(name))
raise ConfigError(_('values must be a tuple for {0}').format(name))
self._values = values
if open_values not in (True, False):
raise ConfigError('Open_values must be a boolean for '
'{0}'.format(name))
raise ConfigError(_('open_values must be a boolean for '
'{0}').format(name))
self._open_values = open_values
super(ChoiceOption, self).__init__(name, doc, default=default,
default_multi=default_multi,
@ -394,7 +395,7 @@ class NetmaskOption(Option):
properties=None, opt_ip=None):
if opt_ip is not None and not isinstance(opt_ip, IPOption) and \
not isinstance(opt_ip, NetworkOption):
raise ValueError('opt_ip must be a IPOption not {}'.format(type(opt_ip)))
raise ValueError(_('opt_ip must be a IPOption not {}').format(type(opt_ip)))
super(NetmaskOption, self).__init__(name, doc, default=default,
default_multi=default_multi,
callback=callback,
@ -411,7 +412,7 @@ class NetmaskOption(Option):
elif isinstance(opt_ip, NetworkOption):
self._consistency = ('cons_network_netmask', (self, opt_ip))
else:
raise ValueError('unknown type for opt_ip')
raise ValueError(_('unknown type for opt_ip'))
def _validate(self, value):
try:
@ -465,7 +466,7 @@ class OptionDescription(BaseInformation):
``OptionDescription`` instances for nested namespaces).
"""
if not valid_name(name):
raise NameError("invalid name: {0} for option descr".format(name))
raise NameError(_("invalid name: {0} for option descr").format(name))
self._name = name
self._informations = {}
self.set_information('doc', doc)
@ -476,8 +477,8 @@ class OptionDescription(BaseInformation):
old = None
for child in valid_child:
if child == old:
raise ConflictConfigError('duplicate option name: '
'{0}'.format(child))
raise ConflictConfigError(_('duplicate option name: '
'{0}').format(child))
old = child
self._children = (tuple(child_names), tuple(children))
validate_requires_arg(requires, self._name)
@ -485,8 +486,8 @@ class OptionDescription(BaseInformation):
self._cache_paths = None
self._consistencies = None
if not isinstance(properties, tuple):
raise ConfigError('invalid properties type {0} for {1},'
' must be a tuple'.format(type(properties), self._name))
raise ConfigError(_('invalid properties type {0} for {1},'
' must be a tuple').format(type(properties), self._name))
self._properties = properties # 'hidden', 'disabled'...
# the group_type is useful for filtering OptionDescriptions in a config
self._group_type = groups.default
@ -498,8 +499,8 @@ class OptionDescription(BaseInformation):
try:
return self._children[1][self._children[0].index(name)]
except ValueError:
raise AttributeError('unknown Option {} in OptionDescription {}'
''.format(name, self._name))
raise AttributeError(_('unknown Option {} in OptionDescription {}'
'').format(name, self._name))
def getkey(self, config):
return tuple([child.getkey(getattr(config, child._name))
@ -550,7 +551,7 @@ class OptionDescription(BaseInformation):
func, opts = option._consistency
for opt in opts:
if opt in _consistencies:
raise ValueError('opt {} already in consistency'.format(opt._name))
raise ValueError(_('opt {} already in consistency').format(opt._name))
_consistencies[opt] = (func, opts)
else:
_currpath.append(attr)
@ -563,8 +564,8 @@ class OptionDescription(BaseInformation):
old = None
for child in valid_child:
if child == old:
raise ConflictConfigError('duplicate option: '
'{0}'.format(child))
raise ConflictConfigError(_('duplicate option: '
'{0}').format(child))
old = child
self._cache_paths = (tuple(cache_option), tuple(cache_path))
self._consistencies = _consistencies
@ -573,13 +574,13 @@ class OptionDescription(BaseInformation):
try:
return self._cache_paths[0][self._cache_paths[1].index(path)]
except ValueError:
raise NotFoundError('no option for path {}'.format(path))
raise NotFoundError(_('no option for path {}').format(path))
def get_path_by_opt(self, opt):
try:
return self._cache_paths[1][self._cache_paths[0].index(opt)]
except ValueError:
raise NotFoundError('no option {} found'.format(opt))
raise NotFoundError(_('no option {} found').format(opt))
# ____________________________________________________________
def set_group_type(self, group_type):
@ -589,8 +590,8 @@ class OptionDescription(BaseInformation):
that lives in `setting.groups`
"""
if self._group_type != groups.default:
ConfigError('cannot change group_type if already set '
'(old {}, new {})'.format(self._group_type, group_type))
ConfigError(_('cannot change group_type if already set '
'(old {}, new {})').format(self._group_type, group_type))
if isinstance(group_type, groups.GroupType):
self._group_type = group_type
if isinstance(group_type, groups.MasterGroupType):
@ -601,12 +602,12 @@ class OptionDescription(BaseInformation):
master = None
for child in self._children[1]:
if isinstance(child, OptionDescription):
raise ConfigError("master group {} shall not have "
"a subgroup".format(self._name))
raise ConfigError(_("master group {} shall not have "
"a subgroup").format(self._name))
if not child.is_multi():
raise ConfigError("not allowed option {0} in group {1}"
raise ConfigError(_("not allowed option {0} in group {1}"
": this option is not a multi"
"".format(child._name, self._name))
"").format(child._name, self._name))
if child._name == self._name:
identical_master_child_name = True
child._multitype = multitypes.master
@ -614,18 +615,18 @@ class OptionDescription(BaseInformation):
else:
slaves.append(child)
if master is None:
raise ConfigError('master group with wrong master name for {}'
''.format(self._name))
raise ConfigError(_('master group with wrong master name for {}'
'').format(self._name))
master._master_slaves = tuple(slaves)
for child in self._children[1]:
if child != master:
child._master_slaves = master
child._multitype = multitypes.slave
if not identical_master_child_name:
raise ConfigError("the master group: {} has not any "
"master child".format(self._name))
raise ConfigError(_("the master group: {} has not any "
"master child").format(self._name))
else:
raise ConfigError('not allowed group_type : {0}'.format(group_type))
raise ConfigError(_('not allowed group_type : {0}').format(group_type))
def get_group_type(self):
return self._group_type
@ -644,8 +645,8 @@ def validate_requires_arg(requires, name):
config_action = {}
for req in requires:
if not type(req) == tuple:
raise RequiresError("malformed requirements type for option:"
" {0}, must be a tuple".format(name))
raise RequiresError(_("malformed requirements type for option:"
" {0}, must be a tuple").format(name))
if len(req) == 3:
action = req[2]
inverse = False
@ -653,11 +654,11 @@ def validate_requires_arg(requires, name):
action = req[2]
inverse = req[3]
else:
raise RequiresError("malformed requirements for option: {0}"
" invalid len".format(name))
raise RequiresError(_("malformed requirements for option: {0}"
" invalid len").format(name))
if action in config_action:
if inverse != config_action[action]:
raise RequiresError("inconsistency in action types for option: {0}"
" action: {1}".format(name, action))
raise RequiresError(_("inconsistency in action types for option: {0}"
" action: {1}").format(name, action))
else:
config_action[action] = inverse

View File

@ -21,6 +21,7 @@ from tiramisu.error import MandatoryError, MultiTypeError, \
ConfigError, ValidateError
from tiramisu.setting import owners, multitypes
from tiramisu.autolib import carry_out_calculation
from tiramisu.i18n import _
class Values(object):
@ -49,8 +50,8 @@ class Values(object):
mastervalue = getattr(self.context, masterpath)
masterlen = len(mastervalue)
if len(value) > masterlen:
raise MultiTypeError("invalid len for the slave: {0}"
" which has {1} as master".format(
raise MultiTypeError(_("invalid len for the slave: {0}"
" which has {1} as master").format(
opt._name, masterpath))
if len(value) < masterlen:
for num in range(0, masterlen - len(value)):
@ -85,18 +86,18 @@ class Values(object):
setting.has_property('mandatory'))
if setting.has_property('mandatory', opt, False) and set_mandatory:
if self._is_empty(opt, value) and opt.is_empty_by_default():
raise MandatoryError("option: {0} is mandatory "
"and shall have a value".format(opt._name))
raise MandatoryError(_("option: {0} is mandatory "
"and shall have a value").format(opt._name))
#empty value
if opt.is_multi():
for val in value:
if val == '':
raise MandatoryError("option: {0} is mandatory "
"and shall have not empty value".format(opt._name))
raise MandatoryError(_("option: {0} is mandatory "
"and shall have not empty value").format(opt._name))
else:
if value == '':
raise MandatoryError("option: {0} is mandatory "
"and shall have not empty value".format(opt._name))
raise MandatoryError(_("option: {0} is mandatory "
"and shall have not empty value").format(opt._name))
def fill_multi(self, opt, result):
"""fills a multi option with default and calculated values
@ -144,23 +145,23 @@ class Values(object):
value = self.fill_multi(opt, value)
self._test_mandatory(opt, value, force_properties)
if validate and not opt.validate(value, self.context, setting.has_property('validator')):
raise ValidateError('invalid calculated value returned'
' for option {0}: {1}'.format(opt._name, value))
raise ValidateError(_('invalid calculated value returned'
' for option {0}: {1}').format(opt._name, value))
return value
def __setitem__(self, opt, value):
if not opt.validate(value, self.context,
self.context.cfgimpl_get_settings().has_property('validator')):
raise ValidateError('invalid value {}'
' for option {}'.format(value, opt._name))
raise ValidateError(_('invalid value {}'
' for option {}').format(value, opt._name))
if opt.is_multi():
if opt.get_multitype() == multitypes.master:
masterlen = len(value)
for slave in opt.master_slaves:
value_slave = self._get_value(slave)
if len(value_slave) > masterlen:
raise MultiTypeError("invalid len for the slave: {0}"
" which has {1} as master".format(
raise MultiTypeError(_("invalid len for the slave: {0}"
" which has {1} as master").format(
slave._name, opt._name))
elif len(value_slave) < masterlen:
for num in range(0, masterlen - len(value_slave)):
@ -168,8 +169,8 @@ class Values(object):
elif opt.get_multitype() == multitypes.slave:
if len(self._get_value(opt.master_slaves)) != len(value):
raise MultiTypeError("invalid len for the slave: {0}"
" which has {1} as master".format(
raise MultiTypeError(_("invalid len for the slave: {0}"
" which has {1} as master").format(
opt._name, opt.master_slaves._name))
if not isinstance(value, Multi):
value = Multi(value, self.context, opt)
@ -177,8 +178,8 @@ class Values(object):
def setitem(self, opt, value):
if type(value) == list:
raise MultiTypeError("the type of the value {0} which is multi shall "
"be Multi and not list".format(str(value)))
raise MultiTypeError(_("the type of the value {0} which is multi shall "
"be Multi and not list").format(str(value)))
self._test_mandatory(opt, value)
self.values[opt] = (self.context.cfgimpl_get_settings().getowner(), value)
@ -190,9 +191,9 @@ class Values(object):
def setowner(self, opt, owner):
if opt not in self.values:
raise ConfigError('no value for {} cannot change owner to {}'.format(opt))
raise ConfigError(_('no value for {1} cannot change owner to {2}').format(opt))
if not isinstance(owner, owners.Owner):
raise TypeError("invalid generic owner {0}".format(str(owner)))
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
self.values[opt] = (owner, self.values[opt][1])
def is_default_owner(self, opt):
@ -233,8 +234,8 @@ class Multi(list):
"""
if not force:
if self.opt.get_multitype() == multitypes.slave:
raise MultiTypeError("cannot append a value on a multi option {0}"
" which is a slave".format(self.opt._name))
raise MultiTypeError(_("cannot append a value on a multi option {0}"
" which is a slave").format(self.opt._name))
elif self.opt.get_multitype() == multitypes.master:
for slave in self.opt.get_master_slaves():
self.context.cfgimpl_get_values()[slave].append(slave.getdefault_multi(), force=True)
@ -244,9 +245,9 @@ class Multi(list):
def _validate(self, value):
if value is not None and not self.opt._validate(value):
raise ConfigError("invalid value {0} "
"for option {1}".format(str(value),
self.opt._name))
raise ConfigError(_("invalid value {0} "
"for option {1}").format(str(value),
self.opt._name))
def pop(self, key, force=False):
"""the list value can be updated (poped)
@ -257,8 +258,8 @@ class Multi(list):
"""
if not force:
if self.opt.multitype == multitypes.slave:
raise MultiTypeError("cannot append a value on a multi option {0}"
" which is a slave".format(self.opt._name))
raise MultiTypeError(_("cannot append a value on a multi option {0}"
" which is a slave").format(self.opt._name))
elif self.opt.multitype == multitypes.master:
for slave in self.opt.get_master_slaves():
self.context.cfgimpl_get_values()[slave].pop(key, force=True)