Skip to content

Commit cf1f3c7

Browse files
jakkdlTeamSpen210A5rocks
authored
typecheck _socket and _core._local (#2705)
* add type hints to _socket and _core.local --------- Co-authored-by: Spencer Brown <[email protected]> Co-authored-by: EXPLOSION <[email protected]>
1 parent 2fd005b commit cf1f3c7

File tree

10 files changed

+455
-189
lines changed

10 files changed

+455
-189
lines changed

docs/source/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
("py:obj", "trio._abc.SendType"),
6363
("py:obj", "trio._abc.T"),
6464
("py:obj", "trio._abc.T_resource"),
65+
("py:class", "trio._threads.T"),
66+
# why aren't these found in stdlib?
6567
("py:class", "types.FrameType"),
6668
("py:class", "P.args"),
6769
("py:class", "P.kwargs"),

docs/source/reference-io.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,14 @@ Socket objects
504504
* :meth:`~socket.socket.set_inheritable`
505505
* :meth:`~socket.socket.get_inheritable`
506506

507+
The internal SocketType
508+
~~~~~~~~~~~~~~~~~~~~~~~~~~
509+
.. autoclass:: _SocketType
510+
..
511+
TODO: adding `:members:` here gives error due to overload+_wraps on `sendto`
512+
TODO: rewrite ... all of the above when fixing _SocketType vs SocketType
513+
514+
507515
.. currentmodule:: trio
508516

509517

pyproject.toml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,25 @@ disallow_untyped_defs = false
4848
# downstream and users have to deal with them.
4949
[[tool.mypy.overrides]]
5050
module = [
51-
"trio._path",
51+
"trio._socket",
52+
"trio._core._local",
53+
"trio._sync",
5254
"trio._file_io",
5355
]
56+
disallow_incomplete_defs = true
5457
disallow_untyped_defs = true
58+
disallow_any_generics = true
59+
disallow_any_decorated = true
60+
disallow_subclassing_any = true
5561

5662
[[tool.mypy.overrides]]
5763
module = [
58-
"trio._dtls",
59-
"trio._abc"
64+
"trio._path",
6065
]
6166
disallow_incomplete_defs = true
6267
disallow_untyped_defs = true
63-
disallow_any_generics = true
64-
disallow_any_decorated = true
68+
#disallow_any_generics = true
69+
#disallow_any_decorated = true
6570
disallow_subclassing_any = true
6671

6772
[tool.pytest.ini_options]

trio/_core/_local.py

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
1+
from __future__ import annotations
2+
3+
from typing import Generic, TypeVar, final
4+
15
# Runvar implementations
26
import attr
37

4-
from .._util import Final
8+
from .._util import Final, NoPublicConstructor
59
from . import _run
610

11+
T = TypeVar("T")
12+
13+
14+
@final
15+
class _NoValue(metaclass=Final):
16+
...
717

8-
@attr.s(eq=False, hash=False, slots=True)
9-
class _RunVarToken:
10-
_no_value = object()
1118

12-
_var = attr.ib()
13-
previous_value = attr.ib(default=_no_value)
14-
redeemed = attr.ib(default=False, init=False)
19+
@attr.s(eq=False, hash=False, slots=False)
20+
class RunVarToken(Generic[T], metaclass=NoPublicConstructor):
21+
_var: RunVar[T] = attr.ib()
22+
previous_value: T | type[_NoValue] = attr.ib(default=_NoValue)
23+
redeemed: bool = attr.ib(default=False, init=False)
1524

1625
@classmethod
17-
def empty(cls, var):
18-
return cls(var)
26+
def _empty(cls, var: RunVar[T]) -> RunVarToken[T]:
27+
return cls._create(var)
1928

2029

2130
@attr.s(eq=False, hash=False, slots=True)
22-
class RunVar(metaclass=Final):
31+
class RunVar(Generic[T], metaclass=Final):
2332
"""The run-local variant of a context variable.
2433
2534
:class:`RunVar` objects are similar to context variable objects,
@@ -28,44 +37,45 @@ class RunVar(metaclass=Final):
2837
2938
"""
3039

31-
_NO_DEFAULT = object()
32-
_name = attr.ib()
33-
_default = attr.ib(default=_NO_DEFAULT)
40+
_name: str = attr.ib()
41+
_default: T | type[_NoValue] = attr.ib(default=_NoValue)
3442

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

46-
if self._default is not self._NO_DEFAULT:
47-
return self._default
56+
if self._default is not _NoValue:
57+
return self._default # type: ignore[return-value]
4858

4959
raise LookupError(self) from None
5060

51-
def set(self, value):
61+
def set(self, value: T) -> RunVarToken[T]:
5262
"""Sets the value of this :class:`RunVar` for this current run
5363
call.
5464
5565
"""
5666
try:
5767
old_value = self.get()
5868
except LookupError:
59-
token = _RunVarToken.empty(self)
69+
token = RunVarToken._empty(self)
6070
else:
61-
token = _RunVarToken(self, old_value)
71+
token = RunVarToken[T]._create(self, old_value)
6272

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

68-
def reset(self, token):
78+
def reset(self, token: RunVarToken[T]) -> None:
6979
"""Resets the value of this :class:`RunVar` to what it was
7080
previously specified by the token.
7181
@@ -81,14 +91,14 @@ def reset(self, token):
8191

8292
previous = token.previous_value
8393
try:
84-
if previous is _RunVarToken._no_value:
85-
_run.GLOBAL_RUN_CONTEXT.runner._locals.pop(self)
94+
if previous is _NoValue:
95+
_run.GLOBAL_RUN_CONTEXT.runner._locals.pop(self) # type: ignore[arg-type]
8696
else:
87-
_run.GLOBAL_RUN_CONTEXT.runner._locals[self] = previous
97+
_run.GLOBAL_RUN_CONTEXT.runner._locals[self] = previous # type: ignore[index, assignment]
8898
except AttributeError:
8999
raise RuntimeError("Cannot be used outside of a run context")
90100

91101
token.redeemed = True
92102

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

0 commit comments

Comments
 (0)