mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-03 12:54:53 -04:00
Use ParamSpec
in a few places (#12667)
This commit is contained in:
parent
c5969b346d
commit
fa0eab9c8e
14 changed files with 148 additions and 68 deletions
|
@ -15,10 +15,10 @@
|
|||
import logging
|
||||
from functools import wraps
|
||||
from types import TracebackType
|
||||
from typing import Any, Callable, Optional, Type, TypeVar, cast
|
||||
from typing import Awaitable, Callable, Optional, Type, TypeVar
|
||||
|
||||
from prometheus_client import Counter
|
||||
from typing_extensions import Protocol
|
||||
from typing_extensions import Concatenate, ParamSpec, Protocol
|
||||
|
||||
from synapse.logging.context import (
|
||||
ContextResourceUsage,
|
||||
|
@ -72,16 +72,21 @@ in_flight: InFlightGauge[_InFlightMetric] = InFlightGauge(
|
|||
)
|
||||
|
||||
|
||||
T = TypeVar("T", bound=Callable[..., Any])
|
||||
P = ParamSpec("P")
|
||||
R = TypeVar("R")
|
||||
|
||||
|
||||
class HasClock(Protocol):
|
||||
clock: Clock
|
||||
|
||||
|
||||
def measure_func(name: Optional[str] = None) -> Callable[[T], T]:
|
||||
"""
|
||||
Used to decorate an async function with a `Measure` context manager.
|
||||
def measure_func(
|
||||
name: Optional[str] = None,
|
||||
) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]:
|
||||
"""Decorate an async method with a `Measure` context manager.
|
||||
|
||||
The Measure is created using `self.clock`; it should only be used to decorate
|
||||
methods in classes defining an instance-level `clock` attribute.
|
||||
|
||||
Usage:
|
||||
|
||||
|
@ -97,18 +102,24 @@ def measure_func(name: Optional[str] = None) -> Callable[[T], T]:
|
|||
|
||||
"""
|
||||
|
||||
def wrapper(func: T) -> T:
|
||||
def wrapper(
|
||||
func: Callable[Concatenate[HasClock, P], Awaitable[R]]
|
||||
) -> Callable[P, Awaitable[R]]:
|
||||
block_name = func.__name__ if name is None else name
|
||||
|
||||
@wraps(func)
|
||||
async def measured_func(self: HasClock, *args: Any, **kwargs: Any) -> Any:
|
||||
async def measured_func(self: HasClock, *args: P.args, **kwargs: P.kwargs) -> R:
|
||||
with Measure(self.clock, block_name):
|
||||
r = await func(self, *args, **kwargs)
|
||||
return r
|
||||
|
||||
return cast(T, measured_func)
|
||||
# There are some shenanigans here, because we're decorating a method but
|
||||
# explicitly making use of the `self` parameter. The key thing here is that the
|
||||
# return type within the return type for `measure_func` itself describes how the
|
||||
# decorated function will be called.
|
||||
return measured_func # type: ignore[return-value]
|
||||
|
||||
return wrapper
|
||||
return wrapper # type: ignore[return-value]
|
||||
|
||||
|
||||
class Measure:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue