Skip to content

Commit 0542bef

Browse files
committed
Use builtin pathlib on Python 3
Fix #5017
1 parent 25cef55 commit 0542bef

File tree

9 files changed

+33
-32
lines changed

9 files changed

+33
-32
lines changed

changelog/5017.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

doc/en/tmpdir.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ The ``tmp_path`` fixture
99
------------------------
1010

1111

12-
13-
1412
You can use the ``tmp_path`` fixture which will
1513
provide a temporary directory unique to the test invocation,
1614
created in the `base temporary directory`_.
1715

18-
``tmp_path`` is a ``pathlib/pathlib2.Path`` object. Here is an example test usage:
16+
``tmp_path`` is a ``pathlib.Path`` object. Here is an example test usage:
1917

2018
.. code-block:: python
2119

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
"attrs>=17.4.0",
99
"more-itertools>=4.0.0",
1010
"atomicwrites>=1.0",
11-
'pathlib2>=2.2.0;python_version<"3.6"',
1211
'colorama;sys_platform=="win32"',
1312
"pluggy>=0.12,<1.0",
1413
"importlib-metadata>=0.12",

src/_pytest/cacheprovider.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def for_config(cls, config):
5050

5151
@staticmethod
5252
def cache_dir_from_config(config):
53-
return resolve_from_str(config.getini("cache_dir"), config.rootdir)
53+
return resolve_from_str(config.getini("cache_dir"), str(config.rootdir))
5454

5555
def warn(self, fmt, **args):
5656
from _pytest.warnings import _issue_warning_captured
@@ -76,7 +76,8 @@ def makedir(self, name):
7676
if len(name.parts) > 1:
7777
raise ValueError("name is not allowed to contain path separators")
7878
res = self._cachedir.joinpath("d", name)
79-
res.mkdir(exist_ok=True, parents=True)
79+
if not res.is_dir():
80+
os.makedirs(str(res))
8081
return py.path.local(res)
8182

8283
def _getvaluepath(self, key):
@@ -115,7 +116,7 @@ def set(self, key, value):
115116
cache_dir_exists_already = True
116117
else:
117118
cache_dir_exists_already = self._cachedir.exists()
118-
path.parent.mkdir(exist_ok=True, parents=True)
119+
os.makedirs(str(path.parent))
119120
except (IOError, OSError):
120121
self.warn("could not create cache path {path}", path=path)
121122
return
@@ -132,14 +133,17 @@ def set(self, key, value):
132133
def _ensure_supporting_files(self):
133134
"""Create supporting files in the cache dir that are not really part of the cache."""
134135
readme_path = self._cachedir / "README.md"
135-
readme_path.write_text(README_CONTENT)
136+
with readme_path.open("w") as f:
137+
f.write(README_CONTENT)
136138

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

141144
cachedir_tag_path = self._cachedir.joinpath("CACHEDIR.TAG")
142-
cachedir_tag_path.write_bytes(CACHEDIR_TAG_CONTENT)
145+
with cachedir_tag_path.open("wb") as f:
146+
f.write(CACHEDIR_TAG_CONTENT)
143147

144148

145149
class LFPlugin:
@@ -160,7 +164,7 @@ def last_failed_paths(self):
160164
try:
161165
return self._last_failed_paths
162166
except AttributeError:
163-
rootpath = Path(self.config.rootdir)
167+
rootpath = Path(str(self.config.rootdir))
164168
result = {rootpath / nodeid.split("::")[0] for nodeid in self.lastfailed}
165169
result = {x for x in result if x.exists()}
166170
self._last_failed_paths = result
@@ -385,7 +389,7 @@ def pytest_report_header(config):
385389
# starting with .., ../.. if sensible
386390

387391
try:
388-
displaypath = cachedir.relative_to(config.rootdir)
392+
displaypath = cachedir.relative_to(str(config.rootdir))
389393
except ValueError:
390394
displaypath = cachedir
391395
return "cachedir: {}".format(displaypath)

src/_pytest/pathlib.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,11 @@
1111
from os.path import expandvars
1212
from os.path import isabs
1313
from os.path import sep
14+
from pathlib import Path
15+
from pathlib import PurePath
1416
from posixpath import sep as posix_sep
1517

