summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2024-04-02 12:47:09 +0200
committerHelmut Grohne <helmut@subdivi.de>2024-04-02 12:47:09 +0200
commit4dfc9730200329aa02dfe7d90358f0a8453afbd2 (patch)
tree7e3e95318844f08dc34e0b004feb3f5324e8e2cd
parent8bf4abdea4ac72449a1c8664e4c8285ab71c3e46 (diff)
downloadpython-linuxnamespaces-4dfc9730200329aa02dfe7d90358f0a8453afbd2.tar.gz
improve AtLocation.join semantics
Also allow joining an AtLocation. When doing that note that any kind of absolute location object (absolute path without fd and any location with an fd) results in just that latter location just like os.path.join returns the latter path when it is absolute. Fixes: 034f732a1af4 ("initial checkin")
-rw-r--r--linuxnamespaces/atlocation.py35
1 files changed, 25 insertions, 10 deletions
diff --git a/linuxnamespaces/atlocation.py b/linuxnamespaces/atlocation.py
index 04e5852..79f55bb 100644
--- a/linuxnamespaces/atlocation.py
+++ b/linuxnamespaces/atlocation.py
@@ -126,21 +126,36 @@ class AtLocation:
self.fd, self.location, self.flags & ~AtFlags.AT_NO_AUTOMOUNT
)
- def joinpath(self, name: PathConvertible) -> "AtLocation":
+ def joinpath(self, other: "AtLocationLike") -> "AtLocation":
"""Combine an AtLocation and a path by doing the equivalent of joining
- them with a slash as separator.
+ them with a slash as separator. The returned AtLocation borrows its fd
+ if any.
"""
- if self.flags & AtFlags.AT_EMPTY_PATH:
- return AtLocation(
- self.fd, name, self.flags & ~AtFlags.AT_EMPTY_PATH
- )
- if not self.location:
- return AtLocation(self.fd, name, self.flags)
+ if isinstance(other, int):
+ # A an fd is considered an absolute AT_EMPTY_PATH path.
+ return AtLocation(other)
+ non_empty_flags = self.flags & ~AtFlags.AT_EMPTY_PATH
+ if isinstance(other, AtLocation):
+ if other.is_absolute():
+ # Absolute path trumps self.
+ return other
+ if non_empty_flags != other.flags:
+ raise ValueError(
+ "cannot join AtLocations with differing flags"
+ )
+ other = other.location
+ if not other:
+ return self
+ elif pathlib.Path(other).is_absolute():
+ return AtLocation(other, flags=non_empty_flags)
+ # other now is a PathConvertible that isn't absolute.
+ if self.flags & AtFlags.AT_EMPTY_PATH or not self.location:
+ return AtLocation(self.fd, other, non_empty_flags)
return AtLocation(
- self.fd, pathlib.Path(self.location).joinpath(name), self.flags
+ self.fd, pathlib.Path(self.location).joinpath(other), self.flags
)
- def __truediv__(self, name: PathConvertible) -> "AtLocation":
+ def __truediv__(self, name: "AtLocationLike") -> "AtLocation":
return self.joinpath(name)
def fileno(self) -> int: