Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit08f8301

Browse files
authored
bpo-43012: removepathlib._Accessor (GH-25701)
Per Pitrou:> The original intent for the “accessor” thing was to have a variant that did all accesses under a filesystem tree in a race condition-free way using openat and friends. It turned out to be much too hairy to actually implement, so was entirely abandoned, but the accessor abstraction was left there.https://discuss.python.org/t/make-pathlib-extensible/3428/2Accessors are:- Lacking any internal purpose - '_NormalAccessor' is the only implementation- Lacking any firm conceptual difference to `Path` objects themselves (inc. subclasses)- Non-public, i.e. underscore prefixed - '_Accessor' and '_NormalAccessor' - Unofficially used to implement customized `Path` objects, but once once [bpo-24132]() is addressed there will be a supported route for that.This patch preserves all existing behaviour.
1 parent187930f commit08f8301

File tree

3 files changed

+78
-130
lines changed

3 files changed

+78
-130
lines changed

‎Lib/pathlib.py‎

Lines changed: 59 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -275,93 +275,6 @@ def make_uri(self, path):
275275
_posix_flavour=_PosixFlavour()
276276

277277

278-
class_Accessor:
279-
"""An accessor implements a particular (system-specific or not) way of
280-
accessing paths on the filesystem."""
281-
282-
283-
class_NormalAccessor(_Accessor):
284-
285-
stat=os.stat
286-
287-
open=io.open
288-
289-
listdir=os.listdir
290-
291-
scandir=os.scandir
292-
293-
chmod=os.chmod
294-
295-
mkdir=os.mkdir
296-
297-
unlink=os.unlink
298-
299-
ifhasattr(os,"link"):
300-
link=os.link
301-
else:
302-
deflink(self,src,dst):
303-
raiseNotImplementedError("os.link() not available on this system")
304-
305-
rmdir=os.rmdir
306-
307-
rename=os.rename
308-
309-
replace=os.replace
310-
311-
ifhasattr(os,"symlink"):
312-
symlink=os.symlink
313-
else:
314-
defsymlink(self,src,dst,target_is_directory=False):
315-
raiseNotImplementedError("os.symlink() not available on this system")
316-
317-
deftouch(self,path,mode=0o666,exist_ok=True):
318-
ifexist_ok:
319-
# First try to bump modification time
320-
# Implementation note: GNU touch uses the UTIME_NOW option of
321-
# the utimensat() / futimens() functions.
322-
try:
323-
os.utime(path,None)
324-
exceptOSError:
325-
# Avoid exception chaining
326-
pass
327-
else:
328-
return
329-
flags=os.O_CREAT|os.O_WRONLY
330-
ifnotexist_ok:
331-
flags|=os.O_EXCL
332-
fd=os.open(path,flags,mode)
333-
os.close(fd)
334-
335-
ifhasattr(os,"readlink"):
336-
readlink=os.readlink
337-
else:
338-
defreadlink(self,path):
339-
raiseNotImplementedError("os.readlink() not available on this system")
340-
341-
defowner(self,path):
342-
try:
343-
importpwd
344-
returnpwd.getpwuid(self.stat(path).st_uid).pw_name
345-
exceptImportError:
346-
raiseNotImplementedError("Path.owner() is unsupported on this system")
347-
348-
defgroup(self,path):
349-
try:
350-
importgrp
351-
returngrp.getgrgid(self.stat(path).st_gid).gr_name
352-
exceptImportError:
353-
raiseNotImplementedError("Path.group() is unsupported on this system")
354-
355-
getcwd=os.getcwd
356-
357-
expanduser=staticmethod(os.path.expanduser)
358-
359-
realpath=staticmethod(os.path.realpath)
360-
361-
362-
_normal_accessor=_NormalAccessor()
363-
364-
365278
#
366279
# Globbing helpers
367280
#
@@ -402,7 +315,7 @@ def select_from(self, parent_path):
402315
path_cls=type(parent_path)
403316
is_dir=path_cls.is_dir
404317
exists=path_cls.exists
405-
scandir=parent_path._accessor.scandir
318+
scandir=path_cls._scandir
406319
ifnotis_dir(parent_path):
407320
returniter([])
408321
returnself._select_from(parent_path,is_dir,exists,scandir)
@@ -949,7 +862,6 @@ class Path(PurePath):
949862
object. You can also instantiate a PosixPath or WindowsPath directly,
950863
but cannot instantiate a WindowsPath on a POSIX system or vice versa.
951864
"""
952-
_accessor=_normal_accessor
953865
__slots__= ()
954866

955867
def__new__(cls,*args,**kwargs):
@@ -988,7 +900,7 @@ def cwd(cls):
988900
"""Return a new path pointing to the current working directory
989901
(as returned by os.getcwd()).
990902
"""
991-
returncls(cls._accessor.getcwd())
903+
returncls(os.getcwd())
992904

993905
@classmethod
994906
defhome(cls):
@@ -1005,16 +917,22 @@ def samefile(self, other_path):
1005917
try:
1006918
other_st=other_path.stat()
1007919
exceptAttributeError:
1008-
other_st=self._accessor.stat(other_path)
920+
other_st=self.__class__(other_path).stat()
1009921
returnos.path.samestat(st,other_st)
1010922

1011923
defiterdir(self):
1012924
"""Iterate over the files in this directory. Does not yield any
1013925
result for the special paths '.' and '..'.
1014926
"""
1015-
fornameinself._accessor.listdir(self):
927+
fornameinos.listdir(self):
1016928
yieldself._make_child_relpath(name)
1017929

930+
def_scandir(self):
931+
# bpo-24132: a future version of pathlib will support subclassing of
932+
# pathlib.Path to customize how the filesystem is accessed. This
933+
# includes scandir(), which is used to implement glob().
934+
returnos.scandir(self)
935+
1018936
defglob(self,pattern):
1019937
"""Iterate over this subtree and yield all existing files (of any
1020938
kind, including directories) matching the given relative pattern.
@@ -1050,7 +968,7 @@ def absolute(self):
1050968
"""
1051969
ifself.is_absolute():
1052970
returnself
1053-
returnself._from_parts([self._accessor.getcwd()]+self._parts)
971+
returnself._from_parts([self.cwd()]+self._parts)
1054972

1055973
defresolve(self,strict=False):
1056974
"""
@@ -1064,7 +982,7 @@ def check_eloop(e):
1064982
raiseRuntimeError("Symlink loop from %r"%e.filename)
1065983

