diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 5c7c8dfe6..d4d06af15 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -148,10 +148,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a on warning categories. tmpdir_factory [session scope] - Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session. + Return a :class:`pytest.TempdirFactory` instance for the test session. tmp_path_factory [session scope] - Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session. + Return a :class:`pytest.TempPathFactory` instance for the test session. tmpdir Return a temporary directory path object which is unique to each test diff --git a/doc/en/example/assertion/test_failures.py b/doc/en/example/assertion/test_failures.py index eda06dfc5..350518b43 100644 --- a/doc/en/example/assertion/test_failures.py +++ b/doc/en/example/assertion/test_failures.py @@ -5,9 +5,9 @@ failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py") pytest_plugins = ("pytester",) -def test_failure_demo_fails_properly(testdir): - target = testdir.tmpdir.join(os.path.basename(failure_demo)) +def test_failure_demo_fails_properly(pytester): + target = pytester.path.joinpath(os.path.basename(failure_demo)) shutil.copy(failure_demo, target) - result = testdir.runpytest(target, syspathinsert=True) + result = pytester.runpytest(target, syspathinsert=True) result.stdout.fnmatch_lines(["*44 failed*"]) assert result.ret != 0 diff --git a/doc/en/example/multipython.py b/doc/en/example/multipython.py index 21bddcd03..9005d31ad 100644 --- a/doc/en/example/multipython.py +++ b/doc/en/example/multipython.py @@ -12,8 +12,8 @@ pythonlist = ["python3.5", "python3.6", "python3.7"] @pytest.fixture(params=pythonlist) -def python1(request, tmpdir): - picklefile = tmpdir.join("data.pickle") +def python1(request, tmp_path): + picklefile = tmp_path / "data.pickle" return Python(request.param, picklefile) @@ -30,8 +30,8 @@ class Python: self.picklefile = picklefile def dumps(self, obj): - dumpfile = self.picklefile.dirpath("dump.py") - dumpfile.write( + dumpfile = self.picklefile.with_name("dump.py") + dumpfile.write_text( textwrap.dedent( r""" import pickle @@ -46,8 +46,8 @@ class Python: subprocess.check_call((self.pythonpath, str(dumpfile))) def load_and_is_true(self, expression): - loadfile = self.picklefile.dirpath("load.py") - loadfile.write( + loadfile = self.picklefile.with_name("load.py") + loadfile.write_text( textwrap.dedent( r""" import pickle diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 18f1945c5..759f308e2 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -768,8 +768,8 @@ case we just write some information out to a ``failures`` file: mode = "a" if os.path.exists("failures") else "w" with open("failures", mode) as f: # let's also access a fixture for the fun of it - if "tmpdir" in item.fixturenames: - extra = " ({})".format(item.funcargs["tmpdir"]) + if "tmp_path" in item.fixturenames: + extra = " ({})".format(item.funcargs["tmp_path"]) else: extra = "" @@ -781,7 +781,7 @@ if you then have failing tests: .. code-block:: python # content of test_module.py - def test_fail1(tmpdir): + def test_fail1(tmp_path): assert 0 @@ -804,9 +804,9 @@ and run them: ================================= FAILURES ================================= ________________________________ test_fail1 ________________________________ - tmpdir = local('PYTEST_TMPDIR/test_fail10') + tmp_path = Path('PYTEST_TMPDIR/test_fail10') - def test_fail1(tmpdir): + def test_fail1(tmp_path): > assert 0 E assert 0 diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 32ded5539..a6a457927 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -213,24 +213,24 @@ Request a unique temporary directory for functional tests .. code-block:: python - # content of test_tmpdir.py - def test_needsfiles(tmpdir): - print(tmpdir) + # content of test_tmp_path.py + def test_needsfiles(tmp_path): + print(tmp_path) assert 0 -List the name ``tmpdir`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory: +List the name ``tmp_path`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory: .. code-block:: pytest - $ pytest -q test_tmpdir.py + $ pytest -q test_tmp_path.py F [100%] ================================= FAILURES ================================= _____________________________ test_needsfiles ______________________________ - tmpdir = local('PYTEST_TMPDIR/test_needsfiles0') + tmp_path = Path('PYTEST_TMPDIR/test_needsfiles0') - def test_needsfiles(tmpdir): - print(tmpdir) + def test_needsfiles(tmp_path): + print(tmp_path) > assert 0 E assert 0 @@ -238,10 +238,10 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look --------------------------- Captured stdout call --------------------------- PYTEST_TMPDIR/test_needsfiles0 ========================= short test summary info ========================== - FAILED test_tmpdir.py::test_needsfiles - assert 0 + FAILED test_tmp_path.py::test_needsfiles - assert 0 1 failed in 0.12s -More info on tmpdir handling is available at :ref:`Temporary directories and files `. +More info on temporary directory handling is available at :ref:`Temporary directories and files `. Find out what kind of builtin :ref:`pytest fixtures ` exist with the command: diff --git a/doc/en/reference/doctest.rst b/doc/en/reference/doctest.rst index b6ef1f5b8..e12f02b62 100644 --- a/doc/en/reference/doctest.rst +++ b/doc/en/reference/doctest.rst @@ -194,7 +194,7 @@ It is possible to use fixtures using the ``getfixture`` helper: .. code-block:: text # content of example.rst - >>> tmp = getfixture('tmpdir') + >>> tmp = getfixture('tmp_path') >>> ... >>> diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index a8faa044f..4c5e668d2 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -284,9 +284,9 @@ Example of a fixture requiring another fixture: .. code-block:: python @pytest.fixture - def db_session(tmpdir): - fn = tmpdir / "db.file" - return connect(str(fn)) + def db_session(tmp_path): + fn = tmp_path / "db.file" + return connect(fn) For more details, consult the full :ref:`fixtures docs `. diff --git a/doc/en/reference/unittest.rst b/doc/en/reference/unittest.rst index 130e7705b..92c1bbfa2 100644 --- a/doc/en/reference/unittest.rst +++ b/doc/en/reference/unittest.rst @@ -190,21 +190,22 @@ and define the fixture function in the context where you want it used. Let's look at an ``initdir`` fixture which makes all test methods of a ``TestCase`` class execute in a temporary directory with a pre-initialized ``samplefile.ini``. Our ``initdir`` fixture itself uses -the pytest builtin :ref:`tmpdir ` fixture to delegate the +the pytest builtin :fixture:`tmp_path` fixture to delegate the creation of a per-test temporary directory: .. code-block:: python # content of test_unittest_cleandir.py + import os import pytest import unittest class MyTest(unittest.TestCase): @pytest.fixture(autouse=True) - def initdir(self, tmpdir): - tmpdir.chdir() # change to pytest-provided temporary directory - tmpdir.join("samplefile.ini").write("# testdata") + def initdir(self, tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) # change to pytest-provided temporary directory + tmp_path.joinpath("samplefile.ini").write_text("# testdata") def test_method(self): with open("samplefile.ini") as f: diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 699738e12..df106abb3 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -875,7 +875,7 @@ class Pytester: def syspathinsert( self, path: Optional[Union[str, "os.PathLike[str]"]] = None ) -> None: - """Prepend a directory to sys.path, defaults to :py:attr:`tmpdir`. + """Prepend a directory to sys.path, defaults to :attr:`path`. This is undone automatically when this object dies at the end of each test. @@ -964,7 +964,7 @@ class Pytester: """ session = Session.from_config(config) assert "::" not in str(arg) - p = legacy_path(arg) + p = Path(os.path.abspath(arg)) config.hook.pytest_sessionstart(session=session) res = session.perform_collect([str(p)], genitems=False)[0] config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK) diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index d30e1e57f..63cfa4c23 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -166,11 +166,11 @@ def get_user() -> Optional[str]: def pytest_configure(config: Config) -> None: - """Create a TempdirFactory and attach it to the config object. + """Create a TempPathFactory and attach it to the config object. This is to comply with existing plugins which expect the handler to be available at pytest_configure time, but ideally should be moved entirely - to the tmpdir_factory session fixture. + to the tmp_path_factory session fixture. """ mp = MonkeyPatch() tmppath_handler = TempPathFactory.from_config(config, _ispytest=True) @@ -182,14 +182,14 @@ def pytest_configure(config: Config) -> None: @fixture(scope="session") def tmpdir_factory(request: FixtureRequest) -> TempdirFactory: - """Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.""" + """Return a :class:`pytest.TempdirFactory` instance for the test session.""" # Set dynamically by pytest_configure() above. return request.config._tmpdirhandler # type: ignore @fixture(scope="session") def tmp_path_factory(request: FixtureRequest) -> TempPathFactory: - """Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.""" + """Return a :class:`pytest.TempPathFactory` instance for the test session.""" # Set dynamically by pytest_configure() above. return request.config._tmp_path_factory # type: ignore diff --git a/testing/example_scripts/tmpdir/tmp_path_fixture.py b/testing/example_scripts/tmpdir/tmp_path_fixture.py new file mode 100644 index 000000000..8675eb2fa --- /dev/null +++ b/testing/example_scripts/tmpdir/tmp_path_fixture.py @@ -0,0 +1,7 @@ +import pytest + + +@pytest.mark.parametrize("a", [r"qwe/\abc"]) +def test_fixture(tmp_path, a): + assert tmp_path.is_dir() + assert list(tmp_path.iterdir()) == [] diff --git a/testing/example_scripts/tmpdir/tmpdir_fixture.py b/testing/example_scripts/tmpdir/tmpdir_fixture.py deleted file mode 100644 index f4ad07462..000000000 --- a/testing/example_scripts/tmpdir/tmpdir_fixture.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest - - -@pytest.mark.parametrize("a", [r"qwe/\abc"]) -def test_fixture(tmpdir, a): - tmpdir.check(dir=1) - assert tmpdir.listdir() == [] diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index e62143e5c..8d0dc538a 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -982,11 +982,11 @@ class TestRequestBasic: def farg(arg1): pass @pytest.fixture(autouse=True) - def sarg(tmpdir): + def sarg(tmp_path): pass def test_function(request, farg): assert set(get_public_names(request.fixturenames)) == \ - set(["tmpdir", "sarg", "arg1", "request", "farg", + set(["sarg", "arg1", "request", "farg", "tmp_path", "tmp_path_factory"]) """ ) @@ -1059,7 +1059,7 @@ class TestRequestBasic: def test_show_fixtures_color_yes(self, pytester: Pytester) -> None: pytester.makepyfile("def test_this(): assert 1") result = pytester.runpytest("--color=yes", "--fixtures") - assert "\x1b[32mtmpdir" in result.stdout.str() + assert "\x1b[32mtmp_path" in result.stdout.str() def test_newstyle_with_request(self, pytester: Pytester) -> None: pytester.makepyfile( @@ -1752,11 +1752,11 @@ class TestAutouseDiscovery: """ import pytest @pytest.fixture(autouse=True) - def perfunction(request, tmpdir): + def perfunction(request, tmp_path): pass @pytest.fixture() - def arg1(tmpdir): + def arg1(tmp_path): pass @pytest.fixture(autouse=True) def perfunction2(arg1): @@ -3334,9 +3334,9 @@ class TestShowFixtures: result = pytester.runpytest("--fixtures") result.stdout.fnmatch_lines( [ - "tmpdir_factory [[]session scope[]]", + "tmp_path_factory [[]session scope[]]", "*for the test session*", - "tmpdir", + "tmp_path", "*temporary directory*", ] ) @@ -3345,9 +3345,9 @@ class TestShowFixtures: result = pytester.runpytest("--fixtures", "-v") result.stdout.fnmatch_lines( [ - "tmpdir_factory [[]session scope[]] -- *tmpdir.py*", + "tmp_path_factory [[]session scope[]] -- *tmpdir.py*", "*for the test session*", - "tmpdir -- *tmpdir.py*", + "tmp_path -- *tmpdir.py*", "*temporary directory*", ] ) @@ -3367,7 +3367,7 @@ class TestShowFixtures: result = pytester.runpytest("--fixtures", p) result.stdout.fnmatch_lines( """ - *tmpdir + *tmp_path *fixtures defined from* *arg1* *hello world* @@ -3395,7 +3395,7 @@ class TestShowFixtures: result = pytester.runpytest("--fixtures") result.stdout.fnmatch_lines( """ - *tmpdir* + *tmp_path* *fixtures defined from*conftest* *arg1* *hello world* @@ -4000,15 +4000,15 @@ class TestScopeOrdering: FIXTURE_ORDER.append('m1') @pytest.fixture(scope='session') - def my_tmpdir_factory(): - FIXTURE_ORDER.append('my_tmpdir_factory') + def my_tmp_path_factory(): + FIXTURE_ORDER.append('my_tmp_path_factory') @pytest.fixture - def my_tmpdir(my_tmpdir_factory): - FIXTURE_ORDER.append('my_tmpdir') + def my_tmp_path(my_tmp_path_factory): + FIXTURE_ORDER.append('my_tmp_path') @pytest.fixture - def f1(my_tmpdir): + def f1(my_tmp_path): FIXTURE_ORDER.append('f1') @pytest.fixture @@ -4022,12 +4022,13 @@ class TestScopeOrdering: request = FixtureRequest(items[0], _ispytest=True) # order of fixtures based on their scope and position in the parameter list assert ( - request.fixturenames == "s1 my_tmpdir_factory p1 m1 f1 f2 my_tmpdir".split() + request.fixturenames + == "s1 my_tmp_path_factory p1 m1 f1 f2 my_tmp_path".split() ) pytester.runpytest() - # actual fixture execution differs: dependent fixtures must be created first ("my_tmpdir") + # actual fixture execution differs: dependent fixtures must be created first ("my_tmp_path") FIXTURE_ORDER = pytest.FIXTURE_ORDER # type: ignore[attr-defined] - assert FIXTURE_ORDER == "s1 my_tmpdir_factory p1 m1 my_tmpdir f1 f2".split() + assert FIXTURE_ORDER == "s1 my_tmp_path_factory p1 m1 my_tmp_path f1 f2".split() def test_func_closure_module(self, pytester: Pytester) -> None: pytester.makepyfile( diff --git a/testing/test_collection.py b/testing/test_collection.py index 5f0b5902a..f015578e2 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1346,7 +1346,6 @@ def test_fscollector_from_parent(pytester: Pytester, request: FixtureRequest) -> Context: https://github.com/pytest-dev/pytest-cpp/pull/47 """ - from _pytest.compat import legacy_path class MyCollector(pytest.File): def __init__(self, *k, x, **kw): @@ -1354,7 +1353,7 @@ def test_fscollector_from_parent(pytester: Pytester, request: FixtureRequest) -> self.x = x collector = MyCollector.from_parent( - parent=request.session, fspath=legacy_path(pytester.path) / "foo", x=10 + parent=request.session, path=pytester.path / "foo", x=10 ) assert collector.x == 10 diff --git a/testing/test_config.py b/testing/test_config.py index b23264e1d..fbeabaff6 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1488,7 +1488,6 @@ class TestOverrideIniArgs: ) pytester.makepyfile( """ - import py.path def test_pathlist(pytestconfig): config_paths = pytestconfig.getini("paths") print(config_paths) diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 6ba9269e5..1062c8c37 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -3,9 +3,9 @@ import os import shlex import subprocess import sys +from pathlib import Path import pytest -from _pytest.compat import legacy_path from _pytest.config import argparsing as parseopt from _pytest.config.exceptions import UsageError from _pytest.monkeypatch import MonkeyPatch @@ -123,11 +123,11 @@ class TestParser: assert not getattr(args, parseopt.FILE_OR_DIR) def test_parse2(self, parser: parseopt.Parser) -> None: - args = parser.parse([legacy_path(".")]) - assert getattr(args, parseopt.FILE_OR_DIR)[0] == legacy_path(".") + args = parser.parse([Path(".")]) + assert getattr(args, parseopt.FILE_OR_DIR)[0] == "." def test_parse_known_args(self, parser: parseopt.Parser) -> None: - parser.parse_known_args([legacy_path(".")]) + parser.parse_known_args([Path(".")]) parser.addoption("--hello", action="store_true") ns = parser.parse_known_args(["x", "--y", "--hello", "this"]) assert ns.hello diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 5823d5115..7b16c69c2 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -618,12 +618,12 @@ def test_linematcher_string_api() -> None: assert str(lm) == "foo\nbar" -def test_pytester_addopts_before_testdir(request, monkeypatch: MonkeyPatch) -> None: +def test_pytest_addopts_before_pytester(request, monkeypatch: MonkeyPatch) -> None: orig = os.environ.get("PYTEST_ADDOPTS", None) monkeypatch.setenv("PYTEST_ADDOPTS", "--orig-unused") - testdir = request.getfixturevalue("testdir") + pytester: Pytester = request.getfixturevalue("pytester") assert "PYTEST_ADDOPTS" not in os.environ - testdir.finalize() + pytester._finalize() assert os.environ.get("PYTEST_ADDOPTS") == "--orig-unused" monkeypatch.undo() assert os.environ.get("PYTEST_ADDOPTS") == orig diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 4dec9c59a..63450eab2 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -21,12 +21,11 @@ from _pytest.pathlib import register_cleanup_lock_removal from _pytest.pathlib import rm_rf from _pytest.pytester import Pytester from _pytest.tmpdir import get_user -from _pytest.tmpdir import TempdirFactory from _pytest.tmpdir import TempPathFactory -def test_tmpdir_fixture(pytester: Pytester) -> None: - p = pytester.copy_example("tmpdir/tmpdir_fixture.py") +def test_tmp_path_fixture(pytester: Pytester) -> None: + p = pytester.copy_example("tmpdir/tmp_path_fixture.py") results = pytester.runpytest(p) results.stdout.fnmatch_lines(["*1 passed*"]) @@ -47,18 +46,16 @@ class FakeConfig: return self -class TestTempdirHandler: +class TestTmpPathHandler: def test_mktemp(self, tmp_path): config = cast(Config, FakeConfig(tmp_path)) - t = TempdirFactory( - TempPathFactory.from_config(config, _ispytest=True), _ispytest=True - ) + t = TempPathFactory.from_config(config, _ispytest=True) tmp = t.mktemp("world") - assert tmp.relto(t.getbasetemp()) == "world0" + assert str(tmp.relative_to(t.getbasetemp())) == "world0" tmp = t.mktemp("this") - assert tmp.relto(t.getbasetemp()).startswith("this") + assert str(tmp.relative_to(t.getbasetemp())).startswith("this") tmp2 = t.mktemp("this") - assert tmp2.relto(t.getbasetemp()).startswith("this") + assert str(tmp2.relative_to(t.getbasetemp())).startswith("this") assert tmp2 != tmp def test_tmppath_relative_basetemp_absolute(self, tmp_path, monkeypatch): @@ -69,12 +66,12 @@ class TestTempdirHandler: assert t.getbasetemp().resolve() == (tmp_path / "hello").resolve() -class TestConfigTmpdir: +class TestConfigTmpPath: def test_getbasetemp_custom_removes_old(self, pytester: Pytester) -> None: mytemp = pytester.path.joinpath("xyz") p = pytester.makepyfile( """ - def test_1(tmpdir): + def test_1(tmp_path): pass """ ) @@ -104,8 +101,8 @@ def test_mktemp(pytester: Pytester, basename: str, is_ok: bool) -> None: mytemp = pytester.mkdir("mytemp") p = pytester.makepyfile( """ - def test_abs_path(tmpdir_factory): - tmpdir_factory.mktemp('{}', numbered=False) + def test_abs_path(tmp_path_factory): + tmp_path_factory.mktemp('{}', numbered=False) """.format( basename ) @@ -157,44 +154,44 @@ def test_tmp_path_always_is_realpath(pytester: Pytester, monkeypatch) -> None: reprec.assertoutcome(passed=1) -def test_tmpdir_too_long_on_parametrization(pytester: Pytester) -> None: +def test_tmp_path_too_long_on_parametrization(pytester: Pytester) -> None: pytester.makepyfile( """ import pytest @pytest.mark.parametrize("arg", ["1"*1000]) - def test_some(arg, tmpdir): - tmpdir.ensure("hello") + def test_some(arg, tmp_path): + tmp_path.joinpath("hello").touch() """ ) reprec = pytester.inline_run() reprec.assertoutcome(passed=1) -def test_tmpdir_factory(pytester: Pytester) -> None: +def test_tmp_path_factory(pytester: Pytester) -> None: pytester.makepyfile( """ import pytest @pytest.fixture(scope='session') - def session_dir(tmpdir_factory): - return tmpdir_factory.mktemp('data', numbered=False) + def session_dir(tmp_path_factory): + return tmp_path_factory.mktemp('data', numbered=False) def test_some(session_dir): - assert session_dir.isdir() + assert session_dir.is_dir() """ ) reprec = pytester.inline_run() reprec.assertoutcome(passed=1) -def test_tmpdir_fallback_tox_env(pytester: Pytester, monkeypatch) -> None: - """Test that tmpdir works even if environment variables required by getpass +def test_tmp_path_fallback_tox_env(pytester: Pytester, monkeypatch) -> None: + """Test that tmp_path works even if environment variables required by getpass module are missing (#1010). """ monkeypatch.delenv("USER", raising=False) monkeypatch.delenv("USERNAME", raising=False) pytester.makepyfile( """ - def test_some(tmpdir): - assert tmpdir.isdir() + def test_some(tmp_path): + assert tmp_path.is_dir() """ ) reprec = pytester.inline_run() @@ -211,15 +208,15 @@ def break_getuser(monkeypatch): @pytest.mark.usefixtures("break_getuser") @pytest.mark.skipif(sys.platform.startswith("win"), reason="no os.getuid on windows") -def test_tmpdir_fallback_uid_not_found(pytester: Pytester) -> None: - """Test that tmpdir works even if the current process's user id does not +def test_tmp_path_fallback_uid_not_found(pytester: Pytester) -> None: + """Test that tmp_path works even if the current process's user id does not correspond to a valid user. """ pytester.makepyfile( """ - def test_some(tmpdir): - assert tmpdir.isdir() + def test_some(tmp_path): + assert tmp_path.is_dir() """ ) reprec = pytester.inline_run()