diff --git a/.travis.yml b/.travis.yml index 20fcba839..9d97a14fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,27 +39,23 @@ jobs: # Explicitly test (older) pytest 5.3. - python: 3.5 - env: TOXENV=py35-dj110-postgres-pytest53-coverage + env: TOXENV=py35-dj111-postgres-pytest53-coverage services: - postgresql - python: 3.4 - env: TOXENV=py34-dj19-sqlite_file-coverage + env: TOXENV=py34-dj111-sqlite_file-coverage - python: 2.7 env: TOXENV=py27-dj111-mysql_myisam-coverage services: - mysql - - python: 2.7 - env: TOXENV=py27-dj18-postgres-coverage - services: - - postgresql # pypy/pypy3: not included with coverage reports (much slower then). - python: pypy env: TOXENV=pypy-dj111-sqlite_file - python: pypy3 - env: TOXENV=pypy3-dj110-sqlite + env: TOXENV=pypy3-dj111-sqlite - stage: test_release python: 3.6 diff --git a/README.rst b/README.rst index 47255c882..6c284ff6d 100644 --- a/README.rst +++ b/README.rst @@ -28,9 +28,9 @@ pytest-django allows you to test your Django project/applications with the `_ * Version compatibility: - * Django: 1.8-1.11, 2.0-2.2, + * Django: 1.11, 2.0-2.2, and latest master branch (compatible at the time of each release) - * Python: CPython 2.7, 3.4-3.7 or PyPy 2, 3 + * Python: CPython 2.7, 3.4-3.8 or PyPy 2, 3 * pytest: >=3.6 * Licence: BSD diff --git a/docs/helpers.rst b/docs/helpers.rst index 76b32492a..96507eefe 100644 --- a/docs/helpers.rst +++ b/docs/helpers.rst @@ -104,8 +104,7 @@ test will fail when trying to access the database. Ignore errors when using the ``--fail-on-template-vars`` option, i.e. do not cause tests to fail if your templates contain invalid variables. - This marker sets the ``string_if_invalid`` template option, or - the older ``settings.TEMPLATE_STRING_IF_INVALID=None`` (Django up to 1.10). + This marker sets the ``string_if_invalid`` template option. See :ref:`django:invalid-template-variables`. Example usage:: diff --git a/pytest_django/compat.py b/pytest_django/compat.py deleted file mode 100644 index 9203a50e1..000000000 --- a/pytest_django/compat.py +++ /dev/null @@ -1,15 +0,0 @@ -# This file cannot be imported from until Django sets up -try: - # Django 1.11 - from django.test.utils import setup_databases, teardown_databases # noqa: F401 -except ImportError: - # In Django prior to 1.11, teardown_databases is only available as a method on DiscoverRunner - from django.test.runner import ( # noqa: F401 - setup_databases, - DiscoverRunner as _DiscoverRunner, - ) - - def teardown_databases(db_cfg, verbosity): - _DiscoverRunner(verbosity=verbosity, interactive=False).teardown_databases( - db_cfg - ) diff --git a/pytest_django/fixtures.py b/pytest_django/fixtures.py index b2cc82580..189c58a9b 100644 --- a/pytest_django/fixtures.py +++ b/pytest_django/fixtures.py @@ -91,7 +91,7 @@ def django_db_setup( django_db_modify_db_settings, ): """Top level fixture to ensure test databases are available""" - from .compat import setup_databases, teardown_databases + from django.test.utils import setup_databases, teardown_databases setup_databases_args = {} @@ -385,27 +385,21 @@ def live_server(request): """ skip_if_no_django() - import django - addr = request.config.getvalue("liveserver") or os.getenv( "DJANGO_LIVE_TEST_SERVER_ADDRESS" ) if addr and ":" in addr: - if django.VERSION >= (1, 11): - ports = addr.split(":")[1] - if "-" in ports or "," in ports: - warnings.warn( - "Specifying multiple live server ports is not supported " - "in Django 1.11. This will be an error in a future " - "pytest-django release." - ) + ports = addr.split(":")[1] + if "-" in ports or "," in ports: + warnings.warn( + "Specifying multiple live server ports is not supported " + "in Django 1.11. This will be an error in a future " + "pytest-django release." + ) if not addr: - if django.VERSION < (1, 11): - addr = "localhost:8081,8100-8200" - else: - addr = "localhost" + addr = "localhost" server = live_server_helper.LiveServer(addr) request.addfinalizer(server.stop) diff --git a/pytest_django/live_server_helper.py b/pytest_django/live_server_helper.py index 94ded3315..1fd52c7f8 100644 --- a/pytest_django/live_server_helper.py +++ b/pytest_django/live_server_helper.py @@ -10,7 +10,6 @@ class LiveServer(object): """ def __init__(self, addr): - import django from django.db import connections from django.test.testcases import LiveServerThread from django.test.utils import modify_settings @@ -39,17 +38,13 @@ def __init__(self, addr): liveserver_kwargs["static_handler"] = _StaticFilesHandler - if django.VERSION < (1, 11): - host, possible_ports = parse_addr(addr) - self.thread = LiveServerThread(host, possible_ports, **liveserver_kwargs) + try: + host, port = addr.split(":") + except ValueError: + host = addr else: - try: - host, port = addr.split(":") - except ValueError: - host = addr - else: - liveserver_kwargs["port"] = int(port) - self.thread = LiveServerThread(host, **liveserver_kwargs) + liveserver_kwargs["port"] = int(port) + self.thread = LiveServerThread(host, **liveserver_kwargs) self._live_server_modified_settings = modify_settings( ALLOWED_HOSTS={"append": host} @@ -79,31 +74,3 @@ def __add__(self, other): def __repr__(self): return "" % self.url - - -def parse_addr(specified_address): - """Parse the --liveserver argument into a host/IP address and port range""" - # This code is based on - # django.test.testcases.LiveServerTestCase.setUpClass - - # The specified ports may be of the form '8000-8010,8080,9200-9300' - # i.e. a comma-separated list of ports or ranges of ports, so we break - # it down into a detailed list of all possible ports. - possible_ports = [] - try: - host, port_ranges = specified_address.split(":") - for port_range in port_ranges.split(","): - # A port range can be of either form: '8000' or '8000-8010'. - extremes = list(map(int, port_range.split("-"))) - assert len(extremes) in (1, 2) - if len(extremes) == 1: - # Port range of the form '8000' - possible_ports.append(extremes[0]) - else: - # Port range of the form '8000-8010' - for port in range(extremes[0], extremes[1] + 1): - possible_ports.append(port) - except Exception: - raise Exception('Invalid address ("%s") for live server.' % specified_address) - - return host, possible_ports diff --git a/pytest_django/migrations.py b/pytest_django/migrations.py index 3c39cb9f6..9cdc91b62 100644 --- a/pytest_django/migrations.py +++ b/pytest_django/migrations.py @@ -1,16 +1,9 @@ # code snippet copied from https://gist.github.com/NotSqrt/5f3c76cd15e40ef62d09 -from pytest_django.lazy_django import get_django_version class DisableMigrations(object): - def __init__(self): - self._django_version = get_django_version() - def __contains__(self, item): return True def __getitem__(self, item): - if self._django_version >= (1, 9): - return None - else: - return "notmigrations" + return None diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 5c59bd540..b3ea205c0 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -590,13 +590,9 @@ def _django_set_urlconf(request): marker = request.node.get_closest_marker("urls") if marker: skip_if_no_django() - import django.conf - try: - from django.urls import clear_url_caches, set_urlconf - except ImportError: - # Removed in Django 2.0 - from django.core.urlresolvers import clear_url_caches, set_urlconf + import django.conf + from django.urls import clear_url_caches, set_urlconf urls = validate_urls(marker) original_urlconf = django.conf.settings.ROOT_URLCONF @@ -643,8 +639,7 @@ def __contains__(self, key): def _get_origin(): stack = inspect.stack() - # Try to use topmost `self.origin` first (Django 1.9+, and with - # TEMPLATE_DEBUG).. + # Find topmost `self.origin`. for f in stack[2:]: func = f[3] if func == "render": @@ -656,30 +651,10 @@ def _get_origin(): if origin is not None: return origin - from django.template import Template - - # finding the ``render`` needle in the stack - frame = reduce( - lambda x, y: y[3] == "render" and "base.py" in y[1] and y or x, stack - ) - # assert 0, stack - frame = frame[0] - # finding only the frame locals in all frame members - f_locals = reduce( - lambda x, y: y[0] == "f_locals" and y or x, inspect.getmembers(frame) - )[1] - # ``django.template.base.Template`` - template = f_locals["self"] - if isinstance(template, Template): - return template.name - def __mod__(self, var): """Handle TEMPLATE_STRING_IF_INVALID % var.""" origin = self._get_origin() - if origin: - msg = "Undefined template variable '%s' in '%s'" % (var, origin) - else: - msg = "Undefined template variable '%s'" % var + msg = "Undefined template variable '%s' in '%s'" % (var, origin) if self.fail: pytest.fail(msg) else: @@ -691,12 +666,7 @@ def __mod__(self, var): ): from django.conf import settings as dj_settings - if dj_settings.TEMPLATES: - dj_settings.TEMPLATES[0]["OPTIONS"][ - "string_if_invalid" - ] = InvalidVarException() - else: - dj_settings.TEMPLATE_STRING_IF_INVALID = InvalidVarException() + dj_settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"] = InvalidVarException() @pytest.fixture(autouse=True) diff --git a/pytest_django_test/settings_base.py b/pytest_django_test/settings_base.py index 050386299..4c9b456f9 100644 --- a/pytest_django_test/settings_base.py +++ b/pytest_django_test/settings_base.py @@ -1,5 +1,3 @@ -import django - ROOT_URLCONF = "pytest_django_test.urls" INSTALLED_APPS = [ "django.contrib.auth", @@ -20,9 +18,6 @@ "django.contrib.messages.middleware.MessageMiddleware", ] -if django.VERSION < (1, 10): - MIDDLEWARE_CLASSES = MIDDLEWARE - TEMPLATES = [ { diff --git a/setup.py b/setup.py index 217593232..f76fc9891 100755 --- a/setup.py +++ b/setup.py @@ -47,9 +47,6 @@ def read(fname): }, classifiers=['Development Status :: 5 - Production/Stable', 'Framework :: Django', - 'Framework :: Django :: 1.8', - 'Framework :: Django :: 1.9', - 'Framework :: Django :: 1.10', 'Framework :: Django :: 1.11', 'Framework :: Django :: 2.0', 'Framework :: Django :: 2.1', diff --git a/tests/conftest.py b/tests/conftest.py index 8b76aba29..cb3728a88 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -81,9 +81,6 @@ def django_testdir(request, testdir, monkeypatch): 'django.contrib.messages.middleware.MessageMiddleware', ] - if django.VERSION < (1, 10): - MIDDLEWARE_CLASSES = MIDDLEWARE - TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', @@ -146,20 +143,3 @@ def create_app_file(code, filename): ) return testdir - - -@pytest.fixture -def django_testdir_initial(django_testdir): - """A django_testdir fixture which provides initial_data.""" - django_testdir.project_root.join("tpkg/app/migrations").remove() - django_testdir.makefile( - ".json", - initial_data=""" - [{ - "pk": 1, - "model": "app.item", - "fields": { "name": "mark_initial_data" } - }]""", - ) - - return django_testdir diff --git a/tests/test_db_setup.py b/tests/test_db_setup.py index 375cb8449..1f7460aab 100644 --- a/tests/test_db_setup.py +++ b/tests/test_db_setup.py @@ -1,6 +1,5 @@ import pytest -from pytest_django.lazy_django import get_django_version from pytest_django_test.db_helpers import ( db_exists, drop_database, @@ -151,7 +150,6 @@ def test_sqlite_test_name_used(self, django_testdir): """ import pytest from django.db import connections - from django import VERSION @pytest.mark.django_db def test_a(): @@ -453,32 +451,6 @@ def test_a(): result.stdout.fnmatch_lines(["*PASSED*test_a*"]) -@pytest.mark.skipif( - get_django_version() >= (1, 9), - reason=( - "Django 1.9 requires migration and has no concept of initial data fixtures" - ), -) -def test_initial_data(django_testdir_initial): - """Test that initial data gets loaded.""" - django_testdir_initial.create_test_module( - """ - import pytest - - from .app.models import Item - - @pytest.mark.django_db - def test_inner(): - assert [x.name for x in Item.objects.all()] \ - == ["mark_initial_data"] - """ - ) - - result = django_testdir_initial.runpytest_subprocess("--tb=short", "-v") - assert result.ret == 0 - result.stdout.fnmatch_lines(["*test_inner*PASSED*"]) - - class TestNativeMigrations(object): """ Tests for Django Migrations """ diff --git a/tests/test_environment.py b/tests/test_environment.py index 95f903a1b..cc07ed6a0 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -95,10 +95,7 @@ def test_ignore(client): ) result = django_testdir.runpytest_subprocess("-s", "--fail-on-template-vars") - if get_django_version() >= (1, 9): - origin = "'*/tpkg/app/templates/invalid_template_base.html'" - else: - origin = "'invalid_template.html'" + origin = "'*/tpkg/app/templates/invalid_template_base.html'" result.stdout.fnmatch_lines_random( [ "tpkg/test_the_test.py F.*", diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py index 2c718c54f..c2ffba229 100644 --- a/tests/test_fixtures.py +++ b/tests/test_fixtures.py @@ -335,7 +335,6 @@ def test_change_settings(self, live_server, settings): def test_settings_restored(self): """Ensure that settings are restored after test_settings_before.""" - import django from django.conf import settings assert TestLiveServer._test_settings_before_run is True @@ -343,10 +342,7 @@ def test_settings_restored(self): "%s.%s" % (settings.__class__.__module__, settings.__class__.__name__) == "django.conf.Settings" ) - if django.VERSION >= (1, 11): - assert settings.ALLOWED_HOSTS == ["testserver"] - else: - assert settings.ALLOWED_HOSTS == ["*"] + assert settings.ALLOWED_HOSTS == ["testserver"] def test_transactions(self, live_server): if not connections_support_transactions(): @@ -445,9 +441,6 @@ def test_serve_static_dj17_without_staticfiles_app(self, live_server, settings): with pytest.raises(HTTPError): urlopen(live_server + "/static/a_file.txt").read() - @pytest.mark.skipif( - get_django_version() < (1, 11), reason="Django >= 1.11 required" - ) def test_specified_port_range_error_message_django_111(self, django_testdir): django_testdir.create_test_module( """ diff --git a/tests/test_urls.py b/tests/test_urls.py index 9001fddce..9cce8db61 100644 --- a/tests/test_urls.py +++ b/tests/test_urls.py @@ -5,10 +5,8 @@ @pytest.mark.urls("pytest_django_test.urls_overridden") def test_urls(): - try: - from django.urls import is_valid_path - except ImportError: - from django.core.urlresolvers import is_valid_path + from django.urls import is_valid_path + assert settings.ROOT_URLCONF == "pytest_django_test.urls_overridden" assert is_valid_path("/overridden_url/") @@ -33,10 +31,7 @@ def fake_view(request): testdir.makepyfile( """ - try: - from django.urls import reverse, NoReverseMatch - except ImportError: # Django < 2.0 - from django.core.urlresolvers import reverse, NoReverseMatch + from django.urls import reverse, NoReverseMatch import pytest @pytest.mark.urls('myurls') @@ -80,10 +75,7 @@ def fake_view(request): testdir.makepyfile( """ - try: - from django.urls import reverse, NoReverseMatch - except ImportError: # Django < 2.0 - from django.core.urlresolvers import reverse, NoReverseMatch + from django.urls import reverse, NoReverseMatch import pytest @pytest.mark.urls('myurls') diff --git a/tox.ini b/tox.ini index 2a75506b4..fd0e90c34 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,11 @@ [tox] envlist = py37-dj{30,22,21,20,111}-postgres - py36-dj{30,22,21,20,111,110,19,18}-postgres - py35-dj{22,21,20,111,110,19,18}-postgres - py34-dj{20,111,110}-postgres - py27-dj{111,110}-{mysql_innodb,mysql_myisam,postgres} - py27-dj{111,110,19,18}-postgres + py36-dj{30,22,21,20,111}-postgres + py35-dj{22,21,20,111}-postgres + py34-dj{20,111}-postgres + py27-dj{111}-{mysql_innodb,mysql_myisam,postgres} + py27-dj{111}-postgres checkqa [testenv] @@ -17,9 +17,6 @@ deps = dj21: Django>=2.1,<2.2 dj20: Django>=2.0,<2.1 dj111: Django>=1.11,<1.12 - dj110: Django>=1.10,<1.11 - dj19: Django>=1.9,<1.10 - dj18: Django>=1.8,<1.9 mysql_myisam: mysqlclient==1.4.2.post1 mysql_innodb: mysqlclient==1.4.2.post1