1066984
try:
1067-
s=self._accessor.realpath(self,strict=strict)
985+
s=os.path.realpath(self,strict=strict)
1068986
exceptOSErrorase:
1069987
check_eloop(e)
1070988
raise
@@ -1084,19 +1002,28 @@ def stat(self, *, follow_symlinks=True):
10841002
Return the result of the stat() system call on this path, like
10851003
os.stat() does.
10861004
"""
1087-
returnself._accessor.stat(self,follow_symlinks=follow_symlinks)
1005+
returnos.stat(self,follow_symlinks=follow_symlinks)
10881006

10891007
defowner(self):
10901008
"""
10911009
Return the login name of the file owner.
10921010
"""
1093-
returnself._accessor.owner(self)
1011+
try:
1012+
importpwd
1013+
returnpwd.getpwuid(self.stat().st_uid).pw_name
1014+
exceptImportError:
1015+
raiseNotImplementedError("Path.owner() is unsupported on this system")
10941016

10951017
defgroup(self):
10961018
"""
10971019
Return the group name of the file gid.
10981020
"""
1099-
returnself._accessor.group(self)
1021+
1022+
try:
1023+
importgrp
1024+
returngrp.getgrgid(self.stat().st_gid).gr_name
1025+
exceptImportError:
1026+
raiseNotImplementedError("Path.group() is unsupported on this system")
11001027

11011028
defopen(self,mode='r',buffering=-1,encoding=None,
11021029
errors=None,newline=None):
@@ -1106,8 +1033,7 @@ def open(self, mode='r', buffering=-1, encoding=None,
11061033
"""
11071034
if"b"notinmode:
11081035
encoding=io.text_encoding(encoding)
1109-
returnself._accessor.open(self,mode,buffering,encoding,errors,
1110-
newline)
1036+
returnio.open(self,mode,buffering,encoding,errors,newline)
11111037

