- Fix documentation: 0.9.2 requires `deserialize
` of types to explicitly
deal with the potential to receive ``colander.null``.
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
Changes
|
||||
=======
|
||||
|
||||
Next release
|
||||
------------
|
||||
|
||||
- Fix documentation: 0.9.2 requires ``deserialize`` of types to explicitly
|
||||
deal with the potential to receive ``colander.null``.
|
||||
|
||||
0.9.2 (2011-03-28)
|
||||
------------------
|
||||
|
||||
|
@@ -87,13 +87,12 @@ of our definitions, a ``Person`` represents:
|
||||
Schema Node Objects
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A schema is composed of one or more *schema node* objects, each
|
||||
typically of the class :class:`colander.SchemaNode`, usually in a
|
||||
nested arrangement. Each schema node object has a required *type*, an
|
||||
optional deserialization *validator*, an optional *default*, an
|
||||
optional *missing*, an optional *title*, an optional *description*, an
|
||||
optional *widget*, and a slightly less optional *name*. It also
|
||||
accepts *arbitrary* keyword arguments, which are attached directly as
|
||||
A schema is composed of one or more *schema node* objects, each typically of
|
||||
the class :class:`colander.SchemaNode`, usually in a nested arrangement.
|
||||
Each schema node object has a required *type*, an optional deserialization
|
||||
*validator*, an optional *default*, an optional *missing*, an optional
|
||||
*title*, an optional *description*, and a slightly less optional *name*. It
|
||||
also accepts *arbitrary* keyword arguments, which are attached directly as
|
||||
attributes to the node instance.
|
||||
|
||||
The *type* of a schema node indicates its data type (such as
|
||||
@@ -126,19 +125,20 @@ of the *name*.
|
||||
The *description* of a schema node is metadata about a schema node
|
||||
that can be used by higher-level systems. By default, it is empty.
|
||||
|
||||
The *widget* of a schema node is a concept used only by higher level
|
||||
systems (such as form systems). By default it is ``None``. It won't
|
||||
be discussed any further in the Colander documentation; it will
|
||||
instead be explained in the context of the documentation of systems
|
||||
which make use of it.
|
||||
|
||||
Any other keyword arguments to a schema node constructor will be
|
||||
attached to the node unmolested (e.g. when ``foo=1`` is passed, the
|
||||
resulting schema node will have an attribute named ``foo`` with the
|
||||
value ``1``).
|
||||
|
||||
.. note:: Abitrary keyword arguments are allowed to a schema node
|
||||
constructor in Colander 0.9+. Prior version disallow them.
|
||||
.. note:: You may see some higher-level systems (such as Deform) pass a
|
||||
``widget`` argument to a SchemaNode constructor. Such systems make use of
|
||||
the fact that a SchemaNode can be passed arbitrary keyword arguments for
|
||||
extension purposes. ``widget`` and other keyword arguments not enumerated
|
||||
here but which are passed during schema node construction by someone
|
||||
constructing a schema for a particular purpose are not used internally by
|
||||
Colander; they are instead only meaningful to higher-level systems which
|
||||
consume Colander schemas. Abitrary keyword arguments are allowed to a
|
||||
schema node constructor in Colander 0.9+. Prior version disallow them.
|
||||
|
||||
The name of a schema node that is introduced as a class-level
|
||||
attribute of a :class:`colander.MappingSchema`,
|
||||
|
@@ -27,13 +27,15 @@ scope.
|
||||
What Is Schema Binding?
|
||||
-----------------------
|
||||
|
||||
- Values passed to a SchemaNode (e.g. ``description``, ``missing``,
|
||||
etc.) may be an instance of the ``colander.deferred`` class.
|
||||
Instances of the ``colander.deferred`` class are callables which
|
||||
accept two positional arguments: a ``node`` and a ``kw`` dictionary.
|
||||
- Any values passed as a keyword argument to a SchemaNode
|
||||
(e.g. ``description``, ``missing``, etc.) may be an instance of the
|
||||
``colander.deferred`` class. Instances of the ``colander.deferred`` class
|
||||
are callables which accept two positional arguments: a ``node`` and a
|
||||
``kw`` dictionary.
|
||||
|
||||
- When a schema node is bound, it is cloned, and any
|
||||
``colander.deferred`` values it has as attributes will be resolved.
|
||||
- When a schema node is bound, it is cloned, and any ``colander.deferred``
|
||||
values it has as attributes will be resolved by invoking the callable
|
||||
represented by the deferred value.
|
||||
|
||||
- A ``colander.deferred`` value is a callable that accepts two
|
||||
positional arguments: the schema node being bound and a set of
|
||||
|
@@ -9,18 +9,19 @@ a new :term:`validator`.
|
||||
Defining a New Type
|
||||
-------------------
|
||||
|
||||
A new type is a class with two methods:: ``serialize`` and
|
||||
``deserialize``. ``serialize`` converts a Python data structure (an
|
||||
:term:`appstruct`) into a serialization (a :term:`cstruct`).
|
||||
``deserialize`` converts a serialized value (a :term:`cstruct`) into a
|
||||
Python data structure (a :term:`appstruct`).
|
||||
A new type is a class with two methods:: ``serialize`` and ``deserialize``.
|
||||
``serialize`` converts a Python data structure (an :term:`appstruct`) into a
|
||||
serialization (a :term:`cstruct`). ``deserialize`` converts a serialized
|
||||
value (a :term:`cstruct`) into a Python data structure (a :term:`appstruct`).
|
||||
|
||||
Here's a type which implements boolean serialization and
|
||||
deserialization. It serializes a boolean to the string ``true`` or
|
||||
``false`` or the special :attr:`colander.null` sentinel; it then
|
||||
deserializes a string (presumably ``true`` or ``false``, but allows
|
||||
some wiggle room for ``t``, ``on``, ``yes``, ``y``, and ``1``) to a
|
||||
boolean value.
|
||||
An Example
|
||||
~~~~~~~~~~
|
||||
|
||||
Here's a type which implements boolean serialization and deserialization. It
|
||||
serializes a boolean to the string ``true`` or ``false`` or the special
|
||||
:attr:`colander.null` sentinel; it then deserializes a string (presumably
|
||||
``true`` or ``false``, but allows some wiggle room for ``t``, ``on``,
|
||||
``yes``, ``y``, and ``1``) to a boolean value.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
@@ -36,6 +37,8 @@ boolean value.
|
||||
return appstruct and 'true' or 'false'
|
||||
|
||||
def deserialize(self, node, cstruct):
|
||||
if cstruct is null:
|
||||
return null
|
||||
if not isinstance(cstruct, basestring):
|
||||
raise Invalid(node, '%r is not a string' % cstruct)
|
||||
value = cstruct.lower()
|
||||
@@ -43,13 +46,6 @@ boolean value.
|
||||
return True
|
||||
return False
|
||||
|
||||
Note that the ``deserialize`` method of a type does not need to
|
||||
explicitly deserialize the :attr:`colander.null` value.
|
||||
Deserialization of the null value is dealt with at a higher level
|
||||
(with the :meth:`colander.SchemaNode.deserialize` method); a type will
|
||||
never receive an :attr:`colander.null` value as a ``cstruct`` argument
|
||||
to its ``deserialize`` method.
|
||||
|
||||
Here's how you would use the resulting class as part of a schema:
|
||||
|
||||
.. code-block:: python
|
||||
@@ -61,33 +57,60 @@ Here's how you would use the resulting class as part of a schema:
|
||||
interested = colander.SchemaNode(Boolean())
|
||||
|
||||
The above schema has a member named ``interested`` which will now be
|
||||
serialized and deserialized as a boolean, according to the logic
|
||||
defined in the ``Boolean`` type class.
|
||||
serialized and deserialized as a boolean, according to the logic defined in
|
||||
the ``Boolean`` type class.
|
||||
|
||||
Note that the only two real constraints of a type class are:
|
||||
Implementing Type Classes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- it must deal specially with the value :attr:`colander.null` within
|
||||
``serialize``, translating it to a type-specific null value.
|
||||
The constraints of a type class implementation are:
|
||||
|
||||
- its ``serialize`` method must be able to make sense of a value
|
||||
generated by its ``deserialize`` method and vice versa, except that
|
||||
the ``deserialize`` method needn't deal with the
|
||||
:attr:`colander.null` value specially even if the ``serialize``
|
||||
method returns it.
|
||||
- It must have both a ``serialize`` and ``deserialize`` method.
|
||||
|
||||
- it must deal specially with the value :attr:`colander.null` within both
|
||||
``serialize`` and ``deserialize``.
|
||||
|
||||
- its ``serialize`` method must be able to make sense of a value generated by
|
||||
its ``deserialize`` method and vice versa.
|
||||
|
||||
The ``serialize`` method of a type accepts two values: ``node``, and
|
||||
``appstruct``. ``node`` will be the schema node associated with this
|
||||
type. It is used when the type must raise a :exc:`colander.Invalid`
|
||||
error, which expects a schema node as its first constructor argument.
|
||||
``appstruct`` will be the :term:`appstruct` value that needs to be
|
||||
serialized.
|
||||
``appstruct``. ``node`` will be the schema node associated with this type.
|
||||
The node is used when the type must raise a :exc:`colander.Invalid` error,
|
||||
which expects a schema node as its first constructor argument. ``appstruct``
|
||||
will be the :term:`appstruct` value that needs to be serialized.
|
||||
|
||||
The deserialize and method of a type accept two values: ``node``, and
|
||||
``cstruct``. ``node`` will be the schema node associated with this
|
||||
type. It is used when the type must raise a :exc:`colander.Invalid`
|
||||
error, which expects a schema node as its first constructor argument.
|
||||
``cstruct`` will be the :term:`cstruct` value that needs to be
|
||||
deserialized.
|
||||
``cstruct``. ``node`` will be the schema node associated with this type.
|
||||
The node is used when the type must raise a :exc:`colander.Invalid` error,
|
||||
which expects a schema node as its first constructor argument. ``cstruct``
|
||||
will be the :term:`cstruct` value that needs to be deserialized.
|
||||
|
||||
Null Values
|
||||
~~~~~~~~~~~
|
||||
|
||||
The framework requires that both the ``serialize`` method and the
|
||||
``deserialize`` method of a type explicitly deal with the potential to
|
||||
receive a :attr:`colander.null` value. :attr:`colander.null` will be sent to
|
||||
the type during serialization and deserialization in circumstances where a
|
||||
value has not been provided by the data structure being serialized or
|
||||
deserialized. In the common case, when the ``serialize`` or ``deserialize``
|
||||
method of type receives the :attr:`colander.null` value, it should just
|
||||
return :attr:`colander.null` to its caller.
|
||||
|
||||
A type might also choose to return :attr:`colander.null` if the value it
|
||||
receives is *logically* (but not literally) null. For example,
|
||||
:class:`colander.String` type converts the empty string to ``colander.null``
|
||||
within its ``deserialize`` method.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
def deserialize(self, node, cstruct):
|
||||
if not cstruct:
|
||||
return null
|
||||
|
||||
Type Constructors
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
A type class does not need to implement a constructor (``__init__``),
|
||||
but it isn't prevented from doing so if it needs to accept arguments;
|
||||
|
@@ -17,8 +17,11 @@ that the :term:`cstruct` value corresponding to the node it's passed
|
||||
to is missing, and if possible, the value of the ``missing`` attribute
|
||||
of the corresponding node should be used instead.
|
||||
|
||||
Note that :attr:`colander.null` has no relationship to the built-in
|
||||
Python ``None`` value.
|
||||
Note that :attr:`colander.null` has no relationship to the built-in Python
|
||||
``None`` value. ``colander.null`` is used instead of ``None`` because
|
||||
``None`` is a potentially valid value for some serializations and
|
||||
deserializations, and using it as a sentinel would prevent ``None`` from
|
||||
being used in this way.
|
||||
|
||||
.. _serializing_null:
|
||||
|
||||
@@ -206,15 +209,24 @@ When a :attr:`colander.null` sentinel marker is passed to the
|
||||
:meth:`colander.SchemaNode.deserialize` method of a particular node in
|
||||
a schema, the node will take the following steps:
|
||||
|
||||
- If the schema node has an explicit ``missing`` attribute (the node's
|
||||
constructor was supplied with an explicit ``missing`` argument), the
|
||||
``missing`` value will be returned. Note that when this happens,
|
||||
the ``missing`` value is not validated by any schema node validator:
|
||||
it is simply returned.
|
||||
- The *type* object's ``deserialize`` method will be called with the null
|
||||
value to allow the type to convert the null value to a type-specific
|
||||
default. The resulting "appstruct" is used instead of the value passed
|
||||
directly to :meth:`colander.SchemaNode.deserialize` in subsequent
|
||||
operations. Most types, when they receive the ``null`` value will simply
|
||||
return it, however.
|
||||
|
||||
- If the schema node does *not* have an explicitly provided
|
||||
``missing`` attribute (the node's constructor was not supplied with
|
||||
an explicit ``missing`` value), a :exc:`colander.Invalid` exception
|
||||
- If the appstruct value computed by the type's ``deserialize`` method is
|
||||
``colander.null`` and the schema node has an explicit ``missing`` attribute
|
||||
(the node's constructor was supplied with an explicit ``missing``
|
||||
argument), the ``missing`` value will be returned. Note that when this
|
||||
happens, the ``missing`` value is not validated by any schema node
|
||||
validator: it is simply returned.
|
||||
|
||||
- If the appstruct value computed by the type's ``deserialize`` method is
|
||||
``colander.null`` and the schema node does *not* have an explicitly
|
||||
provided ``missing`` attribute (the node's constructor was not supplied
|
||||
with an explicit ``missing`` value), a :exc:`colander.Invalid` exception
|
||||
will be raised with a message indicating that the field is required.
|
||||
|
||||
.. note:: There are differences between serialization and
|
||||
@@ -255,7 +267,7 @@ an ``age`` key of :attr:`colander.null`, the ``missing`` value of
|
||||
|
||||
.. note:: Note that ``None`` can be used for the ``missing`` schema
|
||||
node value as required, as in the above example. It's no different
|
||||
than any other value used as ``missing``. or ``colander.nuil`` can
|
||||
than any other value used as ``missing``. The empty string can
|
||||
also be used as the ``missing`` value if that is helpful.
|
||||
|
||||
The :attr:`colander.null` value is also the default, so it needn't be
|
||||
|
Reference in New Issue
Block a user