summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2014-10-30 22:15:25 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2014-10-30 22:15:25 (GMT)
commitc689101a5eed64923993d61c4fe46d794d1293f5 (patch)
treef9a6999d448440e17f818e593c935d779e93edf5
parente075f1617f90ba4d6ce03ef6e5cc7947f0fd4beb (diff)
parent2b2852b1b4d5bfd006beb202c520c53db8be2901 (diff)
downloadcpython-c689101a5eed64923993d61c4fe46d794d1293f5.zip
cpython-c689101a5eed64923993d61c4fe46d794d1293f5.tar.gz
cpython-c689101a5eed64923993d61c4fe46d794d1293f5.tar.bz2
Issue #22759: Query methods on pathlib.Path() (exists(), is_dir(), etc.) now return False when the underlying stat call raises NotADirectoryError.
-rw-r--r--Lib/pathlib.py18
-rw-r--r--Lib/test/test_pathlib.py10
-rw-r--r--Misc/NEWS3
3 files changed, 22 insertions, 9 deletions
diff --git a/Lib/pathlib.py b/Lib/pathlib.py
index 5134eea..bceae00 100644
--- a/Lib/pathlib.py
+++ b/Lib/pathlib.py
@@ -8,7 +8,7 @@ import re
import sys
from collections import Sequence
from contextlib import contextmanager
-from errno import EINVAL, ENOENT
+from errno import EINVAL, ENOENT, ENOTDIR
from operator import attrgetter
from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
from urllib.parse import quote_from_bytes as urlquote_from_bytes
@@ -1238,7 +1238,7 @@ class Path(PurePath):
try:
self.stat()
except OSError as e:
- if e.errno != ENOENT:
+ if e.errno not in (ENOENT, ENOTDIR):
raise
return False
return True
@@ -1250,7 +1250,7 @@ class Path(PurePath):
try:
return S_ISDIR(self.stat().st_mode)
except OSError as e:
- if e.errno != ENOENT:
+ if e.errno not in (ENOENT, ENOTDIR):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
@@ -1264,7 +1264,7 @@ class Path(PurePath):
try:
return S_ISREG(self.stat().st_mode)
except OSError as e:
- if e.errno != ENOENT:
+ if e.errno not in (ENOENT, ENOTDIR):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
@@ -1277,7 +1277,7 @@ class Path(PurePath):
try:
return S_ISLNK(self.lstat().st_mode)
except OSError as e:
- if e.errno != ENOENT:
+ if e.errno not in (ENOENT, ENOTDIR):
raise
# Path doesn't exist
return False
@@ -1289,7 +1289,7 @@ class Path(PurePath):
try:
return S_ISBLK(self.stat().st_mode)
except OSError as e:
- if e.errno != ENOENT:
+ if e.errno not in (ENOENT, ENOTDIR):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
@@ -1302,7 +1302,7 @@ class Path(PurePath):
try:
return S_ISCHR(self.stat().st_mode)
except OSError as e:
- if e.errno != ENOENT:
+ if e.errno not in (ENOENT, ENOTDIR):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
@@ -1315,7 +1315,7 @@ class Path(PurePath):
try:
return S_ISFIFO(self.stat().st_mode)
except OSError as e:
- if e.errno != ENOENT:
+ if e.errno not in (ENOENT, ENOTDIR):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
@@ -1328,7 +1328,7 @@ class Path(PurePath):
try:
return S_ISSOCK(self.stat().st_mode)
except OSError as e:
- if e.errno != ENOENT:
+ if e.errno not in (ENOENT, ENOTDIR):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py
index 8839888..d668a71 100644
--- a/Lib/test/test_pathlib.py
+++ b/Lib/test/test_pathlib.py
@@ -1292,9 +1292,12 @@ class _BasePathTest(object):
self.assertIs(True, p.exists())
self.assertIs(True, (p / 'dirA').exists())
self.assertIs(True, (p / 'fileA').exists())
+ self.assertIs(False, (p / 'fileA' / 'bah').exists())
if not symlink_skip_reason:
self.assertIs(True, (p / 'linkA').exists())
self.assertIs(True, (p / 'linkB').exists())
+ self.assertIs(True, (p / 'linkB' / 'fileB').exists())
+ self.assertIs(False, (p / 'linkA' / 'bah').exists())
self.assertIs(False, (p / 'foo').exists())
self.assertIs(False, P('/xyzzy').exists())
@@ -1712,6 +1715,7 @@ class _BasePathTest(object):
self.assertTrue((P / 'dirA').is_dir())
self.assertFalse((P / 'fileA').is_dir())
self.assertFalse((P / 'non-existing').is_dir())
+ self.assertFalse((P / 'fileA' / 'bah').is_dir())
if not symlink_skip_reason:
self.assertFalse((P / 'linkA').is_dir())
self.assertTrue((P / 'linkB').is_dir())
@@ -1722,6 +1726,7 @@ class _BasePathTest(object):
self.assertTrue((P / 'fileA').is_file())
self.assertFalse((P / 'dirA').is_file())
self.assertFalse((P / 'non-existing').is_file())
+ self.assertFalse((P / 'fileA' / 'bah').is_file())
if not symlink_skip_reason:
self.assertTrue((P / 'linkA').is_file())
self.assertFalse((P / 'linkB').is_file())
@@ -1732,6 +1737,7 @@ class _BasePathTest(object):
self.assertFalse((P / 'fileA').is_symlink())
self.assertFalse((P / 'dirA').is_symlink())
self.assertFalse((P / 'non-existing').is_symlink())
+ self.assertFalse((P / 'fileA' / 'bah').is_symlink())
if not symlink_skip_reason:
self.assertTrue((P / 'linkA').is_symlink())
self.assertTrue((P / 'linkB').is_symlink())
@@ -1742,6 +1748,7 @@ class _BasePathTest(object):
self.assertFalse((P / 'fileA').is_fifo())
self.assertFalse((P / 'dirA').is_fifo())
self.assertFalse((P / 'non-existing').is_fifo())
+ self.assertFalse((P / 'fileA' / 'bah').is_fifo())
@unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required")
def test_is_fifo_true(self):
@@ -1756,6 +1763,7 @@ class _BasePathTest(object):
self.assertFalse((P / 'fileA').is_socket())
self.assertFalse((P / 'dirA').is_socket())
self.assertFalse((P / 'non-existing').is_socket())
+ self.assertFalse((P / 'fileA' / 'bah').is_socket())
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
def test_is_socket_true(self):
@@ -1776,12 +1784,14 @@ class _BasePathTest(object):
self.assertFalse((P / 'fileA').is_block_device())
self.assertFalse((P / 'dirA').is_block_device())
self.assertFalse((P / 'non-existing').is_block_device())
+ self.assertFalse((P / 'fileA' / 'bah').is_block_device())
def test_is_char_device_false(self):
P = self.cls(BASE)
self.assertFalse((P / 'fileA').is_char_device())
self.assertFalse((P / 'dirA').is_char_device())
self.assertFalse((P / 'non-existing').is_char_device())
+ self.assertFalse((P / 'fileA' / 'bah').is_char_device())
def test_is_char_device_true(self):
# Under Unix, /dev/null should generally be a char device
diff --git a/Misc/NEWS b/Misc/NEWS
index 17db1fc..76fdd8d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -180,6 +180,9 @@ Core and Builtins
Library
-------
+- Issue #22759: Query methods on pathlib.Path() (exists(), is_dir(), etc.)
+ now return False when the underlying stat call raises NotADirectoryError.
+
- Issue #8876: distutils now falls back to copying files when hard linking
doesn't work. This allows use with special filesystems such as VirtualBox
shared folders.