implement, document and test the 'instantiate' decorator
This commit is contained in:
@@ -6,6 +6,9 @@ Features
|
|||||||
|
|
||||||
- Add ``colander.ContainsOnly`` and ``colander.url`` validators.
|
- Add ``colander.ContainsOnly`` and ``colander.url`` validators.
|
||||||
|
|
||||||
|
- Add ``colander.instantiate`` to help define schemas containing
|
||||||
|
mappings and sequences more succinctly.
|
||||||
|
|
||||||
1.0a1 (2013-01-10)
|
1.0a1 (2013-01-10)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@@ -2089,3 +2089,18 @@ def _unflatten_mapping(node, paths, fstruct,
|
|||||||
appstruct[curname] = subnode.typ.unflatten(
|
appstruct[curname] = subnode.typ.unflatten(
|
||||||
subnode, subpaths, subfstruct)
|
subnode, subpaths, subfstruct)
|
||||||
return appstruct
|
return appstruct
|
||||||
|
|
||||||
|
class instantiate(object):
|
||||||
|
"""
|
||||||
|
A decorator which can be used to instantiate :class:`SchemaNode`
|
||||||
|
elements inline within a class definition.
|
||||||
|
|
||||||
|
All parameters passed to the decorator and passed along to the
|
||||||
|
:class:`SchemaNode` during instantiation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self,*args,**kw):
|
||||||
|
self.args,self.kw = args,kw
|
||||||
|
|
||||||
|
def __call__(self,class_):
|
||||||
|
return class_(*self.args,**self.kw)
|
||||||
|
@@ -3337,6 +3337,42 @@ class TestUltraDeclarative(unittest.TestCase, TestFunctional):
|
|||||||
schema = MainSchema()
|
schema = MainSchema()
|
||||||
return schema
|
return schema
|
||||||
|
|
||||||
|
class TestDeclarativeWithInstantiate(unittest.TestCase, TestFunctional):
|
||||||
|
|
||||||
|
def _makeSchema(self, name='schema'):
|
||||||
|
|
||||||
|
import colander
|
||||||
|
|
||||||
|
# an unlikely usage, but goos to test passing
|
||||||
|
# parameters to instantiation works
|
||||||
|
@colander.instantiate(name=name)
|
||||||
|
class schema(colander.MappingSchema):
|
||||||
|
int = colander.SchemaNode(colander.Int(),
|
||||||
|
validator=colander.Range(0, 10))
|
||||||
|
ob = colander.SchemaNode(colander.GlobalObject(package=colander))
|
||||||
|
@colander.instantiate()
|
||||||
|
class seq(colander.SequenceSchema):
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class tup(colander.TupleSchema):
|
||||||
|
tupint = colander.SchemaNode(colander.Int())
|
||||||
|
tupstring = colander.SchemaNode(colander.String())
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class tup(colander.TupleSchema):
|
||||||
|
tupint = colander.SchemaNode(colander.Int())
|
||||||
|
tupstring = colander.SchemaNode(colander.String())
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class seq2(colander.SequenceSchema):
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class mapping(colander.MappingSchema):
|
||||||
|
key = colander.SchemaNode(colander.Int())
|
||||||
|
key2 = colander.SchemaNode(colander.Int())
|
||||||
|
|
||||||
|
return schema
|
||||||
|
|
||||||
class Test_null(unittest.TestCase):
|
class Test_null(unittest.TestCase):
|
||||||
def test___nonzero__(self):
|
def test___nonzero__(self):
|
||||||
from colander import null
|
from colander import null
|
||||||
|
@@ -132,6 +132,8 @@ Schema-Related
|
|||||||
|
|
||||||
.. autoclass:: deferred
|
.. autoclass:: deferred
|
||||||
|
|
||||||
|
.. autoclass:: instantiate
|
||||||
|
|
||||||
.. attribute:: null
|
.. attribute:: null
|
||||||
|
|
||||||
Represents a null value in colander-related operations.
|
Represents a null value in colander-related operations.
|
||||||
|
@@ -982,6 +982,63 @@ indeed be present in the child list of the ``schema`` instance
|
|||||||
``title`` attribute will be ``Some Schema`` (``schema.title`` will return
|
``title`` attribute will be ``Some Schema`` (``schema.title`` will return
|
||||||
``Some Schema``).
|
``Some Schema``).
|
||||||
|
|
||||||
|
Defining A Schema Declaratively
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Previously, we defined the schema in such a way that the individual
|
||||||
|
sequences and mappings within the schema could be re-used in different
|
||||||
|
schemas. If all nodes within a schema are only likely to be used in that
|
||||||
|
schema, then the schema definition can be made more succinct using the
|
||||||
|
:class:`~colander.instantiate` class decorator as shown below:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
import colander
|
||||||
|
|
||||||
|
class Person(colander.MappingSchema):
|
||||||
|
name = colander.SchemaNode(colander.String())
|
||||||
|
age = colander.SchemaNode(colander.Int(),
|
||||||
|
validator=colander.Range(0, 200))
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class friends(colander.SequenceSchema):
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class friend(colander.TupleSchema):
|
||||||
|
rank = colander.SchemaNode(colander.Int(),
|
||||||
|
validator=colander.Range(0, 9999))
|
||||||
|
name = colander.SchemaNode(colander.String())
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class phones(colander.SequenceSchema):
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class phone(colander.MappingSchema):
|
||||||
|
location = colander.SchemaNode(colander.String(),
|
||||||
|
validator=colander.OneOf(['home', 'work']))
|
||||||
|
number = colander.SchemaNode(colander.String())
|
||||||
|
|
||||||
|
If you need to pass parameters when using this style of schema
|
||||||
|
definition, such as a ``missing`` value to a :class:`SchemaNode`
|
||||||
|
during instantiation, you can pass these as parameters to
|
||||||
|
:class:`~colander.instantiate`.
|
||||||
|
For example, if we wanted to limit the number of friends a person can
|
||||||
|
have, and cater for people who have no friends, we could adjust the
|
||||||
|
schema as shown below:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
class Person(colander.MappingSchema):
|
||||||
|
|
||||||
|
@colander.instantiate(missing=(),
|
||||||
|
validator=colander.Length(max=5))
|
||||||
|
class friends(colander.SequenceSchema):
|
||||||
|
|
||||||
|
@colander.instantiate()
|
||||||
|
class friend(colander.TupleSchema):
|
||||||
|
name = colander.SchemaNode(colander.String())
|
||||||
|
|
||||||
Defining A Schema Imperatively
|
Defining A Schema Imperatively
|
||||||
------------------------------
|
------------------------------
|
||||||
|
Reference in New Issue
Block a user