diff options
| author | Chris McDonough <chrism@plope.com> | 2014-05-25 21:27:09 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2014-05-25 21:27:09 -0400 |
| commit | 52e4b59f7264adc373bff4d1a96fd489991ecf8b (patch) | |
| tree | 2e300de4c8adebc67ac1c26bdef9250abe82e28c | |
| parent | a978083b5719faf13e2ccf98ae93d5b03ec0d7cb (diff) | |
| parent | c79c2d9f36f27abfa5e2a72e021298728734138d (diff) | |
| download | pyramid-52e4b59f7264adc373bff4d1a96fd489991ecf8b.tar.gz pyramid-52e4b59f7264adc373bff4d1a96fd489991ecf8b.tar.bz2 pyramid-52e4b59f7264adc373bff4d1a96fd489991ecf8b.zip | |
Merge branch 'master' of github.com:Pylons/pyramid
| -rw-r--r-- | CHANGES.txt | 3 | ||||
| -rw-r--r-- | docs/narr/hooks.rst | 8 | ||||
| -rw-r--r-- | docs/narr/templates.rst | 27 | ||||
| -rw-r--r-- | docs/quick_tutorial/databases.rst | 2 | ||||
| -rw-r--r-- | pyramid/response.py | 18 | ||||
| -rw-r--r-- | pyramid/security.py | 8 | ||||
| -rw-r--r-- | pyramid/tests/fixtures/minimal.jpg | bin | 0 -> 631 bytes | |||
| -rwxr-xr-x | pyramid/tests/fixtures/minimal.pdf | bin | 0 -> 1054 bytes | |||
| -rw-r--r-- | pyramid/tests/fixtures/minimal.xml | 1 | ||||
| -rw-r--r-- | pyramid/tests/test_response.py | 39 | ||||
| -rw-r--r-- | setup.py | 2 |
11 files changed, 72 insertions, 36 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 0c461e550..e60c6efac 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -17,6 +17,9 @@ Bug Fixes using the returned ``Configurator`` during testing. There is now a ``package`` argument that can override this behavior as well. +- Fix an issue where a ``pyramid.response.FileResponse`` may apply a charset + where it does not belong. See https://github.com/Pylons/pyramid/pull/1251 + Docs ---- diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index f2542f1d7..4da36e730 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -985,7 +985,7 @@ Creating a Tween To create a tween, you must write a "tween factory". A tween factory must be a globally importable callable which accepts two arguments: -``handler`` and ``registry``. ``handler`` will be the either the main +``handler`` and ``registry``. ``handler`` will be either the main Pyramid request handling function or another tween. ``registry`` will be the Pyramid :term:`application registry` represented by this Configurator. A tween factory must return the tween (a callable object) when it is called. @@ -1023,7 +1023,7 @@ method: :linenos: class simple_tween_factory(object): - def __init__(handler, registry): + def __init__(self, handler, registry): self.handler = handler self.registry = registry @@ -1040,6 +1040,10 @@ method: return response +You should avoid mutating any state on the tween instance. The tween is +invoked once per request and any shared mutable state needs to be carefully +handled to avoid any race conditions. + The closure style performs slightly better and enables you to conditionally omit the tween from the request processing pipeline (see the following timing tween example), whereas the class style makes it easier to have shared mutable diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index 038dd2594..460cda8ee 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -450,21 +450,24 @@ Available Add-On Template System Bindings The Pylons Project maintains several packages providing bindings to different templating languages including the following: -+------------------------------+------------------------------+ -| Template Language | Pyramid Bindings | -+==============================+==============================+ -| Chameleon_ | pyramid_chameleon_ | -+------------------------------+------------------------------+ -| Jinja2_ | pyramid_jinja2_ | -+------------------------------+------------------------------+ -| Mako_ | pyramid_mako_ | -+------------------------------+------------------------------+ ++---------------------------+----------------------------+--------------------+ +| Template Language | Pyramid Bindings | Default Extensions | ++===========================+============================+====================+ +| Chameleon_ | pyramid_chameleon_ | .pt, .txt | ++---------------------------+----------------------------+--------------------+ +| Jinja2_ | pyramid_jinja2_ | .jinja2 | ++---------------------------+----------------------------+--------------------+ +| Mako_ | pyramid_mako_ | .mak, .mako | ++---------------------------+----------------------------+--------------------+ .. _Chameleon: http://chameleon.readthedocs.org/en/latest/ -.. _pyramid_chameleon: https://pypi.python.org/pypi/pyramid_chameleon +.. _pyramid_chameleon: + http://docs.pylonsproject.org/projects/pyramid-chameleon/en/latest/ .. _Jinja2: http://jinja.pocoo.org/docs/ -.. _pyramid_jinja2: https://pypi.python.org/pypi/pyramid_jinja2 +.. _pyramid_jinja2: + http://docs.pylonsproject.org/projects/pyramid-jinja2/en/latest/ .. _Mako: http://www.makotemplates.org/ -.. _pyramid_mako: https://pypi.python.org/pypi/pyramid_mako +.. _pyramid_mako: + http://docs.pylonsproject.org/projects/pyramid-mako/en/latest/ diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 20b3cd46d..7c019dbfc 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -115,7 +115,7 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests . + $ $VENV/bin/nosetests tutorial .. ----------------------------------------------------------------- Ran 2 tests in 1.141s diff --git a/pyramid/response.py b/pyramid/response.py index 0f61af472..adc903b44 100644 --- a/pyramid/response.py +++ b/pyramid/response.py @@ -52,15 +52,17 @@ class FileResponse(Response): """ def __init__(self, path, request=None, cache_max_age=None, content_type=None, content_encoding=None): - super(FileResponse, self).__init__(conditional_response=True) - self.last_modified = getmtime(path) - if content_type is None: - content_type, content_encoding = mimetypes.guess_type(path, - strict=False) if content_type is None: - content_type = 'application/octet-stream' - self.content_type = content_type - self.content_encoding = content_encoding + content_type, content_encoding = ( + mimetypes.guess_type(path, strict=False)) + if content_type is None: + content_type = 'application/octet-stream' + super(FileResponse, self).__init__( + conditional_response=True, + content_type=content_type, + content_encoding=content_encoding + ) + self.last_modified = getmtime(path) content_length = getsize(path) f = open(path, 'rb') app_iter = None diff --git a/pyramid/security.py b/pyramid/security.py index c98d4e6cc..041155563 100644 --- a/pyramid/security.py +++ b/pyramid/security.py @@ -59,7 +59,7 @@ def has_permission(permission, context, request): deprecated( 'has_permission', 'As of Pyramid 1.5 the "pyramid.security.has_permission" API is now ' - 'deprecated. It will be removed in Pyramd 1.8. Use the ' + 'deprecated. It will be removed in Pyramid 1.8. Use the ' '"has_permission" method of the Pyramid request instead.' ) @@ -77,7 +77,7 @@ def authenticated_userid(request): deprecated( 'authenticated_userid', 'As of Pyramid 1.5 the "pyramid.security.authenticated_userid" API is now ' - 'deprecated. It will be removed in Pyramd 1.8. Use the ' + 'deprecated. It will be removed in Pyramid 1.8. Use the ' '"authenticated_userid" attribute of the Pyramid request instead.' ) @@ -94,7 +94,7 @@ def unauthenticated_userid(request): deprecated( 'unauthenticated_userid', 'As of Pyramid 1.5 the "pyramid.security.unauthenticated_userid" API is ' - 'now deprecated. It will be removed in Pyramd 1.8. Use the ' + 'now deprecated. It will be removed in Pyramid 1.8. Use the ' '"unauthenticated_userid" attribute of the Pyramid request instead.' ) @@ -111,7 +111,7 @@ def effective_principals(request): deprecated( 'effective_principals', 'As of Pyramid 1.5 the "pyramid.security.effective_principals" API is ' - 'now deprecated. It will be removed in Pyramd 1.8. Use the ' + 'now deprecated. It will be removed in Pyramid 1.8. Use the ' '"effective_principals" attribute of the Pyramid request instead.' ) diff --git a/pyramid/tests/fixtures/minimal.jpg b/pyramid/tests/fixtures/minimal.jpg Binary files differnew file mode 100644 index 000000000..1cda9a53d --- /dev/null +++ b/pyramid/tests/fixtures/minimal.jpg diff --git a/pyramid/tests/fixtures/minimal.pdf b/pyramid/tests/fixtures/minimal.pdf Binary files differnew file mode 100755 index 000000000..e267be996 --- /dev/null +++ b/pyramid/tests/fixtures/minimal.pdf diff --git a/pyramid/tests/fixtures/minimal.xml b/pyramid/tests/fixtures/minimal.xml new file mode 100644 index 000000000..1972c155d --- /dev/null +++ b/pyramid/tests/fixtures/minimal.xml @@ -0,0 +1 @@ +<hello/>
\ No newline at end of file diff --git a/pyramid/tests/test_response.py b/pyramid/tests/test_response.py index e6d90f979..8731fa764 100644 --- a/pyramid/tests/test_response.py +++ b/pyramid/tests/test_response.py @@ -23,22 +23,45 @@ class TestFileResponse(unittest.TestCase): from pyramid.response import FileResponse return FileResponse(file, **kw) - def _getPath(self): + def _getPath(self, suffix='txt'): here = os.path.dirname(__file__) - return os.path.join(here, 'fixtures', 'minimal.txt') + return os.path.join(here, 'fixtures', 'minimal.%s' % (suffix,)) - def test_with_content_type(self): - path = self._getPath() + def test_with_image_content_type(self): + path = self._getPath('jpg') r = self._makeOne(path, content_type='image/jpeg') self.assertEqual(r.content_type, 'image/jpeg') + self.assertEqual(r.headers['content-type'], 'image/jpeg') + path = self._getPath() r.app_iter.close() - def test_without_content_type(self): - path = self._getPath() - r = self._makeOne(path) - self.assertEqual(r.content_type, 'text/plain') + def test_with_xml_content_type(self): + path = self._getPath('xml') + r = self._makeOne(path, content_type='application/xml') + self.assertEqual(r.content_type, 'application/xml') + self.assertEqual(r.headers['content-type'], + 'application/xml; charset=UTF-8') r.app_iter.close() + def test_with_pdf_content_type(self): + path = self._getPath('xml') + r = self._makeOne(path, content_type='application/pdf') + self.assertEqual(r.content_type, 'application/pdf') + self.assertEqual(r.headers['content-type'], 'application/pdf') + r.app_iter.close() + + def test_without_content_type(self): + for suffix, content_type in ( + ('txt', 'text/plain; charset=UTF-8'), + ('xml', 'application/xml; charset=UTF-8'), + ('pdf', 'application/pdf') + ): + path = self._getPath(suffix) + r = self._makeOne(path) + self.assertEqual(r.content_type, content_type.split(';')[0]) + self.assertEqual(r.headers['content-type'], content_type) + r.app_iter.close() + class TestFileIter(unittest.TestCase): def _makeOne(self, file, block_size): from pyramid.response import FileIter @@ -91,7 +91,7 @@ setup(name='pyramid', keywords='web wsgi pylons pyramid', author="Chris McDonough, Agendaless Consulting", author_email="pylons-discuss@googlegroups.com", - url="http://pylonsproject.org", + url="http://docs.pylonsproject.org/en/latest/docs/pyramid.html", license="BSD-derived (http://www.repoze.org/LICENSE.txt)", packages=find_packages(), include_package_data=True, |
