Skip to content

Incorrect details for os.path.abspath() documentation #130527

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

Closed
calestyo opened this issue Feb 25, 2025 · 15 comments
Closed

Incorrect details for os.path.abspath() documentation #130527

calestyo opened this issue Feb 25, 2025 · 15 comments
Labels
docs Documentation in the Doc dir

Comments

@calestyo
Copy link
Contributor

Documentation

Return a normalized absolutized version of the pathname *path*. On most
platforms, this is equivalent to calling the function :func:`normpath` as
follows: ``normpath(join(os.getcwd(), path))``.

claim is wrong, because normpath(join(os.getcwd(), path)) is only called when the pathname is not absolute.

If the claim would be true, every absolute pathname would get the cwd prepended.

Cheers,
Chris.

@calestyo calestyo added the docs Documentation in the Doc dir label Feb 25, 2025
@picnixz
Copy link
Member

picnixz commented Feb 25, 2025

AFAICT, we could amend the docs by adding "For non-absolute paths, on most platforms, [...]".

EDIT: See #130527 (comment)

cc @barneygale

@picnixz picnixz changed the title wrong details for os.path.abspath() documentation Incorrect details for os.path.abspath() documentation Feb 25, 2025
@calestyo
Copy link
Contributor Author

Even that would then still be a bit wrong or at least misleading, cause normpath() is indeed called for the absolute pathnames, too.

@calestyo
Copy link
Contributor Author

Oh and one should probably cross check that with what the non POSIX versions of this function actually do, cause the POSIX one makes the check for absoluteness via checking for a leading / only, not via abspath().

@picnixz
Copy link
Member

picnixz commented Feb 25, 2025

Actually, I think I was wrong. os.path.join() takes care of absolute paths:

If a segment is an absolute path (which on Windows requires both a drive and a root), then all previous segments are ignored and joining continues from the absolute path segment.

So, os.path.join(cwd, absolute) gives absolute. It doesn't matter whether os.getcwd() is prepended or not as it would be ignored.

@picnixz
Copy link
Member

picnixz commented Feb 25, 2025

So, we wouldn't have "every absolute pathname would get the cwd prepended."

@picnixz picnixz added the pending The issue will be closed if no feedback is provided label Feb 25, 2025
@calestyo
Copy link
Contributor Author

Actually, I think I was wrong. os.path.join() takes care of absolute paths:

Indeed. But then the original text is actually correct (albeit still confusing IMO, though mainly because join()’s behaviour seems odd to me).

@picnixz
Copy link
Member

picnixz commented Feb 25, 2025

albeit still confusing IMO, though mainly because join()’s behaviour seems odd to me

Yes, but that's how it's been for years so I don't think we can change this =/ So while it could be confusing, we shouldn't forget about join ignoring all segments preceededing an absolute segment.

Now, what we could however do is highlight more that part on the os.path.join docs. We could also add a link to os.path.join in os.path.abspath because the function appears after abspath and not before, so whatever is said in os.path.join is not known to the reader when they read about os.path.abspath.

WDYT @barneygale? Also, do you know why it was chosen that absolute segments make previous segments ignored?

@calestyo
Copy link
Contributor Author

Yes, but that's how it's been for years so I don't think we can change this =/

Sure.

The only alternative would be a join2() or maybe concatenate(), which behaves differently, or that allows to be configured via params from the beginning (e.g. one that makes it behave like join() another, which throws an exception if any but the first argument is absolute).

I guess from the abspath() doc PoV, nothing needs to be done in the strict sense:

It does behave as one would expect it to. And if people like me get confused because of the details, that seemingly differ, they either properly read up join() or - the kind of lazy gits like me - file a bug. ;-)

@picnixz
Copy link
Member

picnixz commented Feb 25, 2025

The only alternative would be a join2() or maybe concatenate(), which behaves differently, or that allows to be configured via params from the beginning (e.g. one that makes it behave like join() another, which throws an exception if any but the first argument is absolute).

I'm not sure we need this kind of function in the stdlib, at least not until someone demonstrates that it's a common pattern that well-known libraries would want. It can be implemented by a utility helper but I don't think it's a function to include.

@picnixz
Copy link
Member

picnixz commented Feb 25, 2025

I'm however still concerned about the fact that we refer to a function in the docs before it has been documented and without any clickable link to it so I guess we can still update the docs of os.path.

@picnixz
Copy link
Member

picnixz commented Feb 25, 2025

I think I'm going to close this one an open a separate issue for reorganizing the os.path documentation because it would have been more helpful to first know about os.path.join before using it in an "this is equivalent to [...]" example

@picnixz picnixz closed this as not planned Won't fix, can't repro, duplicate, stale Feb 25, 2025
@picnixz picnixz removed the pending The issue will be closed if no feedback is provided label Feb 25, 2025
@eli-schwartz
Copy link
Contributor

The behavior is pretty logical IMO. This function operates on paths, not strings. An absolute path can't be joined relative to another path as it is, in fact, absolute and refers absolutely to some location. It doesn't matter whether you calculate the location of /bar relative to /foo or relative to /, it is always still /bar.

I use this notion extensively in build systems. For example the Meson Build System exposed this directly as a DSL function, join_paths() and via the syntactic sugar '/foo' / '/bar'. This is important since many usages of paths do not know whether they are absolute, and if and only if they are relative they should be relative to some base directory (e.g. configure with --libdir=lib, it is relative to --prefix=/usr. Build a path to some file in the source tree, it's relative to the source root unless it's an absolute path to some location outside the source tree).

It's also natively what pathlib objects do including for the div overload. So I would regard it as highly surprising to suspect that anyone would not recognize what it's doing.

If what you actually wanted was string joining, that exists.

os.path.normpath(a + '/' + b)

Or don't care about the doubled forward slashes and skip the normpath (the join function won't normalize literal components with preexisting forward slashes).

@calestyo
Copy link
Contributor Author

The behavior is pretty logical IMO.

Well, this issue isn't really about the behaviour of join(), but IMO its current behaviour is not really logical.

I agree that and absolute path cannot be joint (on the right side) with any other path (regardless of absolute or relative), but IMO join() should then just throw an exception rather than simply ignoring anything that came on the left side, which may point to some error in the code.

But anyway... it is as it is and software may already depend on that (IMO: mis)feature.

@eli-schwartz
Copy link
Contributor

Yeah, I'll repeat that my software considers it a brilliant, intuitive, and highly useful feature and as such I depend on this.

@barneygale
Copy link
Contributor

barneygale commented Feb 26, 2025

In case it's helpful, I imagine that join() is a bit like running os.chdir() on each argument, and then returning the working directory. So for os.path.join('/foo', '/bar'):

$ cd /foo
$ cd /bar
$ pwd
/bar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir
Projects
Status: Todo
Development

No branches or pull requests

4 participants