]> granicus.if.org Git - python/commitdiff
Patch #941486: add os.path.lexists(). Also fix bug #940578 by using lexists in glob...
authorJohannes Gijsbers <jlg@dds.nl>
Mon, 30 Aug 2004 10:19:56 +0000 (10:19 +0000)
committerJohannes Gijsbers <jlg@dds.nl>
Mon, 30 Aug 2004 10:19:56 +0000 (10:19 +0000)
Doc/lib/libglob.tex
Doc/lib/libposixpath.tex
Lib/glob.py
Lib/macpath.py
Lib/ntpath.py
Lib/os2emxpath.py
Lib/plat-riscos/riscospath.py
Lib/posixpath.py
Lib/test/test_glob.py
Lib/test/test_posixpath.py
Misc/NEWS

index 5c1de807bb168661f7ba6b149e1d50da97164cf0..0d0d712b84d24f45a3dfd8b6fe5c86aeba9cf544 100644 (file)
@@ -21,6 +21,7 @@ which must be a string containing a path specification.
 \var{pathname} can be either absolute (like
 \file{/usr/src/Python-1.5/Makefile}) or relative (like
 \file{../../Tools/*/*.gif}), and can contain shell-style wildcards.
+Broken symlinks are included in the results (as in the shell).
 \end{funcdesc}
 
 For example, consider a directory containing only the following files:
index e79df3e744416844efc8c9c949b9e9f493b166fd..066a9616fa12cc6e6c92f9b71bfbd5a6e53d7b23 100644 (file)
@@ -43,6 +43,15 @@ half of the pair returned by \code{split(\var{path})}.
 
 \begin{funcdesc}{exists}{path}
 Return \code{True} if \var{path} refers to an existing path.
+Returns \code{False} for broken symbolic links.
+\end{funcdesc}
+
+\begin{funcdesc}{lexists}{path}
+Return \code{True} if \var{path} refers to an existing path.
+Returns \code{True} for broken symbolic links.  
+Equivalent to \function{exists()} on platforms lacking
+\function{os.lstat()}.
+\versionadded{2.4}
 \end{funcdesc}
 
 \begin{funcdesc}{expanduser}{path}
index d5e508abab9d27d2a5707d4b93673eb4d215952d..4ba41382aa8cd85e9dd8e546336ed9ff55c0471c 100644 (file)
@@ -13,7 +13,7 @@ def glob(pathname):
 
     """
     if not has_magic(pathname):
-        if os.path.exists(pathname):
+        if os.path.lexists(pathname):
             return [pathname]
         else:
             return []
@@ -29,7 +29,7 @@ def glob(pathname):
         for dirname in list:
             if basename or os.path.isdir(dirname):
                 name = os.path.join(dirname, basename)
-                if os.path.exists(name):
+                if os.path.lexists(name):
                     result.append(name)
     else:
         result = []
index 1d3fa5644819a254e5196909861db008b09340f7..bca410e285ff4ec9f1e55790dce0a27907c99620 100644 (file)
@@ -150,7 +150,7 @@ def getctime(filename):
     return os.stat(filename).st_ctime
 
 def exists(s):
-    """Return True if the pathname refers to an existing file or directory."""
+    """Test whether a path exists.  Returns False for broken symbolic links"""    
 
     try:
         st = os.stat(s)
@@ -158,6 +158,18 @@ def exists(s):
         return False
     return True
 
+# Is `stat`/`lstat` a meaningful difference on the Mac?  This is safe in any
+# case.
+
+def lexists(path):
+    """Test whether a path exists.  Returns True for broken symbolic links"""
+
+    try:
+        st = os.lstat(path)
+    except os.error:
+        return False
+    return True
+
 # Return the longest prefix of all list elements.
 
 def commonprefix(m):
index 1f355ecd978f0113f97b591cf5dbd8a2d9e40f2d..649e424f26443e38632901ae54213d3a0932525b 100644 (file)
@@ -249,7 +249,6 @@ def islink(path):
 
 
 # Does a path exist?
-# This is false for dangling symbolic links.
 
 def exists(path):
     """Test whether a path exists"""
@@ -259,6 +258,8 @@ def exists(path):
         return False
     return True
 
+lexists = exists
+
 
 # Is a path a dos directory?
 # This follows symbolic links, so both islink() and isdir() can be true
index 9f8a1dd12c6c6783f23e65e31e7bc1384e190cc4..4c64324e9d7400a281997652bc79839845fc7099 100644 (file)
@@ -220,6 +220,8 @@ def exists(path):
         return False
     return True
 
+lexists = exists
+
 
 # Is a path a directory?
 
index 27b5732ce56c392d5bdfdd9172f9b88c48f70e1e..97b4f65780319bf6d8117aa8d29c1aa3c00c12ce 100644 (file)
@@ -218,6 +218,8 @@ def exists(p):
     except swi.error:
         return 0
 
+lexists = exists
+
 
 def isdir(p):
     """
index 1a259346b83c1b6490f5f00219d02b5959197410..b29eedc38b56723e3c84358326eaf4b84fef0f07 100644 (file)
@@ -174,6 +174,17 @@ def exists(path):
     return True
 
 
+# Being true for dangling symbolic links is also useful.
+
+def lexists(path):
+    """Test whether a path exists.  Returns True for broken symbolic links"""
+    try:
+        st = os.lstat(path)
+    except os.error:
+        return False
+    return True
+
+
 # Is a path a directory?
 # This follows symbolic links, so both islink() and isdir() can be true
 # for the same path.
index 31de30d47f616191364cfdfe4ba0727f632a010e..af81dabb0a4dc41be049a988919f9c127c3090a8 100644 (file)
@@ -48,6 +48,9 @@ class GlobTests(unittest.TestCase):
         self.mktemp('ZZZ')
         self.mktemp('a', 'bcd', 'EF')
         self.mktemp('a', 'bcd', 'efg', 'ha')
+        if hasattr(os, 'symlink'):
+            os.symlink(self.norm('broken'), self.norm('sym1'))
+            os.symlink(self.norm('broken'), self.norm('sym2'))
 
     def tearDown(self):
         deltree(self.tempdir)
@@ -98,6 +101,13 @@ class GlobTests(unittest.TestCase):
         eq(self.glob('?a?', '*F'), map(self.norm, [os.path.join('aaa', 'zzzF'),
                                                    os.path.join('aab', 'F')]))
 
+    def test_glob_broken_symlinks(self):
+        if hasattr(os, 'symlink'):
+            eq = self.assertSequencesEqual_noorder
+            eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')])
+            eq(self.glob('sym1'), [self.norm('sym1')])
+            eq(self.glob('sym2'), [self.norm('sym2')])
+
 
 def test_main():
     run_unittest(GlobTests)
index 1fc3e7c4a6174a54c838cc771993bfe420dfedd3..0a6ed9903e596d1c5f82e944c5cac0d8d20b63b9 100644 (file)
@@ -150,6 +150,7 @@ class PosixPathTest(unittest.TestCase):
                 os.remove(test_support.TESTFN + "1")
                 self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True)
                 self.assertIs(posixpath.exists(test_support.TESTFN + "2"), False)
+                self.assertIs(posixpath.lexists(test_support.TESTFN + "2"), True)
         finally:
             if not f.close():
                 f.close()
@@ -171,6 +172,7 @@ class PosixPathTest(unittest.TestCase):
             f.write("foo")
             f.close()
             self.assertIs(posixpath.exists(test_support.TESTFN), True)
+            self.assertIs(posixpath.lexists(test_support.TESTFN), True)
         finally:
             if not f.close():
                 f.close()
index 58bd46460a17fff54446b531962f824886909107..1cab3045d73420d557e3e535cc6368f470fe05ad 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -79,6 +79,9 @@ Extension modules
 Library
 -------
 
+- Patch #941486: added os.path.lexists(), which returns True for broken
+  symlinks, unlike os.path.exists().
+
 - the random module now uses os.urandom() for seeding if it is available.
   Added a new generator based on os.urandom().