diff --git a/docs/source/conf.py b/docs/source/conf.py index eb278bf65f..46a3f6bae3 100755 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -173,7 +173,6 @@ def autodoc_process_signature( # currently undocumented things logger = getLogger("trio") UNDOCUMENTED = { - "trio._subprocess.HasFileno.fileno", "trio.lowlevel.ParkingLot.broken_by", } diff --git a/newsfragments/3226.bugfix.rst b/newsfragments/3226.bugfix.rst new file mode 100644 index 0000000000..6a79334f25 --- /dev/null +++ b/newsfragments/3226.bugfix.rst @@ -0,0 +1 @@ +Add docstrings that ``pyright --verifytypes`` complains about. diff --git a/src/trio/_core/_io_epoll.py b/src/trio/_core/_io_epoll.py index d7064dc718..7ab3f3aca8 100644 --- a/src/trio/_core/_io_epoll.py +++ b/src/trio/_core/_io_epoll.py @@ -33,6 +33,32 @@ class EpollWaiters: @attrs.frozen(eq=False) class _EpollStatistics: + """DTO class that holds information on current epoll status. + + This class can be used on any platform that supports + epoll functionality (e.g. Linux). + Trio also defines other similar classes for statistics reporting: + ``_WindowsStatistics`` and ``_KqueueStatistics``. + They are similar in function but some fields differ. + All of them have a ``backend`` attribute. + The statistics class best suited for the runtime platform is + imported as the ``IOStatistics`` type. See ``trio._core._run``. + + .. attribute:: tasks_waiting_read + + Number of tasks waiting on read. + + .. attribute:: tasks_waiting_write + + Number of tasks waiting on write. + + .. attribute:: backend + + This attribute holds a string value that corresponds to the statistics type. + This class has ``backend == "epoll"``. + Use ``backend`` attribute to distinguish statistics types at runtime. + """ + tasks_waiting_read: int tasks_waiting_write: int backend: Literal["epoll"] = attrs.field(init=False, default="epoll") diff --git a/src/trio/_core/_io_kqueue.py b/src/trio/_core/_io_kqueue.py index 80d0ce6296..514434f16d 100644 --- a/src/trio/_core/_io_kqueue.py +++ b/src/trio/_core/_io_kqueue.py @@ -26,6 +26,32 @@ @attrs.frozen(eq=False) class _KqueueStatistics: + """DTO class that holds information on current kqueue status. + + This class can be used on any platform that supports + kqueue functionality (e.g. BSD/Darwin). + Trio also defines other similar classes for statistics reporting: + ``_WindowsStatistics`` and ``_EpollStatistics``. + They are similar in function but some fields differ. + All of them have a ``backend`` attribute. + The statistics class best suited for the runtime platform is + imported as the ``IOStatistics`` type. See ``trio._core._run``. + + .. attribute:: tasks_waiting + + Number of tasks that are currently in the waiting state. + + .. attribute:: monitors + + Number of monitors. + + .. attribute:: backend + + This attribute holds a string value that corresponds to the statistics type. + This class has ``backend == "kqueue"``. + Use ``backend`` attribute to distinguish statistics types at runtime. + """ + tasks_waiting: int monitors: int backend: Literal["kqueue"] = attrs.field(init=False, default="kqueue") diff --git a/src/trio/_core/_io_windows.py b/src/trio/_core/_io_windows.py index 7b789c3dec..9c3403d937 100644 --- a/src/trio/_core/_io_windows.py +++ b/src/trio/_core/_io_windows.py @@ -293,6 +293,39 @@ class AFDGroup: @attrs.frozen(eq=False) class _WindowsStatistics: + """DTO class that holds information on current I/O waits status. + + This class is used on the Windows platform. + Trio also defines other similar classes for statistics reporting: + ``_KqueueStatistics`` and ``_EpollStatistics``. + They are similar in function but some fields differ. + All of them have a ``backend`` attribute. + The statistics class best suited for the runtime platform is + imported as the ``IOStatistics`` type. See ``trio._core._run``. + + .. attribute:: tasks_waiting_read + + Number of tasks waiting on read. + + .. attribute:: tasks_waiting_write + + Number of tasks waiting on write. + + .. attribute:: tasks_waiting_overlapped + + Number of tasks waiting on overlapped I/O operations. + + .. attribute:: completion_key_monitors + + Number of completion key monitors. + + .. attribute:: backend + + This attribute holds a string value that corresponds to the statistics type. + This class has ``backend == "windows"``. + Use ``backend`` attribute to distinguish statistics types at runtime. + """ + tasks_waiting_read: int tasks_waiting_write: int tasks_waiting_overlapped: int diff --git a/src/trio/_core/_local.py b/src/trio/_core/_local.py index 21bb913cd9..5d7885eb33 100644 --- a/src/trio/_core/_local.py +++ b/src/trio/_core/_local.py @@ -12,7 +12,13 @@ @final -class _NoValue: ... +class _NoValue: + """Sentinel class object, used as the "undefined" variable value. + + A :class:`~trio.lowlevel.RunVar` variable has this "stub" value + until the variable is assigned an actual value. + It is distinct from ``None``, which is a legitimate value a variable can hold. + """ @final diff --git a/src/trio/_core/_run.py b/src/trio/_core/_run.py index ddd4ea7ee2..93dca680d0 100644 --- a/src/trio/_core/_run.py +++ b/src/trio/_core/_run.py @@ -1486,6 +1486,17 @@ def __del__(self) -> None: @final @attrs.define(eq=False, repr=False) class Task(metaclass=NoPublicConstructor): # type: ignore[explicit-any] + """A ``Task`` object represents a concurrent "thread" of execution. + + See the :class:`~trio.lowlevel.Task` entry in Trio's lowlevel module docs for a detailed description. + Trio's task primitive wraps a coroutine (`types.CoroutineType`), + adding more functionality for stopping and resuming tasks, + for scheduling and canceling tasks, + for associating a ``Task`` with a ``Runner`` and context variables. + A ``Task`` can belong to a :class:`~trio.Nursery` and can spawn + its own child nurseries. See :class:`~trio.Nursery` docs for more information. + """ + _parent_nursery: Nursery | None coro: types.CoroutineType[Any, Outcome[object], Any] # type: ignore[explicit-any] _runner: Runner diff --git a/src/trio/_file_io.py b/src/trio/_file_io.py index d9305ef4ff..a947d9c04f 100644 --- a/src/trio/_file_io.py +++ b/src/trio/_file_io.py @@ -114,7 +114,10 @@ class _HasErrors(Protocol): def errors(self) -> str | None: ... class _HasFileNo(Protocol): - def fileno(self) -> int: ... + """Represents any file-like object that has a file descriptor.""" + + def fileno(self) -> int: + """Return the file descriptor.""" class _HasIsATTY(Protocol): def isatty(self) -> bool: ... diff --git a/src/trio/_socket.py b/src/trio/_socket.py index 504874553a..36a84c96a5 100644 --- a/src/trio/_socket.py +++ b/src/trio/_socket.py @@ -544,6 +544,11 @@ async def _resolve_address_nocp( class SocketType: + """Trio's version of the standard library's :class:`socket.socket`. + + Encompasses some Trio-specific platform handling logic. + """ + def __init__(self) -> None: # make sure this __init__ works with multiple inheritance super().__init__() diff --git a/src/trio/_subprocess.py b/src/trio/_subprocess.py index d73ba3dc23..4bb7018e8e 100644 --- a/src/trio/_subprocess.py +++ b/src/trio/_subprocess.py @@ -98,7 +98,9 @@ def pidfd_open(fd: int, flags: int) -> int: class HasFileno(Protocol): """Represents any file-like object that has a file descriptor.""" - def fileno(self) -> int: ... + def fileno(self) -> int: + """Return the file descriptor.""" + ... @final diff --git a/src/trio/_sync.py b/src/trio/_sync.py index 75d3be721a..90cdac30f6 100644 --- a/src/trio/_sync.py +++ b/src/trio/_sync.py @@ -122,12 +122,27 @@ def __bool__(self) -> Literal[True]: class _HasAcquireRelease(Protocol): """Only classes with acquire() and release() can use the mixin's implementations.""" - async def acquire(self) -> object: ... + async def acquire(self) -> object: + """Acquire the resource (lock). - def release(self) -> object: ... + See docs for :class:`~trio.Lock` and :class:`~trio.StrictFIFOLock` for usage details. + """ + + def release(self) -> object: + """Release the resource (unlock). + + See docs for :class:`~trio.Lock` and :class:`~trio.StrictFIFOLock` for usage details. + """ class AsyncContextManagerMixin: + """An async context manager base class. + + Should be used with the ``_HasAcquireRelease`` Protocol. + Calls ``await self.acquire()`` on entry and ``self.release()`` on exit, + adding :exc:`KeyboardInterrupt` protection support. + """ + @enable_ki_protection async def __aenter__(self: _HasAcquireRelease) -> None: await self.acquire() diff --git a/src/trio/_tests/_check_type_completeness.json b/src/trio/_tests/_check_type_completeness.json index d8a2948cd9..ee3668aca4 100644 --- a/src/trio/_tests/_check_type_completeness.json +++ b/src/trio/_tests/_check_type_completeness.json @@ -1,24 +1,6 @@ { - "Darwin": [ - "No docstring found for function \"trio._unix_pipes.FdStream.close\"", - "No docstring found for function \"trio._unix_pipes.FdStream.fileno\"" - ], - "Linux": [ - "No docstring found for class \"trio._core._io_epoll._EpollStatistics\"", - "No docstring found for function \"trio._unix_pipes.FdStream.close\"", - "No docstring found for function \"trio._unix_pipes.FdStream.fileno\"" - ], + "Darwin": [], + "Linux": [], "Windows": [], - "all": [ - "No docstring found for class \"trio._core._run.Task\"", - "No docstring found for class \"trio._socket.SocketType\"", - "No docstring found for function \"trio._subprocess.HasFileno.fileno\"", - "No docstring found for class \"trio._sync.AsyncContextManagerMixin\"", - "No docstring found for function \"trio._sync._HasAcquireRelease.acquire\"", - "No docstring found for function \"trio._sync._HasAcquireRelease.release\"", - "No docstring found for class \"trio._sync._LockImpl\"", - "No docstring found for class \"trio._core._local._NoValue\"", - "No docstring found for class \"trio.lowlevel.Task\"", - "No docstring found for class \"trio.socket.SocketType\"" - ] + "all": [] } diff --git a/src/trio/_tests/check_type_completeness.py b/src/trio/_tests/check_type_completeness.py index bbf38080d3..c6911da357 100755 --- a/src/trio/_tests/check_type_completeness.py +++ b/src/trio/_tests/check_type_completeness.py @@ -74,30 +74,16 @@ def has_docstring_at_runtime(name: str) -> bool: # on separate platforms. It might also be a decent idea to work the other way around, # a la test_static_tool_sees_class_members # darwin - "trio.lowlevel.current_kqueue", - "trio.lowlevel.monitor_kevent", - "trio.lowlevel.wait_kevent", "trio._core._io_kqueue._KqueueStatistics", # windows "trio._socket.SocketType.share", "trio._core._io_windows._WindowsStatistics", "trio._core._windows_cffi.Handle", - "trio.lowlevel.current_iocp", - "trio.lowlevel.monitor_completion_key", - "trio.lowlevel.readinto_overlapped", - "trio.lowlevel.register_with_iocp", - "trio.lowlevel.wait_overlapped", - "trio.lowlevel.write_overlapped", - "trio.lowlevel.WaitForSingleObject", - "trio.socket.fromshare", # linux # this test will fail on linux, but I don't develop on linux. So the next # person to do so is very welcome to open a pull request and populate with # objects # TODO: these are erroring on all platforms, why? - "trio._highlevel_generic.StapledStream.send_stream", - "trio._highlevel_generic.StapledStream.receive_stream", - "trio._ssl.SSLStream.transport_stream", "trio._file_io._HasFileNo", "trio._file_io._HasFileNo.fileno", ): diff --git a/src/trio/_unix_pipes.py b/src/trio/_unix_pipes.py index 598feb61e2..167dd56098 100644 --- a/src/trio/_unix_pipes.py +++ b/src/trio/_unix_pipes.py @@ -187,11 +187,23 @@ async def receive_some(self, max_bytes: int | None = None) -> bytes: return data def close(self) -> None: + """Close the stream and close file descriptor it's wrapping. + + See the class docstring for details. + """ self._fd_holder.close() async def aclose(self) -> None: + """Close the stream synchronously, then execute a checkpoint. + + See the class docstring for details. + """ self.close() await trio.lowlevel.checkpoint() def fileno(self) -> int: + """Return the file descriptor this `FdStream` is wrapping. + + See the class docstring for details. + """ return self._fd_holder.fd