Skip to content

Commit 89ff6d4

Browse files
committed
Add Windows implementation using os.path.isdir() etc
1 parent 530771d commit 89ff6d4

File tree

1 file changed

+69
-15
lines changed

1 file changed

+69
-15
lines changed

Lib/pathlib/_local.py

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,73 @@ def __repr__(self):
6666
return "<{}.parents>".format(type(self._path).__name__)
6767

6868

69-
class _PathStatus:
70-
"""Implementation of pathlib.types.Status that provides file status
71-
information. Don't try to construct it yourself."""
72-
__slots__ = ('_path', '_repr', '_mode')
69+
class _PathStatusBase:
70+
__slots__ = ('_path', '_repr')
7371

7472
def __init__(self, path):
7573
self._path = str(path)
7674
self._repr = f"<{type(path).__name__}.status>"
77-
self._mode = [None, None]
75+
76+
def __fspath__(self):
77+
return self._path
7878

7979
def __repr__(self):
8080
return self._repr
8181

82+
83+
class _WindowsPathStatus(_PathStatusBase):
84+
__slots__ = ('_exists', '_is_dir', '_is_file', '_is_symlink')
85+
86+
def exists(self, *, follow_symlinks=True):
87+
if not follow_symlinks and self.is_symlink():
88+
return True
89+
try:
90+
return self._exists
91+
except AttributeError:
92+
self._exists = os.path.exists(self)
93+
return self._exists
94+
95+
def is_dir(self, *, follow_symlinks=True):
96+
if not follow_symlinks and self.is_symlink():
97+
return False
98+
try:
99+
return self._is_dir
100+
except AttributeError:
101+
self._is_dir = os.path.isdir(self)
102+
return self._is_dir
103+
104+
def is_file(self, *, follow_symlinks=True):
105+
if not follow_symlinks and self.is_symlink():
106+
return False
107+
try:
108+
return self._is_file
109+
except AttributeError:
110+
self._is_file = os.path.isfile(self)
111+
return self._is_file
112+
113+
def is_symlink(self):
114+
try:
115+
return self._is_symlink
116+
except AttributeError:
117+
self._is_symlink = os.path.islink(self)
118+
return self._is_symlink
119+
120+
121+
class _PosixPathStatus(_PathStatusBase):
122+
"""Implementation of pathlib.types.Status that provides file status
123+
information. Don't try to construct it yourself."""
124+
__slots__ = ('_mode',)
125+
126+
def __init__(self, path):
127+
super().__init__(path)
128+
self._mode = [None, None]
129+
82130
def _get_mode(self, *, follow_symlinks=True):
83131
idx = int(follow_symlinks)
84132
mode = self._mode[idx]
85133
if mode is None:
86134
try:
87-
st = os.stat(self._path, follow_symlinks=follow_symlinks)
135+
st = os.stat(self, follow_symlinks=follow_symlinks)
88136
except (OSError, ValueError):
89137
mode = 0
90138
else:
@@ -121,29 +169,35 @@ def is_symlink(self):
121169
return S_ISLNK(self._get_mode(follow_symlinks=False))
122170

123171

124-
class _DirEntryStatus:
172+
_PathStatus = _WindowsPathStatus if os.name == 'nt' else _PosixPathStatus
173+
174+
175+
class _DirEntryStatus(_PathStatusBase):
125176
"""Implementation of pathlib.types.Status that provides file status
126177
information by querying a wrapped os.DirEntry object. Don't try to
127178
construct it yourself."""
128-
__slots__ = ('_entry', '_repr')
179+
__slots__ = ('_entry', '_exists')
129180

130181
def __init__(self, path, entry):
182+
super().__init__(path)
131183
self._entry = entry
132-
self._repr = f"<{type(path).__name__}.status>"
133-
134-
def __repr__(self):
135-
return self._repr
136184

137185
def exists(self, *, follow_symlinks=True):
138186
"""
139187
Whether this path exists
140188
"""
141-
if follow_symlinks:
189+
if not follow_symlinks:
190+
return True
191+
try:
192+
return self._exists
193+
except AttributeError:
142194
try:
143195
self._entry.stat()
144196
except OSError:
145-
return False
146-
return True
197+
self._exists = False
198+
else:
199+
self._exists = True
200+
return self._exists
147201

148202
def is_dir(self, *, follow_symlinks=True):
149203
"""

0 commit comments

Comments
 (0)