Skip to content

Commit 00abf8a

Browse files
committed
Speed up path construction when recursing
1 parent 09aff17 commit 00abf8a

File tree

2 files changed

+16
-17
lines changed

2 files changed

+16
-17
lines changed

Lib/pathlib/_abc.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def copy_dir(self, source, target, metadata_keys, dir_entry=None):
166166
with source.scandir() as entries:
167167
target.mkdir(exist_ok=self.dirs_exist_ok)
168168
for entry in entries:
169-
src = source.joinpath(entry.name)
169+
src = source._join_dir_entry(entry)
170170
dst = target.joinpath(entry.name)
171171
if not self.follow_symlinks and entry.is_symlink():
172172
self.copy_symlink(src, dst, metadata_keys, entry)
@@ -720,6 +720,12 @@ def write_text(self, data, encoding=None, errors=None, newline=None):
720720
with self.open(mode='w', encoding=encoding, errors=errors, newline=newline) as f:
721721
return f.write(data)
722722

723+
def _join_dir_entry(self, dir_entry):
724+
"""Construct a new path object from the given os.DirEntry-like object,
725+
which should have been generated by calling scandir() on this path.
726+
"""
727+
return self.joinpath(dir_entry.name)
728+
723729
def scandir(self):
724730
"""Yield os.DirEntry objects of the directory contents.
725731
@@ -735,8 +741,8 @@ def iterdir(self):
735741
special entries '.' and '..' are not included.
736742
"""
737743
with self.scandir() as entries:
738-
names = [entry.name for entry in entries]
739-
return map(self.joinpath, names)
744+
entries = list(entries)
745+
return map(self._join_dir_entry, entries)
740746

741747
def _glob_selector(self, parts, case_sensitive, recurse_symlinks):
742748
if case_sensitive is None:
@@ -792,7 +798,7 @@ def walk(self, top_down=True, on_error=None, follow_symlinks=False):
792798
try:
793799
if entry.is_dir(follow_symlinks=follow_symlinks):
794800
if not top_down:
795-
paths.append(path.joinpath(name))
801+
paths.append(path._join_dir_entry(entry))
796802
dirnames.append(name)
797803
else:
798804
filenames.append(name)

Lib/pathlib/_local.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,12 @@ def _filter_trailing_slash(self, paths):
647647
path_str = path_str[:-1]
648648
yield path_str
649649

650+
def _join_dir_entry(self, dir_entry):
651+
path_str = dir_entry.name if str(self) == '.' else dir_entry.path
652+
path = self.with_segments(path_str)
653+
path._str = path_str
654+
return path
655+
650656
def scandir(self):
651657
"""Yield os.DirEntry objects of the directory contents.
652658
@@ -655,19 +661,6 @@ def scandir(self):
655661
"""
656662
return os.scandir(self)
657663

658-
def iterdir(self):
659-
"""Yield path objects of the directory contents.
660-
661-
The children are yielded in arbitrary order, and the
662-
special entries '.' and '..' are not included.
663-
"""
664-
root_dir = str(self)
665-
with os.scandir(root_dir) as scandir_it:
666-
paths = [entry.path for entry in scandir_it]
667-
if root_dir == '.':
668-
paths = map(self._remove_leading_dot, paths)
669-
return map(self._from_parsed_string, paths)
670-
671664
def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=False):
672665
"""Iterate over this subtree and yield all existing files (of any
673666
kind, including directories) matching the given relative pattern.

0 commit comments

Comments
 (0)