mirror of
https://github.com/jazzband/django-downloadview.git
synced 2026-03-16 22:40:25 +00:00
Merge pull request #147 from joehybird/master
Add Django 2.2, Django 3.0 support & Drop Django 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 2.0 and 2.1 as well as Python 3.4 and 3.5
This commit is contained in:
commit
31bb096a77
37 changed files with 182 additions and 130 deletions
32
.travis.yml
32
.travis.yml
|
|
@ -1,28 +1,12 @@
|
|||
language: python
|
||||
dist: bionic
|
||||
python:
|
||||
- "3.5"
|
||||
env:
|
||||
- TOXENV=py27-django15
|
||||
- TOXENV=py27-django16
|
||||
- TOXENV=py27-django17
|
||||
- TOXENV=py27-django18
|
||||
- TOXENV=py27-django19
|
||||
- TOXENV=py27-django110
|
||||
- TOXENV=py27-django111
|
||||
- TOXENV=py34-django15
|
||||
- TOXENV=py34-django16
|
||||
- TOXENV=py34-django17
|
||||
- TOXENV=py34-django18
|
||||
- TOXENV=py34-django19
|
||||
- TOXENV=py34-django110
|
||||
- TOXENV=py34-django111
|
||||
- TOXENV=py35-django18
|
||||
- TOXENV=py35-django19
|
||||
- TOXENV=py34-django110
|
||||
- TOXENV=py34-django111
|
||||
- TOXENV=flake8
|
||||
# - TOXENV=sphinx
|
||||
# - TOXENV=readme
|
||||
- 2.7
|
||||
- 3.6
|
||||
- 3.7
|
||||
- 3.8
|
||||
install:
|
||||
- pip install tox
|
||||
- pip install -q tox-travis
|
||||
script:
|
||||
- make test
|
||||
- tox
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ future releases, check `milestones`_ and :doc:`/about/vision`.
|
|||
1.10 (unreleased)
|
||||
-----------------
|
||||
|
||||
- Nothing changed yet.
|
||||
- Introduced support from Django 1.10 to 2.2.
|
||||
- Drop support of Django 1.5, 1.6 & 1.7
|
||||
|
||||
|
||||
1.9 (2016-03-15)
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ documentation. Maintain it along with code and documentation.
|
|||
.. _`bugtracker`:
|
||||
https://github.com/benoitbryon/django-downloadview/issues
|
||||
.. _`rebase`: http://git-scm.com/book/en/Git-Branching-Rebasing
|
||||
.. _`merge-based rebase`: http://tech.novapost.fr/psycho-rebasing-en.html
|
||||
.. _`merge-based rebase`: https://tech.people-doc.com/psycho-rebasing.html
|
||||
.. _`pip`: https://pypi.python.org/pypi/pip/
|
||||
.. _`tox`: http://tox.testrun.org
|
||||
.. _`tox`: https://tox.readthedocs.io/
|
||||
.. _`Sphinx`: https://pypi.python.org/pypi/Sphinx/
|
||||
.. _`zest.releaser`: https://pypi.python.org/pypi/zest.releaser/
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import os
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.urlresolvers import reverse
|
||||
import django.test
|
||||
|
||||
from django_downloadview.apache import assert_x_sendfile
|
||||
|
||||
from demoproject.compat import reverse
|
||||
from demoproject.apache.views import storage, storage_dir
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"""URL mapping."""
|
||||
from django.conf.urls import url
|
||||
|
||||
from demoproject.compat import patterns
|
||||
from demoproject.apache import views
|
||||
from demoproject.urlpatterns import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
|
|
|
|||
22
demo/demoproject/compat.py
Normal file
22
demo/demoproject/compat.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
from distutils.version import StrictVersion
|
||||
from django.utils.version import get_version
|
||||
|
||||
|
||||
try:
|
||||
from django.conf.urls import patterns # noqa
|
||||
except ImportError:
|
||||
def patterns(prefix, *args):
|
||||
return list(args)
|
||||
|
||||
try:
|
||||
from django.urls import reverse # noqa
|
||||
except ImportError:
|
||||
from django.core.urlresolvers import reverse # noqa
|
||||
|
||||
if StrictVersion(get_version()) >= StrictVersion('2.0'):
|
||||
from django.conf.urls import include as urlinclude # noqa
|
||||
|
||||
def include(arg, namespace=None, app_name=None):
|
||||
return urlinclude((arg, app_name), namespace=namespace)
|
||||
else:
|
||||
from django.conf.urls import include # noqa
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
from django.core.urlresolvers import reverse
|
||||
import django.test
|
||||
|
||||
from django_downloadview import assert_download_response
|
||||
|
||||
from demoproject.compat import reverse
|
||||
|
||||
|
||||
class SimpleURLTestCase(django.test.TestCase):
|
||||
def test_download_response(self):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
from django.conf.urls import url
|
||||
|
||||
from demoproject.compat import patterns
|
||||
from demoproject.http import views
|
||||
from demoproject.urlpatterns import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import os
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.urlresolvers import reverse
|
||||
import django.test
|
||||
|
||||
from django_downloadview.lighttpd import assert_x_sendfile
|
||||
|
||||
from demoproject.compat import reverse
|
||||
from demoproject.lighttpd.views import storage, storage_dir
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"""URL mapping."""
|
||||
from django.conf.urls import url
|
||||
|
||||
from demoproject.compat import patterns
|
||||
from demoproject.lighttpd import views
|
||||
from demoproject.urlpatterns import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import os
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.urlresolvers import reverse
|
||||
import django.test
|
||||
|
||||
from django_downloadview.nginx import assert_x_accel_redirect
|
||||
|
||||
from demoproject.compat import reverse
|
||||
from demoproject.nginx.views import storage, storage_dir
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
from django.conf.urls import url
|
||||
|
||||
from demoproject.compat import patterns
|
||||
from demoproject.nginx import views
|
||||
from demoproject.urlpatterns import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from django.core.files.base import ContentFile
|
||||
from django.core.urlresolvers import reverse
|
||||
import django.test
|
||||
|
||||
from django_downloadview import temporary_media_root, assert_download_response
|
||||
|
||||
from demoproject.compat import reverse
|
||||
from demoproject.object.models import Document
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
from django.conf.urls import url
|
||||
|
||||
from demoproject.compat import patterns
|
||||
from demoproject.object import views
|
||||
from demoproject.urlpatterns import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
from django.core.urlresolvers import reverse
|
||||
import django.test
|
||||
|
||||
from django_downloadview import assert_download_response
|
||||
|
||||
from demoproject.compat import reverse
|
||||
|
||||
|
||||
class StaticPathTestCase(django.test.TestCase):
|
||||
def test_download_response(self):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
from django.conf.urls import url
|
||||
|
||||
from demoproject.compat import patterns
|
||||
from demoproject.path import views
|
||||
from demoproject.urlpatterns import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
|
|
|
|||
|
|
@ -64,14 +64,24 @@ INSTALLED_APPS = (
|
|||
|
||||
|
||||
# BEGIN middlewares
|
||||
MIDDLEWARE_CLASSES = [
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django_downloadview.SmartDownloadMiddleware'
|
||||
]
|
||||
if StrictVersion(get_version()) >= StrictVersion('1.10'):
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django_downloadview.SmartDownloadMiddleware'
|
||||
]
|
||||
else:
|
||||
MIDDLEWARE_CLASSES = [
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django_downloadview.SmartDownloadMiddleware'
|
||||
]
|
||||
# END middlewares
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import datetime
|
|||
import unittest
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http.response import HttpResponseNotModified
|
||||
import django.test
|
||||
|
||||
from django_downloadview import assert_download_response, temporary_media_root
|
||||
from django_downloadview import setup_view
|
||||
|
||||
from demoproject.compat import reverse
|
||||
from demoproject.storage import views
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf.urls import url
|
||||
|
||||
from demoproject.compat import patterns
|
||||
from demoproject.storage import views
|
||||
from demoproject.urlpatterns import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# coding=utf8
|
||||
"""Test suite for demoproject.download."""
|
||||
from django.core.urlresolvers import reverse
|
||||
from demoproject.compat import reverse
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
try:
|
||||
from django.conf.urls import patterns
|
||||
except:
|
||||
def patterns(prefix, *args):
|
||||
return list(args)
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf.urls import include, url
|
||||
from django.conf.urls import url
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from demoproject.urlpatterns import patterns
|
||||
from demoproject.compat import patterns, include
|
||||
|
||||
|
||||
home = TemplateView.as_view(template_name='home.html')
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
from django.core.urlresolvers import reverse
|
||||
import django.test
|
||||
|
||||
from django_downloadview import assert_download_response
|
||||
|
||||
from demoproject.compat import reverse
|
||||
|
||||
|
||||
class TextTestCase(django.test.TestCase):
|
||||
def test_download_response(self):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf.urls import url
|
||||
|
||||
from demoproject.compat import patterns
|
||||
from demoproject.virtual import views
|
||||
from demoproject.urlpatterns import patterns
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ class XSendfileMiddleware(ProxiedDownloadMiddleware):
|
|||
:py:class:`django_downloadview.decorators.DownloadDecorator`.
|
||||
|
||||
"""
|
||||
def __init__(self, source_dir=None, source_url=None, destination_dir=None):
|
||||
def __init__(self,
|
||||
get_response=None,
|
||||
source_dir=None, source_url=None, destination_dir=None):
|
||||
"""Constructor."""
|
||||
super(XSendfileMiddleware, self).__init__(source_dir,
|
||||
source_url,
|
||||
destination_dir)
|
||||
super(XSendfileMiddleware, self).__init__(
|
||||
get_response, source_dir, source_url, destination_dir
|
||||
)
|
||||
|
||||
def process_download_response(self, request, response):
|
||||
"""Replace DownloadResponse instances by XSendfileResponse ones."""
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""File wrappers for use as exchange data between views and responses."""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from io import BytesIO
|
||||
from six.moves.urllib.parse import urlparse
|
||||
|
||||
|
|
@ -122,7 +123,10 @@ class StorageFile(File):
|
|||
Proxy to self.storage.accessed_time(self.name).
|
||||
|
||||
"""
|
||||
return self.storage.accessed(self.name)
|
||||
try:
|
||||
return self.storage.get_accessed_time(self.name)
|
||||
except AttributeError:
|
||||
return self.storage.accessed_time(self.name)
|
||||
|
||||
@property
|
||||
def created_time(self):
|
||||
|
|
@ -131,7 +135,10 @@ class StorageFile(File):
|
|||
Proxy to self.storage.created_time(self.name).
|
||||
|
||||
"""
|
||||
return self.storage.created_time(self.name)
|
||||
try:
|
||||
return self.storage.get_created_time(self.name)
|
||||
except AttributeError:
|
||||
return self.storage.created_time(self.name)
|
||||
|
||||
@property
|
||||
def modified_time(self):
|
||||
|
|
@ -140,7 +147,10 @@ class StorageFile(File):
|
|||
Proxy to self.storage.modified_time(self.name).
|
||||
|
||||
"""
|
||||
return self.storage.modified_time(self.name)
|
||||
try:
|
||||
return self.storage.get_modified_time(self.name)
|
||||
except AttributeError:
|
||||
return self.storage.modified_time(self.name)
|
||||
|
||||
|
||||
class VirtualFile(File):
|
||||
|
|
|
|||
|
|
@ -40,38 +40,38 @@ class TextIteratorIO(io.TextIOBase):
|
|||
|
||||
def read(self, n=None):
|
||||
"""Return content up to ``n`` length."""
|
||||
l = []
|
||||
chunks = []
|
||||
if n is None or n < 0:
|
||||
while True:
|
||||
m = self._read1()
|
||||
if not m:
|
||||
break
|
||||
l.append(m)
|
||||
chunks.append(m)
|
||||
else:
|
||||
while n > 0:
|
||||
m = self._read1(n)
|
||||
if not m:
|
||||
break
|
||||
n -= len(m)
|
||||
l.append(m)
|
||||
return u''.join(l)
|
||||
chunks.append(m)
|
||||
return u''.join(chunks)
|
||||
|
||||
def readline(self):
|
||||
l = []
|
||||
chunks = []
|
||||
while True:
|
||||
i = self._left.find(u'\n')
|
||||
if i == -1:
|
||||
l.append(self._left)
|
||||
chunks.append(self._left)
|
||||
try:
|
||||
self._left = next(self._iter)
|
||||
except StopIteration:
|
||||
self._left = u''
|
||||
break
|
||||
else:
|
||||
l.append(self._left[:i + 1])
|
||||
chunks.append(self._left[:i + 1])
|
||||
self._left = self._left[i + 1:]
|
||||
break
|
||||
return u''.join(l)
|
||||
return u''.join(chunks)
|
||||
|
||||
|
||||
class BytesIteratorIO(io.BytesIO):
|
||||
|
|
@ -108,35 +108,35 @@ class BytesIteratorIO(io.BytesIO):
|
|||
|
||||
def read(self, n=None):
|
||||
"""Return content up to ``n`` length."""
|
||||
l = []
|
||||
chunks = []
|
||||
if n is None or n < 0:
|
||||
while True:
|
||||
m = self._read1()
|
||||
if not m:
|
||||
break
|
||||
l.append(m)
|
||||
chunks.append(m)
|
||||
else:
|
||||
while n > 0:
|
||||
m = self._read1(n)
|
||||
if not m:
|
||||
break
|
||||
n -= len(m)
|
||||
l.append(m)
|
||||
return b''.join(l)
|
||||
chunks.append(m)
|
||||
return b''.join(chunks)
|
||||
|
||||
def readline(self):
|
||||
l = []
|
||||
chunks = []
|
||||
while True:
|
||||
i = self._left.find(b'\n')
|
||||
if i == -1:
|
||||
l.append(self._left)
|
||||
chunks.append(self._left)
|
||||
try:
|
||||
self._left = next(self._iter)
|
||||
except StopIteration:
|
||||
self._left = b''
|
||||
break
|
||||
else:
|
||||
l.append(self._left[:i + 1])
|
||||
chunks.append(self._left[:i + 1])
|
||||
self._left = self._left[i + 1:]
|
||||
break
|
||||
return b''.join(l)
|
||||
return b''.join(chunks)
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ class XSendfileMiddleware(ProxiedDownloadMiddleware):
|
|||
:py:class:`django_downloadview.decorators.DownloadDecorator`.
|
||||
|
||||
"""
|
||||
def __init__(self, source_dir=None, source_url=None, destination_dir=None):
|
||||
def __init__(self,
|
||||
get_response=None,
|
||||
source_dir=None, source_url=None, destination_dir=None):
|
||||
"""Constructor."""
|
||||
super(XSendfileMiddleware, self).__init__(source_dir,
|
||||
source_url,
|
||||
destination_dir)
|
||||
super(XSendfileMiddleware, self).__init__(
|
||||
get_response, source_dir, source_url, destination_dir
|
||||
)
|
||||
|
||||
def process_download_response(self, request, response):
|
||||
"""Replace DownloadResponse instances by XSendfileResponse ones."""
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ import os
|
|||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
try:
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
except ImportError:
|
||||
class MiddlewareMixin(object):
|
||||
def __init__(self, get_response=None):
|
||||
super(MiddlewareMixin, self).__init__()
|
||||
|
||||
from django_downloadview.response import DownloadResponse
|
||||
from django_downloadview.utils import import_member
|
||||
|
||||
|
|
@ -31,7 +38,7 @@ def is_download_response(response):
|
|||
return isinstance(response, DownloadResponse)
|
||||
|
||||
|
||||
class BaseDownloadMiddleware(object):
|
||||
class BaseDownloadMiddleware(MiddlewareMixin):
|
||||
"""Base (abstract) Django middleware that handles download responses.
|
||||
|
||||
Subclasses **must** implement :py:meth:`process_download_response` method.
|
||||
|
|
@ -80,7 +87,8 @@ class RealDownloadMiddleware(BaseDownloadMiddleware):
|
|||
|
||||
class DownloadDispatcherMiddleware(BaseDownloadMiddleware):
|
||||
"Download middleware that dispatches job to several middleware instances."
|
||||
def __init__(self, middlewares=AUTO_CONFIGURE):
|
||||
def __init__(self, get_response=None, middlewares=AUTO_CONFIGURE):
|
||||
super(DownloadDispatcherMiddleware, self).__init__(get_response)
|
||||
#: List of children middlewares.
|
||||
self.middlewares = middlewares
|
||||
if self.middlewares is AUTO_CONFIGURE:
|
||||
|
|
@ -106,9 +114,11 @@ class DownloadDispatcherMiddleware(BaseDownloadMiddleware):
|
|||
class SmartDownloadMiddleware(BaseDownloadMiddleware):
|
||||
"""Easy to configure download middleware."""
|
||||
def __init__(self,
|
||||
get_response=None,
|
||||
backend_factory=AUTO_CONFIGURE,
|
||||
backend_options=AUTO_CONFIGURE):
|
||||
"""Constructor."""
|
||||
super(SmartDownloadMiddleware, self).__init__(get_response)
|
||||
#: :class:`DownloadDispatcher` instance that can hold multiple
|
||||
#: backend instances.
|
||||
self.dispatcher = DownloadDispatcherMiddleware(middlewares=[])
|
||||
|
|
@ -165,8 +175,14 @@ class NoRedirectionMatch(Exception):
|
|||
|
||||
class ProxiedDownloadMiddleware(RealDownloadMiddleware):
|
||||
"""Base class for middlewares that use optimizations of reverse proxies."""
|
||||
def __init__(self, source_dir=None, source_url=None, destination_url=None):
|
||||
def __init__(self,
|
||||
get_response=None,
|
||||
source_dir=None,
|
||||
source_url=None,
|
||||
destination_url=None):
|
||||
"""Constructor."""
|
||||
super(ProxiedDownloadMiddleware, self).__init__(get_response)
|
||||
|
||||
self.source_dir = source_dir
|
||||
self.source_url = source_url
|
||||
self.destination_url = destination_url
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ class XAccelRedirectMiddleware(ProxiedDownloadMiddleware):
|
|||
:py:class:`django_downloadview.decorators.DownloadDecorator`.
|
||||
|
||||
"""
|
||||
def __init__(self, source_dir=None, source_url=None, destination_url=None,
|
||||
def __init__(self,
|
||||
get_response=None,
|
||||
source_dir=None, source_url=None, destination_url=None,
|
||||
expires=None, with_buffering=None, limit_rate=None,
|
||||
media_root=None, media_url=None):
|
||||
"""Constructor."""
|
||||
|
|
@ -42,9 +44,10 @@ class XAccelRedirectMiddleware(ProxiedDownloadMiddleware):
|
|||
source_dir = source_dir
|
||||
else:
|
||||
source_dir = source_dir
|
||||
super(XAccelRedirectMiddleware, self).__init__(source_dir,
|
||||
source_url,
|
||||
destination_url)
|
||||
|
||||
super(XAccelRedirectMiddleware, self).__init__(
|
||||
get_response, source_dir, source_url, destination_url)
|
||||
|
||||
self.expires = expires
|
||||
self.with_buffering = with_buffering
|
||||
self.limit_rate = limit_rate
|
||||
|
|
@ -105,13 +108,14 @@ class SingleXAccelRedirectMiddleware(XAccelRedirectMiddleware):
|
|||
Replaced by ``NGINX_DOWNLOAD_MIDDLEWARE_DESTINATION_URL``.
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
def __init__(self, get_response=None):
|
||||
"""Use Django settings as configuration."""
|
||||
if settings.NGINX_DOWNLOAD_MIDDLEWARE_DESTINATION_URL is None:
|
||||
raise ImproperlyConfigured(
|
||||
'settings.NGINX_DOWNLOAD_MIDDLEWARE_DESTINATION_URL is '
|
||||
'required by %s middleware' % self.__class__.__name__)
|
||||
super(SingleXAccelRedirectMiddleware, self).__init__(
|
||||
get_response=get_response,
|
||||
source_dir=settings.NGINX_DOWNLOAD_MIDDLEWARE_SOURCE_DIR,
|
||||
source_url=settings.NGINX_DOWNLOAD_MIDDLEWARE_SOURCE_URL,
|
||||
destination_url=settings.NGINX_DOWNLOAD_MIDDLEWARE_DESTINATION_URL,
|
||||
|
|
|
|||
|
|
@ -16,11 +16,20 @@ from django.core.exceptions import ImproperlyConfigured
|
|||
|
||||
# In version 1.3, former XAccelRedirectMiddleware has been renamed to
|
||||
# SingleXAccelRedirectMiddleware. So tell the users.
|
||||
middleware = 'django_downloadview.nginx.XAccelRedirectMiddleware'
|
||||
if middleware in settings.MIDDLEWARE_CLASSES:
|
||||
deprecated_middleware = 'django_downloadview.nginx.XAccelRedirectMiddleware'
|
||||
|
||||
|
||||
def get_middlewares():
|
||||
try:
|
||||
return settings.MIDDLEWARE
|
||||
except AttributeError:
|
||||
return settings.MIDDLEWARE_CLASSES
|
||||
|
||||
|
||||
if deprecated_middleware in get_middlewares():
|
||||
raise ImproperlyConfigured(
|
||||
'{middleware} middleware has been renamed as of django-downloadview '
|
||||
'version 1.3. You may use '
|
||||
'{deprecated_middleware} middleware has been renamed as of '
|
||||
'django-downloadview version 1.3. You may use '
|
||||
'"django_downloadview.nginx.SingleXAccelRedirectMiddleware" instead, '
|
||||
'or upgrade to "django_downloadview.SmartDownloadDispatcher". ')
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,8 @@ class DownloadMixin(object):
|
|||
modification_time = calendar.timegm(
|
||||
file_instance.modified_time.utctimetuple())
|
||||
size = file_instance.size
|
||||
except (AttributeError, NotImplementedError):
|
||||
except (AttributeError, NotImplementedError) as e:
|
||||
print("!=======!", e)
|
||||
return True
|
||||
else:
|
||||
return was_modified_since(since, modification_time, size)
|
||||
|
|
|
|||
|
|
@ -75,6 +75,6 @@ Here are main differences between the two projects:
|
|||
.. target-notes::
|
||||
|
||||
.. _`django.contrib.staticfiles provides a view to serve files`:
|
||||
https://docs.djangoproject.com/en/1.9/ref/contrib/staticfiles/#static-file-development-view
|
||||
https://docs.djangoproject.com/en/3.0/ref/contrib/staticfiles/#static-file-development-view
|
||||
.. _`Django ticket #2131`: https://code.djangoproject.com/ticket/2131
|
||||
.. _`django-sendfile`: http://pypi.python.org/pypi/django-sendfile
|
||||
|
|
|
|||
|
|
@ -127,4 +127,4 @@ TextIteratorIO
|
|||
.. target-notes::
|
||||
|
||||
.. _`Django itself provides some file wrappers`:
|
||||
https://docs.djangoproject.com/en/1.9/ref/files/file/
|
||||
https://docs.djangoproject.com/en/3.0/ref/files/file/
|
||||
|
|
|
|||
9
setup.py
9
setup.py
|
|
@ -40,9 +40,10 @@ CLASSIFIERS = [
|
|||
'Framework :: Django',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
]
|
||||
KEYWORDS = ['file',
|
||||
'stream',
|
||||
|
|
@ -58,7 +59,7 @@ KEYWORDS = ['file',
|
|||
PACKAGES = [NAME.replace('-', '_')]
|
||||
REQUIREMENTS = [
|
||||
# BEGIN requirements
|
||||
'Django>=1.5',
|
||||
'Django>=1.11',
|
||||
'requests',
|
||||
'setuptools',
|
||||
'six',
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@ class DeprecatedAPITestCase(django.test.SimpleTestCase):
|
|||
"XAccelRedirectMiddleware in settings triggers ImproperlyConfigured."
|
||||
with override_settings(
|
||||
MIDDLEWARE_CLASSES=[
|
||||
'django_downloadview.nginx.XAccelRedirectMiddleware']):
|
||||
'django_downloadview.nginx.XAccelRedirectMiddleware'],
|
||||
MIDDLEWARE=[
|
||||
'django_downloadview.nginx.XAccelRedirectMiddleware'],):
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
import django_downloadview.nginx.settings
|
||||
reload(django_downloadview.nginx.settings)
|
||||
|
|
|
|||
34
tox.ini
34
tox.ini
|
|
@ -1,46 +1,34 @@
|
|||
[tox]
|
||||
envlist = py{27}-django{15,16,17,18,19,110,111}, py{33,34}-django{15,16,17}, py{34,35}-django{18,19,110,111}, flake8, sphinx, readme
|
||||
envlist = py27-django111,
|
||||
py{35,36,36,37,38}-django{22,30},
|
||||
flake8, sphinx, readme
|
||||
|
||||
[travis]
|
||||
python=
|
||||
3.8: py38, flake8, sphinx, readme
|
||||
|
||||
[testenv]
|
||||
basepython =
|
||||
py27: python2.7
|
||||
py33: python3.3
|
||||
py34: python3.4
|
||||
py35: python3.5
|
||||
deps =
|
||||
coverage
|
||||
django15: Django>=1.5,<1.6
|
||||
django15: django-nose<1.4.3
|
||||
django16: Django>=1.6,<1.7
|
||||
django16: django-nose<1.4.3
|
||||
django17: Django>=1.7,<1.8
|
||||
django17: django-nose<1.4.3
|
||||
django18: Django>=1.8,<1.9
|
||||
django18: django-nose>=1.4.2
|
||||
django19: Django>=1.9,<1.10
|
||||
django19: django-nose>=1.4.3
|
||||
django110: Django>=1.10,<1.11
|
||||
django110: django-nose>=1.4.4
|
||||
django111: Django>=1.11,<2.0
|
||||
django111: django-nose>=1.4.5
|
||||
django22: Django>=2.2,<3.0
|
||||
django30: Django>=3.0,<3.1
|
||||
nose
|
||||
py27: mock
|
||||
commands =
|
||||
pip install -e .
|
||||
pip install -e demo
|
||||
demo test --cover-package=django_downloadview --cover-package=demoproject {posargs: tests demoproject}
|
||||
python -Wd {envbindir}/demo test --cover-package=django_downloadview --cover-package=demoproject {posargs: tests demoproject}
|
||||
coverage erase
|
||||
pip freeze
|
||||
|
||||
[testenv:flake8]
|
||||
basepython = python3.5
|
||||
deps =
|
||||
flake8
|
||||
commands =
|
||||
flake8 demo django_downloadview tests
|
||||
|
||||
[testenv:sphinx]
|
||||
basepython = python3.5
|
||||
deps =
|
||||
Sphinx
|
||||
commands =
|
||||
|
|
@ -50,7 +38,6 @@ whitelist_externals =
|
|||
make
|
||||
|
||||
[testenv:readme]
|
||||
basepython = python3.5
|
||||
deps =
|
||||
docutils
|
||||
pygments
|
||||
|
|
@ -62,7 +49,6 @@ whitelist_externals =
|
|||
mkdir
|
||||
|
||||
[testenv:release]
|
||||
basepython = python3.5
|
||||
deps =
|
||||
wheel
|
||||
zest.releaser
|
||||
|
|
|
|||
Loading…
Reference in a new issue