Skip to content

Commit

Permalink
Merge pull request #7 from sprockets/repackage
Browse files Browse the repository at this point in the history
Repackage into a package
  • Loading branch information
amberheilman committed Jan 12, 2016
2 parents d60ca09 + 478868d commit d215718
Show file tree
Hide file tree
Showing 15 changed files with 223 additions and 68 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ language: python
python:
- 2.7
- 3.4
- 3.5
- pypy
install:
- pip install codecov
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2015 AWeber Communications
Copyright (c) 2015-2016 AWeber Communications
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
Expand Down
12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ functions as parameters:
import json
from sprockets.mixins import mediatype
from sprockets.mixins.mediatype import content
from tornado import web
def make_application():
application = web.Application([
# insert your handlers here
])
mediatype.add_text_content_type(application,
'application/json', 'utf-8',
json.dumps, json.loads)
content.add_text_content_type(application,
'application/json', 'utf-8',
json.dumps, json.loads)
return application
Expand All @@ -40,10 +40,10 @@ instance that the mix-in uses to manipulate the request and response bodies.

.. code-block:: python
from sprockets.mixins import mediatype
from sprockets.mixins.mediatype import content
from tornado import web
class SomeHandler(mediatype.ContentMixin, web.RequestHandler):
class SomeHandler(content.ContentMixin, web.RequestHandler):
def get(self):
self.send_response({'data': 'value'})
self.finish()
Expand Down
2 changes: 1 addition & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
API Documentation
=================
.. currentmodule:: sprockets.mixins.mediatype
.. currentmodule:: sprockets.mixins.mediatype.content

Content Type Handling
---------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
source_suffix = '.rst'
master_doc = 'index'
project = 'sprockets.mixins.mediatype'
copyright = '2015, AWeber Communications'
copyright = '2015-2016, AWeber Communications'
release = __version__
version = '.'.join(release.split('.')[0:1])

Expand Down
4 changes: 0 additions & 4 deletions docs/examples.rst

This file was deleted.

10 changes: 8 additions & 2 deletions docs/history.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
Version History
===============

`Next Release`_
---------------
- Repackage from a module into a package. Distributing raw modules inside
of a namespace package is unreliable and questionably correct.

`1.0.4`_ (14 Sep 2015)
---------------------
----------------------
- Support using the default_content_type in the settings if request does not
contain the Accept header

`1.0.3`_ (10 Sep 2015)
---------------------
----------------------
- Update installation files

`1.0.2`_ (9 Sep 2015)
Expand All @@ -22,6 +27,7 @@ Version History
---------------------
- Initial Release

.. _Next Release: https://github.com/sprockets/sprockets.http/compare/1.0.4...HEAD
.. _1.0.4: https://github.com/sprockets/sprockets.http/compare/1.0.3...1.0.4
.. _1.0.3: https://github.com/sprockets/sprockets.http/compare/1.0.2...1.0.3
.. _1.0.2: https://github.com/sprockets/sprockets.http/compare/1.0.1...1.0.2
Expand Down
16 changes: 8 additions & 8 deletions examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import logging
import signal

from sprockets.mixins import mediatype
from sprockets.mixins.mediatype import content
from tornado import ioloop, web
import msgpack


class SimpleHandler(mediatype.ContentMixin, web.RequestHandler):
class SimpleHandler(content.ContentMixin, web.RequestHandler):

def post(self):
body = self.get_request_body()
Expand All @@ -18,12 +18,12 @@ def post(self):

def make_application(**settings):
application = web.Application([web.url(r'/', SimpleHandler)], **settings)
mediatype.set_default_content_type(application, 'application/json',
encoding='utf-8')
mediatype.add_binary_content_type(application, 'application/msgpack',
msgpack.packb, msgpack.unpackb)
mediatype.add_text_content_type(application, 'application/json', 'utf-8',
json.dumps, json.loads)
content.set_default_content_type(application, 'application/json',
encoding='utf-8')
content.add_binary_content_type(application, 'application/msgpack',
msgpack.packb, msgpack.unpackb)
content.add_text_content_type(application, 'application/json', 'utf-8',
json.dumps, json.loads)
return application


Expand Down
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
universal = 1

[nosetests]
with-coverage = 1
cover-branches = 1
cover-erase = 1
cover-package = sprockets.mixins
6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import os
import setuptools

from sprockets.mixins import mediatype


def read_requirements(file_name):
requirements = []
Expand All @@ -28,15 +30,15 @@ def read_requirements(file_name):

