update
This commit is contained in:
139
CHANGES.txt
139
CHANGES.txt
@@ -34,8 +34,10 @@ Features
|
|||||||
create a bundle of default node behavior. The subclass can define the
|
create a bundle of default node behavior. The subclass can define the
|
||||||
following methods and attributes: ``preparer``, ``validator``, ``default``,
|
following methods and attributes: ``preparer``, ``validator``, ``default``,
|
||||||
``missing``, ``name``, ``title``, ``description``, ``widget``, and
|
``missing``, ``name``, ``title``, ``description``, ``widget``, and
|
||||||
``after_bind``. For example, the older, more imperative style that
|
``after_bind``.
|
||||||
looked like this still works::
|
|
||||||
|
For example, the older, more imperative style that looked like this still
|
||||||
|
works, of course::
|
||||||
|
|
||||||
from colander import SchemaNode
|
from colander import SchemaNode
|
||||||
|
|
||||||
@@ -45,19 +47,19 @@ Features
|
|||||||
title='Ranged Int'
|
title='Ranged Int'
|
||||||
)
|
)
|
||||||
|
|
||||||
But you can alternately now do something like::
|
But you can alternately now do something like this::
|
||||||
|
|
||||||
from colander import SchemaNode
|
from colander import SchemaNode
|
||||||
|
|
||||||
class RangedIntSchemaNode(SchemaNode):
|
class RangedIntSchemaNode(SchemaNode):
|
||||||
validator = colander.range(0, 10)
|
validator = colander.Range(0, 10)
|
||||||
default = 10
|
default = 10
|
||||||
title = 'Ranged Int'
|
title = 'Ranged Int'
|
||||||
|
|
||||||
ranged_int = RangedInt()
|
ranged_int = RangedInt()
|
||||||
|
|
||||||
Values that are expected to be callables can be methods of the schemanode
|
Values that are expected to be callables can now alternately be methods of
|
||||||
subclass instead of plain attributes::
|
the schemanode subclass instead of plain attributes::
|
||||||
|
|
||||||
from colander import SchemaNode
|
from colander import SchemaNode
|
||||||
|
|
||||||
@@ -71,22 +73,22 @@ Features
|
|||||||
|
|
||||||
ranged_int = RangedInt()
|
ranged_int = RangedInt()
|
||||||
|
|
||||||
When implementing a method value that expects ``node``, ``node`` must be
|
Note that when implementing a method value such as ``validator`` that
|
||||||
provided in the call signature, even though ``node`` will almost always be
|
expects to receive a ``node`` argument, ``node`` must be provided in the
|
||||||
the same as ``self``. This is because Colander simply treats the method
|
call signature, even though ``node`` will almost always be the same as
|
||||||
as another kind of callable, be it a method, or a function, or an instance
|
``self``. This is because Colander simply treats the method as another
|
||||||
that has a ``__call__`` method. It doesn't care that it happens to be a
|
kind of callable, be it a method, or a function, or an instance that has a
|
||||||
method of ``self``, and it needs to support callables that are not
|
``__call__`` method. It doesn't care that it happens to be a method of
|
||||||
methods, so it sends ``node`` in regardless.
|
``self``, and it needs to support callables that are not methods, so it
|
||||||
|
sends ``node`` in regardless.
|
||||||
|
|
||||||
Normal inheritance rules apply to class attributes and methods defined in
|
Normal inheritance rules apply to class attributes and methods defined in
|
||||||
a schemanode subclass. If your schemanode subclass inherits from another
|
a schemanode subclass. If your schemanode subclass inherits from another
|
||||||
schemanode class, your schemanode subclass' methods and class attributes
|
schemanode class, your schemanode subclass' methods and class attributes
|
||||||
will override the superclass' methods and class attributes.
|
will override the superclass' methods and class attributes.
|
||||||
|
|
||||||
Method values that need to be deferred for binding cannot currently be
|
You can't currently use *method* definitions as ``colander.deferred``
|
||||||
implemented as ``colander.deferred`` callables. For example this will
|
callables. For example this will *not* work::
|
||||||
*not* work::
|
|
||||||
|
|
||||||
from colander import SchemaNode
|
from colander import SchemaNode
|
||||||
|
|
||||||
@@ -110,9 +112,33 @@ Features
|
|||||||
|
|
||||||
TypeError: avalidator() takes exactly 3 arguments (2 given)
|
TypeError: avalidator() takes exactly 3 arguments (2 given)
|
||||||
|
|
||||||
Instead of trying to defer methods via a decorator, you can instead use
|
However, if you treat the thing being decorated as a function instead of a
|
||||||
the ``bindings`` attribute of ``self`` to obtain access to the bind
|
method (remove the ``self`` argument from the argument list), it will
|
||||||
parameters within values that are methody::
|
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 the ``bindings`` attribute of ``self`` to
|
||||||
|
obtain access to the bind parameters within values that are plain old
|
||||||
|
methods::
|
||||||
|
|
||||||
from colander import SchemaNode
|
from colander import SchemaNode
|
||||||
|
|
||||||
@@ -129,42 +155,18 @@ Features
|
|||||||
ranged_int = RangedInt()
|
ranged_int = RangedInt()
|
||||||
bound_range_int = ranged_int.bind(request=request)
|
bound_range_int = ranged_int.bind(request=request)
|
||||||
|
|
||||||
You can use ``after_bind`` to set attributes of the schemanode that rely
|
If the things you're trying to defer aren't callables like ``validator``,
|
||||||
on binding variables, such as ``missing`` and ``default``::
|
but they're instead just plain attributes like ``missing`` or ``default``,
|
||||||
|
instead of using a ``colander.deferred``, you can use ``after_bind`` to
|
||||||
|
set attributes of the schemanode that rely on binding variables::
|
||||||
|
|
||||||
from colander import SchemaNode
|
from colander import SchemaNode
|
||||||
|
|
||||||
class RangedIntSchemaNode(SchemaNode):
|
class UserIdSchemaNode(SchemaNode):
|
||||||
default = 10
|
title = 'User Id'
|
||||||
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')
|
|
||||||
|
|
||||||
def after_bind(self, node, kw):
|
def after_bind(self, node, kw):
|
||||||
self.request = kw['request']
|
self.default = kw['request'].user.id
|
||||||
self.default = self.request.user.id
|
|
||||||
|
|
||||||
Non-method values can still be implemented as ``colander.deferred``
|
|
||||||
however::
|
|
||||||
|
|
||||||
from colander import SchemaNode
|
|
||||||
|
|
||||||
def _missing(node, kw):
|
|
||||||
request = kw['request']
|
|
||||||
if request.user.name == 'admin':
|
|
||||||
return 10
|
|
||||||
return 20
|
|
||||||
|
|
||||||
class RangedIntSchemaNode(SchemaNode):
|
|
||||||
default = 10
|
|
||||||
title = 'Ranged Int'
|
|
||||||
missing = colander.deferred(_missing)
|
|
||||||
|
|
||||||
ranged_int = RangedInt()
|
|
||||||
|
|
||||||
You can override the default values of a schemanode subclass in its
|
You can override the default values of a schemanode subclass in its
|
||||||
constructor::
|
constructor::
|
||||||
@@ -180,18 +182,41 @@ Features
|
|||||||
|
|
||||||
In the above example, the validation will be done on 0-20, not 0-10.
|
In the above example, the validation will be done on 0-20, not 0-10.
|
||||||
|
|
||||||
If your schema node names conflict with schema value attribute names, you
|
If a schema node name conflicts with a schema value attribute name on the
|
||||||
can work around it with the ``name`` argument to the schema node::
|
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
|
from colander import SchemaNode, Schema
|
||||||
|
|
||||||
class TitleNode(SchemaNode):
|
|
||||||
validator = colander.range(0, 10)
|
|
||||||
default = 10
|
|
||||||
|
|
||||||
class SomeSchema(Schema):
|
class SomeSchema(Schema):
|
||||||
title = 'Some Schema'
|
title = 'Some Schema'
|
||||||
thisnamewontmatter = TitleNode(name='title')
|
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, a ``title`` SchemaNode will
|
||||||
|
indeed be present in the child list of the ``schema`` instance
|
||||||
|
(``schema['title']`` will return the title SchemaNode) and the schema's
|
||||||
|
``title`` attribute will be ``Some Schema`` (schema.title will return
|
||||||
|
``Some Schema``).
|
||||||
|
|
||||||
Backwards Incompatibilities
|
Backwards Incompatibilities
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
Reference in New Issue
Block a user