From fbcce774fb33b57673c99f9e82058c507e212611 Mon Sep 17 00:00:00 2001 From: synthomat Date: Tue, 13 May 2014 13:29:56 +0200 Subject: Update hooks.rst 'self' param was omitted in the constructor of simple_tween_factory class --- docs/narr/hooks.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index f2542f1d7..94be31bbc 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -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 -- cgit v1.2.3 From 739fbc26639a06900a8638d0e5de7441e41ff810 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Fri, 16 May 2014 10:32:42 -0500 Subject: Docs: narr/templates.rst: Doc default extensions of each template system. --- docs/narr/templates.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index 038dd2594..cd13afde8 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -450,15 +450,15 @@ 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 -- cgit v1.2.3 From 71ad608da8651417d238bcce3337362db72d25b0 Mon Sep 17 00:00:00 2001 From: krysros Date: Fri, 16 May 2014 22:03:39 +0200 Subject: fix typo --- pyramid/security.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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.' ) -- cgit v1.2.3 From e858454e9cc375a633bfb7b39bdd4391f79e2531 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Fri, 16 May 2014 17:18:00 -0500 Subject: Docs: narr/templates.rst: Link template bindings to pyramid docs. --- docs/narr/templates.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index cd13afde8..460cda8ee 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -461,10 +461,13 @@ templating languages including the following: +---------------------------+----------------------------+--------------------+ .. _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/ -- cgit v1.2.3 From 8dbe013e65134001bd48eb54935beb71d7333a37 Mon Sep 17 00:00:00 2001 From: dobesv Date: Thu, 27 Feb 2014 16:22:36 -0800 Subject: Don't incorrectly default charset on FileResponse By passing the content_type into the constructor to Response, we can allow it to decide intelligently whether the default charset should apply. Otherwise we'd have to replicate that logic somehow, or live with weird charset annotations on images, pdfs, and zips. --- pyramid/response.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pyramid/response.py b/pyramid/response.py index 0f61af472..ff1dd25d5 100644 --- a/pyramid/response.py +++ b/pyramid/response.py @@ -28,6 +28,14 @@ _BLOCK_SIZE = 4096 * 64 # 256K class Response(_Response): pass +def maybe_guess_mimetype(content_type, content_encoding, 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' + return dict(content_type=content_type, content_encoding=content_encoding) + class FileResponse(Response): """ A Response object that can be used to serve a static file from disk @@ -52,15 +60,8 @@ 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) + super(FileResponse, self).__init__(conditional_response=True, **maybe_guess_mimetype(content_type, content_encoding, path)) 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_length = getsize(path) f = open(path, 'rb') app_iter = None -- cgit v1.2.3 From 4823d8577f3dd09f908ed8e4381b4050400022db Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Thu, 6 Mar 2014 19:34:29 -0800 Subject: Add tests for the content_type fix. --- pyramid/response.py | 18 +++++++++--------- pyramid/tests/fixtures/minimal.pdf | Bin 0 -> 1054 bytes pyramid/tests/fixtures/minimal.xml | 1 + pyramid/tests/test_response.py | 23 +++++++++++++++++------ 4 files changed, 27 insertions(+), 15 deletions(-) create mode 100755 pyramid/tests/fixtures/minimal.pdf create mode 100644 pyramid/tests/fixtures/minimal.xml diff --git a/pyramid/response.py b/pyramid/response.py index ff1dd25d5..6b5f0a561 100644 --- a/pyramid/response.py +++ b/pyramid/response.py @@ -28,14 +28,6 @@ _BLOCK_SIZE = 4096 * 64 # 256K class Response(_Response): pass -def maybe_guess_mimetype(content_type, content_encoding, 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' - return dict(content_type=content_type, content_encoding=content_encoding) - class FileResponse(Response): """ A Response object that can be used to serve a static file from disk @@ -60,7 +52,15 @@ 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, **maybe_guess_mimetype(content_type, content_encoding, 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' + 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') diff --git a/pyramid/tests/fixtures/minimal.pdf b/pyramid/tests/fixtures/minimal.pdf new file mode 100755 index 000000000..e267be996 Binary files /dev/null and b/pyramid/tests/fixtures/minimal.pdf 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 @@ + \ No newline at end of file diff --git a/pyramid/tests/test_response.py b/pyramid/tests/test_response.py index e6d90f979..afd354d97 100644 --- a/pyramid/tests/test_response.py +++ b/pyramid/tests/test_response.py @@ -23,21 +23,32 @@ 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() r = self._makeOne(path, content_type='image/jpeg') self.assertEqual(r.content_type, 'image/jpeg') + self.assertEqual(r.headers.get('content-type'), 'image/jpeg') + path = self._getPath() + 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_without_content_type(self): - path = self._getPath() - r = self._makeOne(path) - self.assertEqual(r.content_type, 'text/plain') - r.app_iter.close() + 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): -- cgit v1.2.3 From c8a58abb1ed5705defb7d7464e4f0d086fe13a21 Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Thu, 6 Mar 2014 21:29:52 -0800 Subject: Expand tests - make sure pdf, jpeg types also are not annotated with a charset. --- pyramid/tests/fixtures/minimal.jpg | Bin 0 -> 631 bytes pyramid/tests/test_response.py | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 pyramid/tests/fixtures/minimal.jpg diff --git a/pyramid/tests/fixtures/minimal.jpg b/pyramid/tests/fixtures/minimal.jpg new file mode 100644 index 000000000..1cda9a53d Binary files /dev/null and b/pyramid/tests/fixtures/minimal.jpg differ diff --git a/pyramid/tests/test_response.py b/pyramid/tests/test_response.py index afd354d97..8061ecac5 100644 --- a/pyramid/tests/test_response.py +++ b/pyramid/tests/test_response.py @@ -27,17 +27,27 @@ class TestFileResponse(unittest.TestCase): here = os.path.dirname(__file__) 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.get('content-type'), 'image/jpeg') + self.assertEqual(r.headers['content-type'], 'image/jpeg') path = self._getPath() + + 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'), -- cgit v1.2.3 From 745edec7be7c4c4be56cbdf01ffe3543cb3348e2 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Fri, 16 May 2014 21:34:02 -0500 Subject: close resources and 80-char line width --- pyramid/response.py | 3 ++- pyramid/tests/test_response.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pyramid/response.py b/pyramid/response.py index 6b5f0a561..adc903b44 100644 --- a/pyramid/response.py +++ b/pyramid/response.py @@ -53,7 +53,8 @@ class FileResponse(Response): def __init__(self, path, request=None, cache_max_age=None, content_type=None, content_encoding=None): if content_type is None: - content_type, content_encoding = mimetypes.guess_type(path, strict=False) + content_type, content_encoding = ( + mimetypes.guess_type(path, strict=False)) if content_type is None: content_type = 'application/octet-stream' super(FileResponse, self).__init__( diff --git a/pyramid/tests/test_response.py b/pyramid/tests/test_response.py index 8061ecac5..8731fa764 100644 --- a/pyramid/tests/test_response.py +++ b/pyramid/tests/test_response.py @@ -25,7 +25,7 @@ class TestFileResponse(unittest.TestCase): def _getPath(self, suffix='txt'): here = os.path.dirname(__file__) - return os.path.join(here, 'fixtures', 'minimal.%s'%(suffix,)) + return os.path.join(here, 'fixtures', 'minimal.%s' % (suffix,)) def test_with_image_content_type(self): path = self._getPath('jpg') @@ -33,12 +33,14 @@ class TestFileResponse(unittest.TestCase): self.assertEqual(r.content_type, 'image/jpeg') self.assertEqual(r.headers['content-type'], 'image/jpeg') path = self._getPath() + r.app_iter.close() 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') + self.assertEqual(r.headers['content-type'], + 'application/xml; charset=UTF-8') r.app_iter.close() def test_with_pdf_content_type(self): -- cgit v1.2.3 From dc9c386fb762defd97313cb6261fcd95f7321e71 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Fri, 16 May 2014 21:54:40 -0500 Subject: update changelog --- CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) 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 ---- -- cgit v1.2.3 From d194f3df5b5941251a36e0e7d535eaf0d633dd1b Mon Sep 17 00:00:00 2001 From: flibustenet Date: Sun, 18 May 2014 11:26:48 +0200 Subject: Draw attention that tweens instances are unique and shared between threads Forgetting that tween instance are not instantiated for each request leads to threads issues difficult to detect --- docs/narr/hooks.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 94be31bbc..91392ce7a 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -1017,7 +1017,8 @@ You can write the tween factory as a simple closure-returning function: return simple_tween Alternatively, the tween factory can be a class with the ``__call__`` magic -method: +method (the instance will be unique, be aware that it will be shared +between threads): .. code-block:: python :linenos: -- cgit v1.2.3 From bf669af7f10ec81280fd8dbee43e414fa75457c5 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 21 May 2014 11:03:13 -0500 Subject: clarify tween thread-safety --- docs/narr/hooks.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 91392ce7a..fe7749cac 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. @@ -995,6 +995,11 @@ A tween is called with a single argument, ``request``, which is the A tween should return a :term:`response`, usually the one generated by the downstream Pyramid application. +The tween factory will be shared between requests and is used to create one +tween per-request. Shared mutable state on the factory itself needs to be +carefully handled, and should be avoided unless you are willing to handle +the race conditions that may arise. + You can write the tween factory as a simple closure-returning function: .. code-block:: python @@ -1017,8 +1022,7 @@ You can write the tween factory as a simple closure-returning function: return simple_tween Alternatively, the tween factory can be a class with the ``__call__`` magic -method (the instance will be unique, be aware that it will be shared -between threads): +method: .. code-block:: python :linenos: -- cgit v1.2.3 From 2c096b0a8b7a83f5ded54a3fd6c048cd5f01b9a4 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 21 May 2014 12:20:56 -0500 Subject: oops, re-clarify that tweens should not have mutable state --- docs/narr/hooks.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index fe7749cac..4da36e730 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -995,11 +995,6 @@ A tween is called with a single argument, ``request``, which is the A tween should return a :term:`response`, usually the one generated by the downstream Pyramid application. -The tween factory will be shared between requests and is used to create one -tween per-request. Shared mutable state on the factory itself needs to be -carefully handled, and should be avoided unless you are willing to handle -the race conditions that may arise. - You can write the tween factory as a simple closure-returning function: .. code-block:: python @@ -1045,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 -- cgit v1.2.3 From c740e8bd20c049cbab43ce0a1cd5a4533fe6b849 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 May 2014 10:41:02 -0500 Subject: fix project url --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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, -- cgit v1.2.3 From c79c2d9f36f27abfa5e2a72e021298728734138d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 25 May 2014 16:36:09 -0700 Subject: Bring in #1352 --- docs/quick_tutorial/databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 -- cgit v1.2.3