Skip to content

Commit

Permalink
Update mypy to 0.950 and fix complaints (matrix-org#12650)
Browse files Browse the repository at this point in the history
  • Loading branch information
David Robertson authored May 6, 2022
1 parent c2d50e9 commit 2607b3e
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 57 deletions.
1 change: 1 addition & 0 deletions changelog.d/12650.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update to mypy 0.950.
64 changes: 34 additions & 30 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ flake8-bugbear = "==21.3.2"
flake8 = "*"

# Typechecking
mypy = "==0.931"
mypy-zope = "==0.3.5"
mypy = "*"
mypy-zope = "*"
types-bleach = ">=4.1.0"
types-commonmark = ">=0.9.2"
types-jsonschema = ">=3.2.0"
Expand Down
19 changes: 13 additions & 6 deletions stubs/sortedcontainers/sorteddict.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,19 @@ class SortedDict(Dict[_KT, _VT]):
def popitem(self, index: int = ...) -> Tuple[_KT, _VT]: ...
def peekitem(self, index: int = ...) -> Tuple[_KT, _VT]: ...
def setdefault(self, key: _KT, default: Optional[_VT] = ...) -> _VT: ...
@overload
def update(self, __map: Mapping[_KT, _VT], **kwargs: _VT) -> None: ...
@overload
def update(self, __iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ...
@overload
def update(self, **kwargs: _VT) -> None: ...
# Mypy now reports the first overload as an error, because typeshed widened the type
# of `__map` to its internal `_typeshed.SupportsKeysAndGetItem` type in
# https://github.com/python/typeshed/pull/6653
# Since sorteddicts don't change the signature of `update` from that of `dict`, we
# let the stubs for `update` inherit from the stubs for `dict`. (I suspect we could
# do the same for many othe methods.) We leave the stubs commented to better track
# how this file has evolved from the original stubs.
# @overload
# def update(self, __map: Mapping[_KT, _VT], **kwargs: _VT) -> None: ...
# @overload
# def update(self, __iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ...
# @overload
# def update(self, **kwargs: _VT) -> None: ...
def __reduce__(
self,
) -> Tuple[
Expand Down
3 changes: 2 additions & 1 deletion synapse/appservice/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Tuple

from prometheus_client import Counter
from typing_extensions import TypeGuard

from synapse.api.constants import EventTypes, Membership, ThirdPartyEntityKind
from synapse.api.errors import CodeMessageException
Expand Down Expand Up @@ -66,7 +67,7 @@ def _is_valid_3pe_metadata(info: JsonDict) -> bool:
return True


def _is_valid_3pe_result(r: JsonDict, field: str) -> bool:
def _is_valid_3pe_result(r: object, field: str) -> TypeGuard[JsonDict]:
if not isinstance(r, dict):
return False

Expand Down
3 changes: 2 additions & 1 deletion synapse/config/appservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ def load_appservices(
) -> List[ApplicationService]:
"""Returns a list of Application Services from the config files."""
if not isinstance(config_files, list):
logger.warning("Expected %s to be a list of AS config files.", config_files)
# type-ignore: this function gets arbitrary json value; we do use this path.
logger.warning("Expected %s to be a list of AS config files.", config_files) # type: ignore[unreachable]
return []

# Dicts of value -> filename
Expand Down
4 changes: 3 additions & 1 deletion synapse/events/presence_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ async def get_users_for_states(
# run all the callbacks for get_users_for_states and combine the results
for callback in self._get_users_for_states_callbacks:
try:
result = await callback(state_updates)
# Note: result is an object here, because we don't trust modules to
# return the types they're supposed to.
result: object = await callback(state_updates)
except Exception as e:
logger.warning("Failed to run module API callback %s: %s", callback, e)
continue
Expand Down
3 changes: 2 additions & 1 deletion synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -1427,7 +1427,7 @@ async def persist_and_notify_client_event(
# Validate a newly added alias or newly added alt_aliases.

original_alias = None
original_alt_aliases: List[str] = []
original_alt_aliases: object = []

original_event_id = event.unsigned.get("replaces_state")
if original_event_id:
Expand Down Expand Up @@ -1455,6 +1455,7 @@ async def persist_and_notify_client_event(
# If the old version of alt_aliases is of an unknown form,
# completely replace it.
if not isinstance(original_alt_aliases, (list, tuple)):
# TODO: check that the original_alt_aliases' entries are all strings
original_alt_aliases = []

# Check that each alias is currently valid.
Expand Down
44 changes: 34 additions & 10 deletions synapse/metrics/background_process_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
Type,
TypeVar,
Union,
cast,
)

from prometheus_client import Metric
from prometheus_client.core import REGISTRY, Counter, Gauge
from typing_extensions import ParamSpec

from twisted.internet import defer

Expand Down Expand Up @@ -256,24 +256,48 @@ async def run() -> Optional[R]:
return defer.ensureDeferred(run())


F = TypeVar("F", bound=Callable[..., Awaitable[Optional[Any]]])
P = ParamSpec("P")


def wrap_as_background_process(desc: str) -> Callable[[F], F]:
"""Decorator that wraps a function that gets called as a background
process.
def wrap_as_background_process(
desc: str,
) -> Callable[
[Callable[P, Awaitable[Optional[R]]]],
Callable[P, "defer.Deferred[Optional[R]]"],
]:
"""Decorator that wraps an asynchronous function `func`, returning a synchronous
decorated function. Calling the decorated version runs `func` as a background
process, forwarding all arguments verbatim.
That is,
@wrap_as_background_process
def func(*args): ...
func(1, 2, third=3)
is equivalent to:
def func(*args): ...
run_as_background_process(func, 1, 2, third=3)
Equivalent to calling the function with `run_as_background_process`
The former can be convenient if `func` needs to be run as a background process in
multiple places.
"""

def wrap_as_background_process_inner(func: F) -> F:
def wrap_as_background_process_inner(
func: Callable[P, Awaitable[Optional[R]]]
) -> Callable[P, "defer.Deferred[Optional[R]]"]:
@wraps(func)
def wrap_as_background_process_inner_2(
*args: Any, **kwargs: Any
*args: P.args, **kwargs: P.kwargs
) -> "defer.Deferred[Optional[R]]":
return run_as_background_process(desc, func, *args, **kwargs)
# type-ignore: mypy is confusing kwargs with the bg_start_span kwarg.
# Argument 4 to "run_as_background_process" has incompatible type
# "**P.kwargs"; expected "bool"
# See https://github.com/python/mypy/issues/8862
return run_as_background_process(desc, func, *args, **kwargs) # type: ignore[arg-type]

return cast(F, wrap_as_background_process_inner_2)
return wrap_as_background_process_inner_2

return wrap_as_background_process_inner

Expand Down
10 changes: 5 additions & 5 deletions tests/storage/test_monthly_active_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,19 +222,19 @@ def test_reap_monthly_active_users_reserved_users(self):
self.store.user_add_threepid(user, "email", email, now, now)
)

d = self.store.db_pool.runInteraction(
"initialise", self.store._initialise_reserved_users, threepids
self.get_success(
self.store.db_pool.runInteraction(
"initialise", self.store._initialise_reserved_users, threepids
)
)
self.get_success(d)

count = self.get_success(self.store.get_monthly_active_count())
self.assertEqual(count, initial_users)

users = self.get_success(self.store.get_registered_reserved_users())
self.assertEqual(len(users), reserved_user_number)

d = self.store.reap_monthly_active_users()
self.get_success(d)
self.get_success(self.store.reap_monthly_active_users())

count = self.get_success(self.store.get_monthly_active_count())
self.assertEqual(count, self.hs.config.server.max_mau_value)
Expand Down

0 comments on commit 2607b3e

Please sign in to comment.