i18n-ize colander.
This commit is contained in:
@@ -3,10 +3,20 @@ import itertools
|
|||||||
import iso8601
|
import iso8601
|
||||||
import pprint
|
import pprint
|
||||||
import re
|
import re
|
||||||
|
import translationstring
|
||||||
|
|
||||||
|
_ = translationstring.TranslationStringFactory('colander')
|
||||||
|
|
||||||
class _missing(object):
|
class _missing(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def interpolate(msgs):
|
||||||
|
for s in msgs:
|
||||||
|
if hasattr(s, 'interpolate'):
|
||||||
|
yield s.interpolate()
|
||||||
|
else:
|
||||||
|
yield s
|
||||||
|
|
||||||
class Invalid(Exception):
|
class Invalid(Exception):
|
||||||
"""
|
"""
|
||||||
An exception raised by data types and validators indicating that
|
An exception raised by data types and validators indicating that
|
||||||
@@ -113,7 +123,7 @@ class Invalid(Exception):
|
|||||||
exc.msg and msgs.append(exc.msg)
|
exc.msg and msgs.append(exc.msg)
|
||||||
keyname = exc._keyname()
|
keyname = exc._keyname()
|
||||||
keyname and keyparts.append(keyname)
|
keyname and keyparts.append(keyname)
|
||||||
errors['.'.join(keyparts)] = '; '.join(msgs)
|
errors['.'.join(keyparts)] = '; '.join(interpolate(msgs))
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@@ -164,7 +174,7 @@ class Function(object):
|
|||||||
The default value for the ``message`` when not provided via the
|
The default value for the ``message`` when not provided via the
|
||||||
constructor is ``Invalid value``.
|
constructor is ``Invalid value``.
|
||||||
"""
|
"""
|
||||||
def __init__(self, function, message='Invalid value'):
|
def __init__(self, function, message=_('Invalid value')):
|
||||||
self.function = function
|
self.function = function
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
@@ -189,7 +199,7 @@ class Regex(object):
|
|||||||
def __init__(self, regex, msg=None):
|
def __init__(self, regex, msg=None):
|
||||||
self.match_object = re.compile(regex)
|
self.match_object = re.compile(regex)
|
||||||
if msg is None:
|
if msg is None:
|
||||||
self.msg = "String does not match expected pattern"
|
self.msg = _("String does not match expected pattern")
|
||||||
else:
|
else:
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
|
|
||||||
@@ -204,7 +214,7 @@ class Email(Regex):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, msg=None):
|
def __init__(self, msg=None):
|
||||||
if msg is None:
|
if msg is None:
|
||||||
msg = "Invalid email address"
|
msg = _("Invalid email address")
|
||||||
super(Email, self).__init__(
|
super(Email, self).__init__(
|
||||||
u'(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$', msg=msg)
|
u'(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$', msg=msg)
|
||||||
|
|
||||||
@@ -219,23 +229,22 @@ class Range(object):
|
|||||||
:exc:`colander.Invalid` error when reporting a validation failure
|
:exc:`colander.Invalid` error when reporting a validation failure
|
||||||
caused by a value not meeting the minimum. If ``min_err`` is
|
caused by a value not meeting the minimum. If ``min_err`` is
|
||||||
specified, it must be a string. The string may contain the
|
specified, it must be a string. The string may contain the
|
||||||
replacement targets ``%(min)s`` and ``%(val)s``, representing the
|
replacement targets ``${min}`` and ``${val}``, representing the
|
||||||
minimum value and the provided value respectively. If it is not
|
minimum value and the provided value respectively. If it is not
|
||||||
provided, it defaults to ``'%(val)s is less than minimum value
|
provided, it defaults to ``'${val} is less than minimum value
|
||||||
%(min)s'``.
|
${min}'``.
|
||||||
|
|
||||||
``max_err`` is used to form the ``msg`` of the
|
``max_err`` is used to form the ``msg`` of the
|
||||||
:exc:`colander.Invalid` error when reporting a validation failure
|
:exc:`colander.Invalid` error when reporting a validation failure
|
||||||
caused by a value exceeding the maximum. If ``max_err`` is
|
caused by a value exceeding the maximum. If ``max_err`` is
|
||||||
specified, it must be a string. The string may contain the
|
specified, it must be a string. The string may contain the
|
||||||
replacement targets ``%(max)s`` and ``%(val)s``, representing the
|
replacement targets ``${max}`` and ``${val}``, representing the
|
||||||
maximum value and the provided value respectively. If it is not
|
maximum value and the provided value respectively. If it is not
|
||||||
provided, it defaults to ``'%(val)s is greater than maximum value
|
provided, it defaults to ``'${val} is greater than maximum value
|
||||||
%(max)s'``.
|
${max}'``.
|
||||||
"""
|
"""
|
||||||
|
min_err = _('${val} is less than minimum value ${min}')
|
||||||
min_err = '%(val)s is less than minimum value %(min)s'
|
max_err = _('${val} is greater than maximum value ${max}')
|
||||||
max_err = '%(val)s is greater than maximum value %(max)s'
|
|
||||||
|
|
||||||
def __init__(self, min=None, max=None, min_err=None, max_err=None):
|
def __init__(self, min=None, max=None, min_err=None, max_err=None):
|
||||||
self.min = min
|
self.min = min
|
||||||
@@ -248,11 +257,13 @@ class Range(object):
|
|||||||
def __call__(self, node, value):
|
def __call__(self, node, value):
|
||||||
if self.min is not None:
|
if self.min is not None:
|
||||||
if value < self.min:
|
if value < self.min:
|
||||||
raise Invalid(node,self.min_err % {'val':value, 'min':self.min})
|
min_err = _(self.min_err, mapping={'val':value, 'min':self.min})
|
||||||
|
raise Invalid(node, min_err)
|
||||||
|
|
||||||
if self.max is not None:
|
if self.max is not None:
|
||||||
if value > self.max:
|
if value > self.max:
|
||||||
raise Invalid(node,self.max_err % {'val':value, 'max':self.max})
|
max_err = _(self.max_err, mapping={'val':value, 'max':self.max})
|
||||||
|
raise Invalid(node, max_err)
|
||||||
|
|
||||||
class Length(object):
|
class Length(object):
|
||||||
""" Validator which succeeds if the value passed to it has a
|
""" Validator which succeeds if the value passed to it has a
|
||||||
@@ -265,26 +276,28 @@ class Length(object):
|
|||||||
def __call__(self, node, value):
|
def __call__(self, node, value):
|
||||||
if self.min is not None:
|
if self.min is not None:
|
||||||
if len(value) < self.min:
|
if len(value) < self.min:
|
||||||
raise Invalid(
|
min_err = _('Shorter than minimum length ${min}',
|
||||||
node,
|
mapping={'min':self.min})
|
||||||
'Shorter than minimum length %s' % self.min)
|
raise Invalid(node, min_err)
|
||||||
|
|
||||||
if self.max is not None:
|
if self.max is not None:
|
||||||
if len(value) > self.max:
|
if len(value) > self.max:
|
||||||
raise Invalid(
|
max_err = _('Longer than maximum length ${max}',
|
||||||
node,
|
mapping={'max':self.max})
|
||||||
'Longer than maximum length %s' % self.max)
|
raise Invalid(node, max_err)
|
||||||
|
|
||||||
class OneOf(object):
|
class OneOf(object):
|
||||||
""" Validator which succeeds if the value passed to it is one of
|
""" Validator which succeeds if the value passed to it is one of
|
||||||
a fixed set of values """
|
a fixed set of values """
|
||||||
def __init__(self, values):
|
def __init__(self, choices):
|
||||||
self.values = values
|
self.choices = choices
|
||||||
|
|
||||||
def __call__(self, node, value):
|
def __call__(self, node, value):
|
||||||
if not value in self.values:
|
if not value in self.choices:
|
||||||
raise Invalid(node, '"%s" is not one of %s' % (
|
choices = ', '.join(['%s' % x for x in self.choices])
|
||||||
value, ', '.join(['%s' % x for x in self.values])))
|
err = _('"${val}" is not one of ${choices}',
|
||||||
|
mapping={'val':value, 'choices':choices})
|
||||||
|
raise Invalid(node, err)
|
||||||
|
|
||||||
class Mapping(object):
|
class Mapping(object):
|
||||||
""" A type which represents a mapping of names to nodes.
|
""" A type which represents a mapping of names to nodes.
|
||||||
@@ -350,7 +363,10 @@ class Mapping(object):
|
|||||||
try:
|
try:
|
||||||
return dict(value)
|
return dict(value)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise Invalid(node, '%r is not a mapping type: %s' % (value, e))
|
raise Invalid(node,
|
||||||
|
_('"${val}" is not a mapping type: ${err}',
|
||||||
|
mapping = {'val':value, 'err':e})
|
||||||
|
)
|
||||||
|
|
||||||
def _impl(self, node, value, callback, default_callback, unknown=None,
|
def _impl(self, node, value, callback, default_callback, unknown=None,
|
||||||
partial=None):
|
partial=None):
|
||||||
@@ -375,7 +391,9 @@ class Mapping(object):
|
|||||||
if not partial:
|
if not partial:
|
||||||
raise Invalid(
|
raise Invalid(
|
||||||
subnode,
|
subnode,
|
||||||
'"%s" is required but missing' % subnode.name)
|
_('"${val}" is required but missing',
|
||||||
|
mapping={'val':subnode.name})
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
result[name] = default_callback(subnode)
|
result[name] = default_callback(subnode)
|
||||||
@@ -388,8 +406,11 @@ class Mapping(object):
|
|||||||
|
|
||||||
if unknown == 'raise':
|
if unknown == 'raise':
|
||||||
if value:
|
if value:
|
||||||
raise Invalid(node,
|
raise Invalid(
|
||||||
'Unrecognized keys in mapping: %r' % value)
|
node,
|
||||||
|
_('Unrecognized keys in mapping: "${val}"',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
|
|
||||||
elif unknown == 'preserve':
|
elif unknown == 'preserve':
|
||||||
result.update(value)
|
result.update(value)
|
||||||
@@ -435,15 +456,20 @@ class Tuple(Positional):
|
|||||||
"""
|
"""
|
||||||
def _validate(self, node, value):
|
def _validate(self, node, value):
|
||||||
if not hasattr(value, '__iter__'):
|
if not hasattr(value, '__iter__'):
|
||||||
raise Invalid(node, '%r is not iterable' % value)
|
raise Invalid(
|
||||||
|
node,
|
||||||
|
_('"${val}" is not iterable', mapping={'val':value})
|
||||||
|
)
|
||||||
|
|
||||||
valuelen, nodelen = len(value), len(node.children)
|
valuelen, nodelen = len(value), len(node.children)
|
||||||
|
|
||||||
if valuelen != nodelen:
|
if valuelen != nodelen:
|
||||||
raise Invalid(
|
raise Invalid(
|
||||||
node,
|
node,
|
||||||
('%s has an incorrect number of elements '
|
_('"${val}" has an incorrect number of elements '
|
||||||
'(expected %s, was %s)' % (value, nodelen, valuelen)))
|
'(expected ${exp}, was ${was})',
|
||||||
|
mapping={'val':value, 'exp':nodelen, 'was':valuelen})
|
||||||
|
)
|
||||||
|
|
||||||
return list(value)
|
return list(value)
|
||||||
|
|
||||||
@@ -510,7 +536,9 @@ class Sequence(Positional):
|
|||||||
if accept_scalar:
|
if accept_scalar:
|
||||||
return [value]
|
return [value]
|
||||||
else:
|
else:
|
||||||
raise Invalid(node, '%r is not iterable' % value)
|
raise Invalid(node, _('"${val}" is not iterable',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
|
|
||||||
def _impl(self, node, value, callback, accept_scalar):
|
def _impl(self, node, value, callback, accept_scalar):
|
||||||
if accept_scalar is None:
|
if accept_scalar is None:
|
||||||
@@ -612,10 +640,12 @@ class String(object):
|
|||||||
if not isinstance(value, unicode):
|
if not isinstance(value, unicode):
|
||||||
value = unicode(str(value), self.encoding)
|
value = unicode(str(value), self.encoding)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise Invalid(node, '%r is not a string: %s' % (value, e))
|
raise Invalid(node,
|
||||||
|
_('${val} is not a string: %{err}',
|
||||||
|
mapping={'val':value, 'err':e}))
|
||||||
if not value:
|
if not value:
|
||||||
if node.required:
|
if node.required:
|
||||||
raise Invalid(node, 'Required')
|
raise Invalid(node, _('Required'))
|
||||||
value = node.default
|
value = node.default
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@@ -629,7 +659,9 @@ class String(object):
|
|||||||
return result
|
return result
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise Invalid(node,
|
raise Invalid(node,
|
||||||
'%r cannot be serialized to str: %s' % (value, e))
|
_('"${val} cannot be serialized to str: ${err}',
|
||||||
|
mapping={'val':value, 'err':e})
|
||||||
|
)
|
||||||
|
|
||||||
Str = String
|
Str = String
|
||||||
|
|
||||||
@@ -645,15 +677,21 @@ class Integer(object):
|
|||||||
except Exception:
|
except Exception:
|
||||||
if value == '':
|
if value == '':
|
||||||
if node.required:
|
if node.required:
|
||||||
raise Invalid(node, 'Required')
|
raise Invalid(node, _('Required'))
|
||||||
return node.default
|
return node.default
|
||||||
raise Invalid(node, '"%s" is not a number' % value)
|
raise Invalid(node,
|
||||||
|
_('"${val}" is not a number',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
|
|
||||||
def serialize(self, node, value):
|
def serialize(self, node, value):
|
||||||
try:
|
try:
|
||||||
return str(int(value))
|
return str(int(value))
|
||||||
except Exception:
|
except Exception:
|
||||||
raise Invalid(node, '"%s" is not a number' % value)
|
raise Invalid(node,
|
||||||
|
_('"${val}" is not a number',
|
||||||
|
mapping={'val':value}),
|
||||||
|
)
|
||||||
|
|
||||||
Int = Integer
|
Int = Integer
|
||||||
|
|
||||||
@@ -669,15 +707,21 @@ class Float(object):
|
|||||||
except Exception:
|
except Exception:
|
||||||
if value == '':
|
if value == '':
|
||||||
if node.required:
|
if node.required:
|
||||||
raise Invalid(node, 'Required')
|
raise Invalid(node, _('Required'))
|
||||||
return node.default
|
return node.default
|
||||||
raise Invalid(node, '"%s" is not a number' % value)
|
raise Invalid(node,
|
||||||
|
_('"${val}" is not a number',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
|
|
||||||
def serialize(self, node, value):
|
def serialize(self, node, value):
|
||||||
try:
|
try:
|
||||||
return str(float(value))
|
return str(float(value))
|
||||||
except Exception:
|
except Exception:
|
||||||
raise Invalid(node, '"%s" is not a number' % value)
|
raise Invalid(node,
|
||||||
|
_('"${val}" is not a number',
|
||||||
|
mapping={'val':value}),
|
||||||
|
)
|
||||||
|
|
||||||
Int = Integer
|
Int = Integer
|
||||||
|
|
||||||
@@ -699,10 +743,12 @@ class Boolean(object):
|
|||||||
try:
|
try:
|
||||||
value = str(value)
|
value = str(value)
|
||||||
except:
|
except:
|
||||||
raise Invalid(node, '%r is not a string' % value)
|
raise Invalid(node,
|
||||||
|
_('${val} is not a string', mapping={'val':value})
|
||||||
|
)
|
||||||
if not value:
|
if not value:
|
||||||
if node.required:
|
if node.required:
|
||||||
raise Invalid(node, 'Required')
|
raise Invalid(node, _('Required'))
|
||||||
value = node.default
|
value = node.default
|
||||||
value = value.lower()
|
value = value.lower()
|
||||||
if value in ('false', '0'):
|
if value in ('false', '0'):
|
||||||
@@ -759,7 +805,9 @@ class GlobalObject(object):
|
|||||||
if not self.package:
|
if not self.package:
|
||||||
raise Invalid(
|
raise Invalid(
|
||||||
node,
|
node,
|
||||||
'relative name "%s" irresolveable without package' % value)
|
_('relative name "${val}" irresolveable without package',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
if value in ['.', ':']:
|
if value in ['.', ':']:
|
||||||
value = self.package.__name__
|
value = self.package.__name__
|
||||||
else:
|
else:
|
||||||
@@ -774,7 +822,9 @@ class GlobalObject(object):
|
|||||||
if self.package is None:
|
if self.package is None:
|
||||||
raise Invalid(
|
raise Invalid(
|
||||||
node,
|
node,
|
||||||
'relative name "%s" irresolveable without package' % value)
|
_('relative name "${val}" irresolveable without package',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
name = module.split('.')
|
name = module.split('.')
|
||||||
else:
|
else:
|
||||||
name = value.split('.')
|
name = value.split('.')
|
||||||
@@ -782,8 +832,9 @@ class GlobalObject(object):
|
|||||||
if module is None:
|
if module is None:
|
||||||
raise Invalid(
|
raise Invalid(
|
||||||
node,
|
node,
|
||||||
'relative name "%s" irresolveable without package' %
|
_('relative name "${val}" irresolveable without '
|
||||||
value)
|
'package', mapping={'val':value})
|
||||||
|
)
|
||||||
module = module.split('.')
|
module = module.split('.')
|
||||||
name.pop(0)
|
name.pop(0)
|
||||||
while not name[0]:
|
while not name[0]:
|
||||||
@@ -805,7 +856,8 @@ class GlobalObject(object):
|
|||||||
|
|
||||||
def deserialize(self, node, value):
|
def deserialize(self, node, value):
|
||||||
if not isinstance(value, basestring):
|
if not isinstance(value, basestring):
|
||||||
raise Invalid(node, '"%s" is not a string' % value)
|
raise Invalid(node,
|
||||||
|
_('"${val}" is not a string', mapping={'val':value}))
|
||||||
try:
|
try:
|
||||||
if ':' in value:
|
if ':' in value:
|
||||||
return self._pkg_resources_style(node, value)
|
return self._pkg_resources_style(node, value)
|
||||||
@@ -813,13 +865,17 @@ class GlobalObject(object):
|
|||||||
return self._zope_dottedname_style(node, value)
|
return self._zope_dottedname_style(node, value)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise Invalid(node,
|
raise Invalid(node,
|
||||||
'The dotted name "%s" cannot be imported' % value)
|
_('The dotted name "${name}" cannot be imported',
|
||||||
|
mapping={'name':value}))
|
||||||
|
|
||||||
def serialize(self, node, value):
|
def serialize(self, node, value):
|
||||||
try:
|
try:
|
||||||
return value.__name__
|
return value.__name__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise Invalid(node, '%r has no __name__' % value)
|
raise Invalid(node,
|
||||||
|
_('"${val}" has no __name__',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
|
|
||||||
class DateTime(object):
|
class DateTime(object):
|
||||||
""" A type representing a Python ``datetime.datetime`` object.
|
""" A type representing a Python ``datetime.datetime`` object.
|
||||||
@@ -839,10 +895,10 @@ class DateTime(object):
|
|||||||
You can adjust the error message reported by this class by
|
You can adjust the error message reported by this class by
|
||||||
changing its ``err_template`` attribute in a subclass on an
|
changing its ``err_template`` attribute in a subclass on an
|
||||||
instance of this class. By default, the ``err_template``
|
instance of this class. By default, the ``err_template``
|
||||||
attribute is the string ``%(value)s cannot be parsed as an iso8601
|
attribute is the string ``${value} cannot be parsed as an iso8601
|
||||||
date: %(exc)s``. This string is used as the interpolation subject
|
date: ${exc}``. This string is used as the interpolation subject
|
||||||
of a dictionary composed of ``value`` and ``exc``. ``value`` and
|
of a dictionary composed of ``val`` and ``err``. ``val`` and
|
||||||
``exc`` are the unvalidatable value and the exception caused
|
``err`` are the unvalidatable value and the exception caused
|
||||||
trying to convert the value, respectively.
|
trying to convert the value, respectively.
|
||||||
|
|
||||||
For convenience, this type is also willing to coerce
|
For convenience, this type is also willing to coerce
|
||||||
@@ -859,7 +915,7 @@ class DateTime(object):
|
|||||||
The subnodes of the :class:`colander.SchemaNode` that wraps
|
The subnodes of the :class:`colander.SchemaNode` that wraps
|
||||||
this type are ignored.
|
this type are ignored.
|
||||||
"""
|
"""
|
||||||
err_template = '%(value)s cannot be parsed as an iso8601 date: %(exc)s'
|
err_template = _('${val} cannot be parsed as an iso8601 date: ${err}')
|
||||||
def __init__(self, default_tzinfo=None):
|
def __init__(self, default_tzinfo=None):
|
||||||
if default_tzinfo is None:
|
if default_tzinfo is None:
|
||||||
default_tzinfo = iso8601.iso8601.Utc()
|
default_tzinfo = iso8601.iso8601.Utc()
|
||||||
@@ -869,7 +925,10 @@ class DateTime(object):
|
|||||||
if type(value) is datetime.date: # cant use isinstance; dt subs date
|
if type(value) is datetime.date: # cant use isinstance; dt subs date
|
||||||
value = datetime.datetime.combine(value, datetime.time())
|
value = datetime.datetime.combine(value, datetime.time())
|
||||||
if not isinstance(value, datetime.datetime):
|
if not isinstance(value, datetime.datetime):
|
||||||
raise Invalid(node, '%r is not a datetime object' % value)
|
raise Invalid(node,
|
||||||
|
_('"${val}" is not a datetime object',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
if value.tzinfo is None:
|
if value.tzinfo is None:
|
||||||
value = value.replace(tzinfo=self.default_tzinfo)
|
value = value.replace(tzinfo=self.default_tzinfo)
|
||||||
return value.isoformat()
|
return value.isoformat()
|
||||||
@@ -883,8 +942,8 @@ class DateTime(object):
|
|||||||
result = datetime.datetime(year, month, day,
|
result = datetime.datetime(year, month, day,
|
||||||
tzinfo=self.default_tzinfo)
|
tzinfo=self.default_tzinfo)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise Invalid(node, self.err_template % {'value':value,
|
raise Invalid(node, _(self.err_template,
|
||||||
'exc':e})
|
mapping={'val':value, 'err':e}))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
class Date(object):
|
class Date(object):
|
||||||
@@ -899,9 +958,9 @@ class Date(object):
|
|||||||
You can adjust the error message reported by this class by
|
You can adjust the error message reported by this class by
|
||||||
changing its ``err_template`` attribute in a subclass on an
|
changing its ``err_template`` attribute in a subclass on an
|
||||||
instance of this class. By default, the ``err_template``
|
instance of this class. By default, the ``err_template``
|
||||||
attribute is the string ``%(value)s cannot be parsed as an iso8601
|
attribute is the string ``${val} cannot be parsed as an iso8601
|
||||||
date: %(exc)s``. This string is used as the interpolation subject
|
date: ${err}``. This string is used as the interpolation subject
|
||||||
of a dictionary composed of ``value`` and ``exc``. ``value`` and
|
of a dictionary composed of ``val`` and ``err``. ``val`` and
|
||||||
``exc`` are the unvalidatable value and the exception caused
|
``exc`` are the unvalidatable value and the exception caused
|
||||||
trying to convert the value, respectively.
|
trying to convert the value, respectively.
|
||||||
|
|
||||||
@@ -920,18 +979,21 @@ class Date(object):
|
|||||||
The subnodes of the :class:`colander.SchemaNode` that wraps
|
The subnodes of the :class:`colander.SchemaNode` that wraps
|
||||||
this type are ignored.
|
this type are ignored.
|
||||||
"""
|
"""
|
||||||
err_template = '%(value)s cannot be parsed as an iso8601 date: %(exc)s'
|
err_template = _('${val} cannot be parsed as an iso8601 date: ${err}')
|
||||||
def serialize(self, node, value):
|
def serialize(self, node, value):
|
||||||
if isinstance(value, datetime.datetime):
|
if isinstance(value, datetime.datetime):
|
||||||
value = value.date()
|
value = value.date()
|
||||||
if not isinstance(value, datetime.date):
|
if not isinstance(value, datetime.date):
|
||||||
raise Invalid(node, '%r is not a date object' % value)
|
raise Invalid(node,
|
||||||
|
_('"${val}" is not a date object',
|
||||||
|
mapping={'val':value})
|
||||||
|
)
|
||||||
return value.isoformat()
|
return value.isoformat()
|
||||||
|
|
||||||
def deserialize(self, node, value):
|
def deserialize(self, node, value):
|
||||||
if not value:
|
if not value:
|
||||||
if node.required:
|
if node.required:
|
||||||
raise Invalid(node, 'Required')
|
raise Invalid(node, _('Required'))
|
||||||
return node.default
|
return node.default
|
||||||
try:
|
try:
|
||||||
result = iso8601.parse_date(value)
|
result = iso8601.parse_date(value)
|
||||||
@@ -941,8 +1003,10 @@ class Date(object):
|
|||||||
year, month, day = map(int, value.split('-', 2))
|
year, month, day = map(int, value.split('-', 2))
|
||||||
result = datetime.date(year, month, day)
|
result = datetime.date(year, month, day)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise Invalid(node, self.err_template % {'value':value,
|
raise Invalid(node,
|
||||||
'exc':e})
|
_(self.err_template,
|
||||||
|
mapping={'val':value, 'err':e})
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
class SchemaNode(object):
|
class SchemaNode(object):
|
||||||
|
60
colander/locale/colander.pot
Normal file
60
colander/locale/colander.pot
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# Translations template for colander.
|
||||||
|
# Copyright (C) 2010 ORGANIZATION
|
||||||
|
# This file is distributed under the same license as the colander project.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: colander 0.5.2\n"
|
||||||
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
|
"POT-Creation-Date: 2010-04-25 21:06-0400\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"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: Babel 0.9.5\n"
|
||||||
|
|
||||||
|
#: colander/__init__.py:177
|
||||||
|
msgid "Invalid value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:202
|
||||||
|
msgid "String does not match expected pattern"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:217
|
||||||
|
msgid "Invalid email address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:246
|
||||||
|
msgid "${val} is less than minimum value ${min}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:247
|
||||||
|
msgid "${val} is greater than maximum value ${max}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:461
|
||||||
|
msgid "\"${val}\" is not iterable"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:648 colander/__init__.py:680 colander/__init__.py:710
|
||||||
|
#: colander/__init__.py:751 colander/__init__.py:996
|
||||||
|
msgid "Required"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:747
|
||||||
|
msgid "${val} is not a string"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:860
|
||||||
|
msgid "\"${val}\" is not a string"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: colander/__init__.py:918 colander/__init__.py:982
|
||||||
|
msgid "${val} cannot be parsed as an iso8601 date: ${err}"
|
||||||
|
msgstr ""
|
||||||
|
|
@@ -189,7 +189,7 @@ class TestRange(unittest.TestCase):
|
|||||||
def test_min_failure(self):
|
def test_min_failure(self):
|
||||||
validator = self._makeOne(min=1)
|
validator = self._makeOne(min=1)
|
||||||
e = invalid_exc(validator, None, 0)
|
e = invalid_exc(validator, None, 0)
|
||||||
self.assertEqual(e.msg, '0 is less than minimum value 1')
|
self.assertEqual(e.msg.interpolate(), '0 is less than minimum value 1')
|
||||||
|
|
||||||
def test_min_failure_msg_override(self):
|
def test_min_failure_msg_override(self):
|
||||||
validator = self._makeOne(min=1, min_err='wrong')
|
validator = self._makeOne(min=1, min_err='wrong')
|
||||||
@@ -199,7 +199,8 @@ class TestRange(unittest.TestCase):
|
|||||||
def test_max_failure(self):
|
def test_max_failure(self):
|
||||||
validator = self._makeOne(max=1)
|
validator = self._makeOne(max=1)
|
||||||
e = invalid_exc(validator, None, 2)
|
e = invalid_exc(validator, None, 2)
|
||||||
self.assertEqual(e.msg, '2 is greater than maximum value 1')
|
self.assertEqual(e.msg.interpolate(),
|
||||||
|
'2 is greater than maximum value 1')
|
||||||
|
|
||||||
def test_max_failure_msg_override(self):
|
def test_max_failure_msg_override(self):
|
||||||
validator = self._makeOne(max=1, max_err='wrong')
|
validator = self._makeOne(max=1, max_err='wrong')
|
||||||
@@ -272,12 +273,12 @@ class TestLength(unittest.TestCase):
|
|||||||
def test_min_failure(self):
|
def test_min_failure(self):
|
||||||
validator = self._makeOne(min=1)
|
validator = self._makeOne(min=1)
|
||||||
e = invalid_exc(validator, None, '')
|
e = invalid_exc(validator, None, '')
|
||||||
self.assertEqual(e.msg, 'Shorter than minimum length 1')
|
self.assertEqual(e.msg.interpolate(), 'Shorter than minimum length 1')
|
||||||
|
|
||||||
def test_max_failure(self):
|
def test_max_failure(self):
|
||||||
validator = self._makeOne(max=1)
|
validator = self._makeOne(max=1)
|
||||||
e = invalid_exc(validator, None, 'ab')
|
e = invalid_exc(validator, None, 'ab')
|
||||||
self.assertEqual(e.msg, 'Longer than maximum length 1')
|
self.assertEqual(e.msg.interpolate(), 'Longer than maximum length 1')
|
||||||
|
|
||||||
class TestOneOf(unittest.TestCase):
|
class TestOneOf(unittest.TestCase):
|
||||||
def _makeOne(self, values):
|
def _makeOne(self, values):
|
||||||
@@ -291,7 +292,8 @@ class TestOneOf(unittest.TestCase):
|
|||||||
def test_failure(self):
|
def test_failure(self):
|
||||||
validator = self._makeOne([1, 2])
|
validator = self._makeOne([1, 2])
|
||||||
e = invalid_exc(validator, None, None)
|
e = invalid_exc(validator, None, None)
|
||||||
self.assertEqual(e.msg, '"None" is not one of 1, 2')
|
self.assertEqual(e.msg.interpolate(), '"None" is not one of 1, 2')
|
||||||
|
|
||||||
|
|
||||||
class TestMapping(unittest.TestCase):
|
class TestMapping(unittest.TestCase):
|
||||||
def _makeOne(self, *arg, **kw):
|
def _makeOne(self, *arg, **kw):
|
||||||
@@ -314,7 +316,7 @@ class TestMapping(unittest.TestCase):
|
|||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.deserialize, node, None)
|
e = invalid_exc(typ.deserialize, node, None)
|
||||||
self.failUnless(
|
self.failUnless(
|
||||||
e.msg.startswith('None is not a mapping type'))
|
e.msg.interpolate().startswith('"None" is not a mapping type'))
|
||||||
|
|
||||||
def test_deserialize_no_subnodes(self):
|
def test_deserialize_no_subnodes(self):
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
@@ -334,7 +336,9 @@ class TestMapping(unittest.TestCase):
|
|||||||
node.children = [DummySchemaNode(None, name='a')]
|
node.children = [DummySchemaNode(None, name='a')]
|
||||||
typ = self._makeOne(unknown='raise')
|
typ = self._makeOne(unknown='raise')
|
||||||
e = invalid_exc(typ.deserialize, node, {'a':1, 'b':2})
|
e = invalid_exc(typ.deserialize, node, {'a':1, 'b':2})
|
||||||
self.assertEqual(e.msg, "Unrecognized keys in mapping: {'b': 2}")
|
self.assertEqual(e.msg.interpolate(),
|
||||||
|
"Unrecognized keys in mapping: \"{'b': 2}\"")
|
||||||
|
|
||||||
|
|
||||||
def test_deserialize_unknown_preserve(self):
|
def test_deserialize_unknown_preserve(self):
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
@@ -372,7 +376,8 @@ class TestMapping(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.deserialize, node, {'a':1})
|
e = invalid_exc(typ.deserialize, node, {'a':1})
|
||||||
self.assertEqual(e.children[0].msg, '"b" is required but missing')
|
self.assertEqual(e.children[0].msg.interpolate(),
|
||||||
|
'"b" is required but missing')
|
||||||
|
|
||||||
def test_deserialize_subnode_partial(self):
|
def test_deserialize_subnode_partial(self):
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
@@ -389,7 +394,7 @@ class TestMapping(unittest.TestCase):
|
|||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.serialize, node, None)
|
e = invalid_exc(typ.serialize, node, None)
|
||||||
self.failUnless(
|
self.failUnless(
|
||||||
e.msg.startswith('None is not a mapping type'))
|
e.msg.interpolate().startswith('"None" is not a mapping type'))
|
||||||
|
|
||||||
def test_serialize_no_subnodes(self):
|
def test_serialize_no_subnodes(self):
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
@@ -443,8 +448,8 @@ class TestTuple(unittest.TestCase):
|
|||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.deserialize, node, None)
|
e = invalid_exc(typ.deserialize, node, None)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.msg,
|
e.msg.interpolate(),
|
||||||
'None is not iterable')
|
'"None" is not iterable')
|
||||||
self.assertEqual(e.node, node)
|
self.assertEqual(e.node, node)
|
||||||
|
|
||||||
def test_deserialize_no_subnodes(self):
|
def test_deserialize_no_subnodes(self):
|
||||||
@@ -465,16 +470,16 @@ class TestTuple(unittest.TestCase):
|
|||||||
node.children = [DummySchemaNode(None, name='a')]
|
node.children = [DummySchemaNode(None, name='a')]
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.deserialize, node, ('a','b'))
|
e = invalid_exc(typ.deserialize, node, ('a','b'))
|
||||||
self.assertEqual(e.msg,
|
self.assertEqual(e.msg.interpolate(),
|
||||||
"('a', 'b') has an incorrect number of elements (expected 1, was 2)")
|
"\"('a', 'b')\" has an incorrect number of elements (expected 1, was 2)")
|
||||||
|
|
||||||
def test_deserialize_toosmall(self):
|
def test_deserialize_toosmall(self):
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
node.children = [DummySchemaNode(None, name='a')]
|
node.children = [DummySchemaNode(None, name='a')]
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.deserialize, node, ())
|
e = invalid_exc(typ.deserialize, node, ())
|
||||||
self.assertEqual(e.msg,
|
self.assertEqual(e.msg.interpolate(),
|
||||||
"() has an incorrect number of elements (expected 1, was 0)")
|
'"()" has an incorrect number of elements (expected 1, was 0)')
|
||||||
|
|
||||||
def test_deserialize_subnodes_raise(self):
|
def test_deserialize_subnodes_raise(self):
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
@@ -492,8 +497,8 @@ class TestTuple(unittest.TestCase):
|
|||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.serialize, node, None)
|
e = invalid_exc(typ.serialize, node, None)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.msg,
|
e.msg.interpolate(),
|
||||||
'None is not iterable')
|
'"None" is not iterable')
|
||||||
self.assertEqual(e.node, node)
|
self.assertEqual(e.node, node)
|
||||||
|
|
||||||
def test_serialize_no_subnodes(self):
|
def test_serialize_no_subnodes(self):
|
||||||
@@ -514,16 +519,17 @@ class TestTuple(unittest.TestCase):
|
|||||||
node.children = [DummySchemaNode(None, name='a')]
|
node.children = [DummySchemaNode(None, name='a')]
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.serialize, node, ('a','b'))
|
e = invalid_exc(typ.serialize, node, ('a','b'))
|
||||||
self.assertEqual(e.msg,
|
self.assertEqual(e.msg.interpolate(),
|
||||||
"('a', 'b') has an incorrect number of elements (expected 1, was 2)")
|
"\"('a', 'b')\" has an incorrect number of elements (expected 1, was 2)")
|
||||||
|
|
||||||
def test_serialize_toosmall(self):
|
def test_serialize_toosmall(self):
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
node.children = [DummySchemaNode(None, name='a')]
|
node.children = [DummySchemaNode(None, name='a')]
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.serialize, node, ())
|
e = invalid_exc(typ.serialize, node, ())
|
||||||
self.assertEqual(e.msg,
|
self.assertEqual(e.msg.interpolate(),
|
||||||
"() has an incorrect number of elements (expected 1, was 0)")
|
'"()" has an incorrect number of elements (expected 1, was 0)'
|
||||||
|
)
|
||||||
|
|
||||||
def test_serialize_subnodes_raise(self):
|
def test_serialize_subnodes_raise(self):
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
@@ -552,8 +558,8 @@ class TestSequence(unittest.TestCase):
|
|||||||
node.children = [node]
|
node.children = [node]
|
||||||
e = invalid_exc(typ.deserialize, node, None)
|
e = invalid_exc(typ.deserialize, node, None)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.msg,
|
e.msg.interpolate(),
|
||||||
'None is not iterable')
|
'"None" is not iterable')
|
||||||
self.assertEqual(e.node, node)
|
self.assertEqual(e.node, node)
|
||||||
|
|
||||||
def test_deserialize_not_iterable_accept_scalar(self):
|
def test_deserialize_not_iterable_accept_scalar(self):
|
||||||
@@ -592,8 +598,8 @@ class TestSequence(unittest.TestCase):
|
|||||||
node.children = [node]
|
node.children = [node]
|
||||||
e = invalid_exc(typ.serialize, node, None)
|
e = invalid_exc(typ.serialize, node, None)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.msg,
|
e.msg.interpolate(),
|
||||||
'None is not iterable')
|
'"None" is not iterable')
|
||||||
self.assertEqual(e.node, node)
|
self.assertEqual(e.node, node)
|
||||||
|
|
||||||
def test_serialize_not_iterable_accept_scalar(self):
|
def test_serialize_not_iterable_accept_scalar(self):
|
||||||
@@ -894,14 +900,15 @@ class TestGlobalObject(unittest.TestCase):
|
|||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ._zope_dottedname_style, None, '.')
|
e = invalid_exc(typ._zope_dottedname_style, None, '.')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.msg,
|
e.msg.interpolate(),
|
||||||
'relative name "." irresolveable without package')
|
'relative name "." irresolveable without package')
|
||||||
|
|
||||||
def test_zope_dottedname_style_resolve_relative_nocurrentpackage(self):
|
def test_zope_dottedname_style_resolve_relative_nocurrentpackage(self):
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ._zope_dottedname_style, None, '.whatever')
|
e = invalid_exc(typ._zope_dottedname_style, None, '.whatever')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.msg, 'relative name ".whatever" irresolveable without package')
|
e.msg.interpolate(),
|
||||||
|
'relative name ".whatever" irresolveable without package')
|
||||||
|
|
||||||
def test_zope_dottedname_style_irrresolveable_relative(self):
|
def test_zope_dottedname_style_irrresolveable_relative(self):
|
||||||
import colander.tests
|
import colander.tests
|
||||||
@@ -971,7 +978,7 @@ class TestGlobalObject(unittest.TestCase):
|
|||||||
def test_deserialize_not_a_string(self):
|
def test_deserialize_not_a_string(self):
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.deserialize, None, None)
|
e = invalid_exc(typ.deserialize, None, None)
|
||||||
self.assertEqual(e.msg, '"None" is not a string')
|
self.assertEqual(e.msg.interpolate(), '"None" is not a string')
|
||||||
|
|
||||||
def test_deserialize_using_pkgresources_style(self):
|
def test_deserialize_using_pkgresources_style(self):
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
@@ -986,7 +993,7 @@ class TestGlobalObject(unittest.TestCase):
|
|||||||
def test_deserialize_style_raises(self):
|
def test_deserialize_style_raises(self):
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.deserialize, None, 'cant.be.found')
|
e = invalid_exc(typ.deserialize, None, 'cant.be.found')
|
||||||
self.assertEqual(e.msg,
|
self.assertEqual(e.msg.interpolate(),
|
||||||
'The dotted name "cant.be.found" cannot be imported')
|
'The dotted name "cant.be.found" cannot be imported')
|
||||||
|
|
||||||
def test_serialize_ok(self):
|
def test_serialize_ok(self):
|
||||||
@@ -998,7 +1005,7 @@ class TestGlobalObject(unittest.TestCase):
|
|||||||
def test_serialize_fail(self):
|
def test_serialize_fail(self):
|
||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
e = invalid_exc(typ.serialize, None, None)
|
e = invalid_exc(typ.serialize, None, None)
|
||||||
self.assertEqual(e.msg, 'None has no __name__')
|
self.assertEqual(e.msg.interpolate(), '"None" has no __name__')
|
||||||
|
|
||||||
class TestDateTime(unittest.TestCase):
|
class TestDateTime(unittest.TestCase):
|
||||||
def _makeOne(self, *arg, **kw):
|
def _makeOne(self, *arg, **kw):
|
||||||
@@ -1020,7 +1027,8 @@ class TestDateTime(unittest.TestCase):
|
|||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
e = invalid_exc(typ.serialize, node, 'garbage')
|
e = invalid_exc(typ.serialize, node, 'garbage')
|
||||||
self.assertEqual(e.msg, "'garbage' is not a datetime object")
|
self.assertEqual(e.msg.interpolate(),
|
||||||
|
'"garbage" is not a datetime object')
|
||||||
|
|
||||||
def test_serialize_with_date(self):
|
def test_serialize_with_date(self):
|
||||||
import datetime
|
import datetime
|
||||||
@@ -1093,7 +1101,7 @@ class TestDate(unittest.TestCase):
|
|||||||
typ = self._makeOne()
|
typ = self._makeOne()
|
||||||
node = DummySchemaNode(None)
|
node = DummySchemaNode(None)
|
||||||
e = invalid_exc(typ.serialize, node, 'garbage')
|
e = invalid_exc(typ.serialize, node, 'garbage')
|
||||||
self.assertEqual(e.msg, "'garbage' is not a date object")
|
self.assertEqual(e.msg.interpolate(), '"garbage" is not a date object')
|
||||||
|
|
||||||
def test_serialize_with_date(self):
|
def test_serialize_with_date(self):
|
||||||
import datetime
|
import datetime
|
||||||
|
20
setup.cfg
20
setup.cfg
@@ -8,3 +8,23 @@ nocapture=1
|
|||||||
cover-package=colander
|
cover-package=colander
|
||||||
cover-erase=1
|
cover-erase=1
|
||||||
|
|
||||||
|
[compile_catalog]
|
||||||
|
directory = colander/locale
|
||||||
|
domain = colander
|
||||||
|
statistics = true
|
||||||
|
|
||||||
|
[extract_messages]
|
||||||
|
add_comments = TRANSLATORS:
|
||||||
|
output_file = colander/locale/colander.pot
|
||||||
|
width = 80
|
||||||
|
|
||||||
|
[init_catalog]
|
||||||
|
domain = colander
|
||||||
|
input_file = colander/locale/colander.pot
|
||||||
|
output_dir = colander/locale
|
||||||
|
|
||||||
|
[update_catalog]
|
||||||
|
domain = colander
|
||||||
|
input_file = colander/locale/colander.pot
|
||||||
|
output_dir = colander/locale
|
||||||
|
previous = true
|
||||||
|
6
setup.py
6
setup.py
@@ -21,7 +21,7 @@ here = os.path.abspath(os.path.dirname(__file__))
|
|||||||
README = open(os.path.join(here, 'README.txt')).read()
|
README = open(os.path.join(here, 'README.txt')).read()
|
||||||
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
|
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
|
||||||
|
|
||||||
requires = ['iso8601']
|
requires = ['iso8601', 'translationstring']
|
||||||
|
|
||||||
setup(name='colander',
|
setup(name='colander',
|
||||||
version='0.5.2',
|
version='0.5.2',
|
||||||
@@ -43,5 +43,9 @@ setup(name='colander',
|
|||||||
tests_require = requires,
|
tests_require = requires,
|
||||||
install_requires = requires,
|
install_requires = requires,
|
||||||
test_suite="colander",
|
test_suite="colander",
|
||||||
|
message_extractors = { ".": [
|
||||||
|
("**.py", "chameleon_python", None ),
|
||||||
|
("**.pt", "chameleon_xml", None ),
|
||||||
|
]},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user