mirror of
https://github.com/jazzband/django-downloadview.git
synced 2026-03-16 22:40:25 +00:00
Merge d21d07c1e7 into 44f1ca3be3
This commit is contained in:
commit
46d084d444
3 changed files with 56 additions and 0 deletions
|
|
@ -6,6 +6,8 @@ Changelog
|
|||
|
||||
Bugfixes and documentation improvements.
|
||||
|
||||
- Bug #26 - Prevented computation of virtual file's size, unless the file
|
||||
wrapper implements was_modified_since() method.
|
||||
- Bug #34 - Improved support of files that do not implement modification time.
|
||||
- Bug #35 - Fixed README conversion from reStructuredText to HTML (PyPI).
|
||||
|
||||
|
|
|
|||
|
|
@ -173,6 +173,27 @@ class VirtualDownloadView(BaseDownloadView):
|
|||
"""Return wrapper."""
|
||||
raise NotImplementedError()
|
||||
|
||||
def was_modified_since(self, file_instance, since):
|
||||
"""Delegate to file wrapper's was_modified_since, or return True.
|
||||
|
||||
This is the implementation of an edge case: when files are generated
|
||||
on the fly, we cannot guess whether they have been modified or not.
|
||||
If the file wrapper implements ``was_modified_since()`` method, then we
|
||||
trust it. Otherwise it is safer to suppose that the file has been
|
||||
modified.
|
||||
|
||||
This behaviour prevents file size to be computed on the Django side.
|
||||
Because computing file size means iterating over all the file contents,
|
||||
and we want to avoid that whenever possible. As an example, it could
|
||||
reduce all the benefits of working with dynamic file generators...
|
||||
which is a major feature of virtual files.
|
||||
|
||||
"""
|
||||
try:
|
||||
return file_instance.was_modified_since(since)
|
||||
except (AttributeError, NotImplementedError):
|
||||
return True
|
||||
|
||||
|
||||
class HTTPDownloadView(BaseDownloadView):
|
||||
"""Proxy files that live on remote servers."""
|
||||
|
|
|
|||
|
|
@ -48,3 +48,36 @@ class DownloadMixinTestCase(unittest.TestCase):
|
|||
mixin = views.DownloadMixin()
|
||||
since = mock.sentinel.since
|
||||
self.assertTrue(mixin.was_modified_since(file_wrapper, since))
|
||||
|
||||
|
||||
class VirtualDownloadViewTestCase(unittest.TestCase):
|
||||
"""Test suite around
|
||||
:py:class:`django_downloadview.views.VirtualDownloadView`."""
|
||||
def test_was_modified_since_specific(self):
|
||||
"""VirtualDownloadView.was_modified_since() delegates to file wrapper.
|
||||
|
||||
"""
|
||||
file_wrapper = mock.Mock()
|
||||
file_wrapper.was_modified_since = mock.Mock(
|
||||
return_value=mock.sentinel.from_file_wrapper)
|
||||
view = views.VirtualDownloadView()
|
||||
since = mock.sentinel.since
|
||||
return_value = view.was_modified_since(file_wrapper, since)
|
||||
self.assertTrue(return_value is mock.sentinel.from_file_wrapper)
|
||||
file_wrapper.was_modified_since.assert_called_once_with(since)
|
||||
|
||||
def test_was_modified_since_not_implemented(self):
|
||||
"""VirtualDownloadView.was_modified_since() returns True if file
|
||||
wrapper does not implement ``was_modified_since()``."""
|
||||
file_wrapper = mock.Mock()
|
||||
file_wrapper.was_modified_since = mock.Mock(side_effect=AttributeError)
|
||||
modified_time = mock.PropertyMock()
|
||||
setattr(file_wrapper, 'modified_time', modified_time)
|
||||
size = mock.PropertyMock()
|
||||
setattr(file_wrapper, 'size', size)
|
||||
view = views.VirtualDownloadView()
|
||||
since = mock.sentinel.since
|
||||
result = view.was_modified_since(file_wrapper, since)
|
||||
self.assertTrue(result is True)
|
||||
self.assertFalse(modified_time.called)
|
||||
self.assertFalse(size.called)
|
||||
|
|
|
|||
Loading…
Reference in a new issue