-
-
Notifications
You must be signed in to change notification settings - Fork 34.8k
gh-151788: Speed up http.server directory listing by using os.scandir() #151789
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
base: main
Are you sure you want to change the base?
Changes from all commits
0606d02
9ba9f68
57bc982
1138200
d47f9fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -872,13 +872,13 @@ def list_directory(self, path): | |||||||||||||||||
|
|
||||||||||||||||||
| """ | ||||||||||||||||||
| try: | ||||||||||||||||||
| list = os.listdir(path) | ||||||||||||||||||
| with os.scandir(path) as it: | ||||||||||||||||||
| entries = sorted(it, key=lambda e: e.name.lower()) | ||||||||||||||||||
| except OSError: | ||||||||||||||||||
| self.send_error( | ||||||||||||||||||
| HTTPStatus.NOT_FOUND, | ||||||||||||||||||
| "No permission to list directory") | ||||||||||||||||||
| return None | ||||||||||||||||||
| list.sort(key=lambda a: a.lower()) | ||||||||||||||||||
| r = [] | ||||||||||||||||||
| displaypath = self.path | ||||||||||||||||||
| displaypath = displaypath.split('#', 1)[0] | ||||||||||||||||||
|
|
@@ -899,15 +899,24 @@ def list_directory(self, path): | |||||||||||||||||
| r.append(f'<title>{title}</title>\n</head>') | ||||||||||||||||||
| r.append(f'<body>\n<h1>{title}</h1>') | ||||||||||||||||||
| r.append('<hr>\n<ul>') | ||||||||||||||||||
| for name in list: | ||||||||||||||||||
| fullname = os.path.join(path, name) | ||||||||||||||||||
| displayname = linkname = name | ||||||||||||||||||
| for entry in entries: | ||||||||||||||||||
| displayname = linkname = entry.name | ||||||||||||||||||
| # Ignore any OSError raised by the os.DirEntry methods | ||||||||||||||||||
| # to match the behavior of their os.path.* counterpart. | ||||||||||||||||||
| try: | ||||||||||||||||||
| is_dir = entry.is_dir() | ||||||||||||||||||
| except OSError: | ||||||||||||||||||
| is_dir = False | ||||||||||||||||||
| try: | ||||||||||||||||||
| is_symlink = entry.is_symlink() | ||||||||||||||||||
| except OSError: | ||||||||||||||||||
| is_symlink = False | ||||||||||||||||||
| # Append / for directories or @ for symbolic links | ||||||||||||||||||
| if os.path.isdir(fullname): | ||||||||||||||||||
| displayname = name + "/" | ||||||||||||||||||
| linkname = name + "/" | ||||||||||||||||||
| if os.path.islink(fullname): | ||||||||||||||||||
| displayname = name + "@" | ||||||||||||||||||
| if is_dir: | ||||||||||||||||||
|
picnixz marked this conversation as resolved.
|
||||||||||||||||||
| displayname = entry.name + "/" | ||||||||||||||||||
| linkname = entry.name + "/" | ||||||||||||||||||
| if is_symlink: | ||||||||||||||||||
| displayname = entry.name + "@" | ||||||||||||||||||
|
Comment on lines
+916
to
+919
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. Can you avoid having an LLM doing those suggestions please?
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. Sure, AFK today but can do that tonight. Emacs doesn't work so well on phone. You want PR clean without Claude?
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. What I (personally) want usually is:
Our policy is that AI is a tool that can be used but it's not something meant to generate PRs for users that would later take credit for (I'm not saying you are, I'm saying that just how AI PRs usually go: most of the time, people just want to have a contribution and so they simply leave their agent in automode).
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. So, the problem generally is not the AI, it's more that whenever there is an LLM, that LLM tends to choose things that are either useless, weird, and that would have been avoided if a human had directly written the lines. If you prefer writing your code through Claude, it's ok, but keep in mind that reviewers are not responsible for guiding the AI, it's the contributor. If we keep telling their agent through our review "no, not like that", it's as if we were directly using an agent in the least efficient way, and hence we are both losing our time.
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. Ah. FWIW, Claude pointed out that your suggestion resulted in a NameError at string concat below, so it proposed this as easiest way to avoid name global and I accepted it
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. Oh, my bad actually it should have been instead of the two lines. That's why I prefer that you tell me this first before changing otherwise I would get confused.
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. So to reiterate: there is nothing wrong with using Claude (the only think I don't like about it is the long summaries in every PR and trivial things it reports like "all tests pass" which is something I would expect for a PR otherwise it doesn't make sense). It's just that having a 3rd actor usually creates more back and forth between the reviewer and the reviewee.
Comment on lines
+916
to
+919
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.
Suggested change
|
||||||||||||||||||
| # Note: a link to a directory displays with @ and links with / | ||||||||||||||||||
| r.append('<li><a href="%s">%s</a></li>' | ||||||||||||||||||
| % (urllib.parse.quote(linkname, | ||||||||||||||||||
|
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| :class:`http.server.SimpleHTTPRequestHandler` now relies on :func:`os.scandir` | ||
| instead of :func:`os.listdir` to build directory listings, thereby reducing | ||
| the total number of :func:`os.stat` calls per entry. This typically improves | ||
| directory listing performance on filesystems where such calls are slow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.