Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/5017.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``pathlib2`` is no longer used, avoiding a number of problems when mixing ``pathlib2.Path`` and ``pathlib.Path`` objects. pytest now always uses the native ``pathlib`` module.
4 changes: 1 addition & 3 deletions doc/en/tmpdir.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ The ``tmp_path`` fixture
------------------------




You can use the ``tmp_path`` fixture which will
provide a temporary directory unique to the test invocation,
created in the `base temporary directory`_.

``tmp_path`` is a ``pathlib/pathlib2.Path`` object. Here is an example test usage:
``tmp_path`` is a ``pathlib.Path`` object. Here is an example test usage:

.. code-block:: python

Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"attrs>=17.4.0",
"more-itertools>=4.0.0",
"atomicwrites>=1.0",
'pathlib2>=2.2.0;python_version<"3.6"',
'colorama;sys_platform=="win32"',
"pluggy>=0.12,<1.0",
"importlib-metadata>=0.12",
Expand Down
22 changes: 13 additions & 9 deletions src/_pytest/cacheprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def for_config(cls, config):

@staticmethod
def cache_dir_from_config(config):
return resolve_from_str(config.getini("cache_dir"), config.rootdir)
return resolve_from_str(config.getini("cache_dir"), str(config.rootdir))

def warn(self, fmt, **args):
from _pytest.warnings import _issue_warning_captured
Expand All @@ -76,7 +76,8 @@ def makedir(self, name):
if len(name.parts) > 1:
raise ValueError("name is not allowed to contain path separators")
res = self._cachedir.joinpath("d", name)
res.mkdir(exist_ok=True, parents=True)
if not res.is_dir():
os.makedirs(str(res))
Copy link
Member

@asottile asottile Jun 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.makedirs(..., exist_ok=True) I believe is less prone to race conditions

return py.path.local(res)

def _getvaluepath(self, key):
Expand Down Expand Up @@ -115,7 +116,7 @@ def set(self, key, value):
cache_dir_exists_already = True
else:
cache_dir_exists_already = self._cachedir.exists()
path.parent.mkdir(exist_ok=True, parents=True)
os.makedirs(str(path.parent))
except (IOError, OSError):
self.warn("could not create cache path {path}", path=path)
return
Expand All @@ -132,14 +133,17 @@ def set(self, key, value):
def _ensure_supporting_files(self):
"""Create supporting files in the cache dir that are not really part of the cache."""
readme_path = self._cachedir / "README.md"
readme_path.write_text(README_CONTENT)
with readme_path.open("w") as f:
f.write(README_CONTENT)

gitignore_path = self._cachedir.joinpath(".gitignore")
msg = "# Created by pytest automatically.\n*"
gitignore_path.write_text(msg, encoding="UTF-8")
with gitignore_path.open("w", encoding="UTF-8") as f:
f.write(msg)

cachedir_tag_path = self._cachedir.joinpath("CACHEDIR.TAG")
cachedir_tag_path.write_bytes(CACHEDIR_TAG_CONTENT)
with cachedir_tag_path.open("wb") as f:
f.write(CACHEDIR_TAG_CONTENT)


class LFPlugin:
Expand All @@ -160,7 +164,7 @@ def last_failed_paths(self):
try:
return self._last_failed_paths
except AttributeError:
rootpath = Path(self.config.rootdir)
rootpath = Path(str(self.config.rootdir))
result = {rootpath / nodeid.split("::")[0] for nodeid in self.lastfailed}
result = {x for x in result if x.exists()}
self._last_failed_paths = result
Expand All @@ -174,7 +178,7 @@ def pytest_ignore_collect(self, path):
if self.active and self.config.getoption("lf") and path.isfile():
last_failed_paths = self.last_failed_paths()
if last_failed_paths:
skip_it = Path(path) not in self.last_failed_paths()
skip_it = Path(str(path)) not in self.last_failed_paths()
if skip_it:
self._skipped_files += 1
return skip_it
Expand Down Expand Up @@ -385,7 +389,7 @@ def pytest_report_header(config):
# starting with .., ../.. if sensible

try:
displaypath = cachedir.relative_to(config.rootdir)
displaypath = cachedir.relative_to(str(config.rootdir))
except ValueError:
displaypath = cachedir
return "cachedir: {}".format(displaypath)
Expand Down
8 changes: 2 additions & 6 deletions src/_pytest/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@
from os.path import expandvars
from os.path import isabs
from os.path import sep
from pathlib import Path
from pathlib import PurePath
from posixpath import sep as posix_sep


