diff options
author | Helmut Grohne <helmut@subdivi.de> | 2024-04-02 12:47:09 +0200 |
---|---|---|
committer | Helmut Grohne <helmut@subdivi.de> | 2024-04-02 12:47:09 +0200 |
commit | 4dfc9730200329aa02dfe7d90358f0a8453afbd2 (patch) | |
tree | 7e3e95318844f08dc34e0b004feb3f5324e8e2cd | |
parent | 8bf4abdea4ac72449a1c8664e4c8285ab71c3e46 (diff) | |
download | python-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.py | 35 |
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: |