summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2012-01-16 15:31:17 -0500
committerChris McDonough <chrism@plope.com>2012-01-16 15:31:17 -0500
commit83086463eb6f129fe7d02d90b866eb6780581da2 (patch)
treefc56780313e929b34847ede44870194022c13887
parentb20d68703af695c80e7844e8aae61ccf31cedaaa (diff)
downloadpyramid-83086463eb6f129fe7d02d90b866eb6780581da2.tar.gz
pyramid-83086463eb6f129fe7d02d90b866eb6780581da2.tar.bz2
pyramid-83086463eb6f129fe7d02d90b866eb6780581da2.zip
- Responses generated by Pyramid's ``static_view`` now use
a ``wsgi.file_wrapper`` (see http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling) when one is provided by the web server.
-rw-r--r--CHANGES.txt5
-rw-r--r--pyramid/static.py34
-rw-r--r--pyramid/tests/test_static.py16
3 files changed, 35 insertions, 20 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index a755f6418..fc7fc1cab 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,11 @@ Features
This method provides conflict detection and is the suggested way to add
properties to a request.
+- Responses generated by Pyramid's ``static_view`` now use
+ a ``wsgi.file_wrapper`` (see
+ http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling)
+ when one is provided by the web server.
+
1.3a5 (2012-01-09)
==================
diff --git a/pyramid/static.py b/pyramid/static.py
index 61ee67573..b82bc1bc4 100644
--- a/pyramid/static.py
+++ b/pyramid/static.py
@@ -47,11 +47,13 @@ def init_mimetypes(mimetypes):
# has been applied on the Python 2 trunk).
init_mimetypes(mimetypes)
+_BLOCK_SIZE = 4096 * 64 # 256K
+
class _FileResponse(Response):
"""
Serves a static filelike object.
"""
- def __init__(self, path, cache_max_age):
+ def __init__(self, path, cache_max_age, request):
super(_FileResponse, self).__init__(conditional_response=True)
self.last_modified = getmtime(path)
content_type, content_encoding = mimetypes.guess_type(path,
@@ -61,34 +63,26 @@ class _FileResponse(Response):
self.content_type = content_type
self.content_encoding = content_encoding
content_length = getsize(path)
- self.app_iter = _FileIter(open(path, 'rb'), content_length)
+ f = open(path, 'rb')
+ environ = request.environ
+ if 'wsgi.file_wrapper' in environ:
+ app_iter = environ['wsgi.file_wrapper'](f, _BLOCK_SIZE)
+ else:
+ app_iter = _FileIter(open(path, 'rb'))
+ self.app_iter = app_iter
# assignment of content_length must come after assignment of app_iter
self.content_length = content_length
if cache_max_age is not None:
self.cache_expires = cache_max_age
class _FileIter(object):
- block_size = 4096 * 64 # (256K)
+ block_size = _BLOCK_SIZE
- def __init__(self, file, size=None):
+ def __init__(self, file):
self.file = file
- self.size = size
def __iter__(self):
- return self
-
- def next(self):
- chunk_size = self.block_size
- if self.size is not None:
- if chunk_size > self.size:
- chunk_size = self.size
- self.size -= chunk_size
- data = self.file.read(chunk_size)
- if not data:
- raise StopIteration
- return data
-
- __next__ = next # py3
+ return iter(lambda: self.file.read(self.block_size), b'')
def close(self):
self.file.close()
@@ -186,7 +180,7 @@ class static_view(object):
if not exists(filepath):
return HTTPNotFound(request.url)
- return _FileResponse(filepath ,self.cache_max_age)
+ return _FileResponse(filepath ,self.cache_max_age, request)
def add_slash_redirect(self, request):
url = request.path_url + '/'
diff --git a/pyramid/tests/test_static.py b/pyramid/tests/test_static.py
index bd2c2adef..4edd2728e 100644
--- a/pyramid/tests/test_static.py
+++ b/pyramid/tests/test_static.py
@@ -112,6 +112,22 @@ class Test_static_view_use_subpath_False(unittest.TestCase):
response = inst(context, request)
self.assertTrue(b'<html>static</html>' in response.body)
+ def test_resource_is_file_with_wsgi_file_wrapper(self):
+ from pyramid.static import _BLOCK_SIZE
+ inst = self._makeOne('pyramid.tests:fixtures/static')
+ request = self._makeRequest({'PATH_INFO':'/index.html'})
+ class _Wrapper(object):
+ def __init__(self, file, block_size=None):
+ self.file = file
+ self.block_size = block_size
+ request.environ['wsgi.file_wrapper'] = _Wrapper
+ context = DummyContext()
+ response = inst(context, request)
+ app_iter = response.app_iter
+ self.assertTrue(isinstance(app_iter, _Wrapper))
+ self.assertTrue(b'<html>static</html>' in app_iter.file.read())
+ self.assertEqual(app_iter.block_size, _BLOCK_SIZE)
+
def test_resource_is_file_with_cache_max_age(self):
inst = self._makeOne('pyramid.tests:fixtures/static', cache_max_age=600)
request = self._makeRequest({'PATH_INFO':'/index.html'})