Skip to content

Add dir_fd to os.path.lexists() & os.path.isdir() #117967

Description

@nineteendo

Feature or enhancement

Proposal:

glob currently needs its own implementation of os.path.lexists() & os.path.isdir() to support dir_fd:

cpython/Lib/glob.py

Lines 201 to 222 in f74e512

def _lexists(pathname, dir_fd):
# Same as os.path.lexists(), but with dir_fd
if dir_fd is None:
return os.path.lexists(pathname)
try:
os.lstat(pathname, dir_fd=dir_fd)
except (OSError, ValueError):
return False
else:
return True
def _isdir(pathname, dir_fd):
# Same as os.path.isdir(), but with dir_fd
if dir_fd is None:
return os.path.isdir(pathname)
try:
st = os.stat(pathname, dir_fd=dir_fd)
except (OSError, ValueError):
return False
else:
return stat.S_ISDIR(st.st_mode)

We could refactor this by adding dir_fd to os.path.lexists() & os.path.isdir():

-def lexists(path):
+def lexists(path, *, dir_fd: int | None = None):
     """Test whether a path exists.  Returns True for broken symbolic links"""
     try:
-        os.lstat(path)
+        os.lstat(path, dir_fd=dir_fd)
     except (OSError, ValueError):
         return False
     return True
-def isdir(s):
+def isdir(s, *, dir_fd: int | None = None):
     """Return true if the pathname refers to an existing directory."""
     try:
-        st = os.stat(s)
+        st = os.stat(s, dir_fd=dir_fd)
     except (OSError, ValueError):
         return False
     return stat.S_ISDIR(st.st_mode)

Note: nt._path_isdir() (& nt._path_lexists() when #117842 lands) need to raise an error for this.

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Activity

  1. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Apr 17, 2024
  2. nineteendo commented on Apr 17, 2024

    @nineteendo
    ContributorAuthor

    cc @serhiy-storchaka before I start implementing this: is this something you would support?

  3. serhiy-storchaka commented on Apr 17, 2024

    @serhiy-storchaka
    Member

    It is trivially implemented via os.stat. glob implements private helpers for historical reasons -- they should behave exactly like os.path versions.

    If there will be other uses of such functions in several different places, it will be worth to add this feature.

  4. nineteendo commented on Apr 17, 2024

    @nineteendo
    ContributorAuthor

    It is trivially implemented via os.stat.

    Note that that's overkill on Windows. You're right because dir_fd isn't supported on Windows, sorry.

    glob implements private helpers for historical reasons

    They could still be simplified in that case:

    def _lexists(pathname, dir_fd):
        # Same as os.path.lexists()
        return os.path.lexists(pathname, dir_fd=dir_fd)
    
    def _isdir(pathname, dir_fd):
        # Same as os.path.isdir()
        return os.path.isdir(pathname, dir_fd=dir_fd)
  5. nineteendo commented on Apr 17, 2024

    @nineteendo
    ContributorAuthor

    @barneygale, do you think this can speed things up? No, it can't, but it could also be used for #117737.

  6. eryksun commented on Apr 17, 2024

    @eryksun
    Contributor

    Note: nt._path_isdir() (& nt._path_lexists() when #117842 lands) would also need to be updated.

    The builtin _path_* functions on Windows would have to be modified to raise NotImplementedError if the new dir_fd argument isn't None.

    FYI, the NT kernel supports opening relative to a handle, which the Windows API makes use of when opening relative to the working directory. However, it's not directly exposed in the Windows API. A fundamental problem is that ".." components are resolved logically on Windows by the user-mode runtime library. Thus using a safe open on NT requires that the normalized relative path doesn't begin with a ".." component.

  7. barneygale commented on Apr 17, 2024

    @barneygale
    Contributor

    I don't feel strongly about it. I note it would be the first os.path function to accept dir_fd.

  8. nineteendo commented on Apr 17, 2024

    @nineteendo
    ContributorAuthor

    The builtin _path_* functions on Windows would have to be modified to raise NotImplementedError if the new dir_fd argument isn't None.

    I see, I assumed Windows supported it too. Then it can only be used for refactoring glob.

    I note it would be the first os.path function to accept dir_fd.

    At the moment it only seems to be needed for glob, so I'll leave it up to serhiy to decide.

  9. nineteendo commented on Apr 18, 2024

    @nineteendo
    ContributorAuthor

    I'm closing this as there's not much support. Feel free to re-open when you change your mind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions