summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Gijsbers <jlg@dds.nl>2004-08-30 10:19:56 +0000
committerJohannes Gijsbers <jlg@dds.nl>2004-08-30 10:19:56 +0000
commite54bb8574dd05077c532c8ae6555d1a2c405602b (patch)
tree1d4da777072be19b752556c402dbc5c58626cea0
parent852b004d0ba4c2f193311421344266778ef7b9ef (diff)
downloadcpython-e54bb8574dd05077c532c8ae6555d1a2c405602b.tar.gz
Patch #941486: add os.path.lexists(). Also fix bug #940578 by using lexists in glob.glob.
-rw-r--r--Doc/lib/libglob.tex1
-rw-r--r--Doc/lib/libposixpath.tex9
-rw-r--r--Lib/glob.py4
-rw-r--r--Lib/macpath.py14
-rw-r--r--Lib/ntpath.py3
-rw-r--r--Lib/os2emxpath.py2
-rw-r--r--Lib/plat-riscos/riscospath.py2
-rw-r--r--Lib/posixpath.py11
-rw-r--r--Lib/test/test_glob.py10
-rw-r--r--Lib/test/test_posixpath.py2
-rw-r--r--Misc/NEWS3
11 files changed, 57 insertions, 4 deletions
diff --git a/Doc/lib/libglob.tex b/Doc/lib/libglob.tex
index 5c1de807bb..0d0d712b84 100644
--- a/Doc/lib/libglob.tex
+++ b/Doc/lib/libglob.tex
@@ -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:
diff --git a/Doc/lib/libposixpath.tex b/Doc/lib/libposixpath.tex
index e79df3e744..066a9616fa 100644
--- a/Doc/lib/libposixpath.tex
+++ b/Doc/lib/libposixpath.tex
@@ -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}
diff --git a/Lib/glob.py b/Lib/glob.py
index d5e508abab..4ba41382aa 100644
--- a/Lib/glob.py
+++ b/Lib/glob.py
@@ -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 = []
diff --git a/Lib/macpath.py b/Lib/macpath.py
index 1d3fa56448..bca410e285 100644
--- a/Lib/macpath.py
+++ b/Lib/macpath.py
@@ -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):
diff --git a/Lib/ntpath.py b/Lib/ntpath.py
index 1f355ecd97..649e424f26 100644
--- a/Lib/ntpath.py
+++ b/Lib/ntpath.py
@@ -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
diff --git a/Lib/os2emxpath.py b/Lib/os2emxpath.py
index 9f8a1dd12c..4c64324e9d 100644
--- a/Lib/os2emxpath.py
+++ b/Lib/os2emxpath.py
@@ -220,6 +220,8 @@ def exists(path):
return False
return True
+lexists = exists
+
# Is a path a directory?
diff --git a/Lib/plat-riscos/riscospath.py b/Lib/plat-riscos/riscospath.py
index 27b5732ce5..97b4f65780 100644
--- a/Lib/plat-riscos/riscospath.py
+++ b/Lib/plat-riscos/riscospath.py
@@ -218,6 +218,8 @@ def exists(p):
except swi.error:
return 0
+lexists = exists
+
def isdir(p):
"""
diff --git a/Lib/posixpath.py b/Lib/posixpath.py
index 1a259346b8..b29eedc38b 100644
--- a/Lib/posixpath.py
+++ b/Lib/posixpath.py
@@ -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.
diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py
index 31de30d47f..af81dabb0a 100644
--- a/Lib/test/test_glob.py
+++ b/Lib/test/test_glob.py
@@ -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)
diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py
index 1fc3e7c4a6..0a6ed9903e 100644
--- a/Lib/test/test_posixpath.py
+++ b/Lib/test/test_posixpath.py
@@ -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()
diff --git a/Misc/NEWS b/Misc/NEWS
index 58bd46460a..1cab3045d7 100644
--- 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().