(root)/
Python-3.11.7/
Lib/
test/
test_posixpath.py
       1  import os
       2  import posixpath
       3  import sys
       4  import unittest
       5  from posixpath import realpath, abspath, dirname, basename
       6  from test import test_genericpath
       7  from test.support import import_helper
       8  from test.support import os_helper
       9  from test.support.os_helper import FakePath
      10  from unittest import mock
      11  
      12  try:
      13      import posix
      14  except ImportError:
      15      posix = None
      16  
      17  
      18  # An absolute path to a temporary filename for testing. We can't rely on TESTFN
      19  # being an absolute path, so we need this.
      20  
      21  ABSTFN = abspath(os_helper.TESTFN)
      22  
      23  def skip_if_ABSTFN_contains_backslash(test):
      24      """
      25      On Windows, posixpath.abspath still returns paths with backslashes
      26      instead of posix forward slashes. If this is the case, several tests
      27      fail, so skip them.
      28      """
      29      found_backslash = '\\' in ABSTFN
      30      msg = "ABSTFN is not a posix path - tests fail"
      31      return [test, unittest.skip(msg)(test)][found_backslash]
      32  
      33  def safe_rmdir(dirname):
      34      try:
      35          os.rmdir(dirname)
      36      except OSError:
      37          pass
      38  
      39  class ESC[4;38;5;81mPosixPathTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      40  
      41      def setUp(self):
      42          self.tearDown()
      43  
      44      def tearDown(self):
      45          for suffix in ["", "1", "2"]:
      46              os_helper.unlink(os_helper.TESTFN + suffix)
      47              safe_rmdir(os_helper.TESTFN + suffix)
      48  
      49      def test_join(self):
      50          self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"),
      51                           "/bar/baz")
      52          self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
      53          self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"),
      54                           "/foo/bar/baz/")
      55  
      56          self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"),
      57                           b"/bar/baz")
      58          self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"),
      59                           b"/foo/bar/baz")
      60          self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"),
      61                           b"/foo/bar/baz/")
      62  
      63      def test_split(self):
      64          self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
      65          self.assertEqual(posixpath.split("/"), ("/", ""))
      66          self.assertEqual(posixpath.split("foo"), ("", "foo"))
      67          self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
      68          self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
      69  
      70          self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
      71          self.assertEqual(posixpath.split(b"/"), (b"/", b""))
      72          self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
      73          self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
      74          self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
      75  
      76      def splitextTest(self, path, filename, ext):
      77          self.assertEqual(posixpath.splitext(path), (filename, ext))
      78          self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
      79          self.assertEqual(posixpath.splitext("abc/" + path),
      80                           ("abc/" + filename, ext))
      81          self.assertEqual(posixpath.splitext("abc.def/" + path),
      82                           ("abc.def/" + filename, ext))
      83          self.assertEqual(posixpath.splitext("/abc.def/" + path),
      84                           ("/abc.def/" + filename, ext))
      85          self.assertEqual(posixpath.splitext(path + "/"),
      86                           (filename + ext + "/", ""))
      87  
      88          path = bytes(path, "ASCII")
      89          filename = bytes(filename, "ASCII")
      90          ext = bytes(ext, "ASCII")
      91  
      92          self.assertEqual(posixpath.splitext(path), (filename, ext))
      93          self.assertEqual(posixpath.splitext(b"/" + path),
      94                           (b"/" + filename, ext))
      95          self.assertEqual(posixpath.splitext(b"abc/" + path),
      96                           (b"abc/" + filename, ext))
      97          self.assertEqual(posixpath.splitext(b"abc.def/" + path),
      98                           (b"abc.def/" + filename, ext))
      99          self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
     100                           (b"/abc.def/" + filename, ext))
     101          self.assertEqual(posixpath.splitext(path + b"/"),
     102                           (filename + ext + b"/", b""))
     103  
     104      def test_splitext(self):
     105          self.splitextTest("foo.bar", "foo", ".bar")
     106          self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
     107          self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
     108          self.splitextTest(".csh.rc", ".csh", ".rc")
     109          self.splitextTest("nodots", "nodots", "")
     110          self.splitextTest(".cshrc", ".cshrc", "")
     111          self.splitextTest("...manydots", "...manydots", "")
     112          self.splitextTest("...manydots.ext", "...manydots", ".ext")
     113          self.splitextTest(".", ".", "")
     114          self.splitextTest("..", "..", "")
     115          self.splitextTest("........", "........", "")
     116          self.splitextTest("", "", "")
     117  
     118      def test_isabs(self):
     119          self.assertIs(posixpath.isabs(""), False)
     120          self.assertIs(posixpath.isabs("/"), True)
     121          self.assertIs(posixpath.isabs("/foo"), True)
     122          self.assertIs(posixpath.isabs("/foo/bar"), True)
     123          self.assertIs(posixpath.isabs("foo/bar"), False)
     124  
     125          self.assertIs(posixpath.isabs(b""), False)
     126          self.assertIs(posixpath.isabs(b"/"), True)
     127          self.assertIs(posixpath.isabs(b"/foo"), True)
     128          self.assertIs(posixpath.isabs(b"/foo/bar"), True)
     129          self.assertIs(posixpath.isabs(b"foo/bar"), False)
     130  
     131      def test_basename(self):
     132          self.assertEqual(posixpath.basename("/foo/bar"), "bar")
     133          self.assertEqual(posixpath.basename("/"), "")
     134          self.assertEqual(posixpath.basename("foo"), "foo")
     135          self.assertEqual(posixpath.basename("////foo"), "foo")
     136          self.assertEqual(posixpath.basename("//foo//bar"), "bar")
     137  
     138          self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
     139          self.assertEqual(posixpath.basename(b"/"), b"")
     140          self.assertEqual(posixpath.basename(b"foo"), b"foo")
     141          self.assertEqual(posixpath.basename(b"////foo"), b"foo")
     142          self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
     143  
     144      def test_dirname(self):
     145          self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
     146          self.assertEqual(posixpath.dirname("/"), "/")
     147          self.assertEqual(posixpath.dirname("foo"), "")
     148          self.assertEqual(posixpath.dirname("////foo"), "////")
     149          self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
     150  
     151          self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
     152          self.assertEqual(posixpath.dirname(b"/"), b"/")
     153          self.assertEqual(posixpath.dirname(b"foo"), b"")
     154          self.assertEqual(posixpath.dirname(b"////foo"), b"////")
     155          self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
     156  
     157      def test_islink(self):
     158          self.assertIs(posixpath.islink(os_helper.TESTFN + "1"), False)
     159          self.assertIs(posixpath.lexists(os_helper.TESTFN + "2"), False)
     160  
     161          with open(os_helper.TESTFN + "1", "wb") as f:
     162              f.write(b"foo")
     163          self.assertIs(posixpath.islink(os_helper.TESTFN + "1"), False)
     164  
     165          if os_helper.can_symlink():
     166              os.symlink(os_helper.TESTFN + "1", os_helper.TESTFN + "2")
     167              self.assertIs(posixpath.islink(os_helper.TESTFN + "2"), True)
     168              os.remove(os_helper.TESTFN + "1")
     169              self.assertIs(posixpath.islink(os_helper.TESTFN + "2"), True)
     170              self.assertIs(posixpath.exists(os_helper.TESTFN + "2"), False)
     171              self.assertIs(posixpath.lexists(os_helper.TESTFN + "2"), True)
     172  
     173          self.assertIs(posixpath.islink(os_helper.TESTFN + "\udfff"), False)
     174          self.assertIs(posixpath.islink(os.fsencode(os_helper.TESTFN) + b"\xff"), False)
     175          self.assertIs(posixpath.islink(os_helper.TESTFN + "\x00"), False)
     176          self.assertIs(posixpath.islink(os.fsencode(os_helper.TESTFN) + b"\x00"), False)
     177  
     178      def test_ismount(self):
     179          self.assertIs(posixpath.ismount("/"), True)
     180          self.assertIs(posixpath.ismount(b"/"), True)
     181          self.assertIs(posixpath.ismount(FakePath("/")), True)
     182          self.assertIs(posixpath.ismount(FakePath(b"/")), True)
     183  
     184      def test_ismount_non_existent(self):
     185          # Non-existent mountpoint.
     186          self.assertIs(posixpath.ismount(ABSTFN), False)
     187          try:
     188              os.mkdir(ABSTFN)
     189              self.assertIs(posixpath.ismount(ABSTFN), False)
     190          finally:
     191              safe_rmdir(ABSTFN)
     192  
     193          self.assertIs(posixpath.ismount('/\udfff'), False)
     194          self.assertIs(posixpath.ismount(b'/\xff'), False)
     195          self.assertIs(posixpath.ismount('/\x00'), False)
     196          self.assertIs(posixpath.ismount(b'/\x00'), False)
     197  
     198      @os_helper.skip_unless_symlink
     199      def test_ismount_symlinks(self):
     200          # Symlinks are never mountpoints.
     201          try:
     202              os.symlink("/", ABSTFN)
     203              self.assertIs(posixpath.ismount(ABSTFN), False)
     204          finally:
     205              os.unlink(ABSTFN)
     206  
     207      @unittest.skipIf(posix is None, "Test requires posix module")
     208      def test_ismount_different_device(self):
     209          # Simulate the path being on a different device from its parent by
     210          # mocking out st_dev.
     211          save_lstat = os.lstat
     212          def fake_lstat(path):
     213              st_ino = 0
     214              st_dev = 0
     215              if path == ABSTFN:
     216                  st_dev = 1
     217                  st_ino = 1
     218              return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
     219          try:
     220              os.lstat = fake_lstat
     221              self.assertIs(posixpath.ismount(ABSTFN), True)
     222          finally:
     223              os.lstat = save_lstat
     224  
     225      @unittest.skipIf(posix is None, "Test requires posix module")
     226      def test_ismount_directory_not_readable(self):
     227          # issue #2466: Simulate ismount run on a directory that is not
     228          # readable, which used to return False.
     229          save_lstat = os.lstat
     230          def fake_lstat(path):
     231              st_ino = 0
     232              st_dev = 0
     233              if path.startswith(ABSTFN) and path != ABSTFN:
     234                  # ismount tries to read something inside the ABSTFN directory;
     235                  # simulate this being forbidden (no read permission).
     236                  raise OSError("Fake [Errno 13] Permission denied")
     237              if path == ABSTFN:
     238                  st_dev = 1
     239                  st_ino = 1
     240              return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
     241          try:
     242              os.lstat = fake_lstat
     243              self.assertIs(posixpath.ismount(ABSTFN), True)
     244          finally:
     245              os.lstat = save_lstat
     246  
     247      def test_expanduser(self):
     248          self.assertEqual(posixpath.expanduser("foo"), "foo")
     249          self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
     250  
     251      def test_expanduser_home_envvar(self):
     252          with os_helper.EnvironmentVarGuard() as env:
     253              env['HOME'] = '/home/victor'
     254              self.assertEqual(posixpath.expanduser("~"), "/home/victor")
     255  
     256              # expanduser() strips trailing slash
     257              env['HOME'] = '/home/victor/'
     258              self.assertEqual(posixpath.expanduser("~"), "/home/victor")
     259  
     260              for home in '/', '', '//', '///':
     261                  with self.subTest(home=home):
     262                      env['HOME'] = home
     263                      self.assertEqual(posixpath.expanduser("~"), "/")
     264                      self.assertEqual(posixpath.expanduser("~/"), "/")
     265                      self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
     266  
     267      @unittest.skipIf(sys.platform == "vxworks",
     268                       "no home directory on VxWorks")
     269      def test_expanduser_pwd(self):
     270          pwd = import_helper.import_module('pwd')
     271  
     272          self.assertIsInstance(posixpath.expanduser("~/"), str)
     273          self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
     274  
     275          # if home directory == root directory, this test makes no sense
     276          if posixpath.expanduser("~") != '/':
     277              self.assertEqual(
     278                  posixpath.expanduser("~") + "/",
     279                  posixpath.expanduser("~/")
     280              )
     281              self.assertEqual(
     282                  posixpath.expanduser(b"~") + b"/",
     283                  posixpath.expanduser(b"~/")
     284              )
     285          self.assertIsInstance(posixpath.expanduser("~root/"), str)
     286          self.assertIsInstance(posixpath.expanduser("~foo/"), str)
     287          self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
     288          self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
     289  
     290          with os_helper.EnvironmentVarGuard() as env:
     291              # expanduser should fall back to using the password database
     292              del env['HOME']
     293  
     294              home = pwd.getpwuid(os.getuid()).pw_dir
     295              # $HOME can end with a trailing /, so strip it (see #17809)
     296              home = home.rstrip("/") or '/'
     297              self.assertEqual(posixpath.expanduser("~"), home)
     298  
     299              # bpo-10496: If the HOME environment variable is not set and the
     300              # user (current identifier or name in the path) doesn't exist in
     301              # the password database (pwd.getuid() or pwd.getpwnam() fail),
     302              # expanduser() must return the path unchanged.
     303              with mock.patch.object(pwd, 'getpwuid', side_effect=KeyError), \
     304                   mock.patch.object(pwd, 'getpwnam', side_effect=KeyError):
     305                  for path in ('~', '~/.local', '~vstinner/'):
     306                      self.assertEqual(posixpath.expanduser(path), path)
     307  
     308      NORMPATH_CASES = [
     309          ("", "."),
     310          ("/", "/"),
     311          ("/.", "/"),
     312          ("/./", "/"),
     313          ("/.//.", "/"),
     314          ("/foo", "/foo"),
     315          ("/foo/bar", "/foo/bar"),
     316          ("//", "//"),
     317          ("///", "/"),
     318          ("///foo/.//bar//", "/foo/bar"),
     319          ("///foo/.//bar//.//..//.//baz///", "/foo/baz"),
     320          ("///..//./foo/.//bar", "/foo/bar"),
     321          (".", "."),
     322          (".//.", "."),
     323          ("..", ".."),
     324          ("../", ".."),
     325          ("../foo", "../foo"),
     326          ("../../foo", "../../foo"),
     327          ("../foo/../bar", "../bar"),
     328          ("../../foo/../bar/./baz/boom/..", "../../bar/baz"),
     329          ("/..", "/"),
     330          ("/..", "/"),
     331          ("/../", "/"),
     332          ("/..//", "/"),
     333          ("//.", "//"),
     334          ("//..", "//"),
     335          ("//...", "//..."),
     336          ("//../foo", "//foo"),
     337          ("//../../foo", "//foo"),
     338          ("/../foo", "/foo"),
     339          ("/../../foo", "/foo"),
     340          ("/../foo/../", "/"),
     341          ("/../foo/../bar", "/bar"),
     342          ("/../../foo/../bar/./baz/boom/..", "/bar/baz"),
     343          ("/../../foo/../bar/./baz/boom/.", "/bar/baz/boom"),
     344          ("foo/../bar/baz", "bar/baz"),
     345          ("foo/../../bar/baz", "../bar/baz"),
     346          ("foo/../../../bar/baz", "../../bar/baz"),
     347          ("foo///../bar/.././../baz/boom", "../baz/boom"),
     348          ("foo/bar/../..///../../baz/boom", "../../baz/boom"),
     349          ("/foo/..", "/"),
     350          ("/foo/../..", "/"),
     351          ("//foo/..", "//"),
     352          ("//foo/../..", "//"),
     353          ("///foo/..", "/"),
     354          ("///foo/../..", "/"),
     355          ("////foo/..", "/"),
     356          ("/////foo/..", "/"),
     357      ]
     358  
     359      def test_normpath(self):
     360          for path, expected in self.NORMPATH_CASES:
     361              with self.subTest(path):
     362                  result = posixpath.normpath(path)
     363                  self.assertEqual(result, expected)
     364  
     365              path = path.encode('utf-8')
     366              expected = expected.encode('utf-8')
     367              with self.subTest(path, type=bytes):
     368                  result = posixpath.normpath(path)
     369                  self.assertEqual(result, expected)
     370  
     371      @skip_if_ABSTFN_contains_backslash
     372      def test_realpath_curdir(self):
     373          self.assertEqual(realpath('.'), os.getcwd())
     374          self.assertEqual(realpath('./.'), os.getcwd())
     375          self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
     376  
     377          self.assertEqual(realpath(b'.'), os.getcwdb())
     378          self.assertEqual(realpath(b'./.'), os.getcwdb())
     379          self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
     380  
     381      @skip_if_ABSTFN_contains_backslash
     382      def test_realpath_pardir(self):
     383          self.assertEqual(realpath('..'), dirname(os.getcwd()))
     384          self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
     385          self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
     386  
     387          self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
     388          self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
     389          self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
     390  
     391      @os_helper.skip_unless_symlink
     392      @skip_if_ABSTFN_contains_backslash
     393      def test_realpath_basic(self):
     394          # Basic operation.
     395          try:
     396              os.symlink(ABSTFN+"1", ABSTFN)
     397              self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
     398          finally:
     399              os_helper.unlink(ABSTFN)
     400  
     401      @os_helper.skip_unless_symlink
     402      @skip_if_ABSTFN_contains_backslash
     403      def test_realpath_strict(self):
     404          # Bug #43757: raise FileNotFoundError in strict mode if we encounter
     405          # a path that does not exist.
     406          try:
     407              os.symlink(ABSTFN+"1", ABSTFN)
     408              self.assertRaises(FileNotFoundError, realpath, ABSTFN, strict=True)
     409              self.assertRaises(FileNotFoundError, realpath, ABSTFN + "2", strict=True)
     410          finally:
     411              os_helper.unlink(ABSTFN)
     412  
     413      @os_helper.skip_unless_symlink
     414      @skip_if_ABSTFN_contains_backslash
     415      def test_realpath_relative(self):
     416          try:
     417              os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
     418              self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
     419          finally:
     420              os_helper.unlink(ABSTFN)
     421  
     422      @os_helper.skip_unless_symlink
     423      @skip_if_ABSTFN_contains_backslash
     424      def test_realpath_symlink_loops(self):
     425          # Bug #930024, return the path unchanged if we get into an infinite
     426          # symlink loop in non-strict mode (default).
     427          try:
     428              os.symlink(ABSTFN, ABSTFN)
     429              self.assertEqual(realpath(ABSTFN), ABSTFN)
     430  
     431              os.symlink(ABSTFN+"1", ABSTFN+"2")
     432              os.symlink(ABSTFN+"2", ABSTFN+"1")
     433              self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
     434              self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
     435  
     436              self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
     437              self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
     438              self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
     439              os.symlink(ABSTFN+"x", ABSTFN+"y")
     440              self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
     441                               ABSTFN + "y")
     442              self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
     443                               ABSTFN + "1")
     444  
     445              os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
     446              self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
     447  
     448              os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
     449                         basename(ABSTFN) + "c", ABSTFN+"c")
     450              self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
     451  
     452              # Test using relative path as well.
     453              with os_helper.change_cwd(dirname(ABSTFN)):
     454                  self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
     455          finally:
     456              os_helper.unlink(ABSTFN)
     457              os_helper.unlink(ABSTFN+"1")
     458              os_helper.unlink(ABSTFN+"2")
     459              os_helper.unlink(ABSTFN+"y")
     460              os_helper.unlink(ABSTFN+"c")
     461              os_helper.unlink(ABSTFN+"a")
     462  
     463      @os_helper.skip_unless_symlink
     464      @skip_if_ABSTFN_contains_backslash
     465      def test_realpath_symlink_loops_strict(self):
     466          # Bug #43757, raise OSError if we get into an infinite symlink loop in
     467          # strict mode.
     468          try:
     469              os.symlink(ABSTFN, ABSTFN)
     470              self.assertRaises(OSError, realpath, ABSTFN, strict=True)
     471  
     472              os.symlink(ABSTFN+"1", ABSTFN+"2")
     473              os.symlink(ABSTFN+"2", ABSTFN+"1")
     474              self.assertRaises(OSError, realpath, ABSTFN+"1", strict=True)
     475              self.assertRaises(OSError, realpath, ABSTFN+"2", strict=True)
     476  
     477              self.assertRaises(OSError, realpath, ABSTFN+"1/x", strict=True)
     478              self.assertRaises(OSError, realpath, ABSTFN+"1/..", strict=True)
     479              self.assertRaises(OSError, realpath, ABSTFN+"1/../x", strict=True)
     480              os.symlink(ABSTFN+"x", ABSTFN+"y")
     481              self.assertRaises(OSError, realpath,
     482                                ABSTFN+"1/../" + basename(ABSTFN) + "y", strict=True)
     483              self.assertRaises(OSError, realpath,
     484                                ABSTFN+"1/../" + basename(ABSTFN) + "1", strict=True)
     485  
     486              os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
     487              self.assertRaises(OSError, realpath, ABSTFN+"a", strict=True)
     488  
     489              os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
     490                         basename(ABSTFN) + "c", ABSTFN+"c")
     491              self.assertRaises(OSError, realpath, ABSTFN+"c", strict=True)
     492  
     493              # Test using relative path as well.
     494              with os_helper.change_cwd(dirname(ABSTFN)):
     495                  self.assertRaises(OSError, realpath, basename(ABSTFN), strict=True)
     496          finally:
     497              os_helper.unlink(ABSTFN)
     498              os_helper.unlink(ABSTFN+"1")
     499              os_helper.unlink(ABSTFN+"2")
     500              os_helper.unlink(ABSTFN+"y")
     501              os_helper.unlink(ABSTFN+"c")
     502              os_helper.unlink(ABSTFN+"a")
     503  
     504      @os_helper.skip_unless_symlink
     505      @skip_if_ABSTFN_contains_backslash
     506      def test_realpath_repeated_indirect_symlinks(self):
     507          # Issue #6975.
     508          try:
     509              os.mkdir(ABSTFN)
     510              os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
     511              os.symlink('self/self/self', ABSTFN + '/link')
     512              self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
     513          finally:
     514              os_helper.unlink(ABSTFN + '/self')
     515              os_helper.unlink(ABSTFN + '/link')
     516              safe_rmdir(ABSTFN)
     517  
     518      @os_helper.skip_unless_symlink
     519      @skip_if_ABSTFN_contains_backslash
     520      def test_realpath_deep_recursion(self):
     521          depth = 10
     522          try:
     523              os.mkdir(ABSTFN)
     524              for i in range(depth):
     525                  os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
     526              os.symlink('.', ABSTFN + '/0')
     527              self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
     528  
     529              # Test using relative path as well.
     530              with os_helper.change_cwd(ABSTFN):
     531                  self.assertEqual(realpath('%d' % depth), ABSTFN)
     532          finally:
     533              for i in range(depth + 1):
     534                  os_helper.unlink(ABSTFN + '/%d' % i)
     535              safe_rmdir(ABSTFN)
     536  
     537      @os_helper.skip_unless_symlink
     538      @skip_if_ABSTFN_contains_backslash
     539      def test_realpath_resolve_parents(self):
     540          # We also need to resolve any symlinks in the parents of a relative
     541          # path passed to realpath. E.g.: current working directory is
     542          # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
     543          # realpath("a"). This should return /usr/share/doc/a/.
     544          try:
     545              os.mkdir(ABSTFN)
     546              os.mkdir(ABSTFN + "/y")
     547              os.symlink(ABSTFN + "/y", ABSTFN + "/k")
     548  
     549              with os_helper.change_cwd(ABSTFN + "/k"):
     550                  self.assertEqual(realpath("a"), ABSTFN + "/y/a")
     551          finally:
     552              os_helper.unlink(ABSTFN + "/k")
     553              safe_rmdir(ABSTFN + "/y")
     554              safe_rmdir(ABSTFN)
     555  
     556      @os_helper.skip_unless_symlink
     557      @skip_if_ABSTFN_contains_backslash
     558      def test_realpath_resolve_before_normalizing(self):
     559          # Bug #990669: Symbolic links should be resolved before we
     560          # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
     561          # in the following hierarchy:
     562          # a/k/y
     563          #
     564          # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
     565          # then realpath("link-y/..") should return 'k', not 'a'.
     566          try:
     567              os.mkdir(ABSTFN)
     568              os.mkdir(ABSTFN + "/k")
     569              os.mkdir(ABSTFN + "/k/y")
     570              os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
     571  
     572              # Absolute path.
     573              self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
     574              # Relative path.
     575              with os_helper.change_cwd(dirname(ABSTFN)):
     576                  self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
     577                                   ABSTFN + "/k")
     578          finally:
     579              os_helper.unlink(ABSTFN + "/link-y")
     580              safe_rmdir(ABSTFN + "/k/y")
     581              safe_rmdir(ABSTFN + "/k")
     582              safe_rmdir(ABSTFN)
     583  
     584      @os_helper.skip_unless_symlink
     585      @skip_if_ABSTFN_contains_backslash
     586      def test_realpath_resolve_first(self):
     587          # Bug #1213894: The first component of the path, if not absolute,
     588          # must be resolved too.
     589  
     590          try:
     591              os.mkdir(ABSTFN)
     592              os.mkdir(ABSTFN + "/k")
     593              os.symlink(ABSTFN, ABSTFN + "link")
     594              with os_helper.change_cwd(dirname(ABSTFN)):
     595                  base = basename(ABSTFN)
     596                  self.assertEqual(realpath(base + "link"), ABSTFN)
     597                  self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
     598          finally:
     599              os_helper.unlink(ABSTFN + "link")
     600              safe_rmdir(ABSTFN + "/k")
     601              safe_rmdir(ABSTFN)
     602  
     603      def test_relpath(self):
     604          (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
     605          try:
     606              curdir = os.path.split(os.getcwd())[-1]
     607              self.assertRaises(ValueError, posixpath.relpath, "")
     608              self.assertEqual(posixpath.relpath("a"), "a")
     609              self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
     610              self.assertEqual(posixpath.relpath("a/b"), "a/b")
     611              self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
     612              self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
     613              self.assertEqual(posixpath.relpath("a/b", "../c"),
     614                               "../"+curdir+"/a/b")
     615              self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
     616              self.assertEqual(posixpath.relpath("a", "a"), ".")
     617              self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
     618              self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
     619              self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
     620              self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
     621              self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
     622              self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
     623              self.assertEqual(posixpath.relpath("/", "/"), '.')
     624              self.assertEqual(posixpath.relpath("/a", "/a"), '.')
     625              self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
     626          finally:
     627              os.getcwd = real_getcwd
     628  
     629      def test_relpath_bytes(self):
     630          (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
     631          try:
     632              curdir = os.path.split(os.getcwdb())[-1]
     633              self.assertRaises(ValueError, posixpath.relpath, b"")
     634              self.assertEqual(posixpath.relpath(b"a"), b"a")
     635              self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
     636              self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
     637              self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
     638              self.assertEqual(posixpath.relpath(b"a", b"../b"),
     639                               b"../"+curdir+b"/a")
     640              self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
     641                               b"../"+curdir+b"/a/b")
     642              self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
     643              self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
     644              self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
     645              self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
     646              self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
     647              self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
     648              self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
     649              self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
     650              self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
     651              self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
     652              self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
     653  
     654              self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
     655              self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
     656          finally:
     657              os.getcwdb = real_getcwdb
     658  
     659      def test_commonpath(self):
     660          def check(paths, expected):
     661              self.assertEqual(posixpath.commonpath(paths), expected)
     662              self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]),
     663                               os.fsencode(expected))
     664          def check_error(exc, paths):
     665              self.assertRaises(exc, posixpath.commonpath, paths)
     666              self.assertRaises(exc, posixpath.commonpath,
     667                                [os.fsencode(p) for p in paths])
     668  
     669          self.assertRaises(ValueError, posixpath.commonpath, [])
     670          check_error(ValueError, ['/usr', 'usr'])
     671          check_error(ValueError, ['usr', '/usr'])
     672  
     673          check(['/usr/local'], '/usr/local')
     674          check(['/usr/local', '/usr/local'], '/usr/local')
     675          check(['/usr/local/', '/usr/local'], '/usr/local')
     676          check(['/usr/local/', '/usr/local/'], '/usr/local')
     677          check(['/usr//local', '//usr/local'], '/usr/local')
     678          check(['/usr/./local', '/./usr/local'], '/usr/local')
     679          check(['/', '/dev'], '/')
     680          check(['/usr', '/dev'], '/')
     681          check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib')
     682          check(['/usr/lib/', '/usr/lib64/'], '/usr')
     683  
     684          check(['/usr/lib', '/usr/lib64'], '/usr')
     685          check(['/usr/lib/', '/usr/lib64'], '/usr')
     686  
     687          check(['spam'], 'spam')
     688          check(['spam', 'spam'], 'spam')
     689          check(['spam', 'alot'], '')
     690          check(['and/jam', 'and/spam'], 'and')
     691          check(['and//jam', 'and/spam//'], 'and')
     692          check(['and/./jam', './and/spam'], 'and')
     693          check(['and/jam', 'and/spam', 'alot'], '')
     694          check(['and/jam', 'and/spam', 'and'], 'and')
     695  
     696          check([''], '')
     697          check(['', 'spam/alot'], '')
     698          check_error(ValueError, ['', '/spam/alot'])
     699  
     700          self.assertRaises(TypeError, posixpath.commonpath,
     701                            [b'/usr/lib/', '/usr/lib/python3'])
     702          self.assertRaises(TypeError, posixpath.commonpath,
     703                            [b'/usr/lib/', 'usr/lib/python3'])
     704          self.assertRaises(TypeError, posixpath.commonpath,
     705                            [b'usr/lib/', '/usr/lib/python3'])
     706          self.assertRaises(TypeError, posixpath.commonpath,
     707                            ['/usr/lib/', b'/usr/lib/python3'])
     708          self.assertRaises(TypeError, posixpath.commonpath,
     709                            ['/usr/lib/', b'usr/lib/python3'])
     710          self.assertRaises(TypeError, posixpath.commonpath,
     711                            ['usr/lib/', b'/usr/lib/python3'])
     712  
     713  
     714  class ESC[4;38;5;81mPosixCommonTest(ESC[4;38;5;149mtest_genericpathESC[4;38;5;149m.ESC[4;38;5;149mCommonTest, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     715      pathmodule = posixpath
     716      attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
     717  
     718  
     719  class ESC[4;38;5;81mPathLikeTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     720  
     721      path = posixpath
     722  
     723      def setUp(self):
     724          self.file_name = os_helper.TESTFN
     725          self.file_path = FakePath(os_helper.TESTFN)
     726          self.addCleanup(os_helper.unlink, self.file_name)
     727          with open(self.file_name, 'xb', 0) as file:
     728              file.write(b"test_posixpath.PathLikeTests")
     729  
     730      def assertPathEqual(self, func):
     731          self.assertEqual(func(self.file_path), func(self.file_name))
     732  
     733      def test_path_normcase(self):
     734          self.assertPathEqual(self.path.normcase)
     735  
     736      def test_path_isabs(self):
     737          self.assertPathEqual(self.path.isabs)
     738  
     739      def test_path_join(self):
     740          self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
     741                           self.path.join('a', 'b', 'c'))
     742  
     743      def test_path_split(self):
     744          self.assertPathEqual(self.path.split)
     745  
     746      def test_path_splitext(self):
     747          self.assertPathEqual(self.path.splitext)
     748  
     749      def test_path_splitdrive(self):
     750          self.assertPathEqual(self.path.splitdrive)
     751  
     752      def test_path_basename(self):
     753          self.assertPathEqual(self.path.basename)
     754  
     755      def test_path_dirname(self):
     756          self.assertPathEqual(self.path.dirname)
     757  
     758      def test_path_islink(self):
     759          self.assertPathEqual(self.path.islink)
     760  
     761      def test_path_lexists(self):
     762          self.assertPathEqual(self.path.lexists)
     763  
     764      def test_path_ismount(self):
     765          self.assertPathEqual(self.path.ismount)
     766  
     767      def test_path_expanduser(self):
     768          self.assertPathEqual(self.path.expanduser)
     769  
     770      def test_path_expandvars(self):
     771          self.assertPathEqual(self.path.expandvars)
     772  
     773      def test_path_normpath(self):
     774          self.assertPathEqual(self.path.normpath)
     775  
     776      def test_path_abspath(self):
     777          self.assertPathEqual(self.path.abspath)
     778  
     779      def test_path_realpath(self):
     780          self.assertPathEqual(self.path.realpath)
     781  
     782      def test_path_relpath(self):
     783          self.assertPathEqual(self.path.relpath)
     784  
     785      def test_path_commonpath(self):
     786          common_path = self.path.commonpath([self.file_path, self.file_name])
     787          self.assertEqual(common_path, self.file_name)
     788  
     789  
     790  if __name__=="__main__":
     791      unittest.main()