From 69bb9d864dac2e8b283286a7efc975ce3ee1aa18 Mon Sep 17 00:00:00 2001 From: Fabre Florian Date: Tue, 7 Jan 2020 09:54:20 +0100 Subject: [PATCH 01/11] Add Django 2.x targets to tox & travis scripts --- .travis.yml | 55 ++++++++++++++++++++++---------------- demo/demoproject/compat.py | 11 ++++++++ tox.ini | 38 ++++++++++++++++---------- 3 files changed, 67 insertions(+), 37 deletions(-) create mode 100644 demo/demoproject/compat.py diff --git a/.travis.yml b/.travis.yml index c6931de..277568f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,28 +1,37 @@ language: python +dist: xenial +sudo: true python: - - "3.5" + - 2.7 + - 3.4 + - 3.5 + - 3.6 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 + - DJANGO="1.8" + - DJANGO="1.9" + - DJANGO="1.10" + - DJANGO="1.11" + - DJANGO="2.0" + - DJANGO="2.1" + - DJANGO="2.2" +matrix: + - exclude: + - python: 2.7 + env: DJANGO="2.0" + + - python: 2.7 + env: DJANGO="2.1" + + - python: 3.4 + env: DJANGO="2.1" + + - python: 2.7 + env: DJANGO="2.2" + + - python: 3.4 + env: DJANGO="2.2" install: + - pip install tox + - pip install -q tox-travis script: - - make test + - tox diff --git a/demo/demoproject/compat.py b/demo/demoproject/compat.py new file mode 100644 index 0000000..6930bf5 --- /dev/null +++ b/demo/demoproject/compat.py @@ -0,0 +1,11 @@ + +try: + from django.conf.urls import patterns +except Exception: + def urlpatterns(prefix, *args): + return list(args) + +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse diff --git a/tox.ini b/tox.ini index 1f9b5d5..e2e6130 100644 --- a/tox.ini +++ b/tox.ini @@ -1,20 +1,27 @@ [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 = py{27}-django{18,19,110,111}, + py{34,35,36}-django{18,19,110,111,20,21,22}, + flake8, sphinx, readme + +[tox:travis] +2.7 = py27 +3.4 = py34 +3.5 = py35 +3.6 = py36, flake8, sphinx, readme + +[travis:env] +DJANGO = + 1.8: django18 + 1.9: django19 + 1.10: django110 + 1.11: django111 + 2.0: django20 + 2.1: django21 + 2.2: django22 [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 @@ -23,12 +30,15 @@ deps = django110: django-nose>=1.4.4 django111: Django>=1.11,<2.0 django111: django-nose>=1.4.5 + django20: Django>=2.0,<2.1 + django21: Django>=2.1,<2.2 + django22: Django>=2.2,<3.0 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 @@ -62,7 +72,7 @@ whitelist_externals = mkdir [testenv:release] -basepython = python3.5 +basepython = python3.6 deps = wheel zest.releaser From 4aa44b9dbe84e9bd0c6afbc28d613c6fdc03e415 Mon Sep 17 00:00:00 2001 From: Fabre Florian Date: Tue, 7 Jan 2020 09:57:48 +0100 Subject: [PATCH 02/11] Fix django.conf.urls compatibility issues --- demo/demoproject/apache/tests.py | 2 +- demo/demoproject/apache/urls.py | 2 +- demo/demoproject/compat.py | 15 +++++++++++++-- demo/demoproject/http/tests.py | 3 ++- demo/demoproject/http/urls.py | 3 ++- demo/demoproject/lighttpd/tests.py | 2 +- demo/demoproject/lighttpd/urls.py | 2 +- demo/demoproject/nginx/tests.py | 2 +- demo/demoproject/nginx/urls.py | 2 +- demo/demoproject/object/tests.py | 2 +- demo/demoproject/object/urls.py | 3 ++- demo/demoproject/path/tests.py | 3 ++- demo/demoproject/path/urls.py | 3 ++- demo/demoproject/storage/tests.py | 2 +- demo/demoproject/storage/urls.py | 2 +- demo/demoproject/tests.py | 3 ++- demo/demoproject/urlpatterns.py | 5 ----- demo/demoproject/urls.py | 4 ++-- demo/demoproject/virtual/tests.py | 3 ++- demo/demoproject/virtual/urls.py | 2 +- 20 files changed, 39 insertions(+), 26 deletions(-) delete mode 100644 demo/demoproject/urlpatterns.py diff --git a/demo/demoproject/apache/tests.py b/demo/demoproject/apache/tests.py index c24d7a9..b5c9bb6 100644 --- a/demo/demoproject/apache/tests.py +++ b/demo/demoproject/apache/tests.py @@ -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 diff --git a/demo/demoproject/apache/urls.py b/demo/demoproject/apache/urls.py index aec9cdf..7af509e 100644 --- a/demo/demoproject/apache/urls.py +++ b/demo/demoproject/apache/urls.py @@ -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( diff --git a/demo/demoproject/compat.py b/demo/demoproject/compat.py index 6930bf5..c1ed757 100644 --- a/demo/demoproject/compat.py +++ b/demo/demoproject/compat.py @@ -1,11 +1,22 @@ +from distutils.version import StrictVersion +from django.utils.version import get_version + try: from django.conf.urls import patterns -except Exception: - def urlpatterns(prefix, *args): +except ImportError: + def patterns(prefix, *args): return list(args) try: from django.urls import reverse except ImportError: from django.core.urlresolvers import reverse + +if StrictVersion(get_version()) >= StrictVersion('2.0'): + from django.conf.urls import include as urlinclude + + def include(arg, namespace=None, app_name=None): + return urlinclude((arg, app_name), namespace=namespace) +else: + from django.conf.urls import include diff --git a/demo/demoproject/http/tests.py b/demo/demoproject/http/tests.py index 4296790..7e6a1eb 100644 --- a/demo/demoproject/http/tests.py +++ b/demo/demoproject/http/tests.py @@ -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): diff --git a/demo/demoproject/http/urls.py b/demo/demoproject/http/urls.py index f8e0c92..6198c39 100644 --- a/demo/demoproject/http/urls.py +++ b/demo/demoproject/http/urls.py @@ -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( '', diff --git a/demo/demoproject/lighttpd/tests.py b/demo/demoproject/lighttpd/tests.py index 4918d15..2a9fc89 100644 --- a/demo/demoproject/lighttpd/tests.py +++ b/demo/demoproject/lighttpd/tests.py @@ -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 diff --git a/demo/demoproject/lighttpd/urls.py b/demo/demoproject/lighttpd/urls.py index a325a37..c300ec1 100644 --- a/demo/demoproject/lighttpd/urls.py +++ b/demo/demoproject/lighttpd/urls.py @@ -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( diff --git a/demo/demoproject/nginx/tests.py b/demo/demoproject/nginx/tests.py index d3c7930..b8e599b 100644 --- a/demo/demoproject/nginx/tests.py +++ b/demo/demoproject/nginx/tests.py @@ -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 diff --git a/demo/demoproject/nginx/urls.py b/demo/demoproject/nginx/urls.py index 1f13ecb..874a7a7 100644 --- a/demo/demoproject/nginx/urls.py +++ b/demo/demoproject/nginx/urls.py @@ -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( diff --git a/demo/demoproject/object/tests.py b/demo/demoproject/object/tests.py index 527936a..2530d3b 100644 --- a/demo/demoproject/object/tests.py +++ b/demo/demoproject/object/tests.py @@ -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 diff --git a/demo/demoproject/object/urls.py b/demo/demoproject/object/urls.py index 03e7fd4..ee3f54c 100644 --- a/demo/demoproject/object/urls.py +++ b/demo/demoproject/object/urls.py @@ -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( '', diff --git a/demo/demoproject/path/tests.py b/demo/demoproject/path/tests.py index facef1b..6fe25a8 100644 --- a/demo/demoproject/path/tests.py +++ b/demo/demoproject/path/tests.py @@ -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): diff --git a/demo/demoproject/path/urls.py b/demo/demoproject/path/urls.py index 17dad33..161203d 100644 --- a/demo/demoproject/path/urls.py +++ b/demo/demoproject/path/urls.py @@ -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( '', diff --git a/demo/demoproject/storage/tests.py b/demo/demoproject/storage/tests.py index 8536781..3f0abc2 100644 --- a/demo/demoproject/storage/tests.py +++ b/demo/demoproject/storage/tests.py @@ -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 diff --git a/demo/demoproject/storage/urls.py b/demo/demoproject/storage/urls.py index 53cd38c..1932cd4 100644 --- a/demo/demoproject/storage/urls.py +++ b/demo/demoproject/storage/urls.py @@ -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( diff --git a/demo/demoproject/tests.py b/demo/demoproject/tests.py index 35e6304..9bfc783 100644 --- a/demo/demoproject/tests.py +++ b/demo/demoproject/tests.py @@ -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 diff --git a/demo/demoproject/urlpatterns.py b/demo/demoproject/urlpatterns.py deleted file mode 100644 index 6e046ad..0000000 --- a/demo/demoproject/urlpatterns.py +++ /dev/null @@ -1,5 +0,0 @@ -try: - from django.conf.urls import patterns -except: - def patterns(prefix, *args): - return list(args) diff --git a/demo/demoproject/urls.py b/demo/demoproject/urls.py index dc43654..6ec45f7 100755 --- a/demo/demoproject/urls.py +++ b/demo/demoproject/urls.py @@ -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') diff --git a/demo/demoproject/virtual/tests.py b/demo/demoproject/virtual/tests.py index a8b92b0..63aa74e 100644 --- a/demo/demoproject/virtual/tests.py +++ b/demo/demoproject/virtual/tests.py @@ -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): diff --git a/demo/demoproject/virtual/urls.py b/demo/demoproject/virtual/urls.py index 2595b3f..2ad7105 100644 --- a/demo/demoproject/virtual/urls.py +++ b/demo/demoproject/virtual/urls.py @@ -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( From 0ad5e1238aee9434e86a4374d9a11a13a869c448 Mon Sep 17 00:00:00 2001 From: Fabre Florian Date: Tue, 7 Jan 2020 09:58:36 +0100 Subject: [PATCH 03/11] Fix middleware compatibility issues --- demo/demoproject/settings.py | 26 ++++++++++++++------- django_downloadview/apache/middlewares.py | 10 ++++---- django_downloadview/lighttpd/middlewares.py | 10 ++++---- django_downloadview/middlewares.py | 22 ++++++++++++++--- django_downloadview/nginx/middlewares.py | 14 +++++++---- django_downloadview/nginx/settings.py | 17 ++++++++++---- tests/api.py | 4 +++- 7 files changed, 74 insertions(+), 29 deletions(-) diff --git a/demo/demoproject/settings.py b/demo/demoproject/settings.py index c091ce6..cb548a8 100755 --- a/demo/demoproject/settings.py +++ b/demo/demoproject/settings.py @@ -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 diff --git a/django_downloadview/apache/middlewares.py b/django_downloadview/apache/middlewares.py index ee854b3..9f4b716 100644 --- a/django_downloadview/apache/middlewares.py +++ b/django_downloadview/apache/middlewares.py @@ -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.""" diff --git a/django_downloadview/lighttpd/middlewares.py b/django_downloadview/lighttpd/middlewares.py index c19e158..626f293 100644 --- a/django_downloadview/lighttpd/middlewares.py +++ b/django_downloadview/lighttpd/middlewares.py @@ -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.""" diff --git a/django_downloadview/middlewares.py b/django_downloadview/middlewares.py index bcabce5..3cbc291 100644 --- a/django_downloadview/middlewares.py +++ b/django_downloadview/middlewares.py @@ -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 diff --git a/django_downloadview/nginx/middlewares.py b/django_downloadview/nginx/middlewares.py index 1ad2fcc..71fc31d 100644 --- a/django_downloadview/nginx/middlewares.py +++ b/django_downloadview/nginx/middlewares.py @@ -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, diff --git a/django_downloadview/nginx/settings.py b/django_downloadview/nginx/settings.py index 63dd551..804766a 100644 --- a/django_downloadview/nginx/settings.py +++ b/django_downloadview/nginx/settings.py @@ -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". ') diff --git a/tests/api.py b/tests/api.py index f50dccc..9ef17fd 100644 --- a/tests/api.py +++ b/tests/api.py @@ -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) From ac1e4dc9ce31b14a14af3f8e6984cf1a6ce7aed8 Mon Sep 17 00:00:00 2001 From: Fabre Florian Date: Tue, 7 Jan 2020 11:34:51 +0100 Subject: [PATCH 04/11] Fix StorageFile compatibility & some lint issues --- demo/demoproject/compat.py | 10 +++++----- django_downloadview/files.py | 16 +++++++++++++--- django_downloadview/io.py | 32 +++++++++++++++---------------- django_downloadview/views/base.py | 3 ++- tox.ini | 3 --- 5 files changed, 36 insertions(+), 28 deletions(-) diff --git a/demo/demoproject/compat.py b/demo/demoproject/compat.py index c1ed757..5e2dc71 100644 --- a/demo/demoproject/compat.py +++ b/demo/demoproject/compat.py @@ -3,20 +3,20 @@ from django.utils.version import get_version try: - from django.conf.urls import patterns + from django.conf.urls import patterns # noqa except ImportError: def patterns(prefix, *args): return list(args) try: - from django.urls import reverse + from django.urls import reverse # noqa except ImportError: - from django.core.urlresolvers import reverse + from django.core.urlresolvers import reverse # noqa if StrictVersion(get_version()) >= StrictVersion('2.0'): - from django.conf.urls import include as urlinclude + 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 + from django.conf.urls import include # noqa diff --git a/django_downloadview/files.py b/django_downloadview/files.py index c6b4e0d..70061f1 100644 --- a/django_downloadview/files.py +++ b/django_downloadview/files.py @@ -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): diff --git a/django_downloadview/io.py b/django_downloadview/io.py index 1935413..882c87f 100644 --- a/django_downloadview/io.py +++ b/django_downloadview/io.py @@ -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) diff --git a/django_downloadview/views/base.py b/django_downloadview/views/base.py index 29121c3..c476d83 100644 --- a/django_downloadview/views/base.py +++ b/django_downloadview/views/base.py @@ -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) diff --git a/tox.ini b/tox.ini index e2e6130..fcf97dc 100644 --- a/tox.ini +++ b/tox.ini @@ -11,9 +11,6 @@ envlist = py{27}-django{18,19,110,111}, [travis:env] DJANGO = - 1.8: django18 - 1.9: django19 - 1.10: django110 1.11: django111 2.0: django20 2.1: django21 From 256974ab804a3c1328adbe1be6fd8b4f36115c1b Mon Sep 17 00:00:00 2001 From: Fabre Florian Date: Tue, 7 Jan 2020 11:55:19 +0100 Subject: [PATCH 05/11] Update changelog --- CHANGELOG | 3 ++- setup.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0efd530..cf1d150 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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) diff --git a/setup.py b/setup.py index 6cf665e..09c7988 100644 --- a/setup.py +++ b/setup.py @@ -40,9 +40,9 @@ 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.6', ] KEYWORDS = ['file', 'stream', @@ -58,7 +58,7 @@ KEYWORDS = ['file', PACKAGES = [NAME.replace('-', '_')] REQUIREMENTS = [ # BEGIN requirements - 'Django>=1.5', + 'Django>=1.5,<3.0', 'requests', 'setuptools', 'six', From 433b2d5b806718b59c60effb24acbab2d31bbccd Mon Sep 17 00:00:00 2001 From: Fabre Florian Date: Tue, 7 Jan 2020 12:44:04 +0100 Subject: [PATCH 06/11] Fix travis matrix --- .travis.yml | 30 +++++++++++++++--------------- tox.ini | 3 +++ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 277568f..f36f2cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,29 +7,29 @@ python: - 3.5 - 3.6 env: - - DJANGO="1.8" - - DJANGO="1.9" - - DJANGO="1.10" - - DJANGO="1.11" - - DJANGO="2.0" - - DJANGO="2.1" - - DJANGO="2.2" -matrix: + - DJANGO=1.8 + - DJANGO=1.9 + - DJANGO=1.10 + - DJANGO=1.11 + - DJANGO=2.0 + - DJANGO=2.1 + - DJANGO=2.2 +jobs: - exclude: - python: 2.7 - env: DJANGO="2.0" + env: DJANGO=2.0 - python: 2.7 - env: DJANGO="2.1" - - - python: 3.4 - env: DJANGO="2.1" + env: DJANGO=2.1 - python: 2.7 - env: DJANGO="2.2" + env: DJANGO=2.2 - python: 3.4 - env: DJANGO="2.2" + env: DJANGO=2.1 + + - python: 3.4 + env: DJANGO=2.2 install: - pip install tox - pip install -q tox-travis diff --git a/tox.ini b/tox.ini index fcf97dc..0400eca 100644 --- a/tox.ini +++ b/tox.ini @@ -11,6 +11,9 @@ envlist = py{27}-django{18,19,110,111}, [travis:env] DJANGO = + 1.8: django18 + 1.9: django19 + 1.10: django10 1.11: django111 2.0: django20 2.1: django21 From 9a82b76faf1ef8a71d3913e6c45e506da192ca20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20HUBSCHER?= Date: Tue, 7 Jan 2020 14:03:49 +0100 Subject: [PATCH 07/11] @natim review. --- .travis.yml | 29 ++++------------------------- tox.ini | 29 +++++------------------------ 2 files changed, 9 insertions(+), 49 deletions(-) diff --git a/.travis.yml b/.travis.yml index f36f2cb..adb49ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,35 +1,14 @@ language: python -dist: xenial -sudo: true +dist: bionic python: - 2.7 - - 3.4 - - 3.5 - 3.6 + - 3.7 + - 3.8 env: - - DJANGO=1.8 - - DJANGO=1.9 - - DJANGO=1.10 - DJANGO=1.11 - - DJANGO=2.0 - - DJANGO=2.1 - DJANGO=2.2 -jobs: - - exclude: - - python: 2.7 - env: DJANGO=2.0 - - - python: 2.7 - env: DJANGO=2.1 - - - python: 2.7 - env: DJANGO=2.2 - - - python: 3.4 - env: DJANGO=2.1 - - - python: 3.4 - env: DJANGO=2.2 + - DJANGO=3.0 install: - pip install tox - pip install -q tox-travis diff --git a/tox.ini b/tox.ini index 0400eca..3a13a2f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,38 +1,23 @@ [tox] -envlist = py{27}-django{18,19,110,111}, - py{34,35,36}-django{18,19,110,111,20,21,22}, +envlist = py27-django111, + py{35,36,36,37,38}-django{22,30}, flake8, sphinx, readme [tox:travis] -2.7 = py27 -3.4 = py34 -3.5 = py35 -3.6 = py36, flake8, sphinx, readme +3.8 = py38, flake8, sphinx, readme [travis:env] DJANGO = - 1.8: django18 - 1.9: django19 - 1.10: django10 1.11: django111 - 2.0: django20 - 2.1: django21 2.2: django22 + 3.0: django30 [testenv] deps = coverage - 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 - django20: Django>=2.0,<2.1 - django21: Django>=2.1,<2.2 django22: Django>=2.2,<3.0 + django30: Django>=3.0,<3.1 nose py27: mock commands = @@ -43,14 +28,12 @@ commands = pip freeze [testenv:flake8] -basepython = python3.5 deps = flake8 commands = flake8 demo django_downloadview tests [testenv:sphinx] -basepython = python3.5 deps = Sphinx commands = @@ -60,7 +43,6 @@ whitelist_externals = make [testenv:readme] -basepython = python3.5 deps = docutils pygments @@ -72,7 +54,6 @@ whitelist_externals = mkdir [testenv:release] -basepython = python3.6 deps = wheel zest.releaser From 2988aa65e72227fe0b581b2765117ee3ad78794d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20HUBSCHER?= Date: Tue, 7 Jan 2020 14:11:59 +0100 Subject: [PATCH 08/11] Simplify travis config. --- .travis.yml | 4 ---- tox.ini | 11 +++-------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index adb49ac..eff1a53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,6 @@ python: - 3.6 - 3.7 - 3.8 -env: - - DJANGO=1.11 - - DJANGO=2.2 - - DJANGO=3.0 install: - pip install tox - pip install -q tox-travis diff --git a/tox.ini b/tox.ini index 3a13a2f..0fcb13c 100644 --- a/tox.ini +++ b/tox.ini @@ -3,14 +3,9 @@ envlist = py27-django111, py{35,36,36,37,38}-django{22,30}, flake8, sphinx, readme -[tox:travis] -3.8 = py38, flake8, sphinx, readme - -[travis:env] -DJANGO = - 1.11: django111 - 2.2: django22 - 3.0: django30 +[travis] +python= + 3.8: py38, flake8, sphinx, readme [testenv] deps = From cc1e77c4055f2ab3ce80074dc81932b44c64091e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20HUBSCHER?= Date: Tue, 7 Jan 2020 14:13:49 +0100 Subject: [PATCH 09/11] Update setup.py --- setup.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 09c7988..5dce0b0 100644 --- a/setup.py +++ b/setup.py @@ -40,9 +40,10 @@ CLASSIFIERS = [ 'Framework :: Django', 'License :: OSI Approved :: BSD License', 'Programming Language :: Python :: 2.7', - '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,<3.0', + 'Django>=1.11', 'requests', 'setuptools', 'six', From 1ce8aedfd15a678334720e1d9de7b3463bef348d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20HUBSCHER?= Date: Tue, 7 Jan 2020 14:17:08 +0100 Subject: [PATCH 10/11] Update documentation link. --- docs/about/alternatives.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/about/alternatives.txt b/docs/about/alternatives.txt index 140ce87..91742f2 100644 --- a/docs/about/alternatives.txt +++ b/docs/about/alternatives.txt @@ -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 From 28a077b1c3995749ad9f77bd84c9d68f0d491db4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20HUBSCHER?= Date: Tue, 7 Jan 2020 14:22:08 +0100 Subject: [PATCH 11/11] Another broken link. --- CONTRIBUTING.rst | 4 ++-- docs/files.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 26d8289..646da8b 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -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/ diff --git a/docs/files.txt b/docs/files.txt index ac451ad..bd82b30 100644 --- a/docs/files.txt +++ b/docs/files.txt @@ -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/