From 93855017ba6d46a7e83c289b29defc9e82a24d55 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 26 Mar 2022 11:48:50 -0700 Subject: [PATCH 01/16] src/bin/sage: Implement 'sage --pytest' --- src/bin/sage | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/bin/sage b/src/bin/sage index d8432a43c8d..69a157b7d1f 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -443,6 +443,10 @@ usage_advanced() { echo " --help -- show tox help" command -v tox &>/dev/null || \ echo " (not installed currently, run sage -i tox)" + echo " --pytest [options] -- run pytest on the Sage library" + command -v pytest &>/dev/null || \ + echo " (not installed currently, run sage -i pytest)" + echo " --help -- show pytest help" fi echo echo "Some developer utilities:" @@ -940,10 +944,24 @@ if [ "$1" = '-tox' -o "$1" = '--tox' ]; then if command -v tox >/dev/null ; then exec tox -c "$SAGE_SRC" "$@" else - echo "Run sage -i tox to install" + echo "Run 'sage -i tox' to install" fi else - echo >&2 "error: Sage source directory or tox.ini not avialable" + echo >&2 "error: Sage source directory or tox.ini not available" + exit 1 + fi +fi + +if [ "$1" = '-pytest' -o "$1" = '--pytest' ]; then + shift + if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then + if command -v pytest >/dev/null ; then + exec pytest --rootdir="$SAGE_SRC" --import-mode importlib "$@" + else + echo "Run 'sage -i pytest' to install" + fi + else + echo >&2 "error: Sage source directory or tox.ini not available" exit 1 fi fi From f67476f065a2ef7c4b03fcad486ace6e08d9230c Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 27 Mar 2022 15:50:44 +0200 Subject: [PATCH 02/16] Add some test and prelimary code --- .vscode/settings.json | 6 +++++- src/test_doctest.py | 11 +++++++++++ src/tox.ini | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/test_doctest.py diff --git a/.vscode/settings.json b/.vscode/settings.json index 5844f80998f..9cdc0e3b980 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,9 +14,13 @@ "pkgs/sagemath-objects/sage": true, "pkgs/sagemath-standard/sage": true, }, + "python.testing.pytestPath": "./sage -t", "python.testing.pytestEnabled": true, "python.testing.pytestArgs": [ - "src" + "src/test_doctests.py", + "--rootdir=src/sage", + "-c=src/tox.ini", + "--doctest-modules", ], "python.testing.unittestEnabled": false, } diff --git a/src/test_doctest.py b/src/test_doctest.py new file mode 100644 index 00000000000..37cb7d89995 --- /dev/null +++ b/src/test_doctest.py @@ -0,0 +1,11 @@ +def something(): + """ a doctest in a docstring + >>> something() + 42 + + some other doctest + + >>> something() + 1 + 43 + """ + return 42 diff --git a/src/tox.ini b/src/tox.ini index 58aa21be8a5..e15471fd742 100644 --- a/src/tox.ini +++ b/src/tox.ini @@ -155,6 +155,7 @@ commands = codespell \ [pytest] python_files = *_test.py +norecursedirs = local prefix venv build pkgs .git src/sage/pkgs src/doc src/bin src/sage/src/sage_setup [coverage:run] source = sage From abbb61fd2cb99836ab37448326dab7e7e7f37fd7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 27 Mar 2022 08:42:42 -0700 Subject: [PATCH 03/16] src/conftest.py: import sage.all to avoid cyclic import errors --- src/conftest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/conftest.py b/src/conftest.py index 33135c9e333..91a6c31e17a 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -12,6 +12,9 @@ from typing import Any import pytest +import sage.all # to avoid cyclic import errors + + # Ignore a few test files that are (not yet) using pytest collect_ignore = [ "sage/misc/nested_class_test.py", From 9bb72ea9ec314940f3c874d492de241fdec96548 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 27 Mar 2022 09:31:36 -0700 Subject: [PATCH 04/16] src/conftest.py: Add # type: ignore, add reference to trac ticket --- src/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conftest.py b/src/conftest.py index 91a6c31e17a..96d06aa2c04 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -12,7 +12,7 @@ from typing import Any import pytest -import sage.all # to avoid cyclic import errors +import sage.all # type: ignore # to avoid cyclic import errors, see Trac #33580 # Ignore a few test files that are (not yet) using pytest From 2c167045d66e049751876ddc755304940265c32a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 27 Mar 2022 09:32:11 -0700 Subject: [PATCH 05/16] src/conftest.py: Remove outdated text --- src/conftest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/conftest.py b/src/conftest.py index 96d06aa2c04..c1dc286fe1a 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -4,8 +4,6 @@ This file configures pytest and provides some global fixtures. See https://docs.pytest.org/en/latest/index.html for more details. - -At the moment, Sage is not yet using any tests based on pytest. """ from __future__ import annotations From 30642ba190ae9a6a6090b11e51a317a2534028db Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 27 Mar 2022 11:20:06 -0700 Subject: [PATCH 06/16] src/bin/sage: Handle 'sage -pytest' without file args --- src/bin/sage | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/bin/sage b/src/bin/sage index 69a157b7d1f..cd91656e1ea 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -956,7 +956,14 @@ if [ "$1" = '-pytest' -o "$1" = '--pytest' ]; then shift if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then if command -v pytest >/dev/null ; then - exec pytest --rootdir="$SAGE_SRC" --import-mode importlib "$@" + # If no non-option arguments are given, provide one + for a in $*; do + case $a in + -*) ;; + *) exec pytest --rootdir="$SAGE_SRC" --import-mode importlib "$@" + esac + done + exec pytest --rootdir="$SAGE_SRC" --import-mode importlib "$@" "$SAGE_SRC" else echo "Run 'sage -i pytest' to install" fi From 538ead395132b0fde5b9e4ee0738c1883610e82f Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 29 Mar 2022 16:25:54 +0000 Subject: [PATCH 07/16] First working prototype --- src/bin/sage | 4 +- src/conftest.py | 104 +++++++++++++++++++++++++++++++++++++++++++- src/test_doctest.py | 17 +++++--- 3 files changed, 116 insertions(+), 9 deletions(-) diff --git a/src/bin/sage b/src/bin/sage index cd91656e1ea..1bcf0214ebe 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -960,10 +960,10 @@ if [ "$1" = '-pytest' -o "$1" = '--pytest' ]; then for a in $*; do case $a in -*) ;; - *) exec pytest --rootdir="$SAGE_SRC" --import-mode importlib "$@" + *) exec pytest --rootdir="$SAGE_SRC" --import-mode importlib --doctest-modules "$@" esac done - exec pytest --rootdir="$SAGE_SRC" --import-mode importlib "$@" "$SAGE_SRC" + exec pytest --rootdir="$SAGE_SRC" --import-mode importlib --doctest-modules "$@" "$SAGE_SRC" else echo "Run 'sage -i pytest' to install" fi diff --git a/src/conftest.py b/src/conftest.py index c1dc286fe1a..5edf6015972 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -7,11 +7,24 @@ """ from __future__ import annotations -from typing import Any + +from typing import Any, Iterable + import pytest +from _pytest.doctest import ( + DoctestItem, + DoctestModule, + _get_checker, + _get_continue_on_failure, + _get_runner, + _is_mocked, + _patch_unwrap_mock_aware, + get_optionflags, +) +from _pytest.pathlib import import_path import sage.all # type: ignore # to avoid cyclic import errors, see Trac #33580 - +from sage.doctest.parsing import SageDocTestParser # Ignore a few test files that are (not yet) using pytest collect_ignore = [ @@ -21,6 +34,92 @@ ] +def pytest_collect_file(file_path, parent): + if file_path.suffix == ".py": + return SageDoctestModule.from_parent(parent, path=file_path) + + +class SageDoctestModule(DoctestModule): + """ + This is essentially a copy of `DoctestModule` from + https://github.com/pytest-dev/pytest/blob/main/src/_pytest/doctest.py. + The only change is that we use `SageDocTestParser` to extract the doctests. + """ + + def collect(self) -> Iterable[DoctestItem]: + import doctest + + class MockAwareDocTestFinder(doctest.DocTestFinder): + """A hackish doctest finder that overrides stdlib internals to fix a stdlib bug. + https://github.com/pytest-dev/pytest/issues/3456 + https://bugs.python.org/issue25532 + """ + + def __init__(self) -> None: + super().__init__(parser=SageDocTestParser(set(["sage"]))) + + def _find_lineno(self, obj, source_lines): + """Doctest code does not take into account `@property`, this + is a hackish way to fix it. https://bugs.python.org/issue17446 + Wrapped Doctests will need to be unwrapped so the correct + line number is returned. This will be reported upstream. #8796 + """ + if isinstance(obj, property): + obj = getattr(obj, "fget", obj) + + if hasattr(obj, "__wrapped__"): + # Get the main obj in case of it being wrapped + obj = inspect.unwrap(obj) + + # Type ignored because this is a private function. + return super()._find_lineno( # type:ignore[misc] + obj, + source_lines, + ) + + def _find( + self, tests, obj, name, module, source_lines, globs, seen + ) -> None: + if _is_mocked(obj): + return + with _patch_unwrap_mock_aware(): + + # Type ignored because this is a private function. + super()._find( # type:ignore[misc] + tests, obj, name, module, source_lines, globs, seen + ) + + if self.path.name == "conftest.py": + module = self.config.pluginmanager._importconftest( + self.path, + self.config.getoption("importmode"), + rootpath=self.config.rootpath, + ) + else: + try: + module = import_path(self.path, root=self.config.rootpath) + except ImportError: + if self.config.getvalue("doctest_ignore_import_errors"): + pytest.skip("unable to import module %r" % self.path) + else: + raise + # Uses internal doctest module parsing mechanism. + finder = MockAwareDocTestFinder() + optionflags = get_optionflags(self) + runner = _get_runner( + verbose=False, + optionflags=optionflags, + checker=_get_checker(), + continue_on_failure=_get_continue_on_failure(self.config), + ) + + for test in finder.find(module, module.__name__): + if test.examples: # skip empty doctests + yield DoctestItem.from_parent( + self, name=test.name, runner=runner, dtest=test + ) + + @pytest.fixture(autouse=True) def add_imports(doctest_namespace: dict[str, Any]): """ @@ -29,4 +128,5 @@ def add_imports(doctest_namespace: dict[str, Any]): See `pytest documentation `. """ import sage.all # type: ignore # implicitly used below by calling locals() + doctest_namespace.update(**locals()) diff --git a/src/test_doctest.py b/src/test_doctest.py index 37cb7d89995..b0e12f1998e 100644 --- a/src/test_doctest.py +++ b/src/test_doctest.py @@ -1,11 +1,18 @@ +from sage.all import Integer + def something(): """ a doctest in a docstring - >>> something() - 42 + + EXAMPLES:: + + sage: something() + 42 + sage: something() + 1 + 43 - some other doctest + TESTS:: - >>> something() + 1 - 43 + sage: something() + 44 """ return 42 From d36adf4084c117fbb3da87232c74ba6b155d0307 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 5 Apr 2022 18:11:48 +0000 Subject: [PATCH 08/16] Fix import of sage.all in tests --- src/conftest.py | 8 ++++---- src/test_doctest.py | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/conftest.py b/src/conftest.py index 13b9ff568d9..c80e06b2f23 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -22,6 +22,7 @@ get_optionflags, ) from _pytest.pathlib import import_path +import inspect import sage.all # type: ignore # to avoid cyclic import errors, see Trac #33580 from sage.doctest.parsing import SageDocTestParser @@ -113,7 +114,7 @@ def _find( ) -import sage.all # type: ignore # to avoid cyclic import errors, see Trac #33580 +from sage.all import * # type: ignore # to avoid cyclic import errors, see Trac #33580, and is implicitly used below by calling globals() @pytest.fixture(autouse=True) @@ -123,6 +124,5 @@ def add_imports(doctest_namespace: dict[str, Any]): See `pytest documentation `. """ - import sage.all # type: ignore # implicitly used below by calling locals() - - doctest_namespace.update(**locals()) + # Inject sage.all into each doctest + doctest_namespace.update(**globals()) diff --git a/src/test_doctest.py b/src/test_doctest.py index b0e12f1998e..d3f5d5cdfb2 100644 --- a/src/test_doctest.py +++ b/src/test_doctest.py @@ -1,5 +1,3 @@ -from sage.all import Integer - def something(): """ a doctest in a docstring From 813a5416f05702eecfe5fd1b54f3ae379ca1981a Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 5 Apr 2022 18:12:03 +0000 Subject: [PATCH 09/16] Add vs code config to debug pytest --- .vscode/launch.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index fcf2e9c45d8..677f3a243cd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,17 @@ { "version": "0.2.0", "configurations": [ + { + "name": "Sage: Pytest", + "type": "python", + "request": "launch", + "module": "pytest", + "args": [ + "${file}" + ], + "console": "integratedTerminal", + "justMyCode": false + }, { "name": "Python: Current File", "type": "python", @@ -10,4 +21,4 @@ "justMyCode": false } ], -} +} \ No newline at end of file From d3fdd951e5c37ebdac17f8d1fbc86ed8f36dff7e Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 5 Apr 2022 19:08:36 +0000 Subject: [PATCH 10/16] Cleanup vscode config --- .vscode/settings.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9cdc0e3b980..562b8dc479b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,10 +14,8 @@ "pkgs/sagemath-objects/sage": true, "pkgs/sagemath-standard/sage": true, }, - "python.testing.pytestPath": "./sage -t", "python.testing.pytestEnabled": true, "python.testing.pytestArgs": [ - "src/test_doctests.py", "--rootdir=src/sage", "-c=src/tox.ini", "--doctest-modules", From 58e11d707764c4e7c85bf1c5beb8bf257c0318d8 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 5 Apr 2022 19:09:14 +0000 Subject: [PATCH 11/16] Fix checker and namespace injection --- src/conftest.py | 28 ++++++++++++++++++---------- src/tox.ini | 1 + 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/conftest.py b/src/conftest.py index c80e06b2f23..913c53ae91f 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -14,7 +14,6 @@ from _pytest.doctest import ( DoctestItem, DoctestModule, - _get_checker, _get_continue_on_failure, _get_runner, _is_mocked, @@ -24,9 +23,11 @@ from _pytest.pathlib import import_path import inspect -import sage.all # type: ignore # to avoid cyclic import errors, see Trac #33580 -from sage.doctest.parsing import SageDocTestParser - +# Import sage.all is necessary to: +# - avoid cyclic import errors, see Trac #33580 +# - inject it into globals namespace for doctests +import sage.all +from sage.doctest.parsing import SageDocTestParser, SageOutputChecker def pytest_collect_file(file_path, parent): if file_path.suffix == ".py": @@ -37,7 +38,8 @@ class SageDoctestModule(DoctestModule): """ This is essentially a copy of `DoctestModule` from https://github.com/pytest-dev/pytest/blob/main/src/_pytest/doctest.py. - The only change is that we use `SageDocTestParser` to extract the doctests. + The only change is that we use `SageDocTestParser` to extract the doctests + and `SageOutputChecker` to verify the output. """ def collect(self) -> Iterable[DoctestItem]: @@ -103,7 +105,7 @@ def _find( runner = _get_runner( verbose=False, optionflags=optionflags, - checker=_get_checker(), + checker=SageOutputChecker(), continue_on_failure=_get_continue_on_failure(self.config), ) @@ -114,9 +116,6 @@ def _find( ) -from sage.all import * # type: ignore # to avoid cyclic import errors, see Trac #33580, and is implicitly used below by calling globals() - - @pytest.fixture(autouse=True) def add_imports(doctest_namespace: dict[str, Any]): """ @@ -125,4 +124,13 @@ def add_imports(doctest_namespace: dict[str, Any]): See `pytest documentation `. """ # Inject sage.all into each doctest - doctest_namespace.update(**globals()) + dict_all = sage.all.__dict__ + + # Remove '__package__' item from the globals since it is not + # always in the globals in an actual Sage session. + dict_all.pop('__package__', None) + + sage_namespace = dict(dict_all) + sage_namespace['__name__'] = '__main__' + + doctest_namespace.update(**sage_namespace) diff --git a/src/tox.ini b/src/tox.ini index 43d50ae7b9d..fa8e5b76024 100644 --- a/src/tox.ini +++ b/src/tox.ini @@ -158,6 +158,7 @@ commands = codespell \ python_files = *_test.py norecursedirs = local prefix venv build pkgs .git src/sage/pkgs src/doc src/bin src/sage/src/sage_setup addopts = --import-mode importlib +doctest_optionflags = NORMALIZE_WHITESPACE ELLIPSIS [coverage:run] source = sage From e62c29b48b8fb6e23a597cc12584fe1a209092d3 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 6 May 2022 21:10:35 +0000 Subject: [PATCH 12/16] Cleanup imports --- src/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conftest.py b/src/conftest.py index 67eafddf6bc..b45ea31fcb9 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -7,8 +7,9 @@ """ from __future__ import annotations -from pathlib import Path +import inspect +from pathlib import Path from typing import Any, Iterable import pytest @@ -22,7 +23,6 @@ get_optionflags, ) from _pytest.pathlib import import_path -import inspect # Import sage.all is necessary to: # - avoid cyclic import errors, see Trac #33580 From 3ee9815f55793429d2ea444a5b823ed18b006d6a Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 6 May 2022 22:31:36 +0000 Subject: [PATCH 13/16] Add test that pytest correctly fails on example --- ...{test_doctest.py => conftest_inputtest.py} | 0 src/conftest_test.py | 51 +++++++++++++++++++ 2 files changed, 51 insertions(+) rename src/{test_doctest.py => conftest_inputtest.py} (100%) create mode 100644 src/conftest_test.py diff --git a/src/test_doctest.py b/src/conftest_inputtest.py similarity index 100% rename from src/test_doctest.py rename to src/conftest_inputtest.py diff --git a/src/conftest_test.py b/src/conftest_test.py new file mode 100644 index 00000000000..dcf166fd969 --- /dev/null +++ b/src/conftest_test.py @@ -0,0 +1,51 @@ +import subprocess + + +class TestOldDoctestSageScript: + """Run `sage --t`.""" + + def test_invoke_on_inputtest_file(self): + result = subprocess.run( + ["sage", "-t", "./src/conftest_inputtest.py"], + capture_output=True, + text=True, + ) + assert result.returncode == 1 # There are failures in the input test + assert ( + "Failed example:\n" + " something()\n" + "Expected:\n" + " 44\n" + "Got:\n" + " 42\n" + "" in result.stdout + ) + + +class TestPytestSageScript: + """Run `sage --pytest`.""" + + def test_invoke_on_inputtest_file(self): + result = subprocess.run( + ["sage", "--pytest", "./src/conftest_inputtest.py"], + capture_output=True, + text=True, + ) + assert result.returncode == 1 # There are failures in the input test + assert ( + "004 EXAMPLES::\n" + "005 \n" + "006 sage: something()\n" + "007 42\n" + "008 sage: something() + 1\n" + "009 43\n" + "010 \n" + "011 TESTS::\n" + "012 \n" + "013 sage: something()\n" + "Expected:\n" + " 44\n" + "Got:\n" + " 42\n" + "" in result.stdout + ) From f863428150c03430bbc072d7386f3c8dd9a64221 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 6 May 2022 22:32:43 +0000 Subject: [PATCH 14/16] Only run doctests in pytest when doctest-modules is specified --- src/bin/sage | 4 ++-- src/conftest.py | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/bin/sage b/src/bin/sage index e94cc50940e..1daf4d91538 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -960,10 +960,10 @@ if [ "$1" = '-pytest' -o "$1" = '--pytest' ]; then for a in $*; do case $a in -*) ;; - *) exec pytest --rootdir="$SAGE_SRC" "$@" + *) exec pytest --rootdir="$SAGE_SRC" --doctest-modules "$@" esac done - exec pytest --rootdir="$SAGE_SRC" "$@" "$SAGE_SRC" + exec pytest --rootdir="$SAGE_SRC" --doctest-modules "$@" "$SAGE_SRC" else echo "Run 'sage -i pytest' to install" fi diff --git a/src/conftest.py b/src/conftest.py index b45ea31fcb9..5ec6bc953b9 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -130,7 +130,8 @@ def pytest_collect_file( # hit this here if someone explicitly runs `pytest some_file.pyx`. return pytest.skip("Skipping Cython file") elif file_path.suffix == ".py": - return SageDoctestModule.from_parent(parent, path=file_path) + if parent.config.option.doctestmodules: + return SageDoctestModule.from_parent(parent, path=file_path) @pytest.fixture(autouse=True) @@ -142,12 +143,12 @@ def add_imports(doctest_namespace: dict[str, Any]): """ # Inject sage.all into each doctest dict_all = sage.all.__dict__ - + # Remove '__package__' item from the globals since it is not # always in the globals in an actual Sage session. - dict_all.pop('__package__', None) + dict_all.pop("__package__", None) sage_namespace = dict(dict_all) - sage_namespace['__name__'] = '__main__' - + sage_namespace["__name__"] = "__main__" + doctest_namespace.update(**sage_namespace) From 428a18ca7d8cd9d2423aa2f66dbd069a906ac144 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 8 May 2022 08:52:59 +0000 Subject: [PATCH 15/16] Remove nonexisting paths from config --- src/tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tox.ini b/src/tox.ini index 4780e9a486c..0e805f61fdd 100644 --- a/src/tox.ini +++ b/src/tox.ini @@ -173,7 +173,7 @@ commands = codespell \ [pytest] python_files = *_test.py -norecursedirs = local prefix venv build pkgs .git src/sage/pkgs src/doc src/bin src/sage/src/sage_setup +norecursedirs = local prefix venv build pkgs .git src/doc src/bin addopts = --import-mode importlib doctest_optionflags = NORMALIZE_WHITESPACE ELLIPSIS From cc19e927a49efbd31d693b2f70bad48203ea8a25 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 9 May 2022 12:35:35 +0000 Subject: [PATCH 16/16] Specify importlib as import mode to be consistent --- src/conftest.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/conftest.py b/src/conftest.py index 5ec6bc953b9..f12f0aa0cbc 100644 --- a/src/conftest.py +++ b/src/conftest.py @@ -22,7 +22,7 @@ _patch_unwrap_mock_aware, get_optionflags, ) -from _pytest.pathlib import import_path +from _pytest.pathlib import import_path, ImportMode # Import sage.all is necessary to: # - avoid cyclic import errors, see Trac #33580 @@ -90,7 +90,11 @@ def _find( ) else: try: - module = import_path(self.path, root=self.config.rootpath) + module = import_path( + self.path, + mode=ImportMode.importlib, + root=self.config.rootpath, + ) except ImportError: if self.config.getvalue("doctest_ignore_import_errors"): pytest.skip("unable to import module %r" % self.path)