diff --git a/.gitignore b/.gitignore index 2267b36..f881ed8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*~ *.swp *.pyc *.db diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..18a193c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,46 @@ +sudo: false +language: python +cache: pip + +matrix: + include: + - python: 2.7 + env: DJANGO="Django>=1.8,<1.9" + - python: 3.2 + env: DJANGO="Django>=1.8,<1.9" + - python: 3.3 + env: DJANGO="Django>=1.8,<1.9" + - python: 3.4 + env: DJANGO="Django>=1.8,<1.9" + - python: 3.5 + env: DJANGO="Django>=1.8,<1.9" + - python: 2.7 + env: DJANGO="Django>=1.9,<1.10" + - python: 3.4 + env: DJANGO="Django>=1.9,<1.10" + - python: 3.5 + env: DJANGO="Django>=1.9,<1.10" + - python: 2.7 + env: DJANGO="Django>=1.10,<1.11" + - python: 3.4 + env: DJANGO="Django>=1.10,<1.11" + - python: 3.5 + env: DJANGO="Django>=1.10,<1.11" + - python: 2.7 + env: DJANGO="Django>=1.11,<2.0" + - python: 3.4 + env: DJANGO="Django>=1.11,<2.0" + - python: 3.5 + env: DJANGO="Django>=1.11,<2.0" + - python: 3.6 + env: DJANGO="Django>=1.11,<2.0" + +install: + - pip install $DJANGO + - pip install flake8 + - pip install -e . + +before_script: + - flake8 + +script: ./runtests.sh diff --git a/examples/protected_downloads/download/admin.py b/examples/protected_downloads/download/admin.py index 617ee11..ca4c0b3 100644 --- a/examples/protected_downloads/download/admin.py +++ b/examples/protected_downloads/download/admin.py @@ -3,7 +3,6 @@ from .models import Download +@admin.register(Download) class DownloadAdmin(admin.ModelAdmin): list_display = ['title', 'file'] - -admin.site.register(Download, DownloadAdmin) diff --git a/examples/protected_downloads/download/models.py b/examples/protected_downloads/download/models.py index 0e10dbc..2ca74b2 100644 --- a/examples/protected_downloads/download/models.py +++ b/examples/protected_downloads/download/models.py @@ -1,8 +1,8 @@ -from django.db import models - -from django.contrib.auth.models import User from django.conf import settings +from django.contrib.auth.models import User from django.core.files.storage import FileSystemStorage +from django.db import models +from django.urls import reverse sendfile_storage = FileSystemStorage(location=settings.SENDFILE_ROOT) @@ -17,9 +17,8 @@ class Download(models.Model): def is_user_allowed(self, user): return self.users.filter(pk=user.pk).exists() - def __unicode__(self): + def __str__(self): return self.title - @models.permalink def get_absolute_url(self): - return ('download', [self.pk], {}) + return reverse('download', [self.pk], {}) diff --git a/examples/protected_downloads/download/tests.py b/examples/protected_downloads/download/tests.py deleted file mode 100644 index 501deb7..0000000 --- a/examples/protected_downloads/download/tests.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" - -from django.test import TestCase - - -class SimpleTest(TestCase): - def test_basic_addition(self): - """ - Tests that 1 + 1 always equals 2. - """ - self.assertEqual(1 + 1, 2) diff --git a/examples/protected_downloads/download/urls.py b/examples/protected_downloads/download/urls.py index fd4bb28..8188e4c 100644 --- a/examples/protected_downloads/download/urls.py +++ b/examples/protected_downloads/download/urls.py @@ -1,8 +1,8 @@ -from django.conf.urls.defaults import * +from django.conf.urls import url from .views import download, download_list -urlpatterns = patterns('', +urlpatterns = [ url(r'^$', download_list), url(r'(?P\d+)/$', download, name='download'), -) +] diff --git a/examples/protected_downloads/download/views.py b/examples/protected_downloads/download/views.py index e99b6bc..e49c4ff 100644 --- a/examples/protected_downloads/download/views.py +++ b/examples/protected_downloads/download/views.py @@ -1,8 +1,7 @@ from django.contrib.auth.decorators import login_required -from django.shortcuts import get_object_or_404, render_to_response -from django.http import HttpResponseForbidden from django.db.models import Q -from django.template import RequestContext +from django.http import HttpResponseForbidden +from django.shortcuts import get_object_or_404, render from sendfile import sendfile @@ -29,6 +28,4 @@ def download_list(request): downloads = downloads.filter(Q(is_public=True) | Q(users=request.user)) else: downloads = downloads.filter(is_public=True) - return render_to_response('download/download_list.html', - {'download_list': downloads}, - context_instance=RequestContext(request)) + return render(request, 'download/download_list.html', {'download_list': downloads}) diff --git a/examples/protected_downloads/manage.py b/examples/protected_downloads/manage.py old mode 100644 new mode 100755 index 3e098b0..d9295d1 --- a/examples/protected_downloads/manage.py +++ b/examples/protected_downloads/manage.py @@ -1,14 +1,10 @@ #!/usr/bin/env python +import os +import sys -from __future__ import absolute_import +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from django.core.management import execute_manager -try: - from . import settings # Assumed to be in the same directory. -except ImportError: - import sys - sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) - sys.exit(1) - -if __name__ == "__main__": - execute_manager(settings) +if __name__ == '__main__': + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'protected_downloads.settings') + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) diff --git a/examples/protected_downloads/settings.py b/examples/protected_downloads/settings.py index 245739c..5f507db 100644 --- a/examples/protected_downloads/settings.py +++ b/examples/protected_downloads/settings.py @@ -2,91 +2,83 @@ import os.path +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + +SECRET_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' + DEBUG = True -TEMPLATE_DEBUG = DEBUG -ADMINS = ( - # ('Your Name', 'your_email@domain.com'), -) +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.admin', + 'protected_downloads.download', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] -MANAGERS = ADMINS +ROOT_URLCONF = 'protected_downloads.urls' -PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')], + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(PROJECT_ROOT, 'download.db'), + 'NAME': os.path.join(BASE_DIR, 'download.db'), } } -# Local time zone for this installation. Choices can be found here: -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# although not all choices may be available on all operating systems. -# If running in a Windows environment this must be set to the same as your -# system time zone. -TIME_ZONE = 'America/Chicago' -# Language code for this installation. All choices can be found here: -# http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = 'en-us' +# Internationalization -SITE_ID = 1 +TIME_ZONE = 'UTC' -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. USE_I18N = True -# Absolute path to the directory that holds media. -# Example: "/home/media/media.lawrence.com/" -MEDIA_ROOT = '' - -# URL that handles the media served from MEDIA_ROOT. Make sure to use a -# trailing slash if there is a path component (optional in other cases). -# Examples: "http://media.lawrence.com", "http://example.com/media/" -MEDIA_URL = '' +USE_L10N = True -# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a -# trailing slash. -# Examples: "http://foo.com/media/", "/media/". -ADMIN_MEDIA_PREFIX = '/media/' +USE_TZ = True -# Make this unique, and don't share it with anybody. -SECRET_KEY = 'n309^dwk=@+g72ko--8vjyz&1v0u%xf#*0=wzr=2n#f3hb0a=l' -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.load_template_source', - 'django.template.loaders.app_directories.load_template_source', - # 'django.template.loaders.eggs.load_template_source', -) +# Static files (CSS, JavaScript, Images) -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', -) - -ROOT_URLCONF = 'protected_downloads.urls' - -TEMPLATE_DIRS = ( - os.path.join(PROJECT_ROOT, 'templates'), -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.admin', - 'download', - 'sendfile', -) +STATIC_URL = '/static/' # SENDFILE settings +# Available backends: +# sendfile.backends.development +# sendfile.backends.mod_wsgi +# sendfile.backends.nginx +# sendfile.backends.simple +# sendfile.backends.xsendfile SENDFILE_BACKEND = 'sendfile.backends.development' -#SENDFILE_BACKEND = 'sendfile.backends.xsendfile' -#SENDFILE_BACKEND = 'sendfile.backends.nginx' -SENDFILE_ROOT = os.path.join(PROJECT_ROOT, 'protected') +SENDFILE_ROOT = os.path.join(BASE_DIR, 'protected') SENDFILE_URL = '/protected' diff --git a/examples/protected_downloads/urls.py b/examples/protected_downloads/urls.py index 238d8c7..5ac5804 100644 --- a/examples/protected_downloads/urls.py +++ b/examples/protected_downloads/urls.py @@ -1,9 +1,9 @@ -from django.conf.urls.defaults import * - +from django.conf.urls import include, url from django.contrib import admin + admin.autodiscover() -urlpatterns = patterns('', - (r'^', include('protected_downloads.download.urls')), - (r'^admin/', include(admin.site.urls)), -) +urlpatterns = [ + url(r'^', include('protected_downloads.download.urls')), + url(r'^admin/', admin.site.urls), +] diff --git a/runtests.sh b/runtests.sh new file mode 100755 index 0000000..bcdd5ac --- /dev/null +++ b/runtests.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +DJANGO_SETTINGS_MODULE=tests.settings django-admin test tests "$@" diff --git a/sendfile/__init__.py b/sendfile/__init__.py index 1cc9809..3125994 100644 --- a/sendfile/__init__.py +++ b/sendfile/__init__.py @@ -1,30 +1,31 @@ -VERSION = (0, 3, 11) -__version__ = '.'.join(map(str, VERSION)) - import os.path from mimetypes import guess_type import unicodedata +from importlib import import_module + + +VERSION = (0, 3, 11) +__version__ = '.'.join(map(str, VERSION)) def _lazy_load(fn): _cached = [] + def _decorated(): if not _cached: _cached.append(fn()) return _cached[0] + def clear(): while _cached: _cached.pop() _decorated.clear = clear + return _decorated @_lazy_load def _get_sendfile(): - try: - from importlib import import_module - except ImportError: - from django.utils.importlib import import_module from django.conf import settings from django.core.exceptions import ImproperlyConfigured @@ -35,7 +36,6 @@ def _get_sendfile(): return module.sendfile - def sendfile(request, filename, attachment=False, attachment_filename=None, mimetype=None, encoding=None): ''' create a response to send file using backend configured in SENDFILE_BACKEND @@ -64,20 +64,16 @@ def sendfile(request, filename, attachment=False, attachment_filename=None, mime mimetype = guessed_mimetype else: mimetype = 'application/octet-stream' - + response = _sendfile(request, filename, mimetype=mimetype) if attachment: if attachment_filename is None: attachment_filename = os.path.basename(filename) parts = ['attachment'] if attachment_filename: - try: - from django.utils.encoding import force_text - except ImportError: - # Django 1.3 - from django.utils.encoding import force_unicode as force_text + from django.utils.encoding import force_text attachment_filename = force_text(attachment_filename) - ascii_filename = unicodedata.normalize('NFKD', attachment_filename).encode('ascii','ignore') + ascii_filename = unicodedata.normalize('NFKD', attachment_filename).encode('ascii', 'ignore').decode('ascii') parts.append('filename="%s"' % ascii_filename) if ascii_filename != attachment_filename: from django.utils.http import urlquote diff --git a/sendfile/backends/_internalredirect.py b/sendfile/backends/_internalredirect.py index be4e069..39ec7f3 100644 --- a/sendfile/backends/_internalredirect.py +++ b/sendfile/backends/_internalredirect.py @@ -1,12 +1,8 @@ import os.path from django.conf import settings -from django.utils.encoding import smart_text, smart_bytes - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote +from django.utils.encoding import force_bytes, force_text +from django.utils.six.moves.urllib.parse import quote def _convert_file_to_url(filename): @@ -20,5 +16,5 @@ def _convert_file_to_url(filename): # Python3 urllib.parse.quote accepts both unicode and bytes, while Python2 urllib.quote only accepts bytes. # So use bytes for quoting and then go back to unicode. - url = [smart_bytes(url_component) for url_component in url] - return smart_text(quote(b'/'.join(url))) + url = [force_bytes(url_component) for url_component in url] + return force_text(quote(b'/'.join(url))) diff --git a/sendfile/backends/development.py b/sendfile/backends/development.py index c717836..2c3822d 100644 --- a/sendfile/backends/development.py +++ b/sendfile/backends/development.py @@ -1,7 +1,7 @@ -from django.views.static import serve - import os.path +from django.views.static import serve + def sendfile(request, filename, **kwargs): ''' diff --git a/sendfile/backends/mod_wsgi.py b/sendfile/backends/mod_wsgi.py index 7fcd104..4e042a2 100644 --- a/sendfile/backends/mod_wsgi.py +++ b/sendfile/backends/mod_wsgi.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from django.http import HttpResponse from ._internalredirect import _convert_file_to_url @@ -8,6 +6,9 @@ def sendfile(request, filename, **kwargs): response = HttpResponse() response['Location'] = _convert_file_to_url(filename) + # Workaround for Django < 1.9 + # https://docs.djangoproject.com/en/1.9/releases/1.9/#http-redirects-no-longer-forced-to-absolute-uris + # # need to destroy get_host() to stop django # rewriting our location to include http, so that # mod_wsgi is able to do the internal redirect diff --git a/sendfile/backends/nginx.py b/sendfile/backends/nginx.py index 29dc348..c62fe46 100644 --- a/sendfile/backends/nginx.py +++ b/sendfile/backends/nginx.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from django.http import HttpResponse from ._internalredirect import _convert_file_to_url @@ -8,6 +6,6 @@ def sendfile(request, filename, **kwargs): response = HttpResponse() url = _convert_file_to_url(filename) - response['X-Accel-Redirect'] = url.encode('utf-8') + response['X-Accel-Redirect'] = url return response diff --git a/sendfile/backends/simple.py b/sendfile/backends/simple.py index 9950151..da0aa54 100644 --- a/sendfile/backends/simple.py +++ b/sendfile/backends/simple.py @@ -1,10 +1,7 @@ import os -import stat import re -try: - from email.utils import parsedate_tz, mktime_tz -except ImportError: - from email.Utils import parsedate_tz, mktime_tz +import stat +from email.utils import mktime_tz, parsedate_tz from django.core.files.base import File from django.http import HttpResponse, HttpResponseNotModified diff --git a/sendfile/backends/xsendfile.py b/sendfile/backends/xsendfile.py index a87aa83..bc26cf4 100644 --- a/sendfile/backends/xsendfile.py +++ b/sendfile/backends/xsendfile.py @@ -3,6 +3,6 @@ def sendfile(request, filename, **kwargs): response = HttpResponse() - response['X-Sendfile'] = unicode(filename).encode('utf-8') + response['X-Sendfile'] = filename return response diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..9ee696b --- /dev/null +++ b/setup.cfg @@ -0,0 +1,5 @@ +[bdist_wheel] +universal = 1 + +[flake8] +ignore = E501 diff --git a/setup.py b/setup.py index 406b127..75df3d7 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,4 @@ -from distutils.core import setup - -try: - from distutils.command.build_py import build_py_2to3 as build_py -except ImportError: - from distutils.command.build_py import build_py - +from setuptools import setup version = __import__('sendfile').__version__ @@ -18,30 +12,34 @@ author_email='john@sensibledevelopment.com', url='https://github.com/johnsensible/django-sendfile', license='BSD', - - requires=['Django (>=1.3)'], - install_requires=['Django>=1.3'], - + install_requires=['Django>=1.8'], packages=['sendfile', 'sendfile.backends'], package_dir={ 'sendfile': 'sendfile', 'sendfile.backends': 'sendfile/backends', }, - package_data={ - 'sendfile': ['testfile.txt'], - }, - zip_safe=True, classifiers=[ - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Framework :: Django', + 'Framework :: Django :: 1.8', + 'Framework :: Django :: 1.9', + 'Framework :: Django :: 1.10', + 'Framework :: Django :: 1.11', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Topic :: Software Development :: Libraries :: Python Modules', ], - - cmdclass={'build_py': build_py}, ) diff --git a/sendfile/models.py b/tests/__init__.py similarity index 100% rename from sendfile/models.py rename to tests/__init__.py diff --git a/tests/settings.py b/tests/settings.py new file mode 100644 index 0000000..4ba7f9d --- /dev/null +++ b/tests/settings.py @@ -0,0 +1 @@ +SECRET_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' diff --git a/sendfile/tests.py b/tests/tests.py similarity index 64% rename from sendfile/tests.py rename to tests/tests.py index 0643cae..302f85c 100644 --- a/sendfile/tests.py +++ b/tests/tests.py @@ -1,18 +1,15 @@ # coding=utf-8 - -from django.conf import settings -from django.test import TestCase -from django.http import HttpResponse, Http404, HttpRequest -from django.utils.encoding import smart_str import os.path -from tempfile import mkdtemp import shutil -from sendfile import sendfile as real_sendfile, _get_sendfile +from tempfile import mkdtemp +from unittest import TestCase -try: - from urllib.parse import unquote -except ImportError: - from urllib import unquote +from django.http import Http404, HttpRequest, HttpResponse +from django.test.utils import override_settings +from django.utils.six.moves.urllib.parse import unquote + +from sendfile import sendfile as real_sendfile +from sendfile import _get_sendfile def sendfile(request, filename, **kwargs): @@ -26,11 +23,7 @@ class TempFileTestCase(TestCase): def setUp(self): super(TempFileTestCase, self).setUp() self.TEMP_FILE_ROOT = mkdtemp() - - def tearDown(self): - super(TempFileTestCase, self).tearDown() - if os.path.exists(self.TEMP_FILE_ROOT): - shutil.rmtree(self.TEMP_FILE_ROOT) + self.addCleanup(shutil.rmtree, self.TEMP_FILE_ROOT) def ensure_file(self, filename): path = os.path.join(self.TEMP_FILE_ROOT, filename) @@ -44,52 +37,52 @@ class TestSendfile(TempFileTestCase): def setUp(self): super(TestSendfile, self).setUp() # set ourselves to be the sendfile backend - settings.SENDFILE_BACKEND = 'sendfile.tests' + cm = override_settings(SENDFILE_BACKEND='tests.tests') + cm.enable() + self.addCleanup(cm.disable) _get_sendfile.clear() def _get_readme(self): return self.ensure_file('testfile.txt') def test_404(self): - try: + with self.assertRaises(Http404): real_sendfile(HttpRequest(), 'fhdsjfhjk.txt') - except Http404: - pass def test_sendfile(self): response = real_sendfile(HttpRequest(), self._get_readme()) - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('text/plain', response['Content-Type']) - self.assertEqual(self._get_readme(), smart_str(response.content)) + self.assertEqual(self._get_readme(), response.content.decode(response.charset)) def test_set_mimetype(self): response = real_sendfile(HttpRequest(), self._get_readme(), mimetype='text/plain') - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('text/plain', response['Content-Type']) def test_set_encoding(self): response = real_sendfile(HttpRequest(), self._get_readme(), encoding='utf8') - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('utf8', response['Content-Encoding']) def test_attachment(self): response = real_sendfile(HttpRequest(), self._get_readme(), attachment=True) - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('attachment; filename="testfile.txt"', response['Content-Disposition']) def test_attachment_filename_false(self): response = real_sendfile(HttpRequest(), self._get_readme(), attachment=True, attachment_filename=False) - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('attachment', response['Content-Disposition']) def test_attachment_filename(self): response = real_sendfile(HttpRequest(), self._get_readme(), attachment=True, attachment_filename='tests.txt') - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('attachment; filename="tests.txt"', response['Content-Disposition']) def test_attachment_filename_unicode(self): response = real_sendfile(HttpRequest(), self._get_readme(), attachment=True, attachment_filename='test’s.txt') - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('attachment; filename="tests.txt"; filename*=UTF-8\'\'test%E2%80%99s.txt', response['Content-Disposition']) @@ -97,61 +90,69 @@ class TestXSendfileBackend(TempFileTestCase): def setUp(self): super(TestXSendfileBackend, self).setUp() - settings.SENDFILE_BACKEND = 'sendfile.backends.xsendfile' + cm = override_settings(SENDFILE_BACKEND='sendfile.backends.xsendfile') + cm.enable() + self.addCleanup(cm.disable) _get_sendfile.clear() def test_correct_file_in_xsendfile_header(self): filepath = self.ensure_file('readme.txt') response = real_sendfile(HttpRequest(), filepath) - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual(filepath, response['X-Sendfile']) def test_xsendfile_header_containing_unicode(self): - filepath = self.ensure_file(u'péter_là_gueule.txt') + filepath = self.ensure_file('péter_là_gueule.txt') response = real_sendfile(HttpRequest(), filepath) - self.assertTrue(response is not None) - self.assertEqual(smart_str(filepath), response['X-Sendfile']) + self.assertIsNotNone(response) + self.assertEqual(filepath, response['X-Sendfile']) class TestNginxBackend(TempFileTestCase): def setUp(self): super(TestNginxBackend, self).setUp() - settings.SENDFILE_BACKEND = 'sendfile.backends.nginx' - settings.SENDFILE_ROOT = self.TEMP_FILE_ROOT - settings.SENDFILE_URL = '/private' + cm = override_settings( + SENDFILE_BACKEND='sendfile.backends.nginx', + SENDFILE_ROOT=self.TEMP_FILE_ROOT, + SENDFILE_URL='/private') + cm.enable() + self.addCleanup(cm.disable) _get_sendfile.clear() def test_correct_url_in_xaccelredirect_header(self): filepath = self.ensure_file('readme.txt') response = real_sendfile(HttpRequest(), filepath) - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('/private/readme.txt', response['X-Accel-Redirect']) def test_xaccelredirect_header_containing_unicode(self): - filepath = self.ensure_file(u'péter_là_gueule.txt') + filepath = self.ensure_file('péter_là_gueule.txt') response = real_sendfile(HttpRequest(), filepath) - self.assertTrue(response is not None) - self.assertEqual(u'/private/péter_là_gueule.txt'.encode('utf-8'), unquote(response['X-Accel-Redirect'])) + self.assertIsNotNone(response) + self.assertEqual('/private/péter_là_gueule.txt', unquote(response['X-Accel-Redirect'])) class TestModWsgiBackend(TempFileTestCase): def setUp(self): super(TestModWsgiBackend, self).setUp() - settings.SENDFILE_BACKEND = 'sendfile.backends.mod_wsgi' - settings.SENDFILE_ROOT = self.TEMP_FILE_ROOT - settings.SENDFILE_URL = '/private' + cm = override_settings( + SENDFILE_BACKEND='sendfile.backends.mod_wsgi', + SENDFILE_ROOT=self.TEMP_FILE_ROOT, + SENDFILE_URL='/private') + cm.enable() + self.addCleanup(cm.disable) _get_sendfile.clear() def test_correct_url_in_location_header(self): filepath = self.ensure_file('readme.txt') response = real_sendfile(HttpRequest(), filepath) - self.assertTrue(response is not None) + self.assertIsNotNone(response) self.assertEqual('/private/readme.txt', response['Location']) def test_location_header_containing_unicode(self): - filepath = self.ensure_file(u'péter_là_gueule.txt') + filepath = self.ensure_file('péter_là_gueule.txt') response = real_sendfile(HttpRequest(), filepath) - self.assertTrue(response is not None) - self.assertEqual(u'/private/péter_là_gueule.txt'.encode('utf-8'), unquote(response['Location'])) + self.assertIsNotNone(response) + self.assertEqual('/private/péter_là_gueule.txt', unquote(response['Location']))