Skip to content

Commit d2e254a

Browse files
committed
Move path info from pathlib._local to pathlib._os.
1 parent 47ed3de commit d2e254a

File tree

2 files changed

+164
-163
lines changed

2 files changed

+164
-163
lines changed

Lib/pathlib/_local.py

Lines changed: 4 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from errno import *
88
from glob import _StringGlobber, _no_recurse_symlinks
99
from itertools import chain
10-
from stat import S_IMODE, S_ISDIR, S_ISREG, S_ISLNK, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
10+
from stat import S_IMODE, S_ISDIR, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
1111
from _collections_abc import Sequence
1212

1313
try:
@@ -19,7 +19,7 @@
1919
except ImportError:
2020
grp = None
2121

22-
from pathlib._os import copyfile
22+
from pathlib._os import copyfile, PathInfo, DirEntryInfo
2323
from pathlib._abc import CopyWriter, JoinablePath, WritablePath
2424

2525

@@ -65,165 +65,6 @@ def __repr__(self):
6565
return "<{}.parents>".format(type(self._path).__name__)
6666

6767

68-
class _PathInfoBase:
69-
__slots__ = ()
70-
71-
def __repr__(self):
72-
path_type = "WindowsPath" if os.name == "nt" else "PosixPath"
73-
return f"<{path_type}.info>"
74-
75-
76-
class _DirEntryInfo(_PathInfoBase):
77-
"""Implementation of pathlib.types.PathInfo that provides status
78-
information by querying a wrapped os.DirEntry object. Don't try to
79-
construct it yourself."""
80-
__slots__ = ('_entry', '_exists')
81-
82-
def __init__(self, entry):
83-
self._entry = entry
84-
85-
def exists(self, *, follow_symlinks=True):
86-
"""Whether this path exists."""
87-
if not follow_symlinks:
88-
return True
89-
try:
90-
return self._exists
91-
except AttributeError:
92-
try:
93-
self._entry.stat()
94-
except OSError:
95-
self._exists = False
96-
else:
97-
self._exists = True
98-
return self._exists
99-
100-
def is_dir(self, *, follow_symlinks=True):
101-
"""Whether this path is a directory."""
102-
try:
103-
return self._entry.is_dir(follow_symlinks=follow_symlinks)
104-
except OSError:
105-
return False
106-
107-
def is_file(self, *, follow_symlinks=True):
108-
"""Whether this path is a regular file."""
109-
try:
110-
return self._entry.is_file(follow_symlinks=follow_symlinks)
111-
except OSError:
112-
return False
113-
114-
def is_symlink(self):
115-
"""Whether this path is a symbolic link."""
116-
try:
117-
return self._entry.is_symlink()
118-
except OSError:
119-
return False
120-
121-
122-
class _WindowsPathInfo(_PathInfoBase):
123-
"""Implementation of pathlib.types.PathInfo that provides status
124-
information for Windows paths. Don't try to construct it yourself."""
125-
__slots__ = ('_path', '_exists', '_is_dir', '_is_file', '_is_symlink')
126-
127-
def __init__(self, path):
128-
self._path = str(path)
129-
130-
def exists(self, *, follow_symlinks=True):
131-
"""Whether this path exists."""
132-
if not follow_symlinks and self.is_symlink():
133-
return True
134-
try:
135-
return self._exists
136-
except AttributeError:
137-
if os.path.exists(self._path):
138-
self._exists = True
139-
return True
140-
else:
141-
self._exists = self._is_dir = self._is_file = False
142-
return False
143-
144-
def is_dir(self, *, follow_symlinks=True):
145-
"""Whether this path is a directory."""
146-
if not follow_symlinks and self.is_symlink():
147-
return False
148-
try:
149-
return self._is_dir
150-
except AttributeError:
151-
if os.path.isdir(self._path):
152-
self._is_dir = self._exists = True
153-
return True
154-
else:
155-
self._is_dir = False
156-
return False
157-
158-
def is_file(self, *, follow_symlinks=True):
159-
"""Whether this path is a regular file."""
160-
if not follow_symlinks and self.is_symlink():
161-
return False
162-
try:
163-
return self._is_file
164-
except AttributeError:
165-
if os.path.isfile(self._path):
166-
self._is_file = self._exists = True
167-
return True
168-
else:
169-
self._is_file = False
170-
return False
171-
172-
def is_symlink(self):
173-
"""Whether this path is a symbolic link."""
174-
try:
175-
return self._is_symlink
176-
except AttributeError:
177-
self._is_symlink = os.path.islink(self._path)
178-
return self._is_symlink
179-
180-
181-
class _PosixPathInfo(_PathInfoBase):
182-
"""Implementation of pathlib.types.PathInfo that provides status
183-
information for POSIX paths. Don't try to construct it yourself."""
184-
__slots__ = ('_path', '_mode')
185-
186-
def __init__(self, path):
187-
self._path = str(path)
188-
self._mode = [None, None]
189-
190-
def _get_mode(self, *, follow_symlinks=True):
191-
idx = bool(follow_symlinks)
192-
mode = self._mode[idx]
193-
if mode is None:
194-
try:
195-
st = os.stat(self._path, follow_symlinks=follow_symlinks)
196-
except (OSError, ValueError):
197-
mode = 0
198-
else:
199-
mode = st.st_mode
200-
if follow_symlinks or S_ISLNK(mode):
201-
self._mode[idx] = mode
202-
else:
203-
# Not a symlink, so stat() will give the same result
204-
self._mode = [mode, mode]
205-
return mode
206-
207-
def exists(self, *, follow_symlinks=True):
208-
"""Whether this path exists."""
209-
return self._get_mode(follow_symlinks=follow_symlinks) > 0
210-
211-
def is_dir(self, *, follow_symlinks=True):
212-
"""Whether this path is a directory."""
213-
return S_ISDIR(self._get_mode(follow_symlinks=follow_symlinks))
214-
215-
def is_file(self, *, follow_symlinks=True):
216-
"""Whether this path is a regular file."""
217-
return S_ISREG(self._get_mode(follow_symlinks=follow_symlinks))
218-
219-
def is_symlink(self):
220-
"""Whether this path is a symbolic link."""
221-
return S_ISLNK(self._get_mode(follow_symlinks=False))
222-
223-
224-
_PathInfo = _WindowsPathInfo if os.name == 'nt' else _PosixPathInfo
225-
226-
22768
class _LocalCopyWriter(CopyWriter):
22869
"""This object implements the Path.copy callable. Don't try to construct
22970
it yourself."""
@@ -867,7 +708,7 @@ def info(self):
867708
try:
868709
return self._info
869710
except AttributeError:
870-
self._info = _PathInfo(self)
711+
self._info = PathInfo(self)
871712
return self._info
872713

873714
def stat(self, *, follow_symlinks=True):
@@ -1026,7 +867,7 @@ def _filter_trailing_slash(self, paths):
1026867
def _from_dir_entry(self, dir_entry, path_str):
1027868
path = self.with_segments(path_str)
1028869
path._str = path_str
1029-
path._info = _DirEntryInfo(dir_entry)
870+
path._info = DirEntryInfo(dir_entry)
1030871
return path
1031872

1032873
def iterdir(self):

Lib/pathlib/_os.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
from errno import *
6+
from stat import S_ISDIR, S_ISREG, S_ISLNK
67
import os
78
import sys
89
try:
@@ -162,3 +163,162 @@ def copyfileobj(source_f, target_f):
162163
write_target = target_f.write
163164
while buf := read_source(1024 * 1024):
164165
write_target(buf)
166+
167+
168+
class _PathInfoBase:
169+
__slots__ = ()
170+
171+
def __repr__(self):
172+
path_type = "WindowsPath" if os.name == "nt" else "PosixPath"
173+
return f"<{path_type}.info>"
174+
175+
176+
class _WindowsPathInfo(_PathInfoBase):
177+
"""Implementation of pathlib.types.PathInfo that provides status
178+
information for Windows paths. Don't try to construct it yourself."""
179+
__slots__ = ('_path', '_exists', '_is_dir', '_is_file', '_is_symlink')
180+
181+
def __init__(self, path):
182+
self._path = str(path)
183+
184+
def exists(self, *, follow_symlinks=True):
185+
"""Whether this path exists."""
186+
if not follow_symlinks and self.is_symlink():
187+
return True
188+
try:
189+
return self._exists
190+
except AttributeError:
191+
if os.path.exists(self._path):
192+
self._exists = True
193+
return True
194+
else:
195+
self._exists = self._is_dir = self._is_file = False
196+
return False
197+
198+
def is_dir(self, *, follow_symlinks=True):
199+
"""Whether this path is a directory."""
200+
if not follow_symlinks and self.is_symlink():
201+
return False
202+
try:
203+
return self._is_dir
204+
except AttributeError:
205+
if os.path.isdir(self._path):
206+
self._is_dir = self._exists = True
207+
return True
208+
else:
209+
self._is_dir = False
210+
return False
211+
212+
def is_file(self, *, follow_symlinks=True):
213+
"""Whether this path is a regular file."""
214+
if not follow_symlinks and self.is_symlink():
215+
return False
216+
try:
217+
return self._is_file
218+
except AttributeError:
219+
if os.path.isfile(self._path):
220+
self._is_file = self._exists = True
221+
return True
222+
else:
223+
self._is_file = False
224+
return False
225+
226+
def is_symlink(self):
227+
"""Whether this path is a symbolic link."""
228+
try:
229+
return self._is_symlink
230+
except AttributeError:
231+
self._is_symlink = os.path.islink(self._path)
232+
return self._is_symlink
233+
234+
235+
class _PosixPathInfo(_PathInfoBase):
236+
"""Implementation of pathlib.types.PathInfo that provides status
237+
information for POSIX paths. Don't try to construct it yourself."""
238+
__slots__ = ('_path', '_mode')
239+
240+
def __init__(self, path):
241+
self._path = str(path)
242+
self._mode = [None, None]
243+
244+
def _get_mode(self, *, follow_symlinks=True):
245+
idx = bool(follow_symlinks)
246+
mode = self._mode[idx]
247+
if mode is None:
248+
try:
249+
st = os.stat(self._path, follow_symlinks=follow_symlinks)
250+
except (OSError, ValueError):
251+
mode = 0
252+
else:
253+
mode = st.st_mode
254+
if follow_symlinks or S_ISLNK(mode):
255+
self._mode[idx] = mode
256+
else:
257+
# Not a symlink, so stat() will give the same result
258+
self._mode = [mode, mode]
259+
return mode
260+
261+
def exists(self, *, follow_symlinks=True):
262+
"""Whether this path exists."""
263+
return self._get_mode(follow_symlinks=follow_symlinks) > 0
264+
265+
def is_dir(self, *, follow_symlinks=True):
266+
"""Whether this path is a directory."""
267+
return S_ISDIR(self._get_mode(follow_symlinks=follow_symlinks))
268+
269+
def is_file(self, *, follow_symlinks=True):
270+
"""Whether this path is a regular file."""
271+
return S_ISREG(self._get_mode(follow_symlinks=follow_symlinks))
272+
273+
def is_symlink(self):
274+
"""Whether this path is a symbolic link."""
275+
return S_ISLNK(self._get_mode(follow_symlinks=False))
276+
277+
278+
PathInfo = _WindowsPathInfo if os.name == 'nt' else _PosixPathInfo
279+
280+
281+
class DirEntryInfo(_PathInfoBase):
282+
"""Implementation of pathlib.types.PathInfo that provides status
283+
information by querying a wrapped os.DirEntry object. Don't try to
284+
construct it yourself."""
285+
__slots__ = ('_entry', '_exists')
286+
287+
def __init__(self, entry):
288+
self._entry = entry
289+
290+
def exists(self, *, follow_symlinks=True):
291+
"""Whether this path exists."""
292+
if not follow_symlinks:
293+
return True
294+
try:
295+
return self._exists
296+
except AttributeError:
297+
try:
298+
self._entry.stat()
299+
except OSError:
300+
self._exists = False
301+
else:
302+
self._exists = True
303+
return self._exists
304+
305+
def is_dir(self, *, follow_symlinks=True):
306+
"""Whether this path is a directory."""
307+
try:
308+
return self._entry.is_dir(follow_symlinks=follow_symlinks)
309+
except OSError:
310+
return False
311+
312+
def is_file(self, *, follow_symlinks=True):
313+
"""Whether this path is a regular file."""
314+
try:
315+
return self._entry.is_file(follow_symlinks=follow_symlinks)
316+
except OSError:
317+
return False
318+
319+
def is_symlink(self):
320+
"""Whether this path is a symbolic link."""
321+
try:
322+
return self._entry.is_symlink()
323+
except OSError:
324+
return False

0 commit comments

Comments
 (0)