GH-110109: pathlib tests: store base directory as test class attribute (#113221)

Store the test base directory as a class attribute named `base` rather than
module constants named `BASE`.

The base directory is a local file path, and therefore not ideally suited
to the pathlib ABC tests. In a future commit we'll change its value in
`test_pathlib_abc.py` such that it points to a totally fictitious path, which 
will help to ensure we're not touching the local filesystem.
This commit is contained in:
Barney Gale 2023-12-17 00:07:32 +00:00 committed by GitHub
parent d91e43ed78
commit 2f0ec7fa94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 210 additions and 222 deletions

View file

@ -23,11 +23,6 @@ except ImportError:
grp = pwd = None
# Make sure any symbolic links in the base test path are resolved.
BASE = os.path.realpath(TESTFN)
join = lambda *x: os.path.join(BASE, *x)
rel_join = lambda *x: os.path.join(TESTFN, *x)
only_nt = unittest.skipIf(os.name != 'nt',
'test requires a Windows-compatible system')
only_posix = unittest.skipIf(os.name == 'nt',
@ -937,11 +932,11 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
def setUp(self):
super().setUp()
os.chmod(join('dirE'), 0)
os.chmod(self.pathmod.join(self.base, 'dirE'), 0)
def tearDown(self):
os.chmod(join('dirE'), 0o777)
os_helper.rmtree(BASE)
os.chmod(self.pathmod.join(self.base, 'dirE'), 0o777)
os_helper.rmtree(self.base)
def tempdir(self):
d = os_helper._longpath(tempfile.mkdtemp(suffix='-dirD',
@ -978,23 +973,23 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
P = self.cls
with mock.patch("os.getcwd") as getcwd:
getcwd.return_value = BASE
getcwd.return_value = self.base
# Simple relative paths.
self.assertEqual(str(P().absolute()), BASE)
self.assertEqual(str(P('.').absolute()), BASE)
self.assertEqual(str(P('a').absolute()), os.path.join(BASE, 'a'))
self.assertEqual(str(P('a', 'b', 'c').absolute()), os.path.join(BASE, 'a', 'b', 'c'))
self.assertEqual(str(P().absolute()), self.base)
self.assertEqual(str(P('.').absolute()), self.base)
self.assertEqual(str(P('a').absolute()), os.path.join(self.base, 'a'))
self.assertEqual(str(P('a', 'b', 'c').absolute()), os.path.join(self.base, 'a', 'b', 'c'))
# Symlinks should not be resolved.
self.assertEqual(str(P('linkB', 'fileB').absolute()), os.path.join(BASE, 'linkB', 'fileB'))
self.assertEqual(str(P('brokenLink').absolute()), os.path.join(BASE, 'brokenLink'))
self.assertEqual(str(P('brokenLinkLoop').absolute()), os.path.join(BASE, 'brokenLinkLoop'))
self.assertEqual(str(P('linkB', 'fileB').absolute()), os.path.join(self.base, 'linkB', 'fileB'))
self.assertEqual(str(P('brokenLink').absolute()), os.path.join(self.base, 'brokenLink'))
self.assertEqual(str(P('brokenLinkLoop').absolute()), os.path.join(self.base, 'brokenLinkLoop'))
# '..' entries should be preserved and not normalised.
self.assertEqual(str(P('..').absolute()), os.path.join(BASE, '..'))
self.assertEqual(str(P('a', '..').absolute()), os.path.join(BASE, 'a', '..'))
self.assertEqual(str(P('..', 'b').absolute()), os.path.join(BASE, '..', 'b'))
self.assertEqual(str(P('..').absolute()), os.path.join(self.base, '..'))
self.assertEqual(str(P('a', '..').absolute()), os.path.join(self.base, 'a', '..'))
self.assertEqual(str(P('..', 'b').absolute()), os.path.join(self.base, '..', 'b'))
def _test_home(self, p):
q = self.cls(os.path.expanduser('~'))
@ -1011,11 +1006,11 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self._test_home(self.cls.home())
env.clear()
env['USERPROFILE'] = os.path.join(BASE, 'userprofile')
env['USERPROFILE'] = os.path.join(self.base, 'userprofile')
self._test_home(self.cls.home())
# bpo-38883: ignore `HOME` when set on windows
env['HOME'] = os.path.join(BASE, 'home')
env['HOME'] = os.path.join(self.base, 'home')
self._test_home(self.cls.home())
@unittest.skipIf(is_wasi, "WASI has no user accounts.")
@ -1042,7 +1037,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
def with_segments(self, *pathsegments):
return type(self)(*pathsegments, session_id=self.session_id)
p = P(BASE, session_id=42)
p = P(self.base, session_id=42)
self.assertEqual(42, p.absolute().session_id)
self.assertEqual(42, p.resolve().session_id)
if not is_wasi: # WASI has no user accounts.
@ -1061,7 +1056,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(42, dirpath.session_id)
def test_open_unbuffered(self):
p = self.cls(BASE)
p = self.cls(self.base)
with (p / 'fileA').open('rb', buffering=0) as f:
self.assertIsInstance(f, io.RawIOBase)
self.assertEqual(f.read().strip(), b"this is file A")
@ -1070,15 +1065,15 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
p = self.cls('non', 'exist')
old_cwd = os.getcwd()
os.chdir(BASE)
os.chdir(self.base)
try:
self.assertEqual(p.resolve(), self.cls(BASE, p))
self.assertEqual(p.resolve(), self.cls(self.base, p))
finally:
os.chdir(old_cwd)
@os_helper.skip_unless_working_chmod
def test_chmod(self):
p = self.cls(BASE) / 'fileA'
p = self.cls(self.base) / 'fileA'
mode = p.stat().st_mode
# Clear writable bit.
new_mode = mode & ~0o222
@ -1093,7 +1088,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
@only_posix
@os_helper.skip_unless_working_chmod
def test_chmod_follow_symlinks_true(self):
p = self.cls(BASE) / 'linkA'
p = self.cls(self.base) / 'linkA'
q = p.resolve()
mode = q.stat().st_mode
# Clear writable bit.
@ -1116,7 +1111,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
@unittest.skipUnless(pwd, "the pwd module is needed for this test")
def test_owner(self):
p = self.cls(BASE) / 'fileA'
p = self.cls(self.base) / 'fileA'
expected_uid = p.stat().st_uid
expected_name = self._get_pw_name_or_skip_test(expected_uid)
@ -1129,8 +1124,8 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
if len(all_users) < 2:
self.skipTest("test needs more than one user")
target = self.cls(BASE) / 'fileA'
link = self.cls(BASE) / 'linkA'
target = self.cls(self.base) / 'fileA'
link = self.cls(self.base) / 'linkA'
uid_1, uid_2 = all_users[:2]
os.chown(target, uid_1, -1)
@ -1151,7 +1146,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
@unittest.skipUnless(grp, "the grp module is needed for this test")
def test_group(self):
p = self.cls(BASE) / 'fileA'
p = self.cls(self.base) / 'fileA'
expected_gid = p.stat().st_gid
expected_name = self._get_gr_name_or_skip_test(expected_gid)
@ -1164,8 +1159,8 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
if len(all_groups) < 2:
self.skipTest("test needs more than one group")
target = self.cls(BASE) / 'fileA'
link = self.cls(BASE) / 'linkA'
target = self.cls(self.base) / 'fileA'
link = self.cls(self.base) / 'linkA'
gid_1, gid_2 = all_groups[:2]
os.chown(target, -1, gid_1)
@ -1178,18 +1173,18 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(expected_name, link.group(follow_symlinks=False))
def test_unlink(self):
p = self.cls(BASE) / 'fileA'
p = self.cls(self.base) / 'fileA'
p.unlink()
self.assertFileNotFound(p.stat)
self.assertFileNotFound(p.unlink)
def test_unlink_missing_ok(self):
p = self.cls(BASE) / 'fileAAA'
p = self.cls(self.base) / 'fileAAA'
self.assertFileNotFound(p.unlink)
p.unlink(missing_ok=True)
def test_rmdir(self):
p = self.cls(BASE) / 'dirA'
p = self.cls(self.base) / 'dirA'
for q in p.iterdir():
q.unlink()
p.rmdir()
@ -1198,7 +1193,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
@unittest.skipUnless(hasattr(os, "link"), "os.link() is not present")
def test_hardlink_to(self):
P = self.cls(BASE)
P = self.cls(self.base)
target = P / 'fileA'
size = target.stat().st_size
# linking to another path.
@ -1209,14 +1204,14 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertTrue(target.exists())
# Linking to a str of a relative path.
link2 = P / 'dirA' / 'fileAAA'
target2 = rel_join('fileA')
target2 = self.pathmod.join(TESTFN, 'fileA')
link2.hardlink_to(target2)
self.assertEqual(os.stat(target2).st_size, size)
self.assertTrue(link2.exists())
@unittest.skipIf(hasattr(os, "link"), "os.link() is present")
def test_hardlink_to_unsupported(self):
P = self.cls(BASE)
P = self.cls(self.base)
p = P / 'fileA'
# linking to another path.
q = P / 'dirA' / 'fileAA'
@ -1224,7 +1219,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
q.hardlink_to(p)
def test_rename(self):
P = self.cls(BASE)
P = self.cls(self.base)
p = P / 'fileA'
size = p.stat().st_size
# Renaming to another path.
@ -1234,14 +1229,14 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(q.stat().st_size, size)
self.assertFileNotFound(p.stat)
# Renaming to a str of a relative path.
r = rel_join('fileAAA')
r = self.pathmod.join(TESTFN, 'fileAAA')
renamed_q = q.rename(r)
self.assertEqual(renamed_q, self.cls(r))
self.assertEqual(os.stat(r).st_size, size)
self.assertFileNotFound(q.stat)
def test_replace(self):
P = self.cls(BASE)
P = self.cls(self.base)
p = P / 'fileA'
size = p.stat().st_size
# Replacing a non-existing path.
@ -1251,14 +1246,14 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(q.stat().st_size, size)
self.assertFileNotFound(p.stat)
# Replacing another (existing) path.
r = rel_join('dirB', 'fileB')
r = self.pathmod.join(TESTFN, 'dirB', 'fileB')
replaced_q = q.replace(r)
self.assertEqual(replaced_q, self.cls(r))
self.assertEqual(os.stat(r).st_size, size)
self.assertFileNotFound(q.stat)
def test_touch_common(self):
P = self.cls(BASE)
P = self.cls(self.base)
p = P / 'newfileA'
self.assertFalse(p.exists())
p.touch()
@ -1282,14 +1277,14 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertRaises(OSError, p.touch, exist_ok=False)
def test_touch_nochange(self):
P = self.cls(BASE)
P = self.cls(self.base)
p = P / 'fileA'
p.touch()
with p.open('rb') as f:
self.assertEqual(f.read().strip(), b"this is file A")
def test_mkdir(self):
P = self.cls(BASE)
P = self.cls(self.base)
p = P / 'newdirA'
self.assertFalse(p.exists())
p.mkdir()
@ -1301,7 +1296,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
def test_mkdir_parents(self):
# Creating a chain of directories.
p = self.cls(BASE, 'newdirB', 'newdirC')
p = self.cls(self.base, 'newdirB', 'newdirC')
self.assertFalse(p.exists())
with self.assertRaises(OSError) as cm:
p.mkdir()
@ -1314,7 +1309,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(cm.exception.errno, errno.EEXIST)
# Test `mode` arg.
mode = stat.S_IMODE(p.stat().st_mode) # Default mode.
p = self.cls(BASE, 'newdirD', 'newdirE')
p = self.cls(self.base, 'newdirD', 'newdirE')
p.mkdir(0o555, parents=True)
self.assertTrue(p.exists())
self.assertTrue(p.is_dir())
@ -1325,7 +1320,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(stat.S_IMODE(p.parent.stat().st_mode), mode)
def test_mkdir_exist_ok(self):
p = self.cls(BASE, 'dirB')
p = self.cls(self.base, 'dirB')
st_ctime_first = p.stat().st_ctime
self.assertTrue(p.exists())
self.assertTrue(p.is_dir())
@ -1337,7 +1332,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(p.stat().st_ctime, st_ctime_first)
def test_mkdir_exist_ok_with_parent(self):
p = self.cls(BASE, 'dirC')
p = self.cls(self.base, 'dirC')
self.assertTrue(p.exists())
with self.assertRaises(FileExistsError) as cm:
p.mkdir()
@ -1371,7 +1366,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
(p / 'child' / 'path').mkdir(parents=True)
def test_mkdir_with_child_file(self):
p = self.cls(BASE, 'dirB', 'fileB')
p = self.cls(self.base, 'dirB', 'fileB')
self.assertTrue(p.exists())
# An exception is raised when the last path component is an existing
# regular file, regardless of whether exist_ok is true or not.
@ -1383,7 +1378,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(cm.exception.errno, errno.EEXIST)
def test_mkdir_no_parents_file(self):
p = self.cls(BASE, 'fileA')
p = self.cls(self.base, 'fileA')
self.assertTrue(p.exists())
# An exception is raised when the last path component is an existing
# regular file, regardless of whether exist_ok is true or not.
@ -1396,7 +1391,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
def test_mkdir_concurrent_parent_creation(self):
for pattern_num in range(32):
p = self.cls(BASE, 'dirCPC%d' % pattern_num)
p = self.cls(self.base, 'dirCPC%d' % pattern_num)
self.assertFalse(p.exists())
real_mkdir = os.mkdir
@ -1427,7 +1422,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
def test_symlink_to(self):
if not self.can_symlink:
self.skipTest("symlinks required")
P = self.cls(BASE)
P = self.cls(self.base)
target = P / 'fileA'
# Symlinking a path target.
link = P / 'dirA' / 'linkAA'
@ -1451,7 +1446,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
@unittest.skipIf(hasattr(os, "symlink"), "os.symlink() is present")
def test_symlink_to_unsupported(self):
P = self.cls(BASE)
P = self.cls(self.base)
p = P / 'fileA'
# linking to another path.
q = P / 'dirA' / 'fileAA'
@ -1459,7 +1454,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
q.symlink_to(p)
def test_is_junction(self):
P = self.cls(BASE)
P = self.cls(self.base)
with mock.patch.object(P.pathmod, 'isjunction'):
self.assertEqual(P.is_junction(), P.pathmod.isjunction.return_value)
@ -1469,7 +1464,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
@unittest.skipIf(sys.platform == "vxworks",
"fifo requires special path on VxWorks")
def test_is_fifo_true(self):
P = self.cls(BASE, 'myfifo')
P = self.cls(self.base, 'myfifo')
try:
os.mkfifo(str(P))
except PermissionError as e:
@ -1477,8 +1472,8 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertTrue(P.is_fifo())
self.assertFalse(P.is_socket())
self.assertFalse(P.is_file())
self.assertIs(self.cls(BASE, 'myfifo\udfff').is_fifo(), False)
self.assertIs(self.cls(BASE, 'myfifo\x00').is_fifo(), False)
self.assertIs(self.cls(self.base, 'myfifo\udfff').is_fifo(), False)
self.assertIs(self.cls(self.base, 'myfifo\x00').is_fifo(), False)
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
@unittest.skipIf(
@ -1488,7 +1483,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
is_wasi, "Cannot create socket on WASI."
)
def test_is_socket_true(self):
P = self.cls(BASE, 'mysock')
P = self.cls(self.base, 'mysock')
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.addCleanup(sock.close)
try:
@ -1500,8 +1495,8 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertTrue(P.is_socket())
self.assertFalse(P.is_fifo())
self.assertFalse(P.is_file())
self.assertIs(self.cls(BASE, 'mysock\udfff').is_socket(), False)
self.assertIs(self.cls(BASE, 'mysock\x00').is_socket(), False)
self.assertIs(self.cls(self.base, 'mysock\udfff').is_socket(), False)
self.assertIs(self.cls(self.base, 'mysock\x00').is_socket(), False)
def test_is_char_device_true(self):
# Under Unix, /dev/null should generally be a char device.
@ -1573,7 +1568,7 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
def test_walk_many_open_files(self):
depth = 30
base = self.cls(BASE, 'deep')
base = self.cls(self.base, 'deep')
path = self.cls(base, *(['d']*depth))
path.mkdir(parents=True)
@ -1615,15 +1610,15 @@ class PosixPathTest(PathTest, PurePosixPathTest):
def test_open_mode(self):
old_mask = os.umask(0)
self.addCleanup(os.umask, old_mask)
p = self.cls(BASE)
p = self.cls(self.base)
with (p / 'new_file').open('wb'):
pass
st = os.stat(join('new_file'))
st = os.stat(self.pathmod.join(self.base, 'new_file'))
self.assertEqual(stat.S_IMODE(st.st_mode), 0o666)
os.umask(0o022)
with (p / 'other_new_file').open('wb'):
pass
st = os.stat(join('other_new_file'))
st = os.stat(self.pathmod.join(self.base, 'other_new_file'))
self.assertEqual(stat.S_IMODE(st.st_mode), 0o644)
def test_resolve_root(self):
@ -1642,31 +1637,31 @@ class PosixPathTest(PathTest, PurePosixPathTest):
def test_touch_mode(self):
old_mask = os.umask(0)
self.addCleanup(os.umask, old_mask)
p = self.cls(BASE)
p = self.cls(self.base)
(p / 'new_file').touch()
st = os.stat(join('new_file'))
st = os.stat(self.pathmod.join(self.base, 'new_file'))
self.assertEqual(stat.S_IMODE(st.st_mode), 0o666)
os.umask(0o022)
(p / 'other_new_file').touch()
st = os.stat(join('other_new_file'))
st = os.stat(self.pathmod.join(self.base, 'other_new_file'))
self.assertEqual(stat.S_IMODE(st.st_mode), 0o644)
(p / 'masked_new_file').touch(mode=0o750)
st = os.stat(join('masked_new_file'))
st = os.stat(self.pathmod.join(self.base, 'masked_new_file'))
self.assertEqual(stat.S_IMODE(st.st_mode), 0o750)
def test_glob(self):
P = self.cls
p = P(BASE)
p = P(self.base)
given = set(p.glob("FILEa"))
expect = set() if not os_helper.fs_is_case_insensitive(BASE) else given
expect = set() if not os_helper.fs_is_case_insensitive(self.base) else given
self.assertEqual(given, expect)
self.assertEqual(set(p.glob("FILEa*")), set())
def test_rglob(self):
P = self.cls
p = P(BASE, "dirC")
p = P(self.base, "dirC")
given = set(p.rglob("FILEd"))
expect = set() if not os_helper.fs_is_case_insensitive(BASE) else given
expect = set() if not os_helper.fs_is_case_insensitive(self.base) else given
self.assertEqual(given, expect)
self.assertEqual(set(p.rglob("FILEd*")), set())
@ -1797,17 +1792,17 @@ class WindowsPathTest(PathTest, PureWindowsPathTest):
self.assertEqual(str(P('a', 'b', 'c').absolute()),
os.path.join(share, 'a', 'b', 'c'))
drive = os.path.splitdrive(BASE)[0]
with os_helper.change_cwd(BASE):
drive = os.path.splitdrive(self.base)[0]
with os_helper.change_cwd(self.base):
# Relative path with root
self.assertEqual(str(P('\\').absolute()), drive + '\\')
self.assertEqual(str(P('\\foo').absolute()), drive + '\\foo')
# Relative path on current drive
self.assertEqual(str(P(drive).absolute()), BASE)
self.assertEqual(str(P(drive + 'foo').absolute()), os.path.join(BASE, 'foo'))
self.assertEqual(str(P(drive).absolute()), self.base)
self.assertEqual(str(P(drive + 'foo').absolute()), os.path.join(self.base, 'foo'))
with os_helper.subst_drive(BASE) as other_drive:
with os_helper.subst_drive(self.base) as other_drive:
# Set the working directory on the substitute drive
saved_cwd = os.getcwd()
other_cwd = f'{other_drive}\\dirA'
@ -1820,18 +1815,18 @@ class WindowsPathTest(PathTest, PureWindowsPathTest):
def test_glob(self):
P = self.cls
p = P(BASE)
self.assertEqual(set(p.glob("FILEa")), { P(BASE, "fileA") })
self.assertEqual(set(p.glob("*a\\")), { P(BASE, "dirA/") })
self.assertEqual(set(p.glob("F*a")), { P(BASE, "fileA") })
p = P(self.base)
self.assertEqual(set(p.glob("FILEa")), { P(self.base, "fileA") })
self.assertEqual(set(p.glob("*a\\")), { P(self.base, "dirA/") })
self.assertEqual(set(p.glob("F*a")), { P(self.base, "fileA") })
self.assertEqual(set(map(str, p.glob("FILEa"))), {f"{p}\\fileA"})
self.assertEqual(set(map(str, p.glob("F*a"))), {f"{p}\\fileA"})
def test_rglob(self):
P = self.cls
p = P(BASE, "dirC")
self.assertEqual(set(p.rglob("FILEd")), { P(BASE, "dirC/dirD/fileD") })
self.assertEqual(set(p.rglob("*\\")), { P(BASE, "dirC/dirD/") })
p = P(self.base, "dirC")
self.assertEqual(set(p.rglob("FILEd")), { P(self.base, "dirC/dirD/fileD") })
self.assertEqual(set(p.rglob("*\\")), { P(self.base, "dirC/dirD/") })
self.assertEqual(set(map(str, p.rglob("FILEd"))), {f"{p}\\dirD\\fileD"})
def test_expanduser(self):

View file

@ -18,16 +18,6 @@ class UnsupportedOperationTest(unittest.TestCase):
self.assertTrue(isinstance(pathlib.UnsupportedOperation(), NotImplementedError))
# Make sure any symbolic links in the base test path are resolved.
BASE = os.path.realpath(TESTFN)
join = lambda *x: os.path.join(BASE, *x)
only_nt = unittest.skipIf(os.name != 'nt',
'test requires a Windows-compatible system')
only_posix = unittest.skipIf(os.name == 'nt',
'test requires a POSIX-compatible system')
#
# Tests for the pure classes.
#
@ -62,6 +52,9 @@ class DummyPurePath(pathlib._abc.PurePathBase):
class DummyPurePathTest(unittest.TestCase):
cls = DummyPurePath
# Make sure any symbolic links in the base test path are resolved.
base = os.path.realpath(TESTFN)
# Keys are canonical paths, values are list of tuples of arguments
# supposed to produce equal paths.
equivalences = {
@ -859,7 +852,7 @@ class DummyPathTest(DummyPurePathTest):
cls = DummyPath
can_symlink = False
# (BASE)
# (self.base)
# |
# |-- brokenLink -> non-existing
# |-- dirA
@ -882,7 +875,7 @@ class DummyPathTest(DummyPurePathTest):
def setUp(self):
super().setUp()
pathmod = self.cls.pathmod
p = self.cls(BASE)
p = self.cls(self.base)
p.mkdir(parents=True)
p.joinpath('dirA').mkdir()
p.joinpath('dirB').mkdir()
@ -914,7 +907,7 @@ class DummyPathTest(DummyPurePathTest):
cls._symlinks.clear()
def tempdir(self):
path = self.cls(BASE).with_name('tmp-dirD')
path = self.cls(self.base).with_name('tmp-dirD')
path.mkdir()
return path
@ -927,8 +920,8 @@ class DummyPathTest(DummyPurePathTest):
self.assertEqual(os.path.normcase(path_a), os.path.normcase(path_b))
def test_samefile(self):
fileA_path = os.path.join(BASE, 'fileA')
fileB_path = os.path.join(BASE, 'dirB', 'fileB')
fileA_path = os.path.join(self.base, 'fileA')
fileB_path = os.path.join(self.base, 'dirB', 'fileB')
p = self.cls(fileA_path)
pp = self.cls(fileA_path)
q = self.cls(fileB_path)
@ -937,7 +930,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertFalse(p.samefile(fileB_path))
self.assertFalse(p.samefile(q))
# Test the non-existent file case
non_existent = os.path.join(BASE, 'foo')
non_existent = os.path.join(self.base, 'foo')
r = self.cls(non_existent)
self.assertRaises(FileNotFoundError, p.samefile, r)
self.assertRaises(FileNotFoundError, p.samefile, non_existent)
@ -953,7 +946,7 @@ class DummyPathTest(DummyPurePathTest):
def test_exists(self):
P = self.cls
p = P(BASE)
p = P(self.base)
self.assertIs(True, p.exists())
self.assertIs(True, (p / 'dirA').exists())
self.assertIs(True, (p / 'fileA').exists())
@ -967,11 +960,11 @@ class DummyPathTest(DummyPurePathTest):
self.assertIs(True, (p / 'brokenLink').exists(follow_symlinks=False))
self.assertIs(False, (p / 'foo').exists())
self.assertIs(False, P('/xyzzy').exists())
self.assertIs(False, P(BASE + '\udfff').exists())
self.assertIs(False, P(BASE + '\x00').exists())
self.assertIs(False, P(self.base + '\udfff').exists())
self.assertIs(False, P(self.base + '\x00').exists())
def test_open_common(self):
p = self.cls(BASE)
p = self.cls(self.base)
with (p / 'fileA').open('r') as f:
self.assertIsInstance(f, io.TextIOBase)
self.assertEqual(f.read(), "this is file A\n")
@ -980,7 +973,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertEqual(f.read().strip(), b"this is file A")
def test_read_write_bytes(self):
p = self.cls(BASE)
p = self.cls(self.base)
(p / 'fileA').write_bytes(b'abcdefg')
self.assertEqual((p / 'fileA').read_bytes(), b'abcdefg')
# Check that trying to write str does not truncate the file.
@ -988,7 +981,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertEqual((p / 'fileA').read_bytes(), b'abcdefg')
def test_read_write_text(self):
p = self.cls(BASE)
p = self.cls(self.base)
(p / 'fileA').write_text('äbcdefg', encoding='latin-1')
self.assertEqual((p / 'fileA').read_text(
encoding='utf-8', errors='ignore'), 'bcdefg')
@ -997,7 +990,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertEqual((p / 'fileA').read_text(encoding='latin-1'), 'äbcdefg')
def test_read_text_with_newlines(self):
p = self.cls(BASE)
p = self.cls(self.base)
# Check that `\n` character change nothing
(p / 'fileA').write_bytes(b'abcde\r\nfghlk\n\rmnopq')
self.assertEqual((p / 'fileA').read_text(newline='\n'),
@ -1012,7 +1005,7 @@ class DummyPathTest(DummyPurePathTest):
'abcde\r\nfghlk\n\rmnopq')
def test_write_text_with_newlines(self):
p = self.cls(BASE)
p = self.cls(self.base)
# Check that `\n` character change nothing
(p / 'fileA').write_text('abcde\r\nfghlk\n\rmnopq', newline='\n')
self.assertEqual((p / 'fileA').read_bytes(),
@ -1033,27 +1026,27 @@ class DummyPathTest(DummyPurePathTest):
def test_iterdir(self):
P = self.cls
p = P(BASE)
p = P(self.base)
it = p.iterdir()
paths = set(it)
expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA']
if self.can_symlink:
expected += ['linkA', 'linkB', 'brokenLink', 'brokenLinkLoop']
self.assertEqual(paths, { P(BASE, q) for q in expected })
self.assertEqual(paths, { P(self.base, q) for q in expected })
def test_iterdir_symlink(self):
if not self.can_symlink:
self.skipTest("symlinks required")
# __iter__ on a symlink to a directory.
P = self.cls
p = P(BASE, 'linkB')
p = P(self.base, 'linkB')
paths = set(p.iterdir())
expected = { P(BASE, 'linkB', q) for q in ['fileB', 'linkD'] }
expected = { P(self.base, 'linkB', q) for q in ['fileB', 'linkD'] }
self.assertEqual(paths, expected)
def test_iterdir_nodir(self):
# __iter__ on something that is not a directory.
p = self.cls(BASE, 'fileA')
p = self.cls(self.base, 'fileA')
with self.assertRaises(OSError) as cm:
p.iterdir()
# ENOENT or EINVAL under Windows, ENOTDIR otherwise
@ -1063,9 +1056,9 @@ class DummyPathTest(DummyPurePathTest):
def test_glob_common(self):
def _check(glob, expected):
self.assertEqual(set(glob), { P(BASE, q) for q in expected })
self.assertEqual(set(glob), { P(self.base, q) for q in expected })
P = self.cls
p = P(BASE)
p = P(self.base)
it = p.glob("fileA")
self.assertIsInstance(it, collections.abc.Iterator)
_check(it, ["fileA"])
@ -1101,9 +1094,9 @@ class DummyPathTest(DummyPurePathTest):
P = self.cls
def _check(path, pattern, case_sensitive, expected):
actual = {str(q) for q in path.glob(pattern, case_sensitive=case_sensitive)}
expected = {str(P(BASE, q)) for q in expected}
expected = {str(P(self.base, q)) for q in expected}
self.assertEqual(actual, expected)
path = P(BASE)
path = P(self.base)
_check(path, "DIRB/FILE*", True, [])
_check(path, "DIRB/FILE*", False, ["dirB/fileB"])
_check(path, "dirb/file*", True, [])
@ -1115,9 +1108,9 @@ class DummyPathTest(DummyPurePathTest):
def _check(path, glob, expected):
actual = {path for path in path.glob(glob, follow_symlinks=True)
if "linkD" not in path.parent.parts} # exclude symlink loop.
self.assertEqual(actual, { P(BASE, q) for q in expected })
self.assertEqual(actual, { P(self.base, q) for q in expected })
P = self.cls
p = P(BASE)
p = P(self.base)
_check(p, "fileB", [])
_check(p, "dir*/file*", ["dirB/fileB", "dirC/fileC"])
_check(p, "*A", ["dirA", "fileA", "linkA"])
@ -1140,9 +1133,9 @@ class DummyPathTest(DummyPurePathTest):
self.skipTest("symlinks required")
def _check(path, glob, expected):
actual = {path for path in path.glob(glob, follow_symlinks=False)}
self.assertEqual(actual, { P(BASE, q) for q in expected })
self.assertEqual(actual, { P(self.base, q) for q in expected })
P = self.cls
p = P(BASE)
p = P(self.base)
_check(p, "fileB", [])
_check(p, "dir*/file*", ["dirB/fileB", "dirC/fileC"])
_check(p, "*A", ["dirA", "fileA", "linkA"])
@ -1160,9 +1153,9 @@ class DummyPathTest(DummyPurePathTest):
def test_rglob_common(self):
def _check(glob, expected):
self.assertEqual(set(glob), {P(BASE, q) for q in expected})
self.assertEqual(set(glob), {P(self.base, q) for q in expected})
P = self.cls
p = P(BASE)
p = P(self.base)
it = p.rglob("fileA")
self.assertIsInstance(it, collections.abc.Iterator)
_check(it, ["fileA"])
@ -1187,7 +1180,7 @@ class DummyPathTest(DummyPurePathTest):
])
_check(p.rglob(""), ["./", "dirA/", "dirB/", "dirC/", "dirE/", "dirC/dirD/"])
p = P(BASE, "dirC")
p = P(self.base, "dirC")
_check(p.rglob("*"), ["dirC/fileC", "dirC/novel.txt",
"dirC/dirD", "dirC/dirD/fileD"])
_check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"])
@ -1207,9 +1200,9 @@ class DummyPathTest(DummyPurePathTest):
def _check(path, glob, expected):
actual = {path for path in path.rglob(glob, follow_symlinks=True)
if 'linkD' not in path.parent.parts} # exclude symlink loop.
self.assertEqual(actual, { P(BASE, q) for q in expected })
self.assertEqual(actual, { P(self.base, q) for q in expected })
P = self.cls
p = P(BASE)
p = P(self.base)
_check(p, "fileB", ["dirB/fileB", "dirA/linkC/fileB", "linkB/fileB"])
_check(p, "*/fileA", [])
_check(p, "*/fileB", ["dirB/fileB", "dirA/linkC/fileB", "linkB/fileB"])
@ -1220,7 +1213,7 @@ class DummyPathTest(DummyPurePathTest):
_check(p, "", ["./", "dirA/", "dirA/linkC/", "dirA/linkC/linkD/", "dirB/", "dirB/linkD/",
"dirC/", "dirE/", "dirC/dirD/", "linkB/", "linkB/linkD/"])
p = P(BASE, "dirC")
p = P(self.base, "dirC")
_check(p, "*", ["dirC/fileC", "dirC/novel.txt",
"dirC/dirD", "dirC/dirD/fileD"])
_check(p, "file*", ["dirC/fileC", "dirC/dirD/fileD"])
@ -1236,9 +1229,9 @@ class DummyPathTest(DummyPurePathTest):
self.skipTest("symlinks required")
def _check(path, glob, expected):
actual = {path for path in path.rglob(glob, follow_symlinks=False)}
self.assertEqual(actual, { P(BASE, q) for q in expected })
self.assertEqual(actual, { P(self.base, q) for q in expected })
P = self.cls
p = P(BASE)
p = P(self.base)
_check(p, "fileB", ["dirB/fileB"])
_check(p, "*/fileA", [])
_check(p, "*/fileB", ["dirB/fileB"])
@ -1246,7 +1239,7 @@ class DummyPathTest(DummyPurePathTest):
_check(p, "*/", ["dirA/", "dirB/", "dirC/", "dirC/dirD/", "dirE/"])
_check(p, "", ["./", "dirA/", "dirB/", "dirC/", "dirE/", "dirC/dirD/"])
p = P(BASE, "dirC")
p = P(self.base, "dirC")
_check(p, "*", ["dirC/fileC", "dirC/novel.txt",
"dirC/dirD", "dirC/dirD/fileD"])
_check(p, "file*", ["dirC/fileC", "dirC/dirD/fileD"])
@ -1262,7 +1255,7 @@ class DummyPathTest(DummyPurePathTest):
if not self.can_symlink:
self.skipTest("symlinks required")
P = self.cls
p = P(BASE)
p = P(self.base)
given = set(p.rglob('*'))
expect = {'brokenLink',
'dirA', 'dirA/linkC',
@ -1280,7 +1273,7 @@ class DummyPathTest(DummyPurePathTest):
def test_glob_many_open_files(self):
depth = 30
P = self.cls
p = base = P(BASE) / 'deep'
p = base = P(self.base) / 'deep'
p.mkdir()
for _ in range(depth):
p /= 'd'
@ -1299,30 +1292,30 @@ class DummyPathTest(DummyPurePathTest):
def test_glob_dotdot(self):
# ".." is not special in globs.
P = self.cls
p = P(BASE)
self.assertEqual(set(p.glob("..")), { P(BASE, "..") })
self.assertEqual(set(p.glob("../..")), { P(BASE, "..", "..") })
self.assertEqual(set(p.glob("dirA/..")), { P(BASE, "dirA", "..") })
self.assertEqual(set(p.glob("dirA/../file*")), { P(BASE, "dirA/../fileA") })
p = P(self.base)
self.assertEqual(set(p.glob("..")), { P(self.base, "..") })
self.assertEqual(set(p.glob("../..")), { P(self.base, "..", "..") })
self.assertEqual(set(p.glob("dirA/..")), { P(self.base, "dirA", "..") })
self.assertEqual(set(p.glob("dirA/../file*")), { P(self.base, "dirA/../fileA") })
self.assertEqual(set(p.glob("dirA/../file*/..")), set())
self.assertEqual(set(p.glob("../xyzzy")), set())
self.assertEqual(set(p.glob("xyzzy/..")), set())
self.assertEqual(set(p.glob("/".join([".."] * 50))), { P(BASE, *[".."] * 50)})
self.assertEqual(set(p.glob("/".join([".."] * 50))), { P(self.base, *[".."] * 50)})
def test_glob_permissions(self):
# See bpo-38894
if not self.can_symlink:
self.skipTest("symlinks required")
P = self.cls
base = P(BASE) / 'permissions'
base = P(self.base) / 'permissions'
base.mkdir()
for i in range(100):
link = base / f"link{i}"
if i % 2:
link.symlink_to(P(BASE, "dirE", "nonexistent"))
link.symlink_to(P(self.base, "dirE", "nonexistent"))
else:
link.symlink_to(P(BASE, "dirC"))
link.symlink_to(P(self.base, "dirC"))
self.assertEqual(len(set(base.glob("*"))), 100)
self.assertEqual(len(set(base.glob("*/"))), 50)
@ -1333,7 +1326,7 @@ class DummyPathTest(DummyPurePathTest):
# See gh-87695
if not self.can_symlink:
self.skipTest("symlinks required")
base = self.cls(BASE) / 'long_symlink'
base = self.cls(self.base) / 'long_symlink'
base.mkdir()
bad_link = base / 'bad_link'
bad_link.symlink_to("bad" * 200)
@ -1343,7 +1336,7 @@ class DummyPathTest(DummyPurePathTest):
recursion_limit = 50
# directory_depth > recursion_limit
directory_depth = recursion_limit + 10
base = self.cls(BASE, 'deep')
base = self.cls(self.base, 'deep')
path = base.joinpath(*(['d'] * directory_depth))
path.mkdir(parents=True)
@ -1352,7 +1345,7 @@ class DummyPathTest(DummyPurePathTest):
def test_glob_recursive_no_trailing_slash(self):
P = self.cls
p = P(BASE)
p = P(self.base)
with self.assertWarns(FutureWarning):
p.glob('**')
with self.assertWarns(FutureWarning):
@ -1366,7 +1359,7 @@ class DummyPathTest(DummyPurePathTest):
def test_readlink(self):
if not self.can_symlink:
self.skipTest("symlinks required")
P = self.cls(BASE)
P = self.cls(self.base)
self.assertEqual((P / 'linkA').readlink(), self.cls('fileA'))
self.assertEqual((P / 'brokenLink').readlink(),
self.cls('non-existing'))
@ -1377,7 +1370,7 @@ class DummyPathTest(DummyPurePathTest):
@unittest.skipIf(hasattr(os, "readlink"), "os.readlink() is present")
def test_readlink_unsupported(self):
P = self.cls(BASE)
P = self.cls(self.base)
p = P / 'fileA'
with self.assertRaises(pathlib.UnsupportedOperation):
q.readlink(p)
@ -1393,53 +1386,53 @@ class DummyPathTest(DummyPurePathTest):
if not self.can_symlink:
self.skipTest("symlinks required")
P = self.cls
p = P(BASE, 'foo')
p = P(self.base, 'foo')
with self.assertRaises(OSError) as cm:
p.resolve(strict=True)
self.assertEqual(cm.exception.errno, errno.ENOENT)
# Non-strict
self.assertEqualNormCase(str(p.resolve(strict=False)),
os.path.join(BASE, 'foo'))
p = P(BASE, 'foo', 'in', 'spam')
os.path.join(self.base, 'foo'))
p = P(self.base, 'foo', 'in', 'spam')
self.assertEqualNormCase(str(p.resolve(strict=False)),
os.path.join(BASE, 'foo', 'in', 'spam'))
p = P(BASE, '..', 'foo', 'in', 'spam')
os.path.join(self.base, 'foo', 'in', 'spam'))
p = P(self.base, '..', 'foo', 'in', 'spam')
self.assertEqualNormCase(str(p.resolve(strict=False)),
os.path.abspath(os.path.join('foo', 'in', 'spam')))
# These are all relative symlinks.
p = P(BASE, 'dirB', 'fileB')
p = P(self.base, 'dirB', 'fileB')
self._check_resolve_relative(p, p)
p = P(BASE, 'linkA')
self._check_resolve_relative(p, P(BASE, 'fileA'))
p = P(BASE, 'dirA', 'linkC', 'fileB')
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB'))
p = P(BASE, 'dirB', 'linkD', 'fileB')
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB'))
p = P(self.base, 'linkA')
self._check_resolve_relative(p, P(self.base, 'fileA'))
p = P(self.base, 'dirA', 'linkC', 'fileB')
self._check_resolve_relative(p, P(self.base, 'dirB', 'fileB'))
p = P(self.base, 'dirB', 'linkD', 'fileB')
self._check_resolve_relative(p, P(self.base, 'dirB', 'fileB'))
# Non-strict
p = P(BASE, 'dirA', 'linkC', 'fileB', 'foo', 'in', 'spam')
self._check_resolve_relative(p, P(BASE, 'dirB', 'fileB', 'foo', 'in',
p = P(self.base, 'dirA', 'linkC', 'fileB', 'foo', 'in', 'spam')
self._check_resolve_relative(p, P(self.base, 'dirB', 'fileB', 'foo', 'in',
'spam'), False)
p = P(BASE, 'dirA', 'linkC', '..', 'foo', 'in', 'spam')
p = P(self.base, 'dirA', 'linkC', '..', 'foo', 'in', 'spam')
if os.name == 'nt' and isinstance(p, pathlib.Path):
# In Windows, if linkY points to dirB, 'dirA\linkY\..'
# resolves to 'dirA' without resolving linkY first.
self._check_resolve_relative(p, P(BASE, 'dirA', 'foo', 'in',
self._check_resolve_relative(p, P(self.base, 'dirA', 'foo', 'in',
'spam'), False)
else:
# In Posix, if linkY points to dirB, 'dirA/linkY/..'
# resolves to 'dirB/..' first before resolving to parent of dirB.
self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False)
self._check_resolve_relative(p, P(self.base, 'foo', 'in', 'spam'), False)
# Now create absolute symlinks.
d = self.tempdir()
P(BASE, 'dirA', 'linkX').symlink_to(d)
P(BASE, str(d), 'linkY').symlink_to(join('dirB'))
p = P(BASE, 'dirA', 'linkX', 'linkY', 'fileB')
self._check_resolve_absolute(p, P(BASE, 'dirB', 'fileB'))
P(self.base, 'dirA', 'linkX').symlink_to(d)
P(self.base, str(d), 'linkY').symlink_to(self.pathmod.join(self.base, 'dirB'))
p = P(self.base, 'dirA', 'linkX', 'linkY', 'fileB')
self._check_resolve_absolute(p, P(self.base, 'dirB', 'fileB'))
# Non-strict
p = P(BASE, 'dirA', 'linkX', 'linkY', 'foo', 'in', 'spam')
self._check_resolve_relative(p, P(BASE, 'dirB', 'foo', 'in', 'spam'),
p = P(self.base, 'dirA', 'linkX', 'linkY', 'foo', 'in', 'spam')
self._check_resolve_relative(p, P(self.base, 'dirB', 'foo', 'in', 'spam'),
False)
p = P(BASE, 'dirA', 'linkX', 'linkY', '..', 'foo', 'in', 'spam')
p = P(self.base, 'dirA', 'linkX', 'linkY', '..', 'foo', 'in', 'spam')
if os.name == 'nt' and isinstance(p, pathlib.Path):
# In Windows, if linkY points to dirB, 'dirA\linkY\..'
# resolves to 'dirA' without resolving linkY first.
@ -1447,13 +1440,13 @@ class DummyPathTest(DummyPurePathTest):
else:
# In Posix, if linkY points to dirB, 'dirA/linkY/..'
# resolves to 'dirB/..' first before resolving to parent of dirB.
self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False)
self._check_resolve_relative(p, P(self.base, 'foo', 'in', 'spam'), False)
def test_resolve_dot(self):
# See http://web.archive.org/web/20200623062557/https://bitbucket.org/pitrou/pathlib/issues/9/
if not self.can_symlink:
self.skipTest("symlinks required")
p = self.cls(BASE)
p = self.cls(self.base)
p.joinpath('0').symlink_to('.', target_is_directory=True)
p.joinpath('1').symlink_to(os.path.join('0', '0'), target_is_directory=True)
p.joinpath('2').symlink_to(os.path.join('1', '1'), target_is_directory=True)
@ -1476,30 +1469,30 @@ class DummyPathTest(DummyPurePathTest):
if os.name == 'nt' and issubclass(self.cls, pathlib.Path):
self.skipTest("symlink loops work differently with concrete Windows paths")
# Loops with relative symlinks.
self.cls(BASE, 'linkX').symlink_to('linkX/inside')
self._check_symlink_loop(BASE, 'linkX')
self.cls(BASE, 'linkY').symlink_to('linkY')
self._check_symlink_loop(BASE, 'linkY')
self.cls(BASE, 'linkZ').symlink_to('linkZ/../linkZ')
self._check_symlink_loop(BASE, 'linkZ')
self.cls(self.base, 'linkX').symlink_to('linkX/inside')
self._check_symlink_loop(self.base, 'linkX')
self.cls(self.base, 'linkY').symlink_to('linkY')
self._check_symlink_loop(self.base, 'linkY')
self.cls(self.base, 'linkZ').symlink_to('linkZ/../linkZ')
self._check_symlink_loop(self.base, 'linkZ')
# Non-strict
p = self.cls(BASE, 'linkZ', 'foo')
p = self.cls(self.base, 'linkZ', 'foo')
self.assertEqual(p.resolve(strict=False), p)
# Loops with absolute symlinks.
self.cls(BASE, 'linkU').symlink_to(join('linkU/inside'))
self._check_symlink_loop(BASE, 'linkU')
self.cls(BASE, 'linkV').symlink_to(join('linkV'))
self._check_symlink_loop(BASE, 'linkV')
self.cls(BASE, 'linkW').symlink_to(join('linkW/../linkW'))
self._check_symlink_loop(BASE, 'linkW')
self.cls(self.base, 'linkU').symlink_to(self.pathmod.join(self.base, 'linkU/inside'))
self._check_symlink_loop(self.base, 'linkU')
self.cls(self.base, 'linkV').symlink_to(self.pathmod.join(self.base, 'linkV'))
self._check_symlink_loop(self.base, 'linkV')
self.cls(self.base, 'linkW').symlink_to(self.pathmod.join(self.base, 'linkW/../linkW'))
self._check_symlink_loop(self.base, 'linkW')
# Non-strict
q = self.cls(BASE, 'linkW', 'foo')
q = self.cls(self.base, 'linkW', 'foo')
self.assertEqual(q.resolve(strict=False), q)
def test_stat(self):
statA = self.cls(BASE).joinpath('fileA').stat()
statB = self.cls(BASE).joinpath('dirB', 'fileB').stat()
statC = self.cls(BASE).joinpath('dirC').stat()
statA = self.cls(self.base).joinpath('fileA').stat()
statB = self.cls(self.base).joinpath('dirB', 'fileB').stat()
statC = self.cls(self.base).joinpath('dirC').stat()
# st_mode: files are the same, directory differs.
self.assertIsInstance(statA.st_mode, int)
self.assertEqual(statA.st_mode, statB.st_mode)
@ -1519,29 +1512,29 @@ class DummyPathTest(DummyPurePathTest):
def test_stat_no_follow_symlinks(self):
if not self.can_symlink:
self.skipTest("symlinks required")
p = self.cls(BASE) / 'linkA'
p = self.cls(self.base) / 'linkA'
st = p.stat()
self.assertNotEqual(st, p.stat(follow_symlinks=False))
def test_stat_no_follow_symlinks_nosymlink(self):
p = self.cls(BASE) / 'fileA'
p = self.cls(self.base) / 'fileA'
st = p.stat()
self.assertEqual(st, p.stat(follow_symlinks=False))
def test_lstat(self):
if not self.can_symlink:
self.skipTest("symlinks required")
p = self.cls(BASE)/ 'linkA'
p = self.cls(self.base)/ 'linkA'
st = p.stat()
self.assertNotEqual(st, p.lstat())
def test_lstat_nosymlink(self):
p = self.cls(BASE) / 'fileA'
p = self.cls(self.base) / 'fileA'
st = p.stat()
self.assertEqual(st, p.lstat())
def test_is_dir(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertTrue((P / 'dirA').is_dir())
self.assertFalse((P / 'fileA').is_dir())
self.assertFalse((P / 'non-existing').is_dir())
@ -1554,7 +1547,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertFalse((P / 'dirA\x00').is_dir())
def test_is_dir_no_follow_symlinks(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertTrue((P / 'dirA').is_dir(follow_symlinks=False))
self.assertFalse((P / 'fileA').is_dir(follow_symlinks=False))
self.assertFalse((P / 'non-existing').is_dir(follow_symlinks=False))
@ -1567,7 +1560,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertFalse((P / 'dirA\x00').is_dir(follow_symlinks=False))
def test_is_file(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertTrue((P / 'fileA').is_file())
self.assertFalse((P / 'dirA').is_file())
self.assertFalse((P / 'non-existing').is_file())
@ -1580,7 +1573,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertFalse((P / 'fileA\x00').is_file())
def test_is_file_no_follow_symlinks(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertTrue((P / 'fileA').is_file(follow_symlinks=False))
self.assertFalse((P / 'dirA').is_file(follow_symlinks=False))
self.assertFalse((P / 'non-existing').is_file(follow_symlinks=False))
@ -1593,7 +1586,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertFalse((P / 'fileA\x00').is_file(follow_symlinks=False))
def test_is_mount(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertFalse((P / 'fileA').is_mount())
self.assertFalse((P / 'dirA').is_mount())
self.assertFalse((P / 'non-existing').is_mount())
@ -1602,7 +1595,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertFalse((P / 'linkA').is_mount())
def test_is_symlink(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertFalse((P / 'fileA').is_symlink())
self.assertFalse((P / 'dirA').is_symlink())
self.assertFalse((P / 'non-existing').is_symlink())
@ -1618,7 +1611,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertIs((P / 'linkA\x00').is_file(), False)
def test_is_junction_false(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertFalse((P / 'fileA').is_junction())
self.assertFalse((P / 'dirA').is_junction())
self.assertFalse((P / 'non-existing').is_junction())
@ -1627,7 +1620,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertFalse((P / 'fileA\x00').is_junction())
def test_is_fifo_false(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertFalse((P / 'fileA').is_fifo())
self.assertFalse((P / 'dirA').is_fifo())
self.assertFalse((P / 'non-existing').is_fifo())
@ -1636,7 +1629,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertIs((P / 'fileA\x00').is_fifo(), False)
def test_is_socket_false(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertFalse((P / 'fileA').is_socket())
self.assertFalse((P / 'dirA').is_socket())
self.assertFalse((P / 'non-existing').is_socket())
@ -1645,7 +1638,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertIs((P / 'fileA\x00').is_socket(), False)
def test_is_block_device_false(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertFalse((P / 'fileA').is_block_device())
self.assertFalse((P / 'dirA').is_block_device())
self.assertFalse((P / 'non-existing').is_block_device())
@ -1654,7 +1647,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertIs((P / 'fileA\x00').is_block_device(), False)
def test_is_char_device_false(self):
P = self.cls(BASE)
P = self.cls(self.base)
self.assertFalse((P / 'fileA').is_char_device())
self.assertFalse((P / 'dirA').is_char_device())
self.assertFalse((P / 'non-existing').is_char_device())
@ -1663,7 +1656,7 @@ class DummyPathTest(DummyPurePathTest):
self.assertIs((P / 'fileA\x00').is_char_device(), False)
def test_pickling_common(self):
p = self.cls(BASE, 'fileA')
p = self.cls(self.base, 'fileA')
for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
dumped = pickle.dumps(p, proto)
pp = pickle.loads(dumped)
@ -1683,7 +1676,7 @@ class DummyPathTest(DummyPurePathTest):
self.skipTest("symlinks required")
# Test solving a non-looping chain of symlinks (issue #19887).
P = self.cls(BASE)
P = self.cls(self.base)
P.joinpath('link1').symlink_to(os.path.join('link0', 'link0'), target_is_directory=True)
P.joinpath('link2').symlink_to(os.path.join('link1', 'link1'), target_is_directory=True)
P.joinpath('link3').symlink_to(os.path.join('link2', 'link2'), target_is_directory=True)
@ -1692,16 +1685,16 @@ class DummyPathTest(DummyPurePathTest):
# Resolve absolute paths.
p = (P / 'link0').resolve()
self.assertEqual(p, P)
self.assertEqualNormCase(str(p), BASE)
self.assertEqualNormCase(str(p), self.base)
p = (P / 'link1').resolve()
self.assertEqual(p, P)
self.assertEqualNormCase(str(p), BASE)
self.assertEqualNormCase(str(p), self.base)
p = (P / 'link2').resolve()
self.assertEqual(p, P)
self.assertEqualNormCase(str(p), BASE)
self.assertEqualNormCase(str(p), self.base)
p = (P / 'link3').resolve()
self.assertEqual(p, P)
self.assertEqualNormCase(str(p), BASE)
self.assertEqualNormCase(str(p), self.base)
# Resolve relative paths.
try:
@ -1709,25 +1702,25 @@ class DummyPathTest(DummyPurePathTest):
except pathlib.UnsupportedOperation:
return
old_path = os.getcwd()
os.chdir(BASE)
os.chdir(self.base)
try:
p = self.cls('link0').resolve()
self.assertEqual(p, P)
self.assertEqualNormCase(str(p), BASE)
self.assertEqualNormCase(str(p), self.base)
p = self.cls('link1').resolve()
self.assertEqual(p, P)
self.assertEqualNormCase(str(p), BASE)
self.assertEqualNormCase(str(p), self.base)
p = self.cls('link2').resolve()
self.assertEqual(p, P)
self.assertEqualNormCase(str(p), BASE)
self.assertEqualNormCase(str(p), self.base)
p = self.cls('link3').resolve()
self.assertEqual(p, P)
self.assertEqualNormCase(str(p), BASE)
self.assertEqualNormCase(str(p), self.base)
finally:
os.chdir(old_path)
def test_complex_symlinks_absolute(self):
self._check_complex_symlinks(BASE)
self._check_complex_symlinks(self.base)
def test_complex_symlinks_relative(self):
self._check_complex_symlinks('.')
@ -1750,7 +1743,7 @@ class DummyPathTest(DummyPurePathTest):
# broken_link2
# TEST2/
# tmp4 a lone file
self.walk_path = self.cls(BASE, "TEST1")
self.walk_path = self.cls(self.base, "TEST1")
self.sub1_path = self.walk_path / "SUB1"
self.sub11_path = self.sub1_path / "SUB11"
self.sub2_path = self.walk_path / "SUB2"
@ -1758,8 +1751,8 @@ class DummyPathTest(DummyPurePathTest):
tmp2_path = self.sub1_path / "tmp2"
tmp3_path = self.sub2_path / "tmp3"
self.link_path = self.sub2_path / "link"
t2_path = self.cls(BASE, "TEST2")
tmp4_path = self.cls(BASE, "TEST2", "tmp4")
t2_path = self.cls(self.base, "TEST2")
tmp4_path = self.cls(self.base, "TEST2", "tmp4")
broken_link_path = self.sub2_path / "broken_link"
broken_link2_path = self.sub2_path / "broken_link2"
@ -1886,7 +1879,7 @@ class DummyPathTest(DummyPurePathTest):
recursion_limit = 40
# directory_depth > recursion_limit
directory_depth = recursion_limit + 10
base = self.cls(BASE, 'deep')
base = self.cls(self.base, 'deep')
path = base.joinpath(*(['d'] * directory_depth))
path.mkdir(parents=True)