Skip to content

Commit

Permalink
Merge pull request #504 from czekan/feature/changes-in-colander-valid…
Browse files Browse the repository at this point in the history
…ation

Feature/changes in colander validation
  • Loading branch information
leplatrem committed Dec 2, 2019
2 parents c487ac5 + 8aca015 commit e7e75b4
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 4 deletions.
3 changes: 2 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ CHANGELOG
3.7.0 (unreleased)
==================

- Nothing changed yet.
- Fix updating request.validated dict in ``colander_*_validator``
- Check for ``MappingSchema`` instance in ``colander_*_validator`` (possibly breaking change)


3.6.1 (2019-11-13)
Expand Down
9 changes: 8 additions & 1 deletion cornice/validators/_colander.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def _validator(request, schema=None, deserializer=None, **kwargs):
.. note::
If no schema is defined, this validator does nothing.
Schema should be of type :class:`~colander:colander.MappingSchema`.
:param request: Current request
:type request: :class:`~pyramid:pyramid.request.Request`
Expand All @@ -42,6 +43,10 @@ def _validator(request, schema=None, deserializer=None, **kwargs):
if schema is None:
return

if not isinstance(schema, colander.MappingSchema):
raise TypeError("Schema should inherit from "
"colander.MappingSchema.")

class RequestSchemaMeta(type):
"""
A metaclass that will inject a location class attribute into
Expand All @@ -68,7 +73,9 @@ class RequestSchema(with_metaclass(
pass

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

return _validator

Expand Down
6 changes: 6 additions & 0 deletions docs/source/schema.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ To describe a schema, using Colander and Cornice, here is how you can do:
username = request.validated['username']
return {'success': True}
.. note::

When you use one of ``colander_body_validator``, ``colander_headers_validator``,
``colander_querystring_validator`` etc. it is necessary to set schema which
inherits from :class:`colander.MappingSchema`. If you need to deserialize
:class:`colander.SequenceSchema` you need to use ``colander_validator`` instead.


Using Marshmallow
Expand Down
15 changes: 13 additions & 2 deletions tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,10 +416,21 @@ def test_valid_nonstandard_json(self):
)
self.assertEqual(response.json['username'], 'man')

def test_valid_json_array(self):
def test_json_array_with_colander_body_validator(self):
app = self.make_ordinary_app()

with self.assertRaises(TypeError) as context:
app.post_json(
'/group_signup',
[{'username': 'hey'}, {'username': 'how'}]
)
self.assertIn('Schema should inherit from colander.MappingSchema.',
str(context))

def test_json_array_with_colander_validator(self):
app = self.make_ordinary_app()
response = app.post_json(
'/group_signup',
'/body_group_signup',
[{'username': 'hey'}, {'username': 'how'}]
)
self.assertEqual(response.json['data'],
Expand Down
9 changes: 9 additions & 0 deletions tests/validationapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ def post7(request):
signup = Service(name="signup", path="/signup")
bound = Service(name="bound", path="/bound")
group_signup = Service(name="group signup", path="/group_signup")
body_group_signup = Service(name="body_group signup", path="/body_group_signup")
foobar = Service(name="foobar", path="/foobar")
foobaz = Service(name="foobaz", path="/foobaz")
email_service = Service(name='newsletter', path='/newsletter')
Expand Down Expand Up @@ -214,6 +215,14 @@ class GroupSignupSchema(SequenceSchema):
def group_signup_post(request):
return {'data': request.validated}

class BodyGroupSignupSchema(MappingSchema):
body = GroupSignupSchema()

@body_group_signup.post(schema=BodyGroupSignupSchema(),
validators=(colander_validator,))
def body_group_signup_post(request):
return {'data': request.validated['body']}

def validate_bar(node, value):
if value != 'open':
raise Invalid(node, "The bar is not open.")
Expand Down

0 comments on commit e7e75b4

Please sign in to comment.