setuptools.setup(
name='sprockets.mixins.mediatype',
version='1.0.4',
version=mediatype.__version__,
description='A mixin for reporting handling content-type/accept headers',
long_description='\n' + open('README.rst').read(),
url='https://github.com/sprockets/sprockets.mixins.media_type',
author='AWeber Communications',
author_email='api@aweber.com',
license='BSD',
classifiers=[
'Development Status :: 4 - Beta',
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Natural Language :: English',
Expand Down
45 changes: 45 additions & 0 deletions sprockets/mixins/mediatype/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""
sprockets.mixins.media_type
"""
import functools
import warnings

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

ContentMixin = _error_closure
ContentSettings = _error_closure
add_binary_content_type = _error_closure
add_text_content_type = _error_closure
set_default_content_type = _error_closure


def _mark_deprecated(func):
msg = '{0}.{1} is deprecated, use {0}.content.{1} instead'.format(
'sprockets.mixins.mediatype', func.__name__)

@functools.wraps(func)
def wrapper(*args, **kwargs):
warnings.warn(msg, category=DeprecationWarning)
return func(*args, **kwargs)

return wrapper

add_binary_content_type = _mark_deprecated(add_binary_content_type)
add_text_content_type = _mark_deprecated(add_text_content_type)
set_default_content_type = _mark_deprecated(set_default_content_type)
ContentMixin = _mark_deprecated(ContentMixin)
ContentSettings = _mark_deprecated(ContentSettings)

version_info = (1, 0, 4)
__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__')
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
"""
sprockets.mixins.media_type
===========================
Content handling for Tornado.
- :func:`.set_default_content_type` sets the content type that is
used when an ``Accept`` or ``Content-Type`` header is omitted.
- :func:`.add_binary_content_type` register transcoders for a binary
content type
- :func:`.add_text_content_type` register transcoders for a textual
content type
- :class:`.ContentSettings` an instance of this is attached to
:class:`tornado.web.Application` to hold the content mapping
information for the application
- :class:`.ContentMixin` attaches a :class:`.ContentSettings`
instance to the application and implements request decoding &
response encoding methods
This module is the primary interface for this library. It exposes
functions for registering new content handlers and a mix-in that
adds content handling methods to :class:`~tornado.web.RequestHandler`
instances.
"""
import logging

from ietfparse import algorithms, errors, headers
from tornado import escape, web
from tornado import web

from . import handlers


version_info = (1, 0, 4)
__version__ = '.'.join(str(v) for v in version_info)
logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -110,7 +127,8 @@ def add_binary_content_type(application, content_type, pack, unpack):
"""
settings = ContentSettings.from_application(application)
settings[content_type] = _BinaryContentHandler(content_type, pack, unpack)
settings[content_type] = handlers.BinaryContentHandler(
content_type, pack, unpack)


def add_text_content_type(application, content_type, default_encoding,
Expand All @@ -128,8 +146,8 @@ def add_text_content_type(application, content_type, default_encoding,
"""
settings = ContentSettings.from_application(application)
settings[content_type] = _TextContentHandler(content_type, dumps, loads,
default_encoding)
settings[content_type] = handlers.TextContentHandler(
content_type, dumps, loads, default_encoding)


def set_default_content_type(application, content_type, encoding=None):
Expand Down Expand Up @@ -232,35 +250,3 @@ def send_response(self, body, set_content_type=True):
if set_content_type:
self.set_header('Content-Type', content_type)
self.write(data_bytes)


class _BinaryContentHandler(object):

def __init__(self, content_type, pack, unpack):
self._pack = pack
self._unpack = unpack
self.content_type = content_type

def to_bytes(self, data_dict, encoding=None):
return self.content_type, self._pack(data_dict)

def from_bytes(self, data, encoding=None):
return self._unpack(data)


class _TextContentHandler(object):

def __init__(self, content_type, dumps, loads, default_encoding):
self._dumps = dumps
self._loads = loads
self.content_type = content_type
self.default_encoding = default_encoding

def to_bytes(self, data_dict, encoding=None):
selected = encoding or self.default_encoding
content_type = '{0}; charset="{1}"'.format(self.content_type, selected)
dumped = self._dumps(escape.recursive_unicode(data_dict))
return content_type, dumped.encode(selected)

def from_bytes(self, data, encoding=None):
return self._loads(data.decode(encoding or self.default_encoding))

0 comments on commit d215718

Please sign in to comment.