- Add explicit support for Python 3.4 and PyPy3.
- Add
min_err
andmax_err
arguments toLength
, thus allowing customization of its error messages. - Add Any validator which succeeds if at least one of its subvalidators succeeded.
- Allow localization of error messages returned by
colander.Invalid.asdict
by adding an optionaltranslate
callable argument. - Add a
missing_msg
argument toSchemaNode
that specifies the error message to be used when the node is required and missing
- Fix an issue where the
flatten()
method produces an invalid name (ex: "answer.0.") for the type "Sequence". See Pylons#179
- Removed forked
iso8601
and change to dependency on PyPIiso8601
(due to float rounding bug on microsecond portion when parsing iso8601 datetime string). Left aniso8601.py
stub for backwards compatibility. - Time of "00:00" no longer gives
colander.Invalid
. - Un-break wrapping of callable instances as
colander.deferred
. See Pylons#141. - Set the max length TLD to 22 in
Email
validator based on the current list of valid TLDs. See Pylons#159 - Fix an issue where
drop
was not recognized as a default and was returning thedrop
instance instead of omitting the value. Pylons#139 - Fix an issue where the
SchemaNode.title
was clobbered by thename
when defined as a class attribute. See Pylons#183 and Pylons#185 - Updated translations:
fr
,de
,ja
SchemaNode.deserialize
will now raise anUnboundDeferredError
if the node has an unbound deferred validator. Previously, deferred validators were silently ignored. See Pylons#47
- In 1.0a1, there was a change merged from
Pylons#73 which made it possible to supply
None
as thedefault
value for a String type, and upon serialization, the value would be rendered ascolander.null
if the default were used. This confused people who were actually supplying the valueNone
as a default when the associated appstruct had no value, so the change has been reverted. When you supplyNone
as thedefault
argument to a String, the rendered serialize() value will again be'None'
. Sorry. - Normalize
colander.Function
argumentmessage
to bemsg
. This now matches other APIs within Colander. Themessage
argument is now deprecated and a warning will be emitted. Pylons#31 Pylons#64 iso8601.py
: ConvertValueError
(raised bydatetime
) intoParseErrorr
inparse_date
, so that the validation machinery upstream handles it properly.iso8601.py
: Correctly parse datetimes with a timezone of Z even when the default_timezone is set. These previously had the default timezone.colander.String
schema type now raisescolander.Invalid
when trying to deserialize a non-string item. See Pylons#100
Add
colander.List
type, modeled ondeform.List
: this type preserves ordering, and allows duplicates.It is now possible to use the value
colander.drop
as thedefault
value for items that are subitems of a mapping. Ifcolander.drop
is used as thedefault
for a subnode of a mapping schema, and the mapping appstruct being serialized does not have a value for that schema node, the value will be omitted from the serialized mapping. For instance, the following script, when run would not raise an assertion error:class What(colander.MappingSchema): thing = colander.SchemaNode(colander.String(), default=colander.drop) result = What().serialize({}) # no "thing" in mapping assert result == {}
The
typ
of aSchemaNode
can optionally be pased in as a keyword argument. See Pylons#90Allow interpolation of missing_msg with properties title and name
- Fix bug introduced by supporting spec-mandated truncations of ISO-8601 timezones. A TypeError would be raised instead of Invalid. See Pylons#111.
- Loosen Email validator regex (permit apostrophes, bang, etc in localpart).
- Allow for timezone info objects to be pickled and unpickled "more correctly" (Use '__getinitargs__' to provide unpickling-only defaults). See Pylons#108.
- Support spec-mandated truncations of ISO-8601 timezones.
- Support spec-mandated truncations of ISO-8601 datetimes.
- Allow specifying custom representations of values for boolean fields.
- Ensure that
colander.iso8601.FixedOffset
instances can be unpickled. - Avoid validating strings as sequences under Py3k.
- Sync documentation with 0.9.9 change to use
insert_before
rather thanschema_order
. See Pylons#104
- Add
colander.ContainsOnly
andcolander.url
validators. - Add
colander.instantiate
to help define schemas containing mappings and sequences more succinctly.
- Work around a regression in Python 3.3 for
colander.Decimal
when it's used with aquant
argument but without arounding
argument. See Pylons#66 - Using
SchemaNode(String, default='', ..)
now works properly, or at least more intuitively. Previously if an empty-stringdefault
was supplied, serialization would return a defaulted value ascolander.null
. See Pylons#73. - Stricter checking in colander.Mapping to prevent items which are logically not mappings from being accepted during validation (see Pylons#96).
Add
colander.Set
type, ported fromdeform.Set
Add Python 3.3 to tox configuration and use newer tox testing regime (setup.py dev).
Add Python 3.3 Trove classifier.
Calling
bind
on a schema node e.g.cloned_node = somenode.bind(a=1, b=2)
on a schema node now results in the cloned node having abindings
attribute of the value{'a':1, 'b':2}
.It is no longer necessary to pass a
typ
argument to a SchemaNode constructor if the node class has aschema_type
callable as a class attribute which, when called with no arguments, returns a schema type. This callable will be called to obtain the schema type if atyp
is not supplied to the constructor. The defaultSchemaNode
object'sschema_type
callable raises aNotImplementedError
when it is called.SchemaNode now has a
raise_invalid
method which accepts a message and raises a colander.Invalid exception usingself
as the node and the message as its message.It is now possible and advisable to subclass
SchemaNode
in order to create a bundle of default node behavior. The subclass can define the following methods and attributes:preparer
,validator
,default
,missing
,name
,title
,description
,widget
, andafter_bind
.For example, the older, more imperative style that looked like this still works, of course:
from colander import SchemaNode ranged_int = colander.SchemaNode( validator=colander.Range(0, 10), default = 10, title='Ranged Int' )
But you can alternately now do something like this:
from colander import SchemaNode class RangedIntSchemaNode(SchemaNode): validator = colander.Range(0, 10) default = 10 title = 'Ranged Int' ranged_int = RangedInt()
Values that are expected to be callables can now alternately be methods of the schemanode subclass instead of plain attributes:
from colander import SchemaNode class RangedIntSchemaNode(SchemaNode): default = 10 title = 'Ranged Int' def validator(self, node, cstruct): if not 0 < cstruct < 10: raise colander.Invalid(node, 'Must be between 0 and 10') ranged_int = RangedInt()
Note that when implementing a method value such as
validator
that expects to receive anode
argument,node
must be provided in the call signature, even thoughnode
will almost always be the same asself
. This is because Colander simply treats the method as another kind of callable, be it a method, or a function, or an instance that has a__call__
method. It doesn't care that it happens to be a method ofself
, and it needs to support callables that are not methods, so it sendsnode
in regardless.You can't currently use method definitions as
colander.deferred
callables. For example this will not work:from colander import SchemaNode class RangedIntSchemaNode(SchemaNode): default = 10 title = 'Ranged Int' @colander.deferred def validator(self, node, kw): request = kw['request'] def avalidator(node, cstruct): if not 0 < cstruct < 10: if request.user != 'admin': raise colander.Invalid(node, 'Must be between 0 and 10') return avalidator ranged_int = RangedInt() bound_ranged_int = ranged_int.bind(request=request)
This will result in:
TypeError: avalidator() takes exactly 3 arguments (2 given)
However, if you treat the thing being decorated as a function instead of a method (remove the
self
argument from the argument list), it will indeed work):from colander import SchemaNode class RangedIntSchemaNode(SchemaNode): default = 10 title = 'Ranged Int' @colander.deferred def validator(node, kw): request = kw['request'] def avalidator(node, cstruct): if not 0 < cstruct < 10: if request.user != 'admin': raise colander.Invalid(node, 'Must be between 0 and 10') return avalidator ranged_int = RangedInt() bound_ranged_int = ranged_int.bind(request=request)
In previous releases of Colander, the only way to defer the computation of values was via the
colander.deferred
decorator. In this release, however, you can instead use thebindings
attribute ofself
to obtain access to the bind parameters within values that are plain old methods:from colander import SchemaNode class RangedIntSchemaNode(SchemaNode): default = 10 title = 'Ranged Int' def validator(self, node, cstruct): request = self.bindings['request'] if not 0 < cstruct < 10: if request.user != 'admin': raise colander.Invalid(node, 'Must be between 0 and 10') ranged_int = RangedInt() bound_range_int = ranged_int.bind(request=request)
If the things you're trying to defer aren't callables like
validator
, but they're instead just plain attributes likemissing
ordefault
, instead of using acolander.deferred
, you can useafter_bind
to set attributes of the schemanode that rely on binding variables:from colander import SchemaNode class UserIdSchemaNode(SchemaNode): title = 'User Id' def after_bind(self, node, kw): self.default = kw['request'].user.id
You can override the default values of a schemanode subclass in its constructor:
from colander import SchemaNode class RangedIntSchemaNode(SchemaNode): default = 10 title = 'Ranged Int' validator = colander.Range(0, 10) ranged_int = RangedInt(validator=colander.Range(0, 20))
In the above example, the validation will be done on 0-20, not 0-10.
If a schema node name conflicts with a schema value attribute name on the same class, you can work around it by giving the schema node a bogus name in the class definition but providing a correct
name
argument to the schema node constructor:from colander import SchemaNode, Schema class SomeSchema(Schema): title = 'Some Schema' thisnamewillbeignored = colander.SchemaNode( colander.String(), name='title' )
Note that such a workaround is only required if the conflicting names are attached to the exact same class definition. Colander scrapes off schema node definitions at each class' construction time, so it's not an issue for inherited values. For example:
from colander import SchemaNode, Schema class SomeSchema(Schema): title = colander.SchemaNode(colander.String()) class AnotherSchema(SomeSchema): title = 'Some Schema' schema = AnotherSchema()
In the above example, even though the
title = 'Some Schema'
appears to override the superclass'title
SchemaNode, atitle
SchemaNode will indeed be present in the child list of theschema
instance (schema['title']
will return thetitle
SchemaNode) and the schema'stitle
attribute will beSome Schema
(schema.title
will returnSome Schema
).Normal inheritance rules apply to class attributes and methods defined in a schemanode subclass. If your schemanode subclass inherits from another schemanode class, your schemanode subclass' methods and class attributes will override the superclass' methods and class attributes.
Ordering of child schema nodes when inheritance is used works like this: the "deepest" SchemaNode class in the MRO of the inheritance chain is consulted first for nodes, then the next deepest, then the next, and so on. So the deepest class' nodes come first in the relative ordering of schema nodes, then the next deepest, and so on. For example:
class One(colander.Schema): a = colander.SchemaNode( colander.String(), id='a1', ) b = colander.SchemaNode( colander.String(), id='b1', ) d = colander.SchemaNode( colander.String(), id='d1', ) class Two(One): a = colander.SchemaNode( colander.String(), id='a2', ) c = colander.SchemaNode( colander.String(), id='c2', ) e = colander.SchemaNode( colander.String(), id='e2', ) class Three(Two): b = colander.SchemaNode( colander.String(), id='b3', ) d = colander.SchemaNode( colander.String(), id='d3', ) f = colander.SchemaNode( colander.String(), id='f3', ) three = Three()
The ordering of child nodes computed in the schema node
three
will be['a2', 'b3', 'd3', 'c2', 'e2', 'f3']
. The ordering startsa1
,b1
,d1
because that's the ordering of nodes inOne
, andOne
is the deepest SchemaNode in the inheritance hierarchy. Then it processes the nodes attached toTwo
, the next deepest, which causesa1
to be replaced bya2
, andc2
ande2
to be appended to the node list. Then finally it processes the nodes attached toThree
, which causesb1
to be replaced byb3
, andd1
to be replaced byd3
, then finallyf
is appended.Multiple inheritance works the same way:
class One(colander.Schema): a = colander.SchemaNode( colander.String(), id='a1', ) b = colander.SchemaNode( colander.String(), id='b1', ) d = colander.SchemaNode( colander.String(), id='d1', ) class Two(colander.Schema): a = colander.SchemaNode( colander.String(), id='a2', ) c = colander.SchemaNode( colander.String(), id='c2', ) e = colander.SchemaNode( colander.String(), id='e2', ) class Three(Two, One): b = colander.SchemaNode( colander.String(), id='b3', ) d = colander.SchemaNode( colander.String(), id='d3', ) f = colander.SchemaNode( colander.String(), id='f3', ) three = Three()
The resulting node ordering of
three
is the same as the single inheritance example:['a2', 'b3', 'd3', 'c2', 'e2', 'f3']
due to the MRO deepest-first ordering (One
, thenTwo
, thenThree
).
- Passing non-SchemaNode derivative instances as
*children
into a SchemaNode constructor is no longer supported. Symptom:AttributeError: name
when constructing a SchemaNode.
- Allow the use of
missing=None
for Number. See Pylons#59 . - Create a
colander.Money
type that is a Decimal type with two-decimal-point precision rounded-up. - Allow
quant
androunding
args tocolander.Decimal
constructor. luhnok
validator added (credit card luhn mod10 validator).- Add an
insert
method to SchemaNode objects. - Add an
insert_before
method to SchemaNode objects. - Better class-based mapping schema inheritance model.
- A node declared in a subclass of a mapping schema superclass now overrides any node with the same name inherited from any superclass. Previously, it just repeated and didn't override.
- An
insert_before
keyword argument may be passed to a SchemaNode constructor. This is a string naming a node in a superclass. A node with aninsert_before
will be placed before the named node in a parent mapping schema.
- The
preparer=
argument to SchemaNodes may now be a sequence of preparers. - Added a
cstruct_children
method to SchemaNode. - A new
cstruct_children
API should exist on schema types. IfSchemaNode.cstruct_children
is called on a node with a type that does not have acstruct_children
method, a deprecation warning is emitted and[]
is returned (this may or may not be the correct value for your custom type).
- The inheritance changes required a minor backwards incompatibility: calling
__setitem__
on a SchemaNode will no longer raiseKeyError
when attempting to set a subnode into a node that doesn't already have an existing subnode by that name. Instead, the subnode will be appended to the child list.
- A "Schema Inheritance" section was added to the Basics chapter documentation.
- False evaluating values are now serialized to colander.null for String, Date, and Time. This resolves the issue where a None value would be rendered as 'None' for String, and missing='None' was not possible for Date, Datetime, and Time. See Pylons#1 .
- Updated Brazilian Portugese translations.
- Updated Japanese translations.
- Updated Russian translations.
- Fix documentation: 0.9.3 allowed explicitly passing None to DateTime to have no default timezone applied.
- Add
dev
anddocs
setup.py aliases (e.g.python setup.py dev
).
- Using
schema.flatten(...)
against a mapping schema node without a name produced incorrectly dot-prefixed keys. See Pylons#37 - Fix invalid.asdict for multiple error messages. See Pylons#22 , Pylons#27 , Pylons#12 , and Pylons#2 .
- Invalid.messages() now returns an empty list if there are no messages. See Pylons#21 .
name
passed to a SchemaNode constructor was not respected in declaratively constructed schemas. Now if you passname
to the SchemaNode constructor within the body of a schema class, it will take precedence over the name it's been assigned to in the schema class. See Pylons#39 .- Japanese translation thanks to OCHIAI, Gouji.
- Replaced incorrect
%{err}
with correct${err}
in String.deserialize error message. See Pylons#41
- No longer runs on Python 2.4 or 2.5. Python 2.6+ is now required.
- Python 3.2 compatibility.
- Removed a dependency on the iso8601 package (code from the package is now inlined in Colander itself).
- Added copyright and licensing information for iso8601-derived code to LICENSE.txt.
- Added Czech translation.
- Compile pt_BR translation (it was previously uncompiled).
- Minor docs fixes.
- Documentation added about flatten and unflatten.
flatten
now only includes leaf nodes in the flattened dict.flatten
does not include a path element for the name of the type node for sequences.unflatten
is implemented.- Added
__setitem__
toSchemaNode
, allowing replacement of nodes by name. - Added
get_value
andset_value
methods toSchema
which allow access and mutation of appstructs using dotted name paths. - Add Swedish, French, Chinese translations.
- Add
Time
type. - Add Dutch translation.
- Fix documentation: 0.9.2 requires
deserialize
of types to explicitly deal with the potential to receivecolander.null
. - Use
default_tzinfo
when deserializing naive datetimes. See https://github.com/Pylons/colander/issues#issue/5. - Allow
default_tzinfo
to beNone
when creating acolander.DateTime
. See https://github.com/Pylons/colander/issues#issue/6. - Add the ability to insert a
colander.interfaces.Preparer
between deserialization and validation. See the Preparing section in the documentation.
- Added Polish translation, thanks to Jedrzej Nowak.
- Moved to Pylons Project GitHub (https://github.com/Pylons/colander).
- Add tox.ini for testing purposes.
- New API:
colander.required
. Used as the marker value when amissing
argument is left unspecified. - Bug fix: if a
title
argument which is the empty string orNone
is passed explicitly to a SchemaNode, it is no longer replaced by a title computed from the name. - Add SchemaNode.__contains__ to support "name in schema".
- SchemaNode deserialization now unconditionally calls the schema type's
deserialize
method to obtain an appstruct before attempting to validate. Third party schema types should now returncolander.null
if passed acolander.null
value or another logically "empty" value as a cstruct duringdeserialize
.
- When
colander.null
was unpickled, the reference created during unpickling was not a reference to the singleton but rather a new instance of thecolander._null
class. This was unintentional, because lots of code checks forif x is colander.null
, which will fail across pickling and unpickling. Now the reference created whencolander.null
is pickled is unpickled as the singleton itself.
- SchemaNode constructor now accepts arbitrary keyword arguments. It
sets any unknown values within the
**kw
sequence as attributes of the node object. - Added Spanish locale: thanks to Douglas Cerna for the translations!
- If you use a schema with deferred
validator
,missing
ordefault
attributes, but you use it to perform serialization and deserialization without calling itsbind
method:- If
validator
is deferred, no validation will be performed. - If
missing
is deferred, the field will be considered required. - If
default
is deferred, the serialization default will be assumed to becolander.null
.
- If
- Undocumented internal API for all type objects:
flatten
. External type objects should now inherit fromcolander.SchemaType
to get a default implementation.
- Docstring fixes to
colander.SchemaNode
(missing
is not thenull
value when required, it's a special marker value). - The concept of "schema binding" was added, which allows for a more declarative-looking spelling of schemas and schema nodes which have dependencies on values available after the schema has already been fully constructed. See the new narrative chapter in the documentation entitled "Schema Binding".
- The interface of
colander.SchemaNode
has grown a__delitem__
method. The__iter__
, and__getitem__
methods have now also been properly documented.
- The title of a schema node now defaults to a titleization of the
name
. Underscores in thename
are replaced with empty strings and the first letter of every resulting word is capitalized. Previously thename
was not split on underscores, and the entirety of thename
was capitalized. - A method of the
colander.Invalid
exception namedmessages
was added. It returns an iterable of error messages using themsg
attribute of its related exception node. If themsg
attribute is iterable, it is returned. If it is not iterable, a single-element list containing themsg
value is returned.
- Add an
colander.SchemaNode.__iter__
method, which iterates over the children nodes of a schema node. - The constructor of a
colander.SchemaNode
now accepts awidget
keyword argument, for use by Deform (it is not used internally).
- Make it possible to use
colander.null
as amissing
argument tocolander.SchemaNode
for roundtripping purposes. - Make it possible to pickle
colander.null
.
A release centered around normalizing the treatment of default and missing values.
- Allow
colander.Regex
validator to accept a pattern object instead of just a string. - Get rid of circular reference in Invalid exceptions: Invalid
exceptions now no longer have a
parent
attribute. Instead, they have apositional
attribute, which signifies that the parent node type of the schema node to which they relate inherits from Positional. This attribute isn't an API; it's used only internally for reporting. - Raise a
TypeError
when bogus keyword arguments are passed tocolander.SchemaNode
.
missing
constructor arg to SchemaNode: signifies deserialization default, disambiguated fromdefault
which acted as both serialization and deserialization default previously.Changes necessitated / made possible by SchemaNode
missing
addition:- The
allow_empty
argument of thecolander.String
type was removed (usemissing=''
as a wrapper SchemaNode argument instead).
- The
New concept:
colander.null
input to serialization and deserialization. Use ofcolander.null
normalizes serialization and deserialization default handling.Changes necessitated / made possible by
colander.null
addition:partial
argument and attribute of colander.MappingSchema has- been removed; all serializations are partial, and partial deserializations are not necessary.
colander.null
values are added to the cstruct for partial- serializations instead of omitting missing node values from the cstruct.
colander.null
may now be present in serialized and- deserialized data structures.
sdefault
attribute of SchemaNode has been removed; we never need to serialize a default anymore.- The value
colander.null
will be passed asappstruct
to each type'sserialize
method when a mapping appstruct doesn't have a corresponding key instead ofNone
, as was the practice previously. - The value
colander.null
will be passed ascstruct
to each type'sdeserialize
method when a mapping cstruct doesn't have a corresponding key instead ofNone
, as was the practice previously. - Types now must handle
colander.null
explicitly during serialization.
Updated and expanded documentation, particularly with respect to new
colander.null
handling.The
value
argument`` to theserialize
method of a SchemaNode is now namedappstruct
. It is no longer a required argument; it defaults tocolander.null
now.The
value
argument to thedeserialize
method of a SchemaNode is now namedcstruct
. It is no longer a required argument; it defaults tocolander.null
now.The
value
argument to theserialize
method of each built-in type is now namedappstruct
, and is now required: it is no longer a keyword argument that has a default.The
value
argument to thedeserialize
method of each built-in type is now namedcstruct
, and is now required: it is no longer a keyword argument that has a default.
- The default
encoding
parameter value to thecolander.String
type is stillNone
, however its meaning has changed. An encoding ofNone
now means that no special encoding and decoding of Unicode values is done by the String type. This differs from the previous behavior, whereNone
implied that the encoding wasutf-8
. Pass the encoding asutf-8
specifically to get the older behavior back. This is in support of Deform. - The default
err_template
value attached to thecolander.Date
andcolander.Datetime
types was changed. It is now simplyInvalid date
instead of_('${val} cannot be parsed as an iso8601 date: ${err}')
. This is in support of Deform. - Fix bug in
colander.Boolean
that attempted to call.lower
on a bool value when a default value was found for the schema node.
- Add a Decimal type (number type which uses
decimal.Decimal
as a deserialization target).
- (Hopefully) fix intermittent datetime-granularity-related test failures.
- Internationalized error messages. This required some changes to error message formatting, which may impact you if you were feeding colander an error message template.
- New project dependency:
translationstring
package for internationalization. - New argument to
colander.String
constructor:allow_empty
. This is a boolean representing whether an empty string is a valid value during deserialization, defaulting toFalse
. - Add minimal documentation about the composition of a colander.Invalid exception to the narrative docs.
- Add (existing, but previously non-API) colander.Invalid attributes to its interface within the API documentation.
- Add Email and Regex validators (courtesy Steve Howe).
- Raise a
colander.Invalid
error if acolander.SequenceSchema
is created with more than one member. - Add
Function
validator. - Fix bug in serialization of non-Unicode values in the
String
class. - Get rid of
pserialize
in favor of makingserialize
always partially serialize. - Get rid of
pdeserialize
: it existed only for symmetry. We'll add something like it back later if we need it.
- The constructor arguments to a the
colander.Schema
class are now sent to the constructed SchemaNode rather than to the type it represents. - Allow
colander.Date
andcolander.DateTime
invalid error messages to be customized. - Add a
pos
argument to thecolander.Invalid.add
method. - Add a
__setitem__
method to thecolander.Invalid
class. - The
colander.Mapping
constructor keyword argumentunknown_keys
has been renamed tounknown
. - Allow
colander.Mapping
type to accept a new constructor argument:partial
. - New interface methods required by types and schema nodes:
pserialize
andpdeserialize
. These partially serialize or partially deserialize a value (the definition of "partial" is up to the type).
- 0.4 was mispackaged (CHANGES.txt missing); no code changes from 0.4 however.
- Add
colander.DateTime
andcolander.Date
data types. - Depend on the
iso8601
package for date support.
- Subnodes of a schema node are now kept in the
children
attribute rather than thenodes
attribute. - Add an
sdefault
property tocolander.SchemaNode
objects. - Add a
clone
method tocolander.SchemaNode
objects. - Add a
__str__
method to thecolander.Invalid
exception that prints an error summary. - Various error message improvements.
- Add
colander.Length
validator class.
- Make nodetype overrideable.
- Add __getitem__ to SchemaNode.
- Fix OneOf message.
- Capitalize node titles.
- Deal with empty strings in String, Boolean, and Float types.
- Introduce description; make title the same as name.
- Remove copy method from schemanode.
- Allow schema nodes to have titles.
- The term "structure" is too overloaded to use for schema purposes: structure -> schema node.
- Make Sequence more like Tuple and Mapping (it uses a substructure rather than a structure parameter to denote its type).
- Add __repr__ and copy methods to structure.
- Add accept_scalar flag to Sequence.
- Initial release.