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

View file

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