Skip to content

Commit 9b70a99

Browse files
committed
pythongh-101357: use os.path.exists() etc from pathlib
The following `pathlib.Path` methods now directly call functions in `os.path`: - `samefile()` - `exists()` - `is_dir()` - `is_file()` - `is_symlink()` The original generic implementations of these methods are preserved in a new, internal `_PathWithStat` class. In future this may form the basis of a public `AbstractPath` class. The generic implementation of `is_mount()`, which was removed in 29650fea, is also restored to this class.
1 parent 37f15a5 commit 9b70a99

File tree

1 file changed

+173
-113
lines changed

1 file changed

+173
-113
lines changed

Lib/pathlib.py

+173-113
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,174 @@ class PureWindowsPath(PurePath):
701701
# Filesystem-accessing classes
702702

703703

704-
class Path(PurePath):
704+
class _PathWithStat(PurePath):
705+
def stat(self, *, follow_symlinks=True):
706+
"""
707+
Return the result of the stat() system call on this path, like
708+
os.stat() does.
709+
"""
710+
raise NotImplementedError
711+
712+
def exists(self):
713+
"""
714+
Whether this path exists.
715+
"""
716+
try:
717+
self.stat()
718+
except OSError as e:
719+
if not _ignore_error(e):
720+
raise
721+
return False
722+
except ValueError:
723+
# Non-encodable path
724+
return False
725+
return True
726+
727+
def is_dir(self):
728+
"""
729+
Whether this path is a directory.
730+
"""
731+
try:
732+
return S_ISDIR(self.stat().st_mode)
733+
except OSError as e:
734+
if not _ignore_error(e):
735+
raise
736+
# Path doesn't exist or is a broken symlink
737+
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
738+
return False
739+
except ValueError:
740+
# Non-encodable path
741+
return False
742+
743+
def is_file(self):
744+
"""
745+
Whether this path is a regular file (also True for symlinks pointing
746+
to regular files).
747+
"""
748+
try:
749+
return S_ISREG(self.stat().st_mode)
750+
except OSError as e:
751+
if not _ignore_error(e):
752+
raise
753+
# Path doesn't exist or is a broken symlink
754+
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
755+
return False
756+
except ValueError:
757+
# Non-encodable path
758+
return False
759+
760+
def is_mount(self):
761+
"""
762+
Check if this path is a mount point
763+
"""
764+
# Need to exist and be a dir
765+
if not self.exists() or not self.is_dir():
766+
return False
767+
768+
try:
769+
parent_dev = self.parent.stat().st_dev
770+
except OSError:
771+
return False
772+
773+
dev = self.stat().st_dev
774+
if dev != parent_dev:
775+
return True
776+
ino = self.stat().st_ino
777+
parent_ino = self.parent.stat().st_ino
778+
return ino == parent_ino
779+
780+
def is_symlink(self):
781+
"""
782+
Whether this path is a symbolic link.
783+
"""
784+
try:
785+
return S_ISLNK(self.stat(follow_symlinks=False).st_mode)
786+
except OSError as e:
787+
if not _ignore_error(e):
788+
raise
789+
# Path doesn't exist
790+
return False
791+
except ValueError:
792+
# Non-encodable path
793+
return False
794+
795+
def is_block_device(self):
796+
"""
797+
Whether this path is a block device.
798+
"""
799+
try:
800+
return S_ISBLK(self.stat().st_mode)
801+
except OSError as e:
802+
if not _ignore_error(e):
803+
raise
804+
# Path doesn't exist or is a broken symlink
805+
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
806+
return False
807+
except ValueError:
808+
# Non-encodable path
809+
return False
810+
811+
def is_char_device(self):
812+
"""
813+
Whether this path is a character device.
814+
"""
815+
try:
816+
return S_ISCHR(self.stat().st_mode)
817+
except OSError as e:
818+
if not _ignore_error(e):
819+
raise
820+
# Path doesn't exist or is a broken symlink
821+
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
822+
return False
823+
except ValueError:
824+
# Non-encodable path
825+
return False
826+
827+
def is_fifo(self):
828+
"""
829+
Whether this path is a FIFO.
830+
"""
831+
try:
832+
return S_ISFIFO(self.stat().st_mode)
833+
except OSError as e:
834+
if not _ignore_error(e):
835+
raise
836+
# Path doesn't exist or is a broken symlink
837+
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
838+
return False
839+
except ValueError:
840+
# Non-encodable path
841+
return False
842+
843+
def is_socket(self):
844+
"""
845+
Whether this path is a socket.
846+
"""
847+
try:
848+
return S_ISSOCK(self.stat().st_mode)
849+
except OSError as e:
850+
if not _ignore_error(e):
851+
raise
852+
# Path doesn't exist or is a broken symlink
853+
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
854+
return False
855+
except ValueError:
856+
# Non-encodable path
857+
return False
858+
859+
def samefile(self, other_path):
860+
"""Return whether other_path is the same or not as this file
861+
(as returned by os.path.samefile()).
862+
"""
863+
st = self.stat()
864+
try:
865+
other_st = other_path.stat()
866+
except AttributeError:
867+
other_st = self.__class__(other_path).stat()
868+
return self._flavour.samestat(st, other_st)
869+
870+
871+
class Path(_PathWithStat):
705872
"""PurePath subclass that can make system calls.
706873
707874
Path represents a filesystem path but unlike PurePath, also offers
@@ -770,12 +937,7 @@ def samefile(self, other_path):
770937
"""Return whether other_path is the same or not as this file
771938
(as returned by os.path.samefile()).
772939
"""
773-
st = self.stat()
774-
try:
775-
other_st = other_path.stat()
776-
except AttributeError:
777-
other_st = self.__class__(other_path).stat()
778-
return self._flavour.samestat(st, other_st)
940+
return self._flavour.samefile(self, other_path)
779941

780942
def iterdir(self):
781943
"""Yield path objects of the directory contents.
@@ -1069,49 +1231,20 @@ def exists(self):
10691231
"""
10701232
Whether this path exists.
10711233
"""
1072-
try:
1073-
self.stat()
1074-
except OSError as e:
1075-
if not _ignore_error(e):
1076-
raise
1077-
return False
1078-
except ValueError:
1079-
# Non-encodable path
1080-
return False
1081-
return True
1234+
return self._flavour.exists(self)
10821235

