Repository navigation
gh-89727: Fix os.walk to handle late editing of dirs #100703
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
2767f70
04a16a2
6b0465f
2ff800f
072bdfb
41d7463
d81ff45
431d47a
2829a7d
b59358b
839f31e
1011e19
80b7e82
70cb0c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -355,7 +355,7 @@ def walk(top, topdown=True, onerror=None, followlinks=False): | |
| dirs = [] | ||
| nondirs = [] | ||
| walk_dirs = [] | ||
| cont = False | ||
| use_entry = True | ||
|
|
||
| # We may not have read permission for top, in which case we can't | ||
| # get a list of the files the directory contains. | ||
|
|
@@ -372,7 +372,7 @@ def walk(top, topdown=True, onerror=None, followlinks=False): | |
| except OSError as error: | ||
| if onerror is not None: | ||
| onerror(error) | ||
| cont = True | ||
| use_entry = False | ||
| break | ||
|
|
||
| try: | ||
|
|
@@ -405,19 +405,17 @@ def walk(top, topdown=True, onerror=None, followlinks=False): | |
| if walk_into: | ||
| walk_dirs.append(entry.path) | ||
| if topdown: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Such a high percentage of code in this function is now under either
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was actually thinking about this. I just gave it a shot to see. This seems to me like one of those cases where there are enough little differences in logic that it's much cleaner to separate the two. If we didn't support dir modification for topdown or didn't care about performance it might be simpler, but when you have a lot of the same logic interspersed by a lot of little differences it gets messy. In these kinds of situations I also tend to prefer some duplication between functions over one big function with conditions inside of loops. I also find it easier to look at the two sets of logic separately, but either way works.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think the split version seems fine. Will wait a bit and see if some core devs have opinions. |
||
| if not cont: | ||
| if use_entry: | ||
| # Yield before sub-directory traversal if going top down | ||
| yield top, dirs, nondirs | ||
| # Traverse into sub-directories | ||
| # Append dir names to walk along with top, their parent dir | ||
| stack.append([top, iter(dirs)]) | ||
|
|
||
| while True: | ||
| try: | ||
| value, dirs = stack[-1] | ||
| except IndexError: | ||
| return | ||
| # Set top and scandir_it for the next iteration | ||
| while stack: | ||
| root, dirs = stack[-1] | ||
| for dirname in dirs: | ||
| top = join(value, dirname) | ||
| top = join(root, dirname) | ||
| # bpo-23605: os.path.islink() is used instead of caching | ||
| # entry.is_symlink() result during the loop on os.scandir() because | ||
| # the caller can replace the directory entry during the previous | ||
|
|
@@ -434,16 +432,18 @@ def walk(top, topdown=True, onerror=None, followlinks=False): | |
| stack.pop() | ||
| continue | ||
| break | ||
| else: | ||
| return | ||
| else: | ||
| if not cont: | ||
| # Traverse into sub-directories | ||
| if use_entry: | ||
| # Traverse into sub-directories by appending a value | ||
| # (entry, dirs) where dirs will be walked and then | ||
| # when dirs is exhausted entry will be yielded | ||
| stack.append(((top, dirs, nondirs), iter(walk_dirs))) | ||
|
|
||
| while True: | ||
| try: | ||
| value, dirs = stack[-1] | ||
| except IndexError: | ||
| return | ||
| # Set top and scandir_it for the next iteration | ||
| while stack: | ||
| entry, dirs = stack[-1] | ||
| for top in dirs: | ||
| try: | ||
| scandir_it = scandir(top) | ||
|
|
@@ -454,10 +454,11 @@ def walk(top, topdown=True, onerror=None, followlinks=False): | |
| break | ||
| else: | ||
| stack.pop() | ||
| # Yield after sub-directory traversal if going bottom up | ||
| yield value | ||
| yield entry | ||
| continue | ||
| break | ||
| else: | ||
| return | ||
|
|
||
| __all__.append("walk") | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.