Skip to content

Commit

Permalink
Merge pull request #465 from bowlofeggs/more_validators
Browse files Browse the repository at this point in the history
Add validators for querystring, path, and headers.
  • Loading branch information
leplatrem committed Nov 13, 2017
2 parents e0323c2 + 02fd558 commit ce52659
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 29 deletions.
5 changes: 4 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ CHANGELOG
3.1.0 (unreleased)
==================

- Nothing changed yet.
- In addition to the ``colander_body_validator``, there are now three more similar validators:
``colander_headers_validator``, ``colander_path_validator``, and
``colander_querystring_validator``.
- six is now a required dependency.


3.0.0 (2017-10-20)
Expand Down
8 changes: 7 additions & 1 deletion cornice/validators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@
from webob.multidict import MultiDict
from cornice.validators._colander import (
validator as colander_validator,
body_validator as colander_body_validator)
body_validator as colander_body_validator,
headers_validator as colander_headers_validator,
path_validator as colander_path_validator,
querystring_validator as colander_querystring_validator)


__all__ = ['colander_validator',
'colander_body_validator',
'colander_headers_validator',
'colander_path_validator',
'colander_querystring_validator',
'extract_cstruct',
'DEFAULT_VALIDATORS',
'DEFAULT_FILTERS']
Expand Down
95 changes: 69 additions & 26 deletions cornice/validators/_colander.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,78 @@
import inspect
import warnings

from six import with_metaclass

def body_validator(request, schema=None, deserializer=None, **kwargs):
"""
Validate the body against the schema defined on the service.
The content of the body is deserialized, validated and stored in the
``request.validated`` attribute.
.. note::
If no schema is defined, this validator does nothing.

:param request: Current request
:type request: :class:`~pyramid:pyramid.request.Request`
:param schema: The Colander schema
:param deserializer: Optional deserializer, defaults to
:func:`cornice.validators.extract_cstruct`
def _generate_colander_validator(location):
"""
import colander

if schema is None:
return

class RequestSchema(colander.MappingSchema):
body = _ensure_instantiated(schema)

validator(request, RequestSchema(), deserializer, **kwargs)
request.validated = request.validated.get('body', {})
Generate a colander validator for data from the given location.
:param location: The location in the request to find the data to be
validated, such as "body" or "querystring".
:type location: str
:return: Returns a callable that will validate the request at the given
location.
:rtype: callable
"""
def _validator(request, schema=None, deserializer=None, **kwargs):
"""
Validate the location against the schema defined on the service.
The content of the location is deserialized, validated and stored in
the ``request.validated`` attribute.
.. note::
If no schema is defined, this validator does nothing.
:param request: Current request
:type request: :class:`~pyramid:pyramid.request.Request`
:param schema: The Colander schema
:param deserializer: Optional deserializer, defaults to
:func:`cornice.validators.extract_cstruct`
"""
import colander

if schema is None:
return

class RequestSchemaMeta(type):
"""
A metaclass that will inject a location class attribute into
RequestSchema.
"""
def __new__(cls, name, bases, class_attrs):
"""
Instantiate the RequestSchema class.
:param name: The name of the class we are instantiating. Will
be "RequestSchema".
:type name: str
:param bases: The class's superclasses.
:type bases: tuple
:param dct: The class's class attributes.
:type dct: dict
"""
class_attrs[location] = _ensure_instantiated(schema)
return type(name, bases, class_attrs)

class RequestSchema(with_metaclass(
RequestSchemaMeta, colander.MappingSchema)):
"""A schema to validate the request's location attributes."""
pass

validator(request, RequestSchema(), deserializer, **kwargs)
request.validated = request.validated.get(location, {})

return _validator


body_validator = _generate_colander_validator('body')
headers_validator = _generate_colander_validator('headers')
path_validator = _generate_colander_validator('path')
querystring_validator = _generate_colander_validator('querystring')


def validator(request, schema=None, deserializer=None, **kwargs):
Expand Down
3 changes: 3 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ Validation

.. autofunction:: cornice.validators.extract_cstruct
.. autofunction:: cornice.validators.colander_body_validator
.. autofunction:: cornice.validators.colander_headers_validator
.. autofunction:: cornice.validators.colander_path_validator
.. autofunction:: cornice.validators.colander_querystring_validator
.. autofunction:: cornice.validators.colander_validator


Expand Down
5 changes: 5 additions & 0 deletions docs/source/schema.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ Example:
def post(request):
return request.validated
In addition to ``colander_body_validator()`` as demonstrated above, there are also three more
similar validators, ``colander_headers_validator()``, ``colander_path_validator()``, and
``colander_querystring_validator()``, which validate the given ``Schema`` against the headers, path,
or querystring parameters, respectively.


Multiple request attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
with open(os.path.join(here, 'CHANGES.txt')) as f:
CHANGES = f.read()

requires = ['pyramid>=1.7', 'simplejson']
requires = ['pyramid>=1.7', 'simplejson', 'six']

entry_points = ""
package_data = {}
Expand Down

0 comments on commit ce52659

Please sign in to comment.