"""Test suite around :mod:`django_downloadview.api` and deprecation plan.""" from importlib import import_module, reload import unittest import warnings from django.core.exceptions import ImproperlyConfigured import django.test from django.test.utils import override_settings class APITestCase(unittest.TestCase): """Make sure django_downloadview exposes API.""" def assert_module_attributes(self, module_path, attribute_names): """Assert imported ``module_path`` has ``attribute_names``.""" module = import_module(module_path) missing_attributes = [] for attribute_name in attribute_names: if not hasattr(module, attribute_name): missing_attributes.append(attribute_name) if missing_attributes: self.fail( 'Missing attributes in "{module_path}": {", ".join(missing_attributes)}' ) def test_root_attributes(self): """API is exposed in django_downloadview root package. The goal of this test is to make sure that main items of project's API are easy to import... and prevent refactoring from breaking main API. If this test is broken by refactoring, a :class:`DeprecationWarning` or simimar should be raised. """ api = [ # Views: "ObjectDownloadView", "StorageDownloadView", "PathDownloadView", "HTTPDownloadView", "VirtualDownloadView", "BaseDownloadView", "DownloadMixin", # File wrappers: "StorageFile", "HTTPFile", "VirtualFile", # Responses: "DownloadResponse", "ProxiedDownloadResponse", # Middlewares: "BaseDownloadMiddleware", "DownloadDispatcherMiddleware", "SmartDownloadMiddleware", # Testing: "assert_download_response", "setup_view", "temporary_media_root", # Utilities: "StringIteratorIO", "sendfile", ] self.assert_module_attributes("django_downloadview", api) def test_nginx_attributes(self): """Nginx-related API is exposed in django_downloadview.nginx.""" api = [ "XAccelRedirectResponse", "XAccelRedirectMiddleware", "x_accel_redirect", "assert_x_accel_redirect", ] self.assert_module_attributes("django_downloadview.nginx", api) def test_apache_attributes(self): """Apache-related API is exposed in django_downloadview.apache.""" api = [ "XSendfileResponse", "XSendfileMiddleware", "x_sendfile", "assert_x_sendfile", ] self.assert_module_attributes("django_downloadview.apache", api) def test_lighttpd_attributes(self): """Lighttpd-related API is exposed in django_downloadview.lighttpd.""" api = [ "XSendfileResponse", "XSendfileMiddleware", "x_sendfile", "assert_x_sendfile", ] self.assert_module_attributes("django_downloadview.lighttpd", api) class DeprecatedAPITestCase(django.test.SimpleTestCase): """Make sure using deprecated items raise DeprecationWarning.""" def test_nginx_x_accel_redirect_middleware(self): "XAccelRedirectMiddleware in settings triggers ImproperlyConfigured." with override_settings( MIDDLEWARE=["django_downloadview.nginx.XAccelRedirectMiddleware"], ): with self.assertRaises(ImproperlyConfigured): import django_downloadview.nginx.settings reload(django_downloadview.nginx.settings) def test_nginx_x_accel_redirect_global_settings(self): """Global settings for Nginx middleware are deprecated.""" settings_overrides = { "NGINX_DOWNLOAD_MIDDLEWARE_WITH_BUFFERING": True, "NGINX_DOWNLOAD_MIDDLEWARE_LIMIT_RATE": 32, "NGINX_DOWNLOAD_MIDDLEWARE_EXPIRES": 3600, "NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT": "/", "NGINX_DOWNLOAD_MIDDLEWARE_SOURCE_DIR": "/", "NGINX_DOWNLOAD_MIDDLEWARE_SOURCE_URL": "/", "NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_URL": "/", "NGINX_DOWNLOAD_MIDDLEWARE_DESTINATION_URL": "/", } import django_downloadview.nginx.settings missed_warnings = [] for setting_name, setting_value in settings_overrides.items(): warnings.resetwarnings() warnings.simplefilter("always") with warnings.catch_warnings(record=True) as warning_list: with override_settings(**{setting_name: setting_value}): reload(django_downloadview.nginx.settings) caught = False for warning_item in warning_list: if warning_item.category is DeprecationWarning: if "deprecated" in str(warning_item.message): if setting_name in str(warning_item.message): caught = True break if not caught: missed_warnings.append(setting_name) if missed_warnings: self.fail( f"No DeprecationWarning raised about following settings: " f"{', '.join(missed_warnings)}." )