Issue #22759: Query methods on pathlib.Path() (exists(), is_dir(), etc.) now return False when the underlying stat call raises NotADirectoryError.
This commit is contained in:
commit
c689101a5e
@ -8,7 +8,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
from collections import Sequence
|
from collections import Sequence
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from errno import EINVAL, ENOENT
|
from errno import EINVAL, ENOENT, ENOTDIR
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
|
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
|
from urllib.parse import quote_from_bytes as urlquote_from_bytes
|
||||||
@ -1238,7 +1238,7 @@ class Path(PurePath):
|
|||||||
try:
|
try:
|
||||||
self.stat()
|
self.stat()
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != ENOENT:
|
if e.errno not in (ENOENT, ENOTDIR):
|
||||||
raise
|
raise
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@ -1250,7 +1250,7 @@ class Path(PurePath):
|
|||||||
try:
|
try:
|
||||||
return S_ISDIR(self.stat().st_mode)
|
return S_ISDIR(self.stat().st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != ENOENT:
|
if e.errno not in (ENOENT, ENOTDIR):
|
||||||
raise
|
raise
|
||||||
# Path doesn't exist or is a broken symlink
|
# Path doesn't exist or is a broken symlink
|
||||||
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
||||||
@ -1264,7 +1264,7 @@ class Path(PurePath):
|
|||||||
try:
|
try:
|
||||||
return S_ISREG(self.stat().st_mode)
|
return S_ISREG(self.stat().st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != ENOENT:
|
if e.errno not in (ENOENT, ENOTDIR):
|
||||||
raise
|
raise
|
||||||
# Path doesn't exist or is a broken symlink
|
# Path doesn't exist or is a broken symlink
|
||||||
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
||||||
@ -1277,7 +1277,7 @@ class Path(PurePath):
|
|||||||
try:
|
try:
|
||||||
return S_ISLNK(self.lstat().st_mode)
|
return S_ISLNK(self.lstat().st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != ENOENT:
|
if e.errno not in (ENOENT, ENOTDIR):
|
||||||
raise
|
raise
|
||||||
# Path doesn't exist
|
# Path doesn't exist
|
||||||
return False
|
return False
|
||||||
@ -1289,7 +1289,7 @@ class Path(PurePath):
|
|||||||
try:
|
try:
|
||||||
return S_ISBLK(self.stat().st_mode)
|
return S_ISBLK(self.stat().st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != ENOENT:
|
if e.errno not in (ENOENT, ENOTDIR):
|
||||||
raise
|
raise
|
||||||
# Path doesn't exist or is a broken symlink
|
# Path doesn't exist or is a broken symlink
|
||||||
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
||||||
@ -1302,7 +1302,7 @@ class Path(PurePath):
|
|||||||
try:
|
try:
|
||||||
return S_ISCHR(self.stat().st_mode)
|
return S_ISCHR(self.stat().st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != ENOENT:
|
if e.errno not in (ENOENT, ENOTDIR):
|
||||||
raise
|
raise
|
||||||
# Path doesn't exist or is a broken symlink
|
# Path doesn't exist or is a broken symlink
|
||||||
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
||||||
@ -1315,7 +1315,7 @@ class Path(PurePath):
|
|||||||
try:
|
try:
|
||||||
return S_ISFIFO(self.stat().st_mode)
|
return S_ISFIFO(self.stat().st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != ENOENT:
|
if e.errno not in (ENOENT, ENOTDIR):
|
||||||
raise
|
raise
|
||||||
# Path doesn't exist or is a broken symlink
|
# Path doesn't exist or is a broken symlink
|
||||||
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
||||||
@ -1328,7 +1328,7 @@ class Path(PurePath):
|
|||||||
try:
|
try:
|
||||||
return S_ISSOCK(self.stat().st_mode)
|
return S_ISSOCK(self.stat().st_mode)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != ENOENT:
|
if e.errno not in (ENOENT, ENOTDIR):
|
||||||
raise
|
raise
|
||||||
# Path doesn't exist or is a broken symlink
|
# Path doesn't exist or is a broken symlink
|
||||||
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
|
||||||
|
@ -1292,9 +1292,12 @@ class _BasePathTest(object):
|
|||||||
self.assertIs(True, p.exists())
|
self.assertIs(True, p.exists())
|
||||||
self.assertIs(True, (p / 'dirA').exists())
|
self.assertIs(True, (p / 'dirA').exists())
|
||||||
self.assertIs(True, (p / 'fileA').exists())
|
self.assertIs(True, (p / 'fileA').exists())
|
||||||
|
self.assertIs(False, (p / 'fileA' / 'bah').exists())
|
||||||
if not symlink_skip_reason:
|
if not symlink_skip_reason:
|
||||||
self.assertIs(True, (p / 'linkA').exists())
|
self.assertIs(True, (p / 'linkA').exists())
|
||||||
self.assertIs(True, (p / 'linkB').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 / 'foo').exists())
|
||||||
self.assertIs(False, P('/xyzzy').exists())
|
self.assertIs(False, P('/xyzzy').exists())
|
||||||
|
|
||||||
@ -1712,6 +1715,7 @@ class _BasePathTest(object):
|
|||||||
self.assertTrue((P / 'dirA').is_dir())
|
self.assertTrue((P / 'dirA').is_dir())
|
||||||
self.assertFalse((P / 'fileA').is_dir())
|
self.assertFalse((P / 'fileA').is_dir())
|
||||||
self.assertFalse((P / 'non-existing').is_dir())
|
self.assertFalse((P / 'non-existing').is_dir())
|
||||||
|
self.assertFalse((P / 'fileA' / 'bah').is_dir())
|
||||||
if not symlink_skip_reason:
|
if not symlink_skip_reason:
|
||||||
self.assertFalse((P / 'linkA').is_dir())
|
self.assertFalse((P / 'linkA').is_dir())
|
||||||
self.assertTrue((P / 'linkB').is_dir())
|
self.assertTrue((P / 'linkB').is_dir())
|
||||||
@ -1722,6 +1726,7 @@ class _BasePathTest(object):
|
|||||||
self.assertTrue((P / 'fileA').is_file())
|
self.assertTrue((P / 'fileA').is_file())
|
||||||
self.assertFalse((P / 'dirA').is_file())
|
self.assertFalse((P / 'dirA').is_file())
|
||||||
self.assertFalse((P / 'non-existing').is_file())
|
self.assertFalse((P / 'non-existing').is_file())
|
||||||
|
self.assertFalse((P / 'fileA' / 'bah').is_file())
|
||||||
if not symlink_skip_reason:
|
if not symlink_skip_reason:
|
||||||
self.assertTrue((P / 'linkA').is_file())
|
self.assertTrue((P / 'linkA').is_file())
|
||||||
self.assertFalse((P / 'linkB').is_file())
|
self.assertFalse((P / 'linkB').is_file())
|
||||||
@ -1732,6 +1737,7 @@ class _BasePathTest(object):
|
|||||||
self.assertFalse((P / 'fileA').is_symlink())
|
self.assertFalse((P / 'fileA').is_symlink())
|
||||||
self.assertFalse((P / 'dirA').is_symlink())
|
self.assertFalse((P / 'dirA').is_symlink())
|
||||||
self.assertFalse((P / 'non-existing').is_symlink())
|
self.assertFalse((P / 'non-existing').is_symlink())
|
||||||
|
self.assertFalse((P / 'fileA' / 'bah').is_symlink())
|
||||||
if not symlink_skip_reason:
|
if not symlink_skip_reason:
|
||||||
self.assertTrue((P / 'linkA').is_symlink())
|
self.assertTrue((P / 'linkA').is_symlink())
|
||||||
self.assertTrue((P / 'linkB').is_symlink())
|
self.assertTrue((P / 'linkB').is_symlink())
|
||||||
@ -1742,6 +1748,7 @@ class _BasePathTest(object):
|
|||||||
self.assertFalse((P / 'fileA').is_fifo())
|
self.assertFalse((P / 'fileA').is_fifo())
|
||||||
self.assertFalse((P / 'dirA').is_fifo())
|
self.assertFalse((P / 'dirA').is_fifo())
|
||||||
self.assertFalse((P / 'non-existing').is_fifo())
|
self.assertFalse((P / 'non-existing').is_fifo())
|
||||||
|
self.assertFalse((P / 'fileA' / 'bah').is_fifo())
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required")
|
@unittest.skipUnless(hasattr(os, "mkfifo"), "os.mkfifo() required")
|
||||||
def test_is_fifo_true(self):
|
def test_is_fifo_true(self):
|
||||||
@ -1756,6 +1763,7 @@ class _BasePathTest(object):
|
|||||||
self.assertFalse((P / 'fileA').is_socket())
|
self.assertFalse((P / 'fileA').is_socket())
|
||||||
self.assertFalse((P / 'dirA').is_socket())
|
self.assertFalse((P / 'dirA').is_socket())
|
||||||
self.assertFalse((P / 'non-existing').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")
|
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
|
||||||
def test_is_socket_true(self):
|
def test_is_socket_true(self):
|
||||||
@ -1776,12 +1784,14 @@ class _BasePathTest(object):
|
|||||||
self.assertFalse((P / 'fileA').is_block_device())
|
self.assertFalse((P / 'fileA').is_block_device())
|
||||||
self.assertFalse((P / 'dirA').is_block_device())
|
self.assertFalse((P / 'dirA').is_block_device())
|
||||||
self.assertFalse((P / 'non-existing').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):
|
def test_is_char_device_false(self):
|
||||||
P = self.cls(BASE)
|
P = self.cls(BASE)
|
||||||
self.assertFalse((P / 'fileA').is_char_device())
|
self.assertFalse((P / 'fileA').is_char_device())
|
||||||
self.assertFalse((P / 'dirA').is_char_device())
|
self.assertFalse((P / 'dirA').is_char_device())
|
||||||
self.assertFalse((P / 'non-existing').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):
|
def test_is_char_device_true(self):
|
||||||
# Under Unix, /dev/null should generally be a char device
|
# Under Unix, /dev/null should generally be a char device
|
||||||
|
@ -180,6 +180,9 @@ Core and Builtins
|
|||||||
Library
|
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
|
- Issue #8876: distutils now falls back to copying files when hard linking
|
||||||
doesn't work. This allows use with special filesystems such as VirtualBox
|
doesn't work. This allows use with special filesystems such as VirtualBox
|
||||||
shared folders.
|
shared folders.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user