From 9a790f7bde6b39c0445858218faf4dd190e0464a Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 5 Jun 2019 01:03:05 +0200 Subject: [PATCH 1/4] WIP: drop support for pytest < 4.2 --- pytest_django/plugin.py | 68 +---------------------------------------- setup.py | 2 +- tests/test_unittest.py | 10 +----- 3 files changed, 3 insertions(+), 77 deletions(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 8b6e4ce79..a52f65ece 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -9,7 +9,6 @@ from functools import reduce import os import sys -import types import pytest @@ -51,9 +50,7 @@ PY2 = sys.version_info[0] == 2 -# pytest 4.2 handles unittest setup/teardown itself via wrapping fixtures. _pytest_version_info = tuple(int(x) for x in pytest.__version__.split(".", 2)[:2]) -_handle_unittest_methods = _pytest_version_info < (4, 2) _report_header = [] @@ -364,57 +361,6 @@ def _classmethod_is_defined_at_leaf(cls, method_name): return f is not super_method.__func__ -_disabled_classmethods = {} - - -def _disable_class_methods(cls): - if cls in _disabled_classmethods: - return - - _disabled_classmethods[cls] = ( - # Get the classmethod object (not the resulting bound method), - # otherwise inheritance will be broken when restoring. - cls.__dict__.get("setUpClass"), - _classmethod_is_defined_at_leaf(cls, "setUpClass"), - cls.__dict__.get("tearDownClass"), - _classmethod_is_defined_at_leaf(cls, "tearDownClass"), - ) - - cls.setUpClass = types.MethodType(lambda cls: None, cls) - cls.tearDownClass = types.MethodType(lambda cls: None, cls) - - -def _restore_class_methods(cls): - ( - setUpClass, - restore_setUpClass, - tearDownClass, - restore_tearDownClass, - ) = _disabled_classmethods.pop(cls) - - try: - del cls.setUpClass - except AttributeError: - raise - - try: - del cls.tearDownClass - except AttributeError: - pass - - if restore_setUpClass: - cls.setUpClass = setUpClass - - if restore_tearDownClass: - cls.tearDownClass = tearDownClass - - -def pytest_runtest_setup(item): - if _handle_unittest_methods: - if django_settings_is_configured() and is_django_unittest(item): - _disable_class_methods(item.cls) - - @pytest.hookimpl(tryfirst=True) def pytest_collection_modifyitems(items): def get_order_number(test): @@ -524,20 +470,8 @@ def non_debugging_runtest(self): request.getfixturevalue("django_db_setup") - cls = request.node.cls - with django_db_blocker.unblock(): - if _handle_unittest_methods: - _restore_class_methods(cls) - cls.setUpClass() - _disable_class_methods(cls) - - yield - - _restore_class_methods(cls) - cls.tearDownClass() - else: - yield + yield if mp_debug: mp_debug.undo() diff --git a/setup.py b/setup.py index 217593232..2865f0359 100755 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ def read(fname): python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', setup_requires=['setuptools_scm>=1.11.1'], install_requires=[ - 'pytest>=3.6', + 'pytest>=4.2', 'pathlib2;python_version<"3.4"', ], extras_require={ diff --git a/tests/test_unittest.py b/tests/test_unittest.py index 1f637e374..4789b52a7 100644 --- a/tests/test_unittest.py +++ b/tests/test_unittest.py @@ -145,16 +145,8 @@ def test_pass(self): result = django_testdir.runpytest_subprocess("-v", "-s") expected_lines = [ "* ERROR at setup of TestFoo.test_pass *", + "E * TypeError: *", ] - if _pytest_version_info < (4, 2): - expected_lines += [ - "E *Failed: .setUpClass should be a classmethod", # noqa:E501 - ] - else: - expected_lines += [ - "E * TypeError: *", - ] - result.stdout.fnmatch_lines(expected_lines) assert result.ret == 1 From 36698e3c4a7507c4b0035593054bc58857dc4273 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 5 Jun 2019 01:33:58 +0200 Subject: [PATCH 2/4] tox/Travis: remove pytest41 --- .travis.yml | 4 ---- tox.ini | 2 -- 2 files changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 777e2b7cc..5d2d8e5fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,10 +30,6 @@ jobs: - python: 3.8 env: TOXENV=py38-dj30-sqlite-xdist-coverage - # Explicitly test (older) pytest 4.1. - - python: 3.7 - env: TOXENV=py37-dj21-sqlite-pytest41-coverage - - python: 3.6 env: TOXENV=py36-djmaster-sqlite-coverage diff --git a/tox.ini b/tox.ini index 84bbb9859..beb3d7819 100644 --- a/tox.ini +++ b/tox.ini @@ -27,8 +27,6 @@ deps = postgres: psycopg2-binary coverage: coverage-enable-subprocess - pytest41: pytest>=4.1,<4.2 - pytest41: attrs==17.4.0 xdist: pytest-xdist>=1.15 setenv = From 043470e0d93e5eda885b3cae007d21afd864a6ff Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 5 Jun 2019 02:40:57 +0200 Subject: [PATCH 3/4] remove _classmethod_is_defined_at_leaf --- pytest_django/plugin.py | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index a52f65ece..0e8a95f25 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -334,33 +334,6 @@ def pytest_configure(): _setup_django() -def _classmethod_is_defined_at_leaf(cls, method_name): - super_method = None - - for base_cls in cls.__mro__[1:]: # pragma: no branch - super_method = base_cls.__dict__.get(method_name) - if super_method is not None: - break - - assert super_method is not None, ( - "%s could not be found in base classes" % method_name - ) - - method = getattr(cls, method_name) - - try: - f = method.__func__ - except AttributeError: - pytest.fail("%s.%s should be a classmethod" % (cls, method_name)) - if PY2 and not ( - inspect.ismethod(method) - and inspect.isclass(method.__self__) - and issubclass(cls, method.__self__) - ): - pytest.fail("%s.%s should be a classmethod" % (cls, method_name)) - return f is not super_method.__func__ - - @pytest.hookimpl(tryfirst=True) def pytest_collection_modifyitems(items): def get_order_number(test): From 9135bc1fec0704b13107da51c88e53d55707f1e1 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 18 Mar 2020 14:30:19 +0100 Subject: [PATCH 4/4] test with pytest42 --- .travis.yml | 4 ++++ tox.ini | 3 +++ 2 files changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5d2d8e5fe..71e1743aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,10 @@ jobs: - python: 3.8 env: TOXENV=py38-dj30-sqlite-xdist-coverage + # Explicitly test oldest supported pytest. + - python: 3.7 + env: TOXENV=py37-dj21-sqlite-pytest42-coverage + - python: 3.6 env: TOXENV=py36-djmaster-sqlite-coverage diff --git a/tox.ini b/tox.ini index beb3d7819..9e977628f 100644 --- a/tox.ini +++ b/tox.ini @@ -27,6 +27,9 @@ deps = postgres: psycopg2-binary coverage: coverage-enable-subprocess + # Oldest supported pytest. + pytest42: pytest>=4.2,<4.3 + pytest42: attrs==17.4.0 xdist: pytest-xdist>=1.15 setenv =