
Serhiy Storchaka writes:
The readlink utility from GNU coreutils has three mode for resolving file path:
-f, --canonicalize canonicalize by following every symlink in every
component of the given name recursively; all but the last component must exist
-e, --canonicalize-existing canonicalize by following every symlink in every
component of the given name recursively, all components must exist
-m, --canonicalize-missing canonicalize by following every symlink in every
component of the given name recursively, without requirements on components existence
In Mac OS X (and I suppose other BSDs), realpath(3) implements -e. glibc does none of these, instead:
GNU extensions If the call fails with either EACCES or ENOENT and resolved_path is not NULL, then the prefix of path that is not readable or does not exist is returned in resolved_path.
I suppose this nonstandard behavior is controlled by a #define, but the Linux manpage doesn't specify it.
Current behavior of posixpath.realpath() is matches (besides one minor detail) to `readlink -m`. The behavior of Path.resolve() matches `readlink -e`.
This looks like a bug in posixpath, while Path.resolve follows POSIX. http://pubs.opengroup.org/onlinepubs/009695399/functions/realpath.html sez:
RETURN VALUE
Upon successful completion, realpath() shall return a pointer to the resolved name. Otherwise, realpath() shall return a null pointer and set errno to indicate the error, and the contents of the buffer pointed to by resolved_name are undefined.
ERRORS
The realpath() function shall fail if:
[...] [ENOENT] A component of file_name does not name an existing file or file_name points to an empty string. [ENOTDIR] A component of the path prefix is not a directory.
which corresponds to -e.
I have proposed a patch that adds three-state optional parameter to posixpath.realpath() and I'm going to provide similar patch for Path.resolve(). But I'm not sure this is good API. Are there better variants?
Said parameter will almost always be a constant. Usually in those cases Python prefers to use different functions. Eg,
posixpath.realpath -e posixpath.realpath_require_prefix -f posixpath.realpath_allow_missing -m posixpath.realpath_gnuext GNU extension