Skip to content

Commit

Permalink
Merge pull request #280 from mozilla-services/preserve-schemas
Browse files Browse the repository at this point in the history
Preserve values if colander has unknown="preserve".
  • Loading branch information
almet committed Mar 2, 2015
2 parents d0c580b + 43ebab5 commit e429753
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
8 changes: 8 additions & 0 deletions cornice/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ def validate_colander_schema(schema, request):
"""Validates that the request is conform to the given schema"""
from colander import Invalid, Sequence, drop, null, MappingSchema

schema_type = schema.colander_schema.schema_type()
unknown = getattr(schema_type, 'unknown', None)

if not isinstance(schema.colander_schema, MappingSchema):
raise SchemaError('schema is not a MappingSchema: %s' %
type(schema.colander_schema))
Expand Down Expand Up @@ -150,6 +153,11 @@ def _validate_fields(location, data):
if deserialized is not drop:
request.validated[attr.name] = deserialized

if location == "body" and unknown == 'preserve':
for field, value in data.items():
if field not in request.validated:
request.validated[field] = value

qs, headers, body, path = extract_request_data(request)

_validate_fields('path', path)
Expand Down
20 changes: 20 additions & 0 deletions cornice/tests/test_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
CorniceSchema, validate_colander_schema, SchemaError
)
from cornice.util import extract_json_data
import json

try:
from colander import (
Expand Down Expand Up @@ -106,6 +107,12 @@ class TestingSchemaWithHeader(MappingSchema):
baz = SchemaNode(String(), type='str', location="querystring")
qux = SchemaNode(String(), type='str', location="header")

class PreserveUnkownSchema(MappingSchema):
bar = SchemaNode(String(), type='str')

def schema_type(self, **kw):
return Mapping(unknown='preserve')

def get_mock_request(body, get=None):
# Construct a mock request with the given request body
class MockRegistry(object):
Expand Down Expand Up @@ -349,3 +356,16 @@ def test_extra_params_qs_strict(self):

expected = {'foo': 'test'}
self.assertEqual(expected, dummy_request.validated)

def test_validate_colander_schema_can_preserve_unknown_fields(self):
schema = CorniceSchema.from_colander(PreserveUnkownSchema)

data = json.dumps({"bar": "required_data", "optional": "true"})
dummy_request = get_mock_request(data)
validate_colander_schema(schema, dummy_request)

self.assertDictEqual(dummy_request.validated, {
"bar": "required_data",
"optional": "true"
})
self.assertEqual(len(dummy_request.errors), 0)

0 comments on commit e429753

Please sign in to comment.