summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2014-05-25 21:27:09 -0400
committerChris McDonough <chrism@plope.com>2014-05-25 21:27:09 -0400
commit52e4b59f7264adc373bff4d1a96fd489991ecf8b (patch)
tree2e300de4c8adebc67ac1c26bdef9250abe82e28c
parenta978083b5719faf13e2ccf98ae93d5b03ec0d7cb (diff)
parentc79c2d9f36f27abfa5e2a72e021298728734138d (diff)
downloadpyramid-52e4b59f7264adc373bff4d1a96fd489991ecf8b.tar.gz
pyramid-52e4b59f7264adc373bff4d1a96fd489991ecf8b.tar.bz2
pyramid-52e4b59f7264adc373bff4d1a96fd489991ecf8b.zip
Merge branch 'master' of github.com:Pylons/pyramid
-rw-r--r--CHANGES.txt3
-rw-r--r--docs/narr/hooks.rst8
-rw-r--r--docs/narr/templates.rst27
-rw-r--r--docs/quick_tutorial/databases.rst2
-rw-r--r--pyramid/response.py18
-rw-r--r--pyramid/security.py8
-rw-r--r--pyramid/tests/fixtures/minimal.jpgbin0 -> 631 bytes
-rwxr-xr-xpyramid/tests/fixtures/minimal.pdfbin0 -> 1054 bytes
-rw-r--r--pyramid/tests/fixtures/minimal.xml1
-rw-r--r--pyramid/tests/test_response.py39
-rw-r--r--setup.py2
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
new file mode 100644
index 000000000..1cda9a53d
--- /dev/null
+++ b/pyramid/tests/fixtures/minimal.jpg
Binary files differ
diff --git a/pyramid/tests/fixtures/minimal.pdf b/pyramid/tests/fixtures/minimal.pdf
new file mode 100755
index 000000000..e267be996
--- /dev/null
+++ b/pyramid/tests/fixtures/minimal.pdf
Binary files differ
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
diff --git a/setup.py b/setup.py
index 54ced84e3..c832d3fc8 100644
--- a/setup.py
+++ b/setup.py
@@ -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,