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

typecheck _socket and _core._local #2705

Merged
merged 23 commits into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
83f22ec
adding typehints to _socket and friends
jakkdl Jul 14, 2023
ba5a6ee
Change fromfd() to use the correct type for file descriptors
TeamSpen210 Jul 15, 2023
aa32d87
This also needs to be guarded under TYPE_CHECKING
TeamSpen210 Jul 15, 2023
30e272b
revert changes for python <3.8
jakkdl Jul 17, 2023
399cce7
fixes after review from TeamSpen210
jakkdl Jul 17, 2023
32af4fc
Merge remote-tracking branch 'origin/master' into typing_improvements…
jakkdl Jul 17, 2023
dd828c2
"fix" readthedocs build
jakkdl Jul 17, 2023
87a05be
set merge strategy in .gitattributes
jakkdl Jul 21, 2023
f7fee29
Merge remote-tracking branch 'origin/master' into typing_improvements…
jakkdl Jul 21, 2023
06e004d
fixes after review by A5rocks
jakkdl Jul 21, 2023
2142252
use / for pos-only args
jakkdl Jul 23, 2023
576cb6d
Merge branch 'master' into typing_improvements_socket
jakkdl Jul 23, 2023
7f0911e
Merge remote-tracking branch 'origin/master' into typing_improvements…
jakkdl Jul 26, 2023
831087f
add test to setsockopt, update comments
jakkdl Jul 27, 2023
d8df8cc
Merge remote-tracking branch 'origin/master' into typing_improvements…
jakkdl Jul 27, 2023
37c7944
fix tests on non-linux
jakkdl Jul 27, 2023
c3f3c9d
Merge remote-tracking branch 'origin/master' into typing_improvements…
jakkdl Jul 27, 2023
3972526
Fix missing sys import in test_socket
TeamSpen210 Jul 28, 2023
a06aee2
somewhat hackish cross-platform test
jakkdl Jul 28, 2023
5abc8ce
skip hacky test
jakkdl Jul 28, 2023
8a8b0b7
Merge remote-tracking branch 'origin/master' into typing_improvements…
jakkdl Jul 28, 2023
22fa8df
remove extraneous lines
jakkdl Jul 29, 2023
975da8a
Update trio/_core/_local.py
jakkdl Jul 29, 2023
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
2 changes: 2 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
("py:obj", "trio._abc.SendType"),
("py:obj", "trio._abc.T"),
("py:obj", "trio._abc.T_resource"),
("py:class", "trio._threads.T"),
# why aren't these found in stdlib?
("py:class", "types.FrameType"),
("py:class", "P.args"),
("py:class", "P.kwargs"),
Expand Down
8 changes: 8 additions & 0 deletions docs/source/reference-io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,14 @@ Socket objects
* :meth:`~socket.socket.set_inheritable`
* :meth:`~socket.socket.get_inheritable`

The internal SocketType
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: _SocketType
..
TODO: adding `:members:` here gives error due to overload+_wraps on `sendto`
TODO: rewrite ... all of the above when fixing _SocketType vs SocketType


.. currentmodule:: trio


Expand Down
15 changes: 10 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,25 @@ disallow_untyped_defs = false
# downstream and users have to deal with them.
[[tool.mypy.overrides]]
module = [
"trio._path",
"trio._socket",
"trio._core._local",
"trio._sync",
"trio._file_io",
]
disallow_incomplete_defs = true
disallow_untyped_defs = true
disallow_any_generics = true
disallow_any_decorated = true
disallow_subclassing_any = true

[[tool.mypy.overrides]]
module = [
"trio._dtls",
"trio._abc"
"trio._path",
]
disallow_incomplete_defs = true
disallow_untyped_defs = true
disallow_any_generics = true
disallow_any_decorated = true
#disallow_any_generics = true
#disallow_any_decorated = true
disallow_subclassing_any = true

[tool.pytest.ini_options]
Expand Down
66 changes: 38 additions & 28 deletions trio/_core/_local.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
from __future__ import annotations

from typing import Generic, TypeVar, final

# Runvar implementations
import attr

from .._util import Final
from .._util import Final, NoPublicConstructor
from . import _run

T = TypeVar("T")


@final
class _NoValue:
jakkdl marked this conversation as resolved.
Show resolved Hide resolved
...

@attr.s(eq=False, hash=False, slots=True)
class _RunVarToken:
_no_value = object()

_var = attr.ib()
previous_value = attr.ib(default=_no_value)
redeemed = attr.ib(default=False, init=False)
@attr.s(eq=False, hash=False, slots=False)
class RunVarToken(Generic[T], metaclass=NoPublicConstructor):
_var: RunVar[T] = attr.ib()
previous_value: T | type[_NoValue] = attr.ib(default=_NoValue)
redeemed: bool = attr.ib(default=False, init=False)

@classmethod
def empty(cls, var):
return cls(var)
def _empty(cls, var: RunVar[T]) -> RunVarToken[T]:
return cls._create(var)


@attr.s(eq=False, hash=False, slots=True)
class RunVar(metaclass=Final):
class RunVar(Generic[T], metaclass=Final):
"""The run-local variant of a context variable.

:class:`RunVar` objects are similar to context variable objects,
Expand All @@ -28,44 +37,45 @@ class RunVar(metaclass=Final):

"""

_NO_DEFAULT = object()
_name = attr.ib()
_default = attr.ib(default=_NO_DEFAULT)
_name: str = attr.ib()
_default: T | type[_NoValue] = attr.ib(default=_NoValue)

def get(self, default=_NO_DEFAULT):
def get(self, default: T | type[_NoValue] = _NoValue) -> T:
"""Gets the value of this :class:`RunVar` for the current run call."""
try:
return _run.GLOBAL_RUN_CONTEXT.runner._locals[self]
# not typed yet
return _run.GLOBAL_RUN_CONTEXT.runner._locals[self] # type: ignore[return-value, index]
except AttributeError:
raise RuntimeError("Cannot be used outside of a run context") from None
except KeyError:
# contextvars consistency
if default is not self._NO_DEFAULT:
return default
# `type: ignore` awaiting https://github.com/python/mypy/issues/15553 to be fixed & released
if default is not _NoValue:
return default # type: ignore[return-value]

if self._default is not self._NO_DEFAULT:
return self._default
if self._default is not _NoValue:
return self._default # type: ignore[return-value]

raise LookupError(self) from None

def set(self, value):
def set(self, value: T) -> RunVarToken[T]:
"""Sets the value of this :class:`RunVar` for this current run
call.

"""
try:
old_value = self.get()
except LookupError:
token = _RunVarToken.empty(self)
token = RunVarToken._empty(self)
else:
token = _RunVarToken(self, old_value)
token = RunVarToken[T]._create(self, old_value)

# This can't fail, because if we weren't in Trio context then the
# get() above would have failed.
_run.GLOBAL_RUN_CONTEXT.runner._locals[self] = value
_run.GLOBAL_RUN_CONTEXT.runner._locals[self] = value # type: ignore[assignment, index]
return token

def reset(self, token):
def reset(self, token: RunVarToken[T]) -> None:
"""Resets the value of this :class:`RunVar` to what it was
previously specified by the token.

Expand All @@ -81,14 +91,14 @@ def reset(self, token):

previous = token.previous_value
try:
if previous is _RunVarToken._no_value:
_run.GLOBAL_RUN_CONTEXT.runner._locals.pop(self)
if previous is _NoValue:
_run.GLOBAL_RUN_CONTEXT.runner._locals.pop(self) # type: ignore[arg-type]
else:
_run.GLOBAL_RUN_CONTEXT.runner._locals[self] = previous
_run.GLOBAL_RUN_CONTEXT.runner._locals[self] = previous # type: ignore[index, assignment]
except AttributeError:
raise RuntimeError("Cannot be used outside of a run context")

token.redeemed = True

def __repr__(self):
def __repr__(self) -> str:
return f"<RunVar name={self._name!r}>"
Loading