11121038
defread_bytes(self):
11131039
"""
@@ -1148,21 +1074,38 @@ def readlink(self):
11481074
"""
11491075
Return the path to which the symbolic link points.
11501076
"""
1151-
path=self._accessor.readlink(self)
1152-
returnself._from_parts((path,))
1077+
ifnothasattr(os,"readlink"):
1078+
raiseNotImplementedError("os.readlink() not available on this system")
1079+
returnself._from_parts((os.readlink(self),))
11531080

11541081
deftouch(self,mode=0o666,exist_ok=True):
11551082
"""
11561083
Create this file with the given access mode, if it doesn't exist.
11571084
"""
1158-
self._accessor.touch(self,mode,exist_ok)
1085+
1086+
ifexist_ok:
1087+
# First try to bump modification time
1088+
# Implementation note: GNU touch uses the UTIME_NOW option of
1089+
# the utimensat() / futimens() functions.
1090+
try:
1091+
os.utime(self,None)
1092+
exceptOSError:
1093+
# Avoid exception chaining
1094+
pass
1095+
else:
1096+
return
1097+
flags=os.O_CREAT|os.O_WRONLY
1098+
ifnotexist_ok:
1099+
flags|=os.O_EXCL
1100+
fd=os.open(self,flags,mode)
1101+
os.close(fd)
11591102

11601103
defmkdir(self,mode=0o777,parents=False,exist_ok=False):
11611104
"""
11621105
Create a new directory at this given path.
11631106
"""
11641107
try:
1165-
self._accessor.mkdir(self,mode)
1108+
os.mkdir(self,mode)
11661109
exceptFileNotFoundError:
11671110
ifnotparentsorself.parent==self:
11681111
raise
@@ -1178,7 +1121,7 @@ def chmod(self, mode, *, follow_symlinks=True):
11781121
"""
11791122
Change the permissions of the path, like os.chmod().
11801123
"""
1181-
self._accessor.chmod(self,mode,follow_symlinks=follow_symlinks)
1124+
os.chmod(self,mode,follow_symlinks=follow_symlinks)
11821125

11831126
deflchmod(self,mode):
11841127
"""
@@ -1193,7 +1136,7 @@ def unlink(self, missing_ok=False):
11931136
If the path is a directory, use rmdir() instead.
11941137
"""
11951138
try:
1196-
self._accessor.unlink(self)
1139+
os.unlink(self)
11971140
exceptFileNotFoundError:
11981141
ifnotmissing_ok:
11991142
raise
@@ -1202,7 +1145,7 @@ def rmdir(self):
12021145
"""
12031146
Remove this directory. The directory must be empty.
12041147
"""
1205-
self._accessor.rmdir(self)
1148+
os.rmdir(self)
12061149

12071150
deflstat(self):
12081151
"""
@@ -1221,7 +1164,7 @@ def rename(self, target):
12211164
12221165
Returns the new Path instance pointing to the target path.
12231166
"""
1224-
self._accessor.rename(self,target)
1167+
os.rename(self,target)
12251168
returnself.__class__(target)
12261169

12271170
defreplace(self,target):
@@ -1234,23 +1177,27 @@ def replace(self, target):
12341177
12351178
Returns the new Path instance pointing to the target path.
12361179
"""
1237-
self._accessor.replace(self,target)
1180+
os.replace(self,target)
12381181
returnself.__class__(target)
12391182

12401183
defsymlink_to(self,target,target_is_directory=False):
12411184
"""
12421185
Make this path a symlink pointing to the target path.
12431186
Note the order of arguments (link, target) is the reverse of os.symlink.
12441187
"""
1245-
self._accessor.symlink(target,self,target_is_directory)
1188+
ifnothasattr(os,"symlink"):
1189+
raiseNotImplementedError("os.symlink() not available on this system")
1190+
os.symlink(target,self,target_is_directory)
12461191

12471192
defhardlink_to(self,target):
12481193
"""
12491194
Make this path a hard link pointing to the same file as *target*.
12501195
12511196
Note the order of arguments (self, target) is the reverse of os.link's.
12521197
"""
1253-
self._accessor.link(target,self)
1198+
ifnothasattr(os,"link"):
1199+
raiseNotImplementedError("os.link() not available on this system")
1200+
os.link(target,self)
12541201

12551202
deflink_to(self,target):
12561203
"""
@@ -1268,7 +1215,7 @@ def link_to(self, target):
12681215
"for removal in Python 3.12. "
12691216
"Use pathlib.Path.hardlink_to() instead.",
12701217
DeprecationWarning,stacklevel=2)
1271-
self._accessor.link(self,target)
1218+
self.__class__(target).hardlink_to(self)
12721219

12731220
# Convenience functions for querying the stat results
12741221

@@ -1425,7 +1372,7 @@ def expanduser(self):
14251372
"""
14261373
if (not (self._drvorself._root)and
14271374
self._partsandself._parts[0][:1]=='~'):
1428-
homedir=self._accessor.expanduser(self._parts[0])
1375+
homedir=os.path.expanduser(self._parts[0])
14291376
ifhomedir[:1]=="~":
14301377
raiseRuntimeError("Could not determine home directory.")
14311378
returnself._from_parts([homedir]+self._parts[1:])

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp