mirror of
https://github.com/sprockets/sprockets.mixins.mediatype.git
synced 2024-11-25 03:00:24 +00:00
commit
daacd40488
21 changed files with 97 additions and 192 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -14,6 +14,7 @@ downloads
|
|||
eggs
|
||||
fake-eggs
|
||||
parts
|
||||
.eggs
|
||||
|
||||
# Packages #
|
||||
############
|
||||
|
|
18
.travis.yml
18
.travis.yml
|
@ -1,23 +1,23 @@
|
|||
language: python
|
||||
dist: xenial
|
||||
python:
|
||||
- 2.7
|
||||
- 3.4
|
||||
- 3.5
|
||||
- 3.6
|
||||
- 3.7-dev
|
||||
- pypy
|
||||
- 3.7
|
||||
install:
|
||||
- pip install codecov
|
||||
- pip install -r requires/installation.txt
|
||||
- pip install -r requires/testing.txt
|
||||
script: nosetests
|
||||
- pip install codecov -r requires/development.txt
|
||||
script:
|
||||
- nosetests
|
||||
- python setup.py build_sphinx
|
||||
- python setup.py check
|
||||
- flake8
|
||||
after_success:
|
||||
- codecov
|
||||
deploy:
|
||||
distributions: sdist bdist_wheel
|
||||
provider: pypi
|
||||
on:
|
||||
python: 2.7
|
||||
python: 3.7
|
||||
tags: true
|
||||
all_branches: true
|
||||
user: sprockets
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2015-2016 AWeber Communications
|
||||
Copyright (c) 2015-2018 AWeber Communications
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
|
|
@ -89,13 +89,11 @@ request handlers.
|
|||
class SomeHandler(content.ContentMixin, web.RequestHandler):
|
||||
def get(self):
|
||||
self.send_response({'data': 'value'})
|
||||
self.finish()
|
||||
|
||||
def post(self):
|
||||
body = self.get_request_body()
|
||||
# do whatever
|
||||
self.send_response({'action': 'performed'})
|
||||
self.finish()
|
||||
|
||||
Based on the settings stored in the ``Application`` instance and the HTTP
|
||||
headers, the request and response data will be handled correctly or the
|
||||
|
|
|
@ -33,6 +33,3 @@ Bundled Transcoders
|
|||
|
||||
.. autoclass:: MsgPackTranscoder
|
||||
:members:
|
||||
|
||||
.. autoclass:: BinaryWrapper
|
||||
:members:
|
||||
|
|
11
docs/conf.py
11
docs/conf.py
|
@ -1,23 +1,18 @@
|
|||
import alabaster
|
||||
from sprockets.mixins.mediatype import __version__
|
||||
import pkg_resources
|
||||
|
||||
needs_sphinx = '1.0'
|
||||
extensions = ['sphinx.ext.autodoc',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinxcontrib.autohttp.tornado']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
project = 'sprockets.mixins.mediatype'
|
||||
copyright = '2015-2016, AWeber Communications'
|
||||
release = __version__
|
||||
copyright = '2015-2018, AWeber Communications'
|
||||
release = pkg_resources.get_distribution('sprockets.mixins.mediatype').version
|
||||
version = '.'.join(release.split('.')[0:1])
|
||||
|
||||
pygments_style = 'sphinx'
|
||||
html_theme = 'alabaster'
|
||||
html_style = 'custom.css'
|
||||
html_static_path = ['static']
|
||||
html_theme_path = [alabaster.get_path()]
|
||||
html_sidebars = {
|
||||
'**': ['about.html', 'navigation.html'],
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ class SimpleHandler(content.ContentMixin, web.RequestHandler):
|
|||
body = self.get_request_body()
|
||||
self.set_status(200)
|
||||
self.send_response(body)
|
||||
self.finish()
|
||||
|
||||
|
||||
def make_application(**settings):
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
-e .[msgpack]
|
||||
-r docs.txt
|
||||
-r testing.txt
|
||||
-r installation.txt
|
||||
sphinx>=1.2,<2
|
||||
sphinxcontrib-httpdomain>=1.3,<2
|
||||
|
|
2
requires/docs.txt
Normal file
2
requires/docs.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
sphinx==1.8.2
|
||||
sphinxcontrib-httpdomain==1.7.0
|
|
@ -1,2 +1,2 @@
|
|||
ietfparse>=1.4,<1.5
|
||||
tornado>=3.2,<6
|
||||
tornado>=5,<6
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
coverage>=3.7,<3.99 # prevent installing 4.0b on ALL pip versions
|
||||
mock>=1.3,<2
|
||||
u-msgpack-python>=2,<3
|
||||
nose>=1.3,<2
|
||||
coverage==4.5.2
|
||||
flake8==3.6.0
|
||||
nose==1.3.7
|
||||
tox==3.5.3
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
[bdist_wheel]
|
||||
universal = 1
|
||||
|
||||
[build_sphinx]
|
||||
fresh-env = 1
|
||||
warning-is-error = 1
|
||||
|
||||
[check]
|
||||
strict = 1
|
||||
|
||||
[nosetests]
|
||||
cover-branches = 1
|
||||
cover-erase = 1
|
||||
|
|
59
setup.py
59
setup.py
|
@ -1,38 +1,30 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import setuptools
|
||||
|
||||
from sprockets.mixins import mediatype
|
||||
|
||||
REPO_DIR = pathlib.Path(__name__).parent
|
||||
|
||||
|
||||
def read_requirements(file_name):
|
||||
def read_requirements(name):
|
||||
requirements = []
|
||||
try:
|
||||
with open(os.path.join('requires', file_name)) as req_file:
|
||||
for req_line in req_file:
|
||||
req_line = req_line.strip()
|
||||
if '#' in req_line:
|
||||
req_line = req_line[0:req_line.find('#')].strip()
|
||||
if req_line.startswith('-r'):
|
||||
req_line = req_line[2:].strip()
|
||||
requirements.extend(read_requirements(req_line))
|
||||
else:
|
||||
requirements.append(req_line)
|
||||
except IOError:
|
||||
pass
|
||||
for req_line in REPO_DIR.joinpath(name).read_text().split('\n'):
|
||||
req_line = req_line.strip()
|
||||
if '#' in req_line:
|
||||
req_line = req_line[0:req_line.find('#')].strip()
|
||||
if req_line.startswith('-r'):
|
||||
req_line = req_line[2:].strip()
|
||||
requirements.extend(read_requirements(req_line))
|
||||
else:
|
||||
requirements.append(req_line)
|
||||
return requirements
|
||||
|
||||
|
||||
install_requires = read_requirements('installation.txt')
|
||||
tests_require = read_requirements('testing.txt')
|
||||
|
||||
setuptools.setup(
|
||||
name='sprockets.mixins.mediatype',
|
||||
version=mediatype.__version__,
|
||||
description='A mixin for reporting handling content-type/accept headers',
|
||||
long_description='\n' + open('README.rst').read(),
|
||||
long_description=REPO_DIR.joinpath('README.rst').read_text(),
|
||||
url='https://github.com/sprockets/sprockets.mixins.media_type',
|
||||
author='AWeber Communications',
|
||||
author_email='api@aweber.com',
|
||||
|
@ -43,24 +35,27 @@ setuptools.setup(
|
|||
'License :: OSI Approved :: BSD License',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: Implementation :: CPython',
|
||||
'Programming Language :: Python :: Implementation :: PyPy',
|
||||
'Topic :: Software Development :: Libraries',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules'
|
||||
],
|
||||
packages=setuptools.find_packages(),
|
||||
install_requires=install_requires,
|
||||
tests_require=tests_require,
|
||||
packages=[
|
||||
'sprockets',
|
||||
'sprockets.mixins',
|
||||
'sprockets.mixins.mediatype'
|
||||
],
|
||||
install_requires=read_requirements('requires/installation.txt'),
|
||||
tests_require=read_requirements('requires/testing.txt'),
|
||||
extras_require={
|
||||
'msgpack': ['u-msgpack-python>=2.5.0,<3']
|
||||
},
|
||||
setup_requires=['setuptools_scm'],
|
||||
use_scm_version=True,
|
||||
namespace_packages=['sprockets', 'sprockets.mixins'],
|
||||
test_suite='nose.collector',
|
||||
python_requires='>=3.5',
|
||||
zip_safe=False)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
__import__('pkg_resources').declare_namespace(__name__)
|
|
@ -1 +0,0 @@
|
|||
__import__('pkg_resources').declare_namespace(__name__)
|
|
@ -3,28 +3,11 @@ sprockets.mixins.media_type
|
|||
|
||||
"""
|
||||
|
||||
try:
|
||||
from .content import (ContentMixin, ContentSettings,
|
||||
add_binary_content_type, add_text_content_type,
|
||||
set_default_content_type)
|
||||
|
||||
except ImportError as error: # pragma no cover
|
||||
def _error_closure(*args, **kwargs):
|
||||
raise error
|
||||
|
||||
class ErrorClosureClass(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
raise error
|
||||
|
||||
ContentMixin = ErrorClosureClass
|
||||
ContentSettings = ErrorClosureClass
|
||||
add_binary_content_type = _error_closure
|
||||
add_text_content_type = _error_closure
|
||||
set_default_content_type = _error_closure
|
||||
from .content import (ContentMixin, ContentSettings,
|
||||
add_binary_content_type, add_text_content_type,
|
||||
set_default_content_type)
|
||||
|
||||
|
||||
version_info = (2, 2, 2)
|
||||
__version__ = '.'.join(str(v) for v in version_info)
|
||||
__all__ = ['ContentMixin', 'ContentSettings', 'add_binary_content_type',
|
||||
'add_text_content_type', 'set_default_content_type',
|
||||
'version_info', '__version__']
|
||||
|
|
|
@ -43,7 +43,7 @@ SETTINGS_KEY = 'sprockets.mixins.mediatype.ContentSettings'
|
|||
_warning_issued = False
|
||||
|
||||
|
||||
class ContentSettings(object):
|
||||
class ContentSettings:
|
||||
"""
|
||||
Content selection settings.
|
||||
|
||||
|
@ -75,7 +75,6 @@ class ContentSettings(object):
|
|||
response_body = settings['application/msgpack'].to_bytes(
|
||||
response_dict, encoding='utf-8')
|
||||
self.write(response_body)
|
||||
self.finish()
|
||||
|
||||
def make_application():
|
||||
app = web.Application([web.url('/', SomeHandler)])
|
||||
|
@ -277,7 +276,7 @@ def set_default_content_type(application, content_type, encoding=None):
|
|||
settings.default_encoding = encoding
|
||||
|
||||
|
||||
class ContentMixin(object):
|
||||
class ContentMixin:
|
||||
"""
|
||||
Mix this in to add some content handling methods.
|
||||
|
||||
|
@ -288,7 +287,6 @@ class ContentMixin(object):
|
|||
body = self.get_request_body()
|
||||
# do stuff --> response_dict
|
||||
self.send_response(response_dict)
|
||||
self.finish()
|
||||
|
||||
:meth:`get_request_body` will deserialize the request data into
|
||||
a dictionary based on the :http:header:`Content-Type` request
|
||||
|
@ -300,7 +298,7 @@ class ContentMixin(object):
|
|||
"""
|
||||
|
||||
def initialize(self):
|
||||
super(ContentMixin, self).initialize()
|
||||
super().initialize()
|
||||
self._request_body = None
|
||||
self._best_response_match = None
|
||||
self._logger = getattr(self, 'logger', logger)
|
||||
|
|
|
@ -10,7 +10,7 @@ Basic content handlers.
|
|||
from tornado import escape
|
||||
|
||||
|
||||
class BinaryContentHandler(object):
|
||||
class BinaryContentHandler:
|
||||
"""
|
||||
Pack and unpack binary types.
|
||||
|
||||
|
@ -58,7 +58,7 @@ class BinaryContentHandler(object):
|
|||
return self._unpack(data_bytes)
|
||||
|
||||
|
||||
class TextContentHandler(object):
|
||||
class TextContentHandler:
|
||||
"""
|
||||
Transcodes between textual and object representations.
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ Bundled media type transcoders.
|
|||
"""
|
||||
import base64
|
||||
import json
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
import collections
|
||||
|
@ -20,28 +19,6 @@ except ImportError:
|
|||
from sprockets.mixins.mediatype import handlers
|
||||
|
||||
|
||||
class BinaryWrapper(bytes):
|
||||
"""
|
||||
Ensures that a Python 2 ``str`` is treated as binary.
|
||||
|
||||
Since :class:`bytes` is a synonym for :class:`str` in Python 2,
|
||||
you cannot distinguish between something that should be binary
|
||||
and something that should be encoded as a string. This is a
|
||||
problem in formats `such as msgpack`_ where binary data and
|
||||
strings are encoded differently. The :class:`MsgPackTranscoder`
|
||||
accomodates this by trying to UTF-8 encode a :class:`str` instance
|
||||
and falling back to binary encoding if the transcode fails.
|
||||
|
||||
You can avoid this by wrapping binary content in an instance of
|
||||
this class. The transcoder will then treat it as a binary payload
|
||||
instead of trying to detect whether it is a string or not.
|
||||
|
||||
.. _such as msgpack: http://msgpack.org
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class JSONTranscoder(handlers.TextContentHandler):
|
||||
"""
|
||||
JSON transcoder instance.
|
||||
|
@ -73,8 +50,8 @@ class JSONTranscoder(handlers.TextContentHandler):
|
|||
|
||||
def __init__(self, content_type='application/json',
|
||||
default_encoding='utf-8'):
|
||||
super(JSONTranscoder, self).__init__(content_type, self.dumps,
|
||||
self.loads, default_encoding)
|
||||
super().__init__(content_type, self.dumps, self.loads,
|
||||
default_encoding)
|
||||
self.dump_options = {
|
||||
'default': self.dump_object,
|
||||
'separators': (',', ':'),
|
||||
|
@ -128,13 +105,6 @@ class JSONTranscoder(handlers.TextContentHandler):
|
|||
| :class:`uuid.UUID` | Same as ``str(value)`` |
|
||||
+----------------------------+---------------------------------------+
|
||||
|
||||
.. warning::
|
||||
|
||||
:class:`bytes` instances are treated as character strings by the
|
||||
standard JSON module in Python 2.7 so the *default* object hook
|
||||
is never called. In other words, :class:`bytes` values will not
|
||||
be serialized as Base64 strings in Python 2.7.
|
||||
|
||||
"""
|
||||
if isinstance(obj, uuid.UUID):
|
||||
return str(obj)
|
||||
|
@ -160,18 +130,14 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
|
|||
.. _msgpack format: http://msgpack.org/index.html
|
||||
|
||||
"""
|
||||
if sys.version_info[0] < 3:
|
||||
PACKABLE_TYPES = (bool, int, float, long)
|
||||
else:
|
||||
PACKABLE_TYPES = (bool, int, float)
|
||||
PACKABLE_TYPES = (bool, int, float)
|
||||
|
||||
def __init__(self, content_type='application/msgpack'):
|
||||
if umsgpack is None:
|
||||
raise RuntimeError('Cannot import MsgPackTranscoder, '
|
||||
'umsgpack is not available')
|
||||
|
||||
super(MsgPackTranscoder, self).__init__(content_type, self.packb,
|
||||
self.unpackb)
|
||||
super().__init__(content_type, self.packb, self.unpackb)
|
||||
|
||||
def packb(self, data):
|
||||
"""Pack `data` into a :class:`bytes` instance."""
|
||||
|
@ -206,7 +172,7 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
|
|||
+-------------------------------+-------------------------------+
|
||||
| :class:`float` | `float family`_ |
|
||||
+-------------------------------+-------------------------------+
|
||||
| String (see note) | `str family`_ |
|
||||
| String | `str family`_ |
|
||||
+-------------------------------+-------------------------------+
|
||||
| :class:`bytes` | `bin family`_ |
|
||||
+-------------------------------+-------------------------------+
|
||||
|
@ -214,8 +180,6 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
|
|||
+-------------------------------+-------------------------------+
|
||||
| :class:`memoryview` | `bin family`_ |
|
||||
+-------------------------------+-------------------------------+
|
||||
| :class:`.BinaryWrapper` | `bin family`_ |
|
||||
+-------------------------------+-------------------------------+
|
||||
| :class:`collections.Sequence` | `array family`_ |
|
||||
+-------------------------------+-------------------------------+
|
||||
| :class:`collections.Set` | `array family`_ |
|
||||
|
@ -225,19 +189,6 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
|
|||
| :class:`uuid.UUID` | Converted to String |
|
||||
+-------------------------------+-------------------------------+
|
||||
|
||||
.. note::
|
||||
|
||||
:class:`str` and :class:`bytes` are the same before Python 3.
|
||||
If you want a value to be treated as a binary value, then you
|
||||
should wrap it in :class:`.BinaryWrapper` if there is any
|
||||
chance of running under Python 2.7.
|
||||
|
||||
The processing of :class:`str` in Python 2.x attempts to
|
||||
encode the string as a UTF-8 stream. If the ``encode`` succeeds,
|
||||
then the string is encoded according to the `str family`_.
|
||||
If ``encode`` fails, then the string is encoded according to
|
||||
the `bin family`_ .
|
||||
|
||||
.. _nil byte: https://github.com/msgpack/msgpack/blob/
|
||||
0b8f5ac67cdd130f4d4d4fe6afb839b989fdb86a/spec.md#formats-nil
|
||||
.. _true byte: https://github.com/msgpack/msgpack/blob/
|
||||
|
@ -277,16 +228,6 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
|
|||
if hasattr(datum, 'isoformat'):
|
||||
datum = datum.isoformat()
|
||||
|
||||
if sys.version_info[0] < 3 and isinstance(datum, (str, unicode)):
|
||||
if isinstance(datum, str) and not isinstance(datum, BinaryWrapper):
|
||||
# try to decode this into a string to make the common
|
||||
# case work. If we fail, then send along the bytes.
|
||||
try:
|
||||
datum = datum.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
return datum
|
||||
|
||||
if isinstance(datum, (bytes, str)):
|
||||
return datum
|
||||
|
||||
|
|
56
tests.py
56
tests.py
|
@ -4,7 +4,6 @@ import json
|
|||
import os
|
||||
import pickle
|
||||
import struct
|
||||
import sys
|
||||
import unittest
|
||||
import uuid
|
||||
|
||||
|
@ -28,7 +27,7 @@ class UTC(datetime.tzinfo):
|
|||
return 'UTC'
|
||||
|
||||
|
||||
class Context(object):
|
||||
class Context:
|
||||
"""Super simple class to call setattr on"""
|
||||
def __init__(self):
|
||||
self.settings = {}
|
||||
|
@ -37,27 +36,27 @@ class Context(object):
|
|||
def pack_string(obj):
|
||||
"""Optimally pack a string according to msgpack format"""
|
||||
payload = str(obj).encode('ASCII')
|
||||
l = len(payload)
|
||||
if l < (2 ** 5):
|
||||
prefix = struct.pack('B', 0b10100000 | l)
|
||||
elif l < (2 ** 8):
|
||||
prefix = struct.pack('BB', 0xD9, l)
|
||||
elif l < (2 ** 16):
|
||||
prefix = struct.pack('>BH', 0xDA, l)
|
||||
pl = len(payload)
|
||||
if pl < (2 ** 5):
|
||||
prefix = struct.pack('B', 0b10100000 | pl)
|
||||
elif pl < (2 ** 8):
|
||||
prefix = struct.pack('BB', 0xD9, pl)
|
||||
elif pl < (2 ** 16):
|
||||
prefix = struct.pack('>BH', 0xDA, pl)
|
||||
else:
|
||||
prefix = struct.pack('>BI', 0xDB, l)
|
||||
prefix = struct.pack('>BI', 0xDB, pl)
|
||||
return prefix + payload
|
||||
|
||||
|
||||
def pack_bytes(payload):
|
||||
"""Optimally pack a byte string according to msgpack format"""
|
||||
l = len(payload)
|
||||
if l < (2 ** 8):
|
||||
prefix = struct.pack('BB', 0xC4, l)
|
||||
elif l < (2 ** 16):
|
||||
prefix = struct.pack('>BH', 0xC5, l)
|
||||
pl = len(payload)
|
||||
if pl < (2 ** 8):
|
||||
prefix = struct.pack('BB', 0xC4, pl)
|
||||
elif pl < (2 ** 16):
|
||||
prefix = struct.pack('>BH', 0xC5, pl)
|
||||
else:
|
||||
prefix = struct.pack('>BI', 0xC6, l)
|
||||
prefix = struct.pack('>BI', 0xC6, pl)
|
||||
return prefix + payload
|
||||
|
||||
|
||||
|
@ -111,16 +110,16 @@ class GetRequestBodyTests(testing.AsyncHTTPTestCase):
|
|||
def test_that_request_with_unhandled_type_results_in_415(self):
|
||||
response = self.fetch(
|
||||
'/', method='POST', headers={'Content-Type': 'application/xml'},
|
||||
body=(u'<request><name>value</name>'
|
||||
u'<embedded><utf8>\u2731</utf8></embedded>'
|
||||
u'</request>').encode('utf-8'))
|
||||
body=('<request><name>value</name>'
|
||||
'<embedded><utf8>\u2731</utf8></embedded>'
|
||||
'</request>').encode('utf-8'))
|
||||
self.assertEqual(response.code, 415)
|
||||
|
||||
def test_that_msgpack_request_returns_default_type(self):
|
||||
body = {
|
||||
'name': 'value',
|
||||
'embedded': {
|
||||
'utf8': u'\u2731'
|
||||
'utf8': '\u2731'
|
||||
}
|
||||
}
|
||||
response = self.fetch('/', method='POST', body=umsgpack.packb(body),
|
||||
|
@ -140,7 +139,7 @@ class GetRequestBodyTests(testing.AsyncHTTPTestCase):
|
|||
class JSONTranscoderTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(JSONTranscoderTests, self).setUp()
|
||||
super().setUp()
|
||||
self.transcoder = transcoders.JSONTranscoder()
|
||||
|
||||
def test_that_uuids_are_dumped_as_strings(self):
|
||||
|
@ -161,13 +160,6 @@ class JSONTranscoderTests(unittest.TestCase):
|
|||
self.assertEqual(dumped.replace(' ', ''),
|
||||
'{"now":"%s"}' % obj['now'].isoformat())
|
||||
|
||||
@unittest.skipIf(sys.version_info[0] == 2, 'bytes unsupported on python 2')
|
||||
def test_that_bytes_are_base64_encoded(self):
|
||||
bin = bytes(os.urandom(127))
|
||||
dumped = self.transcoder.dumps({'bin': bin})
|
||||
self.assertEqual(
|
||||
dumped, '{"bin":"%s"}' % base64.b64encode(bin).decode('ASCII'))
|
||||
|
||||
def test_that_bytearrays_are_base64_encoded(self):
|
||||
bin = bytearray(os.urandom(127))
|
||||
dumped = self.transcoder.dumps({'bin': bin})
|
||||
|
@ -226,7 +218,7 @@ class ContentSettingsTests(unittest.TestCase):
|
|||
class ContentFunctionTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ContentFunctionTests, self).setUp()
|
||||
super().setUp()
|
||||
self.context = Context()
|
||||
|
||||
def test_that_add_binary_content_type_creates_binary_handler(self):
|
||||
|
@ -281,11 +273,11 @@ class ContentFunctionTests(unittest.TestCase):
|
|||
class MsgPackTranscoderTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(MsgPackTranscoderTests, self).setUp()
|
||||
super().setUp()
|
||||
self.transcoder = transcoders.MsgPackTranscoder()
|
||||
|
||||
def test_that_strings_are_dumped_as_strings(self):
|
||||
dumped = self.transcoder.packb(u'foo')
|
||||
dumped = self.transcoder.packb('foo')
|
||||
self.assertEqual(self.transcoder.unpackb(dumped), 'foo')
|
||||
self.assertEqual(dumped, pack_string('foo'))
|
||||
|
||||
|
@ -373,6 +365,6 @@ class MsgPackTranscoderTests(unittest.TestCase):
|
|||
|
||||
def test_that_utf8_values_can_be_forced_to_bytes(self):
|
||||
data = b'a ascii value'
|
||||
dumped = self.transcoder.packb(transcoders.BinaryWrapper(data))
|
||||
dumped = self.transcoder.packb(data)
|
||||
self.assertEqual(self.transcoder.unpackb(dumped), data)
|
||||
self.assertEqual(dumped, pack_bytes(data))
|
||||
|
|
6
tox.ini
6
tox.ini
|
@ -1,5 +1,5 @@
|
|||
[tox]
|
||||
envlist = py27,py34,py35,pypy
|
||||
envlist = py35,py36,py37
|
||||
indexserver =
|
||||
default = https://pypi.python.org/simple
|
||||
toxworkdir = build/tox
|
||||
|
@ -7,6 +7,6 @@ skip_missing_interpreters = true
|
|||
|
||||
[testenv]
|
||||
deps =
|
||||
-rrequires/installation.txt
|
||||
-rrequires/testing.txt
|
||||
-e .[msgpack]
|
||||
-r requires/testing.txt
|
||||
commands = nosetests []
|
||||
|
|
Loading…
Reference in a new issue