From 4dfc9730200329aa02dfe7d90358f0a8453afbd2 Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Tue, 2 Apr 2024 12:47:09 +0200 Subject: 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") --- linuxnamespaces/atlocation.py | 35 +++++++++++++++++++++++++---------- 1 file 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: -- cgit v1.2.3