Skip to content

Commit

Permalink
Use builtin pathlib on Python 3
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoddemus committed Jun 5, 2019
1 parent be84ba8 commit e4940c1
Show file tree
Hide file tree
Showing 9 changed files with 34 additions and 33 deletions.
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))
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

0 comments on commit e4940c1

Please sign in to comment.