if sys.version_info[:2] >= (3, 6):
from pathlib import Path, PurePath
else:
from pathlib2 import Path, PurePath

__all__ = ["Path", "PurePath"]


Expand Down Expand Up @@ -254,7 +251,6 @@ def make_numbered_dir_with_cleanup(root, prefix, keep, lock_timeout):


def resolve_from_str(input, root):
assert not isinstance(input, Path), "would break on py2"
root = Path(root)
input = expanduser(input)
input = expandvars(input)
Expand Down
7 changes: 2 additions & 5 deletions src/_pytest/tmpdir.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ def getbasetemp(self):
# use a sub-directory in the temproot to speed-up
# make_numbered_dir() call
rootdir = temproot.joinpath("pytest-of-{}".format(user))
rootdir.mkdir(exist_ok=True)
if not rootdir.is_dir():
os.mkdir(str(rootdir))
basetemp = make_numbered_dir_with_cleanup(
prefix="pytest-", root=rootdir, keep=3, lock_timeout=LOCK_TIMEOUT
)
Expand Down Expand Up @@ -180,10 +181,6 @@ def tmp_path(request, tmp_path_factory):
created as a sub directory of the base temporary
directory. The returned object is a :class:`pathlib.Path`
object.

.. note::

in python < 3.6 this is a pathlib2.Path
"""

return _mk_tmp(request, tmp_path_factory)
15 changes: 10 additions & 5 deletions testing/test_cacheprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def test_config_cache_dataerror(self, testdir):
cache = config.cache
pytest.raises(TypeError, lambda: cache.set("key/name", cache))
config.cache.set("key/name", 0)
config.cache._getvaluepath("key/name").write_bytes(b"123invalid")
with config.cache._getvaluepath("key/name").open("wb") as f:
f.write(b"123invalid")
val = config.cache.get("key/name", -2)
assert val == -2

Expand Down Expand Up @@ -1031,12 +1032,15 @@ def test_gitignore(testdir):
cache.set("foo", "bar")
msg = "# Created by pytest automatically.\n*"
gitignore_path = cache._cachedir.joinpath(".gitignore")
assert gitignore_path.read_text(encoding="UTF-8") == msg
with gitignore_path.open("r", encoding="UTF-8") as f:
assert f.read() == msg

# Does not overwrite existing/custom one.
gitignore_path.write_text("custom")
with gitignore_path.open("w", encoding="UTF-8") as f:
f.write("custom")
cache.set("something", "else")
assert gitignore_path.read_text(encoding="UTF-8") == "custom"
with gitignore_path.open("r", encoding="UTF-8") as f:
assert f.read() == "custom"


def test_does_not_create_boilerplate_in_existing_dirs(testdir):
Expand Down Expand Up @@ -1066,4 +1070,5 @@ def test_cachedir_tag(testdir):
cache = Cache.for_config(config)
cache.set("foo", "bar")
cachedir_tag_path = cache._cachedir.joinpath("CACHEDIR.TAG")
assert cachedir_tag_path.read_bytes() == CACHEDIR_TAG_CONTENT
with cachedir_tag_path.open("rb") as f:
assert f.read() == CACHEDIR_TAG_CONTENT
2 changes: 1 addition & 1 deletion testing/test_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def test_a():
assert len(reports) == 3
test_a_call = reports[1]
test_a_call.path1 = testdir.tmpdir
test_a_call.path2 = Path(testdir.tmpdir)
test_a_call.path2 = Path(str(testdir.tmpdir))
data = test_a_call._to_json()
assert data["path1"] == str(testdir.tmpdir)
assert data["path2"] == str(testdir.tmpdir)
Expand Down
7 changes: 4 additions & 3 deletions testing/test_tmpdir.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ def test_rmtree(self, tmp_path):

adir.mkdir()
afile = adir / "afile"
afile.write_bytes(b"aa")
with afile.open("wb") as f:
f.write(b"aa")

rmtree(adir, force=True)
assert not adir.exists()
Expand All @@ -343,10 +344,10 @@ def attempt_symlink_to(path, to_path):
"""Try to make a symlink from "path" to "to_path", skipping in case this platform
does not support it or we don't have sufficient privileges (common on Windows)."""
try:
Path(path).symlink_to(Path(to_path))
Path(str(path)).symlink_to(Path(to_path))
except OSError:
pytest.skip("could not create symbolic link")


def test_tmpdir_equals_tmp_path(tmpdir, tmp_path):
assert Path(tmpdir) == tmp_path
assert Path(str(tmpdir)) == tmp_path