@@ -611,72 +611,29 @@ class PureWindowsPath(PurePath):
611611 __slots__ = ()
612612
613613
614- class _Info :
615- __slots__ = ('_path' ,)
616-
617- def __init__ (self , path ):
618- self ._path = path
619-
620- def __repr__ (self ):
621- path_type = "WindowsPath" if os .name == "nt" else "PosixPath"
622- return f"<{ path_type } .info>"
623-
624- def _stat (self , * , follow_symlinks = True ):
625- """Return the status as an os.stat_result."""
626- raise NotImplementedError
627-
628- def _posix_permissions (self , * , follow_symlinks = True ):
629- """Return the POSIX file permissions."""
630- return S_IMODE (self ._stat (follow_symlinks = follow_symlinks ).st_mode )
631-
632- def _file_id (self , * , follow_symlinks = True ):
633- """Returns the identifier of the file."""
634- st = self ._stat (follow_symlinks = follow_symlinks )
635- return st .st_dev , st .st_ino
636-
637- def _access_time_ns (self , * , follow_symlinks = True ):
638- """Return the access time in nanoseconds."""
639- return self ._stat (follow_symlinks = follow_symlinks ).st_atime_ns
640-
641- def _mod_time_ns (self , * , follow_symlinks = True ):
642- """Return the modify time in nanoseconds."""
643- return self ._stat (follow_symlinks = follow_symlinks ).st_mtime_ns
644-
645- if hasattr (os .stat_result , 'st_flags' ):
646- def _bsd_flags (self , * , follow_symlinks = True ):
647- """Return the flags."""
648- return self ._stat (follow_symlinks = follow_symlinks ).st_flags
649-
650- if hasattr (os , 'listxattr' ):
651- def _xattrs (self , * , follow_symlinks = True ):
652- """Return the xattrs as a list of (attr, value) pairs, or an empty
653- list if extended attributes aren't supported."""
654- try :
655- return [
656- (attr , os .getxattr (self ._path , attr , follow_symlinks = follow_symlinks ))
657- for attr in os .listxattr (self ._path , follow_symlinks = follow_symlinks )]
658- except OSError as err :
659- if err .errno not in (EPERM , ENOTSUP , ENODATA , EINVAL , EACCES ):
660- raise
661- return []
662-
663-
664614_STAT_RESULT_ERROR = [] # falsy sentinel indicating stat() failed.
665615
666616
667- class _StatResultInfo ( _Info ) :
617+ class _Info :
668618 """Implementation of pathlib.types.PathInfo that provides status
669619 information by querying a wrapped os.stat_result object. Don't try to
670620 construct it yourself."""
671- __slots__ = ('_stat_result' , '_lstat_result' )
621+ __slots__ = ('_path' , '_entry' , ' _stat_result' , '_lstat_result' )
672622
673- def __init__ (self , path ):
674- super ().__init__ (path )
623+ def __init__ (self , path , entry = None ):
624+ self ._path = path
625+ self ._entry = entry
675626 self ._stat_result = None
676627 self ._lstat_result = None
677628
629+ def __repr__ (self ):
630+ path_type = "WindowsPath" if os .name == "nt" else "PosixPath"
631+ return f"<{ path_type } .info>"
632+
678633 def _stat (self , * , follow_symlinks = True ):
679634 """Return the status as an os.stat_result."""
635+ if self ._entry :
636+ return self ._entry .stat (follow_symlinks = follow_symlinks )
680637 if follow_symlinks :
681638 if not self ._stat_result :
682639 try :
@@ -696,6 +653,9 @@ def _stat(self, *, follow_symlinks=True):
696653
697654 def exists (self , * , follow_symlinks = True ):
698655 """Whether this path exists."""
656+ if self ._entry :
657+ if not follow_symlinks :
658+ return True
699659 if follow_symlinks :
700660 if self ._stat_result is _STAT_RESULT_ERROR :
701661 return False
@@ -710,6 +670,11 @@ def exists(self, *, follow_symlinks=True):
710670
711671 def is_dir (self , * , follow_symlinks = True ):
712672 """Whether this path is a directory."""
673+ if self ._entry :
674+ try :
675+ return self ._entry .is_dir (follow_symlinks = follow_symlinks )
676+ except OSError :
677+ return False
713678 if follow_symlinks :
714679 if self ._stat_result is _STAT_RESULT_ERROR :
715680 return False
@@ -724,6 +689,11 @@ def is_dir(self, *, follow_symlinks=True):
724689
725690 def is_file (self , * , follow_symlinks = True ):
726691 """Whether this path is a regular file."""
692+ if self ._entry :
693+ try :
694+ return self ._entry .is_file (follow_symlinks = follow_symlinks )
695+ except OSError :
696+ return False
727697 if follow_symlinks :
728698 if self ._stat_result is _STAT_RESULT_ERROR :
729699 return False
@@ -738,6 +708,11 @@ def is_file(self, *, follow_symlinks=True):
738708
739709 def is_symlink (self ):
740710 """Whether this path is a symbolic link."""
711+ if self ._entry :
712+ try :
713+ return self ._entry .is_symlink ()
714+ except OSError :
715+ return False
741716 if self ._lstat_result is _STAT_RESULT_ERROR :
742717 return False
743718 try :
@@ -746,51 +721,40 @@ def is_symlink(self):
746721 return False
747722 return S_ISLNK (st .st_mode )
748723
724+ def _posix_permissions (self , * , follow_symlinks = True ):
725+ """Return the POSIX file permissions."""
726+ return S_IMODE (self ._stat (follow_symlinks = follow_symlinks ).st_mode )
749727
750- class _DirEntryInfo (_Info ):
751- """Implementation of pathlib.types.PathInfo that provides status
752- information by querying a wrapped os.DirEntry object. Don't try to
753- construct it yourself."""
754- __slots__ = ('_entry' ,)
755-
756- def __init__ (self , entry ):
757- super ().__init__ (entry .path )
758- self ._entry = entry
759-
760- def _stat (self , * , follow_symlinks = True ):
761- """Return the status as an os.stat_result."""
762- return self ._entry .stat (follow_symlinks = follow_symlinks )
728+ def _file_id (self , * , follow_symlinks = True ):
729+ """Returns the identifier of the file."""
730+ st = self ._stat (follow_symlinks = follow_symlinks )
731+ return st .st_dev , st .st_ino
763732
764- def exists (self , * , follow_symlinks = True ):
765- """Whether this path exists."""
766- if not follow_symlinks :
767- return True
768- try :
769- self ._stat (follow_symlinks = follow_symlinks )
770- except OSError :
771- return False
772- return True
733+ def _access_time_ns (self , * , follow_symlinks = True ):
734+ """Return the access time in nanoseconds."""
735+ return self ._stat (follow_symlinks = follow_symlinks ).st_atime_ns
773736
774- def is_dir (self , * , follow_symlinks = True ):
775- """Whether this path is a directory."""
776- try :
777- return self ._entry .is_dir (follow_symlinks = follow_symlinks )
778- except OSError :
779- return False
737+ def _mod_time_ns (self , * , follow_symlinks = True ):
738+ """Return the modify time in nanoseconds."""
739+ return self ._stat (follow_symlinks = follow_symlinks ).st_mtime_ns
780740
781- def is_file (self , * , follow_symlinks = True ):
782- """Whether this path is a regular file."""
783- try :
784- return self ._entry .is_file (follow_symlinks = follow_symlinks )
785- except OSError :
786- return False
741+ if hasattr (os .stat_result , 'st_flags' ):
742+ def _bsd_flags (self , * , follow_symlinks = True ):
743+ """Return the flags."""
744+ return self ._stat (follow_symlinks = follow_symlinks ).st_flags
787745
788- def is_symlink (self ):
789- """Whether this path is a symbolic link."""
790- try :
791- return self ._entry .is_symlink ()
792- except OSError :
793- return False
746+ if hasattr (os , 'listxattr' ):
747+ def _xattrs (self , * , follow_symlinks = True ):
748+ """Return the xattrs as a list of (attr, value) pairs, or an empty
749+ list if extended attributes aren't supported."""
750+ try :
751+ return [
752+ (attr , os .getxattr (self ._path , attr , follow_symlinks = follow_symlinks ))
753+ for attr in os .listxattr (self ._path , follow_symlinks = follow_symlinks )]
754+ except OSError as err :
755+ if err .errno not in (EPERM , ENOTSUP , ENODATA , EINVAL , EACCES ):
756+ raise
757+ return []
794758
795759
796760def _copy_info (info , target , follow_symlinks = True ):
@@ -877,7 +841,7 @@ def info(self):
877841 try :
878842 return self ._info
879843 except AttributeError :
880- self ._info = _StatResultInfo (str (self ))
844+ self ._info = _Info (str (self ))
881845 return self ._info
882846
883847 def stat (self , * , follow_symlinks = True ):
@@ -1057,7 +1021,7 @@ def _filter_trailing_slash(self, paths):
10571021 def _from_dir_entry (self , dir_entry , path_str ):
10581022 path = self .with_segments (path_str )
10591023 path ._str = path_str
1060- path ._info = _DirEntryInfo ( dir_entry )
1024+ path ._info = _Info ( dir_entry . path , dir_entry )
10611025 return path
10621026
10631027 def iterdir (self ):
0 commit comments