Skip to content

Commit

Permalink
Merge 7fcb79d into e4a30e8
Browse files Browse the repository at this point in the history
  • Loading branch information
kpsherva committed Jul 30, 2019
2 parents e4a30e8 + 7fcb79d commit 09336a9
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 6 deletions.
42 changes: 42 additions & 0 deletions invenio_files_rest/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""REST API serializers."""

import json
import warnings
from time import sleep

from flask import current_app, request, url_for
Expand All @@ -18,6 +19,37 @@
from .models import Bucket, MultipartObject, ObjectVersion, Part


class MarshalResultBase(object):
"""Wrapper class to provide backward compatibility with marshmallow 2."""

def __new__(cls, result, errors=None, *args, **kwargs):
"""Instanciate Marshal Result class."""
def data(self):
warnings.warn(
"Schema().dump().data and Schema().dump().errors attributes "
"are deprecated in marshmallow v3.x. Use .dump() "
"and error handler instead.",
category=DeprecationWarning, stacklevel=2)
return result

setattr(cls, 'data', property(data))
return super(MarshalResultBase, cls).__new__(
cls, result, errors, *args, **kwargs)

def __init__(self, result):
"""Initialize MarshalResult."""
super(MarshalResultBase, self).__init__(result)


def dump_wrapper(result):
"""Wrap schema returned dump value."""
if isinstance(result, tuple):
return result
MarshalResult = type('MarshalResult',
(MarshalResultBase, type(result)), {})
return MarshalResult(result)


class BaseSchema(Schema):
"""Base schema for all serializations."""

Expand All @@ -29,6 +61,16 @@ def dump_links(self, o):
"""Get base links."""
return missing

def dump(self, obj, many=None, update_fields=True, **kwargs):
"""Wrap dump result for backward compatibility."""
result = super(BaseSchema, self).dump(obj, many=many, **kwargs)
return dump_wrapper(result)

def dumps(self, obj, many=None, update_fields=True, *args, **kwargs):
"""Wrap dumps result for backward compatibility."""
result = super(BaseSchema, self).dumps(obj, *args, many=many, **kwargs)
return dump_wrapper(result)


class BucketSchema(BaseSchema):
"""Schema for bucket."""
Expand Down
19 changes: 19 additions & 0 deletions invenio_files_rest/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,23 @@ def parse_header_tags():
load_from='partNumber',
location='query',
required=True,
data_key='partNumber',
),
'content_length': fields.Int(
load_from='Content-Length',
location='headers',
required=True,
validate=minsize_validator,
data_key='Content-Length',
),
'content_type': fields.Str(
load_from='Content-Type',
location='headers',
data_key='Content-Type',
),
'content_md5': fields.Str(
data_key='Content-MD5',
load_from='Content-MD5',
location='headers',
),
Expand All @@ -139,17 +144,20 @@ def default_partfactory(part_number=None, content_length=None,
@use_kwargs({
'content_md5': fields.Str(
load_from='Content-MD5',
data_key='Content-MD5',
location='headers',
missing=None,
),
'content_length': fields.Int(
load_from='Content-Length',
data_key='Content-Length',
location='headers',
required=True,
validate=minsize_validator,
),
'content_type': fields.Str(
load_from='Content-Type',
data_key='Content-Type',
location='headers',
missing='',
),
Expand All @@ -174,17 +182,20 @@ def stream_uploadfactory(content_md5=None, content_length=None,
@use_kwargs({
'part_number': fields.Int(
load_from='_chunkNumber',
data_key='_chunkNumber',
location='form',
required=True,
),
'content_length': fields.Int(
load_from='_currentChunkSize',
data_key='_currentChunkSize',
location='form',
required=True,
validate=minsize_validator,
),
'uploaded_file': fields.Raw(
load_from='file',
data_key='file',
location='files',
required=True,
),
Expand All @@ -206,16 +217,19 @@ def ngfileupload_partfactory(part_number=None, content_length=None,
@use_kwargs({
'content_length': fields.Int(
load_from='_totalSize',
data_key='_totalSize',
location='form',
required=True,
),
'content_type': fields.Str(
load_from='Content-Type',
data_key='Content-Type',
location='headers',
required=True,
),
'uploaded_file': fields.Raw(
load_from='file',
data_key='file',
location='files',
required=True,
),
Expand Down Expand Up @@ -444,11 +458,13 @@ class ObjectResource(ContentNegotiatedMethodView):
'version_id': fields.UUID(
location='query',
load_from='versionId',
data_key='versionId',
missing=None,
),
'upload_id': fields.UUID(
location='query',
load_from='uploadId',
data_key='uploadId',
missing=None,
),
'uploads': fields.Raw(
Expand All @@ -472,6 +488,7 @@ class ObjectResource(ContentNegotiatedMethodView):
'upload_id': fields.UUID(
location='query',
load_from='uploadId',
data_key='uploadId',
missing=None,
)
}
Expand All @@ -480,6 +497,7 @@ class ObjectResource(ContentNegotiatedMethodView):
'upload_id': fields.UUID(
location='query',
load_from='uploadId',
data_key='uploadId',
missing=None,
),
}
Expand All @@ -493,6 +511,7 @@ class ObjectResource(ContentNegotiatedMethodView):
locations=('query', 'json'),
missing=None,
load_from='partSize',
data_key='partSize',
),
}

Expand Down
17 changes: 14 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
'pydocstyle>=1.0.0',
'pytest-cov>=1.8.0',
'pytest-pep8>=1.0.6',
'pytest>=3.7.0',
'pytest>=4.0.0,<5.0.0',
]

extras_require = {
Expand All @@ -48,6 +48,14 @@
'invenio-db>=1.0.0',
],
'tests': tests_require,
':python_version<"3.0.0"': [
'marshmallow>=2.15.1,<3.0.0',
'webargs>=1.1.1',
],
':python_version>="3.0.0"': [
'marshmallow>=2.15.1',
'webargs>=1.1.1',
]
}

extras_require['all'] = []
Expand All @@ -63,11 +71,14 @@
'Flask>=0.11.1',
'fs>=0.5.4,<2.0',
'invenio-rest[cors]>=1.0.0',
'marshmallow>=2.15.1,<3.0.0',
# 'marshmallow>=2.15.1,<3.0.0;python_version<"3.0.0"',
# 'marshmallow>=3.0.0rc8;python_version>="3.0.0"',
'simplejson>=3.0.0',
'SQLAlchemy-Utils>=0.31.0',
'webargs>=1.1.1',
# 'webargs>=1.1.1;python_version<"3.0.0"',
# 'webargs>=5.4.0;python_version>="3.0.0"',
'WTForms>=2.0',

]

setup_requires = [
Expand Down
33 changes: 30 additions & 3 deletions tests/test_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@

from __future__ import absolute_import, print_function

from marshmallow import Schema, fields
from collections import namedtuple

from invenio_files_rest.serializer import json_serializer, serializer_mapping
from marshmallow import fields

from invenio_files_rest.serializer import BaseSchema, dump_wrapper, \
json_serializer, serializer_mapping


def test_serialize_pretty(app):
"""Test pretty JSON."""
class TestSchema(Schema):
class TestSchema(BaseSchema):
title = fields.Str(attribute='title')

data = {'title': 'test'}
Expand All @@ -26,10 +29,34 @@ class TestSchema(Schema):

serializer_mapping['TestSchema'] = TestSchema

# TODO This test should be checked if it shouldn't have
# BaseSchema instead of Schema
with app.test_request_context():
assert json_serializer(data=data, context=context).data == \
b'{"title":"test"}'

with app.test_request_context('/?prettyprint=1'):
assert json_serializer(data=data, context=context).data == \
b'{\n "title": "test"\n}'


def test_marshmallow_compatibility():
"""Test wrapper class for marshmallow schema compatibility."""
dict_result = {'test': 1}
list_result = [{'test': 1}, {'test': 2}]
old_marshal = namedtuple('MarshalResult', ['data', 'errors'])
tuple_result = old_marshal({'test': 1}, [{'field': 5}])

wrapped = dump_wrapper(dict_result)

assert wrapped == dict_result
assert wrapped.data == dict_result

wrapped = dump_wrapper(list_result)
assert wrapped == list_result
assert wrapped.data == list_result

wrapped = dump_wrapper(tuple_result)
assert wrapped == tuple_result
assert isinstance(wrapped, tuple)
assert tuple_result.data == dict_result

0 comments on commit 09336a9

Please sign in to comment.