1618

17-
if sys.version_info[:2] >= (3, 6):
18-
from pathlib import Path, PurePath
19-
else:
20-
from pathlib2 import Path, PurePath
21-
2219
__all__ = ["Path", "PurePath"]
2320

2421

@@ -256,7 +253,6 @@ def make_numbered_dir_with_cleanup(root, prefix, keep, lock_timeout):
256253

257254

258255
def resolve_from_str(input, root):
259-
assert not isinstance(input, Path), "would break on py2"
260256
root = Path(root)
261257
input = expanduser(input)
262258
input = expandvars(input)

src/_pytest/tmpdir.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ def getbasetemp(self):
6666
# use a sub-directory in the temproot to speed-up
6767
# make_numbered_dir() call
6868
rootdir = temproot.joinpath("pytest-of-{}".format(user))
69-
rootdir.mkdir(exist_ok=True)
69+
if not rootdir.is_dir():
70+
os.mkdir(str(rootdir))
7071
basetemp = make_numbered_dir_with_cleanup(
7172
prefix="pytest-", root=rootdir, keep=3, lock_timeout=LOCK_TIMEOUT
7273
)
@@ -180,10 +181,6 @@ def tmp_path(request, tmp_path_factory):
180181
created as a sub directory of the base temporary
181182
directory. The returned object is a :class:`pathlib.Path`
182183
object.
183-
184-
.. note::
185-
186-
in python < 3.6 this is a pathlib2.Path
187184
"""
188185

189186
return _mk_tmp(request, tmp_path_factory)

testing/test_cacheprovider.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def test_config_cache_dataerror(self, testdir):
2727
cache = config.cache
2828
pytest.raises(TypeError, lambda: cache.set("key/name", cache))
2929
config.cache.set("key/name", 0)
30-
config.cache._getvaluepath("key/name").write_bytes(b"123invalid")
30+
with config.cache._getvaluepath("key/name").open("wb") as f:
31+
f.write(b"123invalid")
3132
val = config.cache.get("key/name", -2)
3233
assert val == -2
3334

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

10361038
# Does not overwrite existing/custom one.
1037-
gitignore_path.write_text("custom")
1039+
with gitignore_path.open("w", encoding="UTF-8") as f:
1040+
f.write("custom")
10381041
cache.set("something", "else")
1039-
assert gitignore_path.read_text(encoding="UTF-8") == "custom"
1042+
with gitignore_path.open("r", encoding="UTF-8") as f:
1043+
assert f.read() == "custom"
10401044

10411045

10421046
def test_does_not_create_boilerplate_in_existing_dirs(testdir):
@@ -1066,4 +1070,5 @@ def test_cachedir_tag(testdir):
10661070
cache = Cache.for_config(config)
10671071
cache.set("foo", "bar")
10681072
cachedir_tag_path = cache._cachedir.joinpath("CACHEDIR.TAG")
1069-
assert cachedir_tag_path.read_bytes() == CACHEDIR_TAG_CONTENT
1073+
with cachedir_tag_path.open("rb") as f:
1074+
assert f.read() == CACHEDIR_TAG_CONTENT

testing/test_reports.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def test_a():
215215
assert len(reports) == 3
216216
test_a_call = reports[1]
217217
test_a_call.path1 = testdir.tmpdir
218-
test_a_call.path2 = Path(testdir.tmpdir)
218+
test_a_call.path2 = Path(str(testdir.tmpdir))
219219
data = test_a_call._to_json()
220220
assert data["path1"] == str(testdir.tmpdir)
221221
assert data["path2"] == str(testdir.tmpdir)

testing/test_tmpdir.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,8 @@ def test_rmtree(self, tmp_path):
322322

323323
adir.mkdir()
324324
afile = adir / "afile"
325-
afile.write_bytes(b"aa")
325+
with afile.open("wb") as f:
326+
f.write(b"aa")
326327

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

350351

351352
def test_tmpdir_equals_tmp_path(tmpdir, tmp_path):
352-
assert Path(tmpdir) == tmp_path
353+
assert Path(str(tmpdir)) == tmp_path

0 commit comments

Comments
 (0)