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