Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow documentation builds on Windows #3227

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions docs/source/reference-lowlevel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -274,18 +274,21 @@ TODO: these are implemented, but are currently more of a sketch than
anything real. See `#26
<https://github.com/python-trio/trio/issues/26>`__.

.. function:: current_kqueue()
.. autofunction:: current_kqueue()

.. function:: wait_kevent(ident, filter, abort_func)
.. autofunction:: wait_kevent(ident, filter, abort_func)
:async:

.. function:: monitor_kevent(ident, filter)
.. autofunction:: monitor_kevent(ident, filter)
:with: queue


Windows-specific API
--------------------

.. note: this is a function and not `autofunction` since it relies on cffi
compiling some things.

.. function:: WaitForSingleObject(handle)
:async:

Expand All @@ -304,20 +307,20 @@ anything real. See `#26
<https://github.com/python-trio/trio/issues/26>`__ and `#52
<https://github.com/python-trio/trio/issues/52>`__.

.. function:: register_with_iocp(handle)
.. autofunction:: register_with_iocp(handle)

.. function:: wait_overlapped(handle, lpOverlapped)
.. autofunction:: wait_overlapped(handle, lpOverlapped)
:async:

.. function:: write_overlapped(handle, data)
.. autofunction:: write_overlapped(handle, data)
:async:

.. function:: readinto_overlapped(handle, data)
.. autofunction:: readinto_overlapped(handle, data)
:async:

.. function:: current_iocp()
.. autofunction:: current_iocp()

.. function:: monitor_completion_key()
.. autofunction:: monitor_completion_key()
:with: queue


Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,8 @@ exclude_also = [
"@overload",
'class .*\bProtocol\b.*\):',
"raise NotImplementedError",
'TODO: test this line'
'TODO: test this line',
'if "sphinx.ext.autodoc" in sys.modules:',
]
partial_branches = [
"pragma: no branch",
Expand Down
9 changes: 7 additions & 2 deletions src/trio/_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""

import sys
import typing as _t

from ._entry_queue import TrioToken
from ._exceptions import (
Expand Down Expand Up @@ -73,7 +74,9 @@
from ._unbounded_queue import UnboundedQueue, UnboundedQueueStatistics

# Windows imports
if sys.platform == "win32":
if sys.platform == "win32" or (
not _t.TYPE_CHECKING and "sphinx.ext.autodoc" in sys.modules
):
from ._run import (
current_iocp,
monitor_completion_key,
Expand All @@ -83,7 +86,9 @@
write_overlapped,
)
# Kqueue imports
elif sys.platform != "linux" and sys.platform != "win32":
if (sys.platform != "linux" and sys.platform != "win32") or (
not _t.TYPE_CHECKING and "sphinx.ext.autodoc" in sys.modules
):
from ._run import current_kqueue, monitor_kevent, wait_kevent

del sys # It would be better to import sys as _sys, but mypy does not understand it
8 changes: 7 additions & 1 deletion src/trio/_core/_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -2960,6 +2960,12 @@ def in_trio_task() -> bool:
return hasattr(GLOBAL_RUN_CONTEXT, "task")


# export everything for the documentation
if "sphinx.ext.autodoc" in sys.modules:
from ._generated_io_epoll import *
from ._generated_io_kqueue import *
from ._generated_io_windows import *

if sys.platform == "win32":
from ._generated_io_windows import *
from ._io_windows import (
Expand All @@ -2985,7 +2991,7 @@ def in_trio_task() -> bool:
_patchers = sorted({"eventlet", "gevent"}.intersection(sys.modules))
if _patchers:
raise NotImplementedError(
"unsupported platform or primitives trio depends on are monkey-patched out by "
"unsupported platform or primitives Trio depends on are monkey-patched out by "
+ ", ".join(_patchers),
)

Expand Down
13 changes: 11 additions & 2 deletions src/trio/_highlevel_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@
if TYPE_CHECKING:
from collections.abc import Generator

from typing_extensions import Buffer

from ._socket import SocketType

import sys

if sys.version_info >= (3, 12):
# NOTE: this isn't in the `TYPE_CHECKING` since for some reason
# sphinx doesn't autoreload this module for SocketStream
# (hypothesis: it's our module renaming magic)
from collections.abc import Buffer
elif TYPE_CHECKING:
from typing_extensions import Buffer

# XX TODO: this number was picked arbitrarily. We should do experiments to
# tune it. (Or make it dynamic -- one idea is to start small and increase it
# if we observe single reads filling up the whole buffer, at least within some
Expand Down Expand Up @@ -152,6 +160,7 @@ def setsockopt(self, level: int, option: int, value: int | Buffer) -> None: ...
@overload
def setsockopt(self, level: int, option: int, value: None, length: int) -> None: ...

# TODO: rename `length` to `optlen`
def setsockopt(
self,
level: int,
Expand Down
16 changes: 15 additions & 1 deletion src/trio/_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,18 @@ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:

update_wrapper(wrapper, wrapped)
if wrapped.__doc__:
module = wrapped.__module__
# these are exported specially from CPython's intersphinx inventory
module = module.replace("pathlib._local", "pathlib")
module = module.replace("pathlib._abc", "pathlib")

name = wrapped.__qualname__
name = name.replace(
"PathBase", "Path"
) # I'm not sure why this is necessary

wrapper.__doc__ = (
f"Like :meth:`~{wrapped.__module__}.{wrapped.__qualname__}`, but async.\n"
f"Like :meth:`~{module}.{name}`, but async.\n"
f"\n"
f"{cleandoc(wrapped.__doc__)}\n"
)
Expand Down Expand Up @@ -245,6 +255,10 @@ def __repr__(self) -> str:
full_match = _wrap_method(pathlib.Path.full_match)


if Path.relative_to.__doc__: # pragma: no branch
Path.relative_to.__doc__ = Path.relative_to.__doc__.replace(" `..` ", " ``..`` ")


@final
class PosixPath(Path, pathlib.PurePosixPath):
"""An async :class:`pathlib.PosixPath` that executes blocking methods in :meth:`trio.to_thread.run_sync`."""
Expand Down
3 changes: 0 additions & 3 deletions src/trio/_tests/test_unix_pipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@

if posix:
from .._unix_pipes import FdStream
else:
with pytest.raises(ImportError):
from .._unix_pipes import FdStream


async def make_pipe() -> tuple[FdStream, FdStream]:
Expand Down
5 changes: 0 additions & 5 deletions src/trio/_unix_pipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@

assert not TYPE_CHECKING or sys.platform != "win32"

if os.name != "posix":
# We raise an error here rather than gating the import in lowlevel.py
# in order to keep jedi static analysis happy.
raise ImportError

# XX TODO: is this a good number? who knows... it does match the default Linux
# pipe capacity though.
DEFAULT_RECEIVE_SIZE: FinalType = 65536
Expand Down
20 changes: 14 additions & 6 deletions src/trio/lowlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"""

# imports are renamed with leading underscores to indicate they are not part of the public API

import select as _select

# static checkers don't understand if importing this as _sys, so it's deleted later
Expand Down Expand Up @@ -60,8 +59,9 @@

# Uses `from x import y as y` for compatibility with `pyright --verifytypes` (#2625)


if sys.platform == "win32":
if sys.platform == "win32" or (
not _t.TYPE_CHECKING and "sphinx.ext.autodoc" in sys.modules
):
# Windows symbols
from ._core import (
current_iocp as current_iocp,
Expand All @@ -71,13 +71,21 @@
wait_overlapped as wait_overlapped,
write_overlapped as write_overlapped,
)
from ._wait_for_object import WaitForSingleObject as WaitForSingleObject
else:

# don't let documentation import the actual implementation
if sys.platform == "win32": # pragma: no branch
from ._wait_for_object import WaitForSingleObject as WaitForSingleObject

if sys.platform != "win32" or (
not _t.TYPE_CHECKING and "sphinx.ext.autodoc" in sys.modules
):
# Unix symbols
from ._unix_pipes import FdStream as FdStream

# Kqueue-specific symbols
if sys.platform != "linux" and (_t.TYPE_CHECKING or not hasattr(_select, "epoll")):
if (
sys.platform != "linux" and (_t.TYPE_CHECKING or not hasattr(_select, "epoll"))
) or (not _t.TYPE_CHECKING and "sphinx.ext.autodoc" in sys.modules):
from ._core import (
current_kqueue as current_kqueue,
monitor_kevent as monitor_kevent,
Expand Down