Skip to content

Commit

Permalink
Merge pull request #516 from mamalos/support-kwargs-in-marshmallow-va…
Browse files Browse the repository at this point in the history
…lidator

Support kwargs in marshmallow validator
  • Loading branch information
leplatrem committed Dec 5, 2019
2 parents cb50d9b + 236a660 commit 9df75f5
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 17 deletions.
2 changes: 1 addition & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ CHANGELOG
4.1.0 (unreleased)
==================

- Nothing changed yet.
- Add support for passing keyword arguments to marshmallow validator.


4.0.1 (2019-12-02)
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Cornice:
* Gabriela Surita <gsurita@mozilla.com>
* Gael Pasgrimaud <gael@gawel.org>
* George V. Reilly <george@reilly.org>
* George Mamalakis <mamalos@gmail.com>
* Graham Higgins <gjh-github@bel-epa.com>
* G.Tjebbes <g.t@majerti.fr>
* Guillaume Gauvrit <guillaume@gandi.net>
Expand Down
22 changes: 18 additions & 4 deletions cornice/validators/_marshmallow.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ def _validator(request, schema=None, deserializer=None, **kwargs):
The content of the location is deserialized, validated and stored in
the ``request.validated`` attribute.
Keyword arguments to be included when initialising the marshmallow
schema can be passed as a dict in ``kwargs['schema_kwargs']`` variable.
.. note::
If no schema is defined, this validator does nothing.
Expand All @@ -46,10 +49,12 @@ def _validator(request, schema=None, deserializer=None, **kwargs):
if schema is None:
return

schema = _instantiate_schema(schema)
# see if the user wants to set any keyword arguments for their schema
schema_kwargs = kwargs.get('schema_kwargs', {})
schema = _instantiate_schema(schema, **schema_kwargs)

class ValidatedField(marshmallow.fields.Field):
def _deserialize(self, value, attr, data):
def _deserialize(self, value, attr, data, **kwargs):
schema.context.setdefault('request', request)
deserialized = schema.load(value)
# marshmallow 2.x returns a tuple, 3/x will always throw
Expand Down Expand Up @@ -185,8 +190,17 @@ def validator(request, schema=None, deserializer=None, **kwargs):
request.validated.update(deserialized)


def _instantiate_schema(schema):
def _instantiate_schema(schema, **kwargs):
"""
Returns an object of the given marshmallow schema.
:param schema: The marshmallow schema class with which the request should
be validated
:param kwargs: The keyword arguments that will be provided to the
marshmallow schema's constructor
:return: The object of the marshmallow schema
"""
if not inspect.isclass(schema):
raise ValueError('You need to pass Marshmallow class instead '
'of schema instance')
return schema()
return schema(**kwargs)
22 changes: 10 additions & 12 deletions tests/validationapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,16 +357,6 @@ class Meta:
unknown = EXCLUDE
username = marshmallow.fields.String()

class MSignupGroupSchema(marshmallow.Schema):
class Meta:
strict = True
unknown = EXCLUDE
username = marshmallow.fields.String()

def __init__(self, *args, **kwargs):
kwargs['many'] = True
marshmallow.Schema.__init__(self, *args, **kwargs)

import random

class MNeedsContextSchema(marshmallow.Schema):
Expand All @@ -392,8 +382,15 @@ def m_bound_post(request):
def signup_post(request):
return request.validated

@m_group_signup.post(
schema=MSignupGroupSchema, validators=(marshmallow_body_validator,))
# callback that returns a validator with keyword arguments for marshmallow
# schema initialisation. In our case it passes many=True to the desired
# schema
def get_my_marshmallow_validator_with_kwargs(request, **kwargs):
kwargs['schema'] = MSignupSchema
kwargs['schema_kwargs'] = {'many': True}
return marshmallow_body_validator(request, **kwargs)

@m_group_signup.post(validators=(get_my_marshmallow_validator_with_kwargs,))
def m_group_signup_post(request):
return {'data': request.validated}

Expand Down Expand Up @@ -520,6 +517,7 @@ class Meta:
def m_form(request):
return request.validated


def includeme(config):
config.include("cornice")
config.scan("tests.validationapp")
Expand Down

0 comments on commit 9df75f5

Please sign in to comment.