10831236
def is_dir(self):
10841237
"""
10851238
Whether this path is a directory.
10861239
"""
1087-
try:
1088-
return S_ISDIR(self.stat().st_mode)
1089-
except OSError as e:
1090-
if not _ignore_error(e):
1091-
raise
1092-
# Path doesn't exist or is a broken symlink
1093-
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
1094-
return False
1095-
except ValueError:
1096-
# Non-encodable path
1097-
return False
1240+
return self._flavour.isdir(self)
10981241

10991242
def is_file(self):
11001243
"""
11011244
Whether this path is a regular file (also True for symlinks pointing
11021245
to regular files).
11031246
"""
1104-
try:
1105-
return S_ISREG(self.stat().st_mode)
1106-
except OSError as e:
1107-
if not _ignore_error(e):
1108-
raise
1109-
# Path doesn't exist or is a broken symlink
1110-
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
1111-
return False
1112-
except ValueError:
1113-
# Non-encodable path
1114-
return False
1247+
return self._flavour.isfile(self)
11151248

11161249
def is_mount(self):
11171250
"""
@@ -1123,87 +1256,14 @@ def is_symlink(self):
11231256
"""
11241257
Whether this path is a symbolic link.
11251258
"""
1126-
try:
1127-
return S_ISLNK(self.lstat().st_mode)
1128-
except OSError as e:
1129-
if not _ignore_error(e):
1130-
raise
1131-
# Path doesn't exist
1132-
return False
1133-
except ValueError:
1134-
# Non-encodable path
1135-
return False
1259+
return self._flavour.islink(self)
11361260

11371261
def is_junction(self):
11381262
"""
11391263
Whether this path is a junction.
11401264
"""
11411265
return self._flavour.isjunction(self)
11421266

1143-
def is_block_device(self):
1144-
"""
1145-
Whether this path is a block device.
1146-
"""
1147-
try:
1148-
return S_ISBLK(self.stat().st_mode)
1149-
except OSError as e:
1150-
if not _ignore_error(e):
1151-
raise
1152-
# Path doesn't exist or is a broken symlink
1153-
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
1154-
return False
1155-
except ValueError:
1156-
# Non-encodable path
1157-
return False
1158-
1159-
def is_char_device(self):
1160-
"""
1161-
Whether this path is a character device.
1162-
"""
1163-
try:
1164-
return S_ISCHR(self.stat().st_mode)
1165-
except OSError as e:
1166-
if not _ignore_error(e):
1167-
raise
1168-
# Path doesn't exist or is a broken symlink
1169-
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
1170-
return False
1171-
except ValueError:
1172-
# Non-encodable path
1173-
return False
1174-
1175-
def is_fifo(self):
1176-
"""
1177-
Whether this path is a FIFO.
1178-
"""
1179-
try:
1180-
return S_ISFIFO(self.stat().st_mode)
1181-
except OSError as e:
1182-
if not _ignore_error(e):
1183-
raise
1184-
# Path doesn't exist or is a broken symlink
1185-
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
1186-
return False
1187-
except ValueError:
1188-
# Non-encodable path
1189-
return False
1190-
1191-
def is_socket(self):
1192-
"""
1193-
Whether this path is a socket.
1194-
"""
1195-
try:
1196-
return S_ISSOCK(self.stat().st_mode)
1197-
except OSError as e:
1198-
if not _ignore_error(e):
1199-
raise
1200-
# Path doesn't exist or is a broken symlink
1201-
# (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ )
1202-
return False
1203-
except ValueError:
1204-
# Non-encodable path
1205-
return False
1206-
12071267
def expanduser(self):
12081268
""" Return a new path with expanded ~ and ~user constructs
12091269
(as returned by os.path.expanduser)

0 commit comments

Comments
 (0)