changeset: 93289:40497cc445f4 branch: 3.4 parent: 93287:77e5487c4de1 user: Antoine Pitrou date: Thu Oct 30 23:14:03 2014 +0100 files: Lib/pathlib.py Lib/test/test_pathlib.py Misc/NEWS description: Issue #22759: Query methods on pathlib.Path() (exists(), is_dir(), etc.) now return False when the underlying stat call raises NotADirectoryError. diff -r 77e5487c4de1 -r 40497cc445f4 Lib/pathlib.py --- a/Lib/pathlib.py Thu Oct 30 22:55:13 2014 +0100 +++ b/Lib/pathlib.py Thu Oct 30 23:14:03 2014 +0100 @@ -8,7 +8,7 @@ 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 @@ -1187,7 +1187,7 @@ try: self.stat() except OSError as e: - if e.errno != ENOENT: + if e.errno not in (ENOENT, ENOTDIR): raise return False return True @@ -1199,7 +1199,7 @@ 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/) @@ -1213,7 +1213,7 @@ 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/) @@ -1226,7 +1226,7 @@ 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 @@ -1238,7 +1238,7 @@ 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/) @@ -1251,7 +1251,7 @@ 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/) @@ -1264,7 +1264,7 @@ 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/) @@ -1277,7 +1277,7 @@ 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 -r 77e5487c4de1 -r 40497cc445f4 Lib/test/test_pathlib.py --- a/Lib/test/test_pathlib.py Thu Oct 30 22:55:13 2014 +0100 +++ b/Lib/test/test_pathlib.py Thu Oct 30 23:14:03 2014 +0100 @@ -1276,9 +1276,12 @@ 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()) @@ -1626,6 +1629,7 @@ 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()) @@ -1636,6 +1640,7 @@ 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()) @@ -1646,6 +1651,7 @@ 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()) @@ -1656,6 +1662,7 @@ 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): @@ -1670,6 +1677,7 @@ 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): @@ -1690,12 +1698,14 @@ 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 -r 77e5487c4de1 -r 40497cc445f4 Misc/NEWS --- a/Misc/NEWS Thu Oct 30 22:55:13 2014 +0100 +++ b/Misc/NEWS Thu Oct 30 23:14:03 2014 +0100 @@ -33,6 +33,9 @@ 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.