Compare commits
4 Commits
develop
...
clokep/pus
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
239630a31a | ||
|
|
471724b9eb | ||
|
|
1efb8b90ba | ||
|
|
665ef9f495 |
@@ -22,7 +22,13 @@ import mypy.types
|
|||||||
from mypy.erasetype import remove_instance_last_known_values
|
from mypy.erasetype import remove_instance_last_known_values
|
||||||
from mypy.errorcodes import ErrorCode
|
from mypy.errorcodes import ErrorCode
|
||||||
from mypy.nodes import ARG_NAMED_OPT, TempNode, Var
|
from mypy.nodes import ARG_NAMED_OPT, TempNode, Var
|
||||||
from mypy.plugin import FunctionSigContext, MethodSigContext, Plugin
|
from mypy.plugin import (
|
||||||
|
FunctionSigContext,
|
||||||
|
MethodSigContext,
|
||||||
|
Plugin,
|
||||||
|
AttributeContext,
|
||||||
|
CheckerPluginInterface,
|
||||||
|
)
|
||||||
from mypy.typeops import bind_self
|
from mypy.typeops import bind_self
|
||||||
from mypy.types import (
|
from mypy.types import (
|
||||||
AnyType,
|
AnyType,
|
||||||
@@ -40,13 +46,13 @@ class SynapsePlugin(Plugin):
|
|||||||
def get_method_signature_hook(
|
def get_method_signature_hook(
|
||||||
self, fullname: str
|
self, fullname: str
|
||||||
) -> Optional[Callable[[MethodSigContext], CallableType]]:
|
) -> Optional[Callable[[MethodSigContext], CallableType]]:
|
||||||
if fullname.startswith(
|
# if fullname.startswith(
|
||||||
(
|
# (
|
||||||
"synapse.util.caches.descriptors.CachedFunction.__call__",
|
# "synapse.util.caches.descriptors.CachedFunction.__call__",
|
||||||
"synapse.util.caches.descriptors._LruCachedFunction.__call__",
|
# "synapse.util.caches.descriptors._LruCachedFunction.__call__",
|
||||||
)
|
# )
|
||||||
):
|
# ):
|
||||||
return cached_function_method_signature
|
# return cached_function_method_signature
|
||||||
|
|
||||||
if fullname in (
|
if fullname in (
|
||||||
"synapse.util.caches.descriptors._CachedFunctionDescriptor.__call__",
|
"synapse.util.caches.descriptors._CachedFunctionDescriptor.__call__",
|
||||||
@@ -56,6 +62,15 @@ class SynapsePlugin(Plugin):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_attribute_hook(
|
||||||
|
self, fullname: str
|
||||||
|
) -> Optional[Callable[[AttributeContext], mypy.types.Type]]:
|
||||||
|
# Anything in synapse could be wrapped with the cached decorator, but
|
||||||
|
# we know that anything else is *not*.
|
||||||
|
if fullname == "synapse.util.caches.descriptors.CachedFunction.__call__":
|
||||||
|
return cached_function_method_attribute
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _get_true_return_type(signature: CallableType) -> mypy.types.Type:
|
def _get_true_return_type(signature: CallableType) -> mypy.types.Type:
|
||||||
"""
|
"""
|
||||||
@@ -79,6 +94,22 @@ def _get_true_return_type(signature: CallableType) -> mypy.types.Type:
|
|||||||
|
|
||||||
|
|
||||||
def cached_function_method_signature(ctx: MethodSigContext) -> CallableType:
|
def cached_function_method_signature(ctx: MethodSigContext) -> CallableType:
|
||||||
|
return _unwrap_cached_decoratored_function(ctx.default_signature, ctx.api)
|
||||||
|
|
||||||
|
|
||||||
|
def cached_function_method_attribute(ctx: AttributeContext) -> mypy.types.Type:
|
||||||
|
if isinstance(ctx.default_attr_type, Instance):
|
||||||
|
wrapped_callable = ctx.default_attr_type.args[0]
|
||||||
|
assert isinstance(wrapped_callable, CallableType)
|
||||||
|
return ctx.default_attr_type.copy_modified(
|
||||||
|
args=[_unwrap_cached_decoratored_function(wrapped_callable, ctx.api)]
|
||||||
|
)
|
||||||
|
return ctx.default_attr_type
|
||||||
|
|
||||||
|
|
||||||
|
def _unwrap_cached_decoratored_function(
|
||||||
|
wrapped_signature: CallableType, api: CheckerPluginInterface
|
||||||
|
) -> CallableType:
|
||||||
"""Fixes the `CachedFunction.__call__` signature to be correct.
|
"""Fixes the `CachedFunction.__call__` signature to be correct.
|
||||||
|
|
||||||
It already has *almost* the correct signature, except:
|
It already has *almost* the correct signature, except:
|
||||||
@@ -90,12 +121,12 @@ def cached_function_method_signature(ctx: MethodSigContext) -> CallableType:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# 1. Mark this as a bound function signature.
|
# 1. Mark this as a bound function signature.
|
||||||
signature: CallableType = bind_self(ctx.default_signature)
|
signature: CallableType = bind_self(wrapped_signature)
|
||||||
|
|
||||||
# 2. Remove any "cache_context" args.
|
# 2. Remove any "cache_context" args.
|
||||||
#
|
#
|
||||||
# Note: We should be only doing this if `cache_context=True` is set, but if
|
# Note: We should be only doing this if `cache_context=True` is set, but if
|
||||||
# it isn't then the code will raise an exception when its called anyway, so
|
# it isn't then the code will raise an exception when it's called anyway, so
|
||||||
# it's not the end of the world.
|
# it's not the end of the world.
|
||||||
context_arg_index = None
|
context_arg_index = None
|
||||||
for idx, name in enumerate(signature.arg_names):
|
for idx, name in enumerate(signature.arg_names):
|
||||||
@@ -125,7 +156,7 @@ def cached_function_method_signature(ctx: MethodSigContext) -> CallableType:
|
|||||||
arg_kinds=[],
|
arg_kinds=[],
|
||||||
arg_names=[],
|
arg_names=[],
|
||||||
ret_type=NoneType(),
|
ret_type=NoneType(),
|
||||||
fallback=ctx.api.named_generic_type("builtins.function", []),
|
fallback=api.named_generic_type("builtins.function", []),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@@ -137,12 +168,12 @@ def cached_function_method_signature(ctx: MethodSigContext) -> CallableType:
|
|||||||
# 4. Ensure the return type is a Deferred.
|
# 4. Ensure the return type is a Deferred.
|
||||||
ret_arg = _get_true_return_type(signature)
|
ret_arg = _get_true_return_type(signature)
|
||||||
|
|
||||||
# This should be able to use ctx.api.named_generic_type, but that doesn't seem
|
# This should be able to use api.named_generic_type, but that doesn't seem
|
||||||
# to find the correct symbol for anything more than 1 module deep.
|
# to find the correct symbol for anything more than 1 module deep.
|
||||||
#
|
#
|
||||||
# modules is not part of CheckerPluginInterface. The following is a combination
|
# modules is not part of CheckerPluginInterface. The following is a combination
|
||||||
# of TypeChecker.named_generic_type and TypeChecker.lookup_typeinfo.
|
# of TypeChecker.named_generic_type and TypeChecker.lookup_typeinfo.
|
||||||
sym = ctx.api.modules["twisted.internet.defer"].names.get("Deferred") # type: ignore[attr-defined]
|
sym = api.modules["twisted.internet.defer"].names.get("Deferred") # type: ignore[attr-defined]
|
||||||
ret_type = Instance(sym.node, [remove_instance_last_known_values(ret_arg)])
|
ret_type = Instance(sym.node, [remove_instance_last_known_values(ret_arg)])
|
||||||
|
|
||||||
signature = signature.copy_modified(
|
signature = signature.copy_modified(
|
||||||
|
|||||||
@@ -350,40 +350,32 @@ class BulkPushRuleEvaluator:
|
|||||||
actions_by_user: Dict[str, Collection[Union[Mapping, str]]] = {}
|
actions_by_user: Dict[str, Collection[Union[Mapping, str]]] = {}
|
||||||
|
|
||||||
# Gather a bunch of info in parallel.
|
# Gather a bunch of info in parallel.
|
||||||
#
|
|
||||||
# This has a lot of ignored types and casting due to the use of @cached
|
|
||||||
# decorated functions passed into run_in_background.
|
|
||||||
#
|
|
||||||
# See https://github.com/matrix-org/synapse/issues/16606
|
|
||||||
(
|
(
|
||||||
room_member_count,
|
room_member_count,
|
||||||
(power_levels, sender_power_level),
|
(power_levels, sender_power_level),
|
||||||
related_events,
|
related_events,
|
||||||
profiles,
|
profiles,
|
||||||
) = await make_deferred_yieldable(
|
) = await make_deferred_yieldable(
|
||||||
cast(
|
gather_results(
|
||||||
"Deferred[Tuple[int, Tuple[dict, Optional[int]], Dict[str, Dict[str, JsonValue]], Mapping[str, ProfileInfo]]]",
|
(
|
||||||
gather_results(
|
run_in_background(
|
||||||
(
|
self.store.get_number_joined_users_in_room, event.room_id
|
||||||
run_in_background( # type: ignore[call-arg]
|
|
||||||
self.store.get_number_joined_users_in_room, event.room_id # type: ignore[arg-type]
|
|
||||||
),
|
|
||||||
run_in_background(
|
|
||||||
self._get_power_levels_and_sender_level,
|
|
||||||
event,
|
|
||||||
context,
|
|
||||||
event_id_to_event,
|
|
||||||
),
|
|
||||||
run_in_background(self._related_events, event),
|
|
||||||
run_in_background( # type: ignore[call-arg]
|
|
||||||
self.store.get_subset_users_in_room_with_profiles,
|
|
||||||
event.room_id, # type: ignore[arg-type]
|
|
||||||
rules_by_user.keys(), # type: ignore[arg-type]
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
consumeErrors=True,
|
run_in_background(
|
||||||
).addErrback(unwrapFirstError),
|
self._get_power_levels_and_sender_level,
|
||||||
)
|
event,
|
||||||
|
context,
|
||||||
|
event_id_to_event,
|
||||||
|
),
|
||||||
|
run_in_background(self._related_events, event),
|
||||||
|
run_in_background(
|
||||||
|
self.store.get_subset_users_in_room_with_profiles,
|
||||||
|
event.room_id,
|
||||||
|
rules_by_user.keys(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
consumeErrors=True,
|
||||||
|
).addErrback(unwrapFirstError)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Find the event's thread ID.
|
# Find the event's thread ID.
|
||||||
|
|||||||
@@ -395,9 +395,9 @@ def gather_results(
|
|||||||
|
|
||||||
|
|
||||||
def gather_results( # type: ignore[misc]
|
def gather_results( # type: ignore[misc]
|
||||||
deferredList: Tuple["defer.Deferred[T1]", ...],
|
deferredList: Tuple["defer.Deferred[Any]", ...],
|
||||||
consumeErrors: bool = False,
|
consumeErrors: bool = False,
|
||||||
) -> "defer.Deferred[Tuple[T1, ...]]":
|
) -> "defer.Deferred[Tuple[Any, ...]]":
|
||||||
"""Combines a tuple of `Deferred`s into a single `Deferred`.
|
"""Combines a tuple of `Deferred`s into a single `Deferred`.
|
||||||
|
|
||||||
Wraps `defer.gatherResults` to provide type annotations that support heterogenous
|
Wraps `defer.gatherResults` to provide type annotations that support heterogenous
|
||||||
|
|||||||
Reference in New Issue
Block a user