if not stat.S_ISLNK(st.st_mode):
path = newpath
continue
+ if newpath in seen:
+ # Already seen this path
+ path = seen[newpath]
+ if path is not None:
+ # use cached value
+ continue
+ # The symlink is not resolved, so we must have a symlink loop.
+ if strict:
+ # Raise OSError(errno.ELOOP)
+ os.stat(newpath)
+ path = newpath
+ continue
+ target = os.readlink(newpath)
except OSError:
if strict:
raise
path = newpath
continue
# Resolve the symbolic link
- if newpath in seen:
- # Already seen this path
- path = seen[newpath]
- if path is not None:
- # use cached value
- continue
- # The symlink is not resolved, so we must have a symlink loop.
- if strict:
- # Raise OSError(errno.ELOOP)
- os.stat(newpath)
- path = newpath
- continue
seen[newpath] = None # not resolved symlink
- target = os.readlink(newpath)
if target.startswith(sep):
# Symlink target is absolute; reset resolved path.
path = sep
safe_rmdir(ABSTFN + "/k")
safe_rmdir(ABSTFN)
+ @os_helper.skip_unless_symlink
+ @skip_if_ABSTFN_contains_backslash
+ @unittest.skipIf(os.chmod not in os.supports_follow_symlinks, "Can't set symlink permissions")
+ def test_realpath_unreadable_symlink(self):
+ try:
+ os.symlink(ABSTFN+"1", ABSTFN)
+ os.chmod(ABSTFN, 0o000, follow_symlinks=False)
+ self.assertEqual(realpath(ABSTFN), ABSTFN)
+ self.assertEqual(realpath(ABSTFN + '/foo'), ABSTFN + '/foo')
+ self.assertEqual(realpath(ABSTFN + '/../foo'), dirname(ABSTFN) + '/foo')
+ self.assertEqual(realpath(ABSTFN + '/foo/..'), ABSTFN)
+ with self.assertRaises(PermissionError):
+ realpath(ABSTFN, strict=True)
+ finally:
+ os.chmod(ABSTFN, 0o755, follow_symlinks=False)
+ os.unlink(ABSTFN)
+
def test_relpath(self):
(real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
try: