This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: add get_current_dir_name() to os module
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.8
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: Anthony Sottile, bradengroom, eryksun, hoffman, loewis, serhiy.storchaka, vstinner
Priority: normal Keywords: patch

Created on 2005-03-01 16:26 by hoffman, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
get_current_dir_name.patch marcadam, 2013-03-21 02:12 review
Pull Requests
URL Status Linked Edit
PR 10117 closed bradengroom, 2018-10-26 02:41
Messages (19)
msg61185 - (view) Author: Michael Hoffman (hoffman) Date: 2005-03-01 16:26
os.getcwd() does not use the contents of the PWD
environment variable, much as the glibc getcwd() does
not. This means that if a user sets the path using a
symbolic link, it will be dereferenced before being
passed by os.getcwd().

I propose that get_current_dir_name() be added, either
as a call to the glibc get_current_dir_name(), which
uses the PWD environment variable and therefore will
not dereference symbolic links in the path, or as a
fallback to this Pure Python function:

def get_current_dir_name():
    cwd = os.getcwd()
    
    try:
        pwd = os.environ["PWD"]
    except KeyError:
        return cwd

    cwd_stat, pwd_stat = map(os.stat, [cwd, pwd])

    if cwd_stat.st_dev == pwd_stat.st_dev and
cwd_stat.st_ino == pwd_stat.st_ino:
        return pwd
    else:
        return cwd
msg61186 - (view) Author: Michael Hoffman (hoffman) Date: 2005-03-01 16:27
Logged In: YES 
user_id=987664

Hmmm... my indentation seems to have gone by the wayside.
Still you can probably figure out what the code is supposed
to do <wink>
msg61187 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2005-03-13 23:00
Logged In: YES 
user_id=21627

I was going to say "what is the advantage of using the PWD
variable?", but, thinking about it three times, I found that
it gives you what the user typed in the last cd(1),
independent of symbolic links. So even though you wrote what
it does, and how it differs from getcwd, its not at all
obvious that this is a good thing (even though I now agree
it is a good thing)

Would you like to work on a patch? A pure Python
implementation sounds reasonable, if your code is what glibc
does as well. It seems to me that the documentation patch is
really crucial here, or else users will wonder "what the
heck...".
msg61188 - (view) Author: Michael Hoffman (hoffman) Date: 2005-03-14 09:03
Logged In: YES 
user_id=987664

Thanks for your comments. I agree that a better description
of the difference here is necessary.

I just checked the glibc source and this is almost exactly
what it does. It actually does an os.stat on "." and only
calls __getcwd() if necessary. It's in
glibc-2.3.4/io/getdirname.c if you're curious.

I'll make that change and add the patch to my list of things
to do...

Since st_dev and st_ino don't work outside Posix, should I
just return os.getcwd() on other platforms?
msg61189 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2005-03-14 19:17
Logged In: YES 
user_id=21627

Equalling get_current_dir_name and getcwd for non-POSIX
systems seems like a conservative approach, so I'm for it.
Alternatively, one might think that PWD won't be set on
non-POSIX systems.
msg61190 - (view) Author: Michael Hoffman (hoffman) Date: 2005-03-14 19:45
Logged In: YES 
user_id=987664

It might if they were using a ported UNIX shell. But I think
trusting PWD without checking it is a Bad Thing.
msg184830 - (view) Author: Marc Adam Anderson (marcadam) * Date: 2013-03-21 02:12
This enhancement has been implemented. The code is based on hoffman's code. Tests for this enhancement, as well as tests for os.getcwd() have also been added. The docs have been updated and tested locally.
msg328716 - (view) Author: Anthony Sottile (Anthony Sottile) * Date: 2018-10-28 17:46
Does this actually make sense for the `os` module? `PWD` is a variable set by your interactive shell and doesn't really make sense outside that context.

I expect this function to be too easily confused with `os.getcwd()` and a source of bugs when the latter is desired
msg328719 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2018-10-28 18:03
The glibc has a get_current_dir_name() function which returns the same value that getcwd(), the difference is that get_current_dir_name() allocates memory. If someone wants to add a function using PWD env var, a different function name should be found.
msg328755 - (view) Author: Braden Groom (bradengroom) * Date: 2018-10-28 21:27
Victor, FWIW I don't need this functionality and your suggestion on the PR seems reasonable to me. I only picked up this issue as a way to become familiar with contributing to the project. I'm okay with closing both the PR and the ticket.
msg328775 - (view) Author: Michael Hoffman (hoffman) Date: 2018-10-29 00:29
glibc `getcwd()` and `get_current_dir_name()` are not the same. glibc
`get_current_dir_name()` does, in fact, check the `PWD` environment
variable.

https://www.gnu.org/software/libc/manual/html_node/Working-Directory.html

The get_current_dir_name function is basically equivalent to
getcwd (NULL, 0), except the value of the PWD environment variable is first
examined, and if it does in fact correspond to the current directory, that
value is returned. This is a subtle difference which is visible if the path
described by the value in PWD is using one or more symbolic links, in which
case the value returned by getcwd would resolve the symbolic links and
therefore yield a different result.

On Sun, Oct 28, 2018 at 5:27 PM Braden Groom report-at-bugs.python.org
|Python/Example Allow| <16snny1crx82vlt@sneakemail.com> wrote:

>
> Braden Groom <braden.groom@gmail.com> added the comment:
>
> Victor, FWIW I don't need this functionality and your suggestion on the PR
> seems reasonable to me. I only picked up this issue as a way to become
> familiar with contributing to the project. I'm okay with closing both the
> PR and the ticket.
>
> ----------
> nosy: +bradengroom
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue1154351>
> _______________________________________
>
msg328804 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2018-10-29 11:38
man get_current_dir_name():

       get_current_dir_name()  will  malloc(3) an array big enough to hold the
       absolute pathname of the current working directory.  If the environment
       variable  PWD is set, and its value is correct, then that value will be
       returned.  The caller should free(3) the returned buffer.

Oh sorry, I missed that part.

In this case, we should expose os.get_current_dir_name() using this function. But it's a glibc extension:

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       get_current_dir_name():
              _GNU_SOURCE

I'm not sure about adding shutil.get_current_dir_name() which would use os.get_current_dir_name(), or reimplement it in pure Python.
msg328808 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-10-29 11:54
We provide Python implementations for fnmatch, glob, realpath even if there are corresponding libc functions. This makes them available even on platforms that doesn't have native implementations in libc, avoids C limitations, and allow to add new options. I think it is not wrong to provide a Python implementation for get_current_dir_name().

My concerns are that while it can be useful for people that search for get_current_dir_name() in Python, it can be confused for other people.

* getcwd() and get_current_dir_name() are very similar, but have very different names. In what cases the one or other is preferable?

* On Windows getcwd() returns a path without resolved symbolic links, the same as get_current_dir_name(). Shouldn't we provide an option for getting current working directory with resolved symbolic links on all platforms? This will give us three options: resolved symlinks, unresolved symlinks, and platform-depended default.

* get_current_dir_name() works as desired only when current working directory was not changed since the start of the program. Any call of chdir() will make it an alias to getcwd().

* For some libc functions we add options to existing functions rather of duplicating the number of names in the os module. For example the dir_fd  option instead of *at() functions. Wouldn't be better to add a buulean parameter (with platform-depending default) to getcwd()?

* What about pathlib? Does it need corresponding feature?
msg328814 - (view) Author: Michael Hoffman (hoffman) Date: 2018-10-29 12:16
> * For some libc functions we add options to existing functions rather of duplicating the number of names in the os module. For example the dir_fd  option instead of *at() functions. Wouldn't be better to add a buulean parameter (with platform-depending default) to getcwd()?

I agree, adding an option to `getcwd()` would probably be a better approach and reduce some of the other potential confusion.
msg328819 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2018-10-29 12:28
os.stat() has a following_symlinks parameter because there is lstat(). There is no lgetcwd(), only getcwd(). I dislike the parameter choice. Use os.path.realpath() is you want to resolve symbolic links.
msg328821 - (view) Author: Michael Hoffman (hoffman) Date: 2018-10-29 12:35
`getcwd()` in many ways serves the purpose that a `lget_current_dir_name()` might.
msg328872 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2018-10-29 20:58
>  Windows getcwd() returns a path without resolved symbolic links

This provides consistency. If the working directory were resolved, then accessing "../file.ext" after chdir("C:/Temp/link") could be inconsistent with accessing "C:/Temp/link/../file.ext". This is a consequence of the way DOS paths are translated to native NT paths, which is implemented strictly as a string operation. Since "." and ".." are regular names in NT and not necessarily reserved (e.g. FAT32 allows creating a file named ".."), resolving a path POSIX style would require resolving it up to each ".." component. This would entail potentially making many system calls just to normalize a path before even getting to the intended operation.

> Use os.path.realpath() is you want to resolve symbolic links

In Windows, os.path.realpath is an alias for os.path.abspath, so it doesn't resolve links. Use os.path._getfinalpathname to resolve a file-system path. This returns a \\?\ local-device path, which I'd encourage retaining rather than automatically converting to a regular DOS path. The resulting path may be too long for a regular DOS path (if long paths aren't supported), or the final component of the path may conflict with DOS quirks such as reserved device names (e.g. "nul.txt") and ignoring trailing dots and spaces.
msg351403 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-09-09 10:12
I rejected PR 10117 which adds os.get_current_dir_name(). Copy of my comment:
https://github.com/python/cpython/pull/10117#issuecomment-529399532

The os module is thin wrappers to functions of the libc or even system calls. We don't implement heuristic using 2 variants of the same feature: there shutil module is there for that. Compare os.get_terminal_size() to shutil.get_terminal_size() for example.

I close the PR to add os.get_current_dir_name(): IMHO it's more a feature for the shutil module.
msg351404 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-09-09 10:18
I don't see much traction to get this feature into Python. Only a few comments since 2005. I close the issue. The function implement is just a few lines of pure Python code. If you need it, it's easy to put it in your project.

Sorry, but I'm not convinced that we really need this feature in Python.

I close the issue. If you want this feature, please come back with a better rationale. I don't understand which use case is solved by this feature.
History
Date User Action Args
2022-04-11 14:56:09adminsetgithub: 41638
2019-09-09 10:18:14vstinnersetstatus: open -> closed
resolution: rejected
messages: + msg351404

stage: patch review -> resolved
2019-09-09 10:12:41vstinnersetmessages: + msg351403
2018-10-29 20:58:27eryksunsetnosy: + eryksun
messages: + msg328872
2018-10-29 12:35:05hoffmansetmessages: + msg328821
2018-10-29 12:28:30vstinnersetmessages: + msg328819
2018-10-29 12:16:46hoffmansetmessages: + msg328814
2018-10-29 11:54:46serhiy.storchakasetmessages: + msg328808
2018-10-29 11:38:35vstinnersetmessages: + msg328804
2018-10-29 00:29:24hoffmansetmessages: + msg328775
2018-10-28 21:27:25bradengroomsetnosy: + bradengroom
messages: + msg328755
2018-10-28 18:28:24marcadamsetnosy: - marcadam
2018-10-28 18:03:06vstinnersetnosy: + vstinner
messages: + msg328719
2018-10-28 17:46:48Anthony Sottilesetnosy: + Anthony Sottile
messages: + msg328716
2018-10-26 07:51:30serhiy.storchakasetnosy: + serhiy.storchaka
2018-10-26 07:35:38serhiy.storchakasetversions: + Python 3.8, - Python 3.4
2018-10-26 02:41:32bradengroomsetstage: test needed -> patch review
pull_requests: + pull_request9450
2013-03-22 01:53:58berker.peksagsetversions: + Python 3.4, - Python 3.2
2013-03-21 02:12:21marcadamsetfiles: + get_current_dir_name.patch

nosy: + marcadam
messages: + msg184830

keywords: + patch
2010-08-09 03:23:15terry.reedysetversions: + Python 3.2, - Python 3.1, Python 2.7
2009-02-15 23:56:34ajaksu2setstage: test needed
versions: + Python 3.1, Python 2.7
2005-03-01 16:26:00hoffmanm.historiccreate