summaryrefslogtreecommitdiff
path: root/linuxnamespaces/atlocation.py
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2024-05-25 10:22:21 +0200
committerHelmut Grohne <helmut@subdivi.de>2024-05-25 10:22:21 +0200
commitc5c9fe325782a790d563a0a8b1cf62a855a50d81 (patch)
tree16fb8834cd3e260615497faf03f0f78e2929c305 /linuxnamespaces/atlocation.py
parent992e877614476dd40abd11a82ffedc6e261dabdf (diff)
downloadpython-linuxnamespaces-c5c9fe325782a790d563a0a8b1cf62a855a50d81.tar.gz
add a FileDescriptor type
It serves two main purposes. For one thing, it allows telling bare integers and file descriptors apart on a typing level similar to a NewType. For another it adds common methods to a file descriptor and enables closing it via a context manager.
Diffstat (limited to 'linuxnamespaces/atlocation.py')
-rw-r--r--linuxnamespaces/atlocation.py32
1 files changed, 16 insertions, 16 deletions
diff --git a/linuxnamespaces/atlocation.py b/linuxnamespaces/atlocation.py
index 8da5982..8a38650 100644
--- a/linuxnamespaces/atlocation.py
+++ b/linuxnamespaces/atlocation.py
@@ -9,15 +9,16 @@ code for doing so.
import enum
import errno
-import fcntl
import os
import os.path
import pathlib
import stat
import typing
+from .filedescriptor import FileDescriptor
-AT_FDCWD = -100
+
+AT_FDCWD = FileDescriptor(-100)
PathConvertible = typing.Union[str, os.PathLike]
@@ -51,7 +52,7 @@ class AtLocation:
management.
"""
- fd: int
+ fd: FileDescriptor
location: PathConvertible
flags: AtFlags
@@ -63,10 +64,10 @@ class AtLocation:
) -> "AtLocation":
"""The argument thing can be many different thing. If it is an
AtLocation, it is copied and all other arguments must be unset. If it
- is an integer, it is considered to be a file descriptor and the
- location must be unset if flags contains AT_EMPTY_PATH. flags are used
- as is except that AT_EMPTY_PATH is automatically added when given a
- file descriptor and no location.
+ is an integer (e.g. FileDescriptor), it is considered to be a file
+ descriptor and the location must be unset if flags contains
+ AT_EMPTY_PATH. flags are used as is except that AT_EMPTY_PATH is
+ automatically added when given a file descriptor and no location.
"""
if isinstance(thing, AtLocation):
if location is not None or flags != AtFlags.NONE:
@@ -78,7 +79,10 @@ class AtLocation:
if isinstance(thing, int):
if thing < 0 and thing != AT_FDCWD:
raise ValueError("fd cannot be negative")
- obj.fd = thing
+ if isinstance(thing, FileDescriptor):
+ obj.fd = thing
+ else:
+ obj.fd = FileDescriptor(thing)
if location is None:
obj.location = ""
obj.flags = flags | AtFlags.AT_EMPTY_PATH
@@ -100,7 +104,7 @@ class AtLocation:
def close(self) -> None:
"""Close the underlying file descriptor."""
if self.fd >= 0:
- os.close(self.fd)
+ self.fd.close()
self.fd = AT_FDCWD
def as_emptypath(self, inheritable: bool = True) -> "AtLocation":
@@ -109,11 +113,7 @@ class AtLocation:
all cases, the caller is responsible for closing the result object.
"""
if self.flags & AtFlags.AT_EMPTY_PATH:
- newfd = fcntl.fcntl(
- self.fd,
- fcntl.F_DUPFD if inheritable else fcntl.F_DUPFD_CLOEXEC,
- 0,
- )
+ newfd = self.fd.dup(inheritable=inheritable)
return AtLocation(newfd, flags=self.flags)
return AtLocation(
self.open(flags=os.O_PATH | (0 if inheritable else os.O_CLOEXEC))
@@ -175,7 +175,7 @@ class AtLocation:
def __truediv__(self, name: "AtLocationLike") -> "AtLocation":
return self.joinpath(name)
- def fileno(self) -> int:
+ def fileno(self) -> FileDescriptor:
"""Return the underlying file descriptor if this is an AT_EMPTY_PATH
location and raise a ValueError otherwise.
"""
@@ -186,7 +186,7 @@ class AtLocation:
return self.fd
@property
- def fd_or_none(self) -> int | None:
+ def fd_or_none(self) -> FileDescriptor | None:
"""A variant of the fd attribute that replaces AT_FDCWD with None."""
return None if self.fd == AT_FDCWD else self.fd