Skip to content

Commit dc27238

Browse files
committed
Make lambda_handler_decorator grow up a little
1 parent a3960b3 commit dc27238

File tree

1 file changed

+22
-10
lines changed
  • aws_lambda_powertools/middleware_factory

1 file changed

+22
-10
lines changed

aws_lambda_powertools/middleware_factory/factory.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import inspect
33
import logging
44
import os
5-
from typing import Any, Callable, Optional
5+
from typing import Any, Callable, Optional, TypeVar, cast
66

77
from ..shared import constants
88
from ..shared.functions import resolve_truthy_env_var_choice
@@ -11,9 +11,14 @@
1111

1212
logger = logging.getLogger(__name__)
1313

14+
FuncType = TypeVar("FuncType", bound=Callable[..., Any])
15+
1416

1517
# Maintenance: we can't yet provide an accurate return type without ParamSpec etc. see #1066
16-
def lambda_handler_decorator(decorator: Optional[Callable] = None, trace_execution: Optional[bool] = None) -> Callable:
18+
def lambda_handler_decorator(
19+
decorator: Optional[Callable[..., Any]] = None,
20+
trace_execution: Optional[bool] = None,
21+
) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
1722
"""Decorator factory for decorating Lambda handlers.
1823
1924
You can use lambda_handler_decorator to create your own middlewares,
@@ -34,7 +39,7 @@ def lambda_handler_decorator(decorator: Optional[Callable] = None, trace_executi
3439
3540
Parameters
3641
----------
37-
decorator: Callable
42+
decorator: Callable[..., Any]
3843
Middleware to be wrapped by this factory
3944
trace_execution: bool
4045
Flag to explicitly enable trace execution for middlewares.\n
@@ -104,18 +109,21 @@ def lambda_handler(event, context):
104109
"""
105110

106111
if decorator is None:
107-
return functools.partial(lambda_handler_decorator, trace_execution=trace_execution)
112+
return cast(
113+
Callable[[Callable[..., Any]], Callable[..., Any]],
114+
functools.partial(lambda_handler_decorator, trace_execution=trace_execution),
115+
)
108116

109117
trace_execution = resolve_truthy_env_var_choice(
110118
env=os.getenv(constants.MIDDLEWARE_FACTORY_TRACE_ENV, "false"),
111119
choice=trace_execution,
112120
)
113121

114122
@functools.wraps(decorator)
115-
def final_decorator(func: Optional[Callable] = None, **kwargs: Any):
123+
def final_decorator(func: Optional[FuncType] = None, *args: Any, **kwargs: Any) -> FuncType:
116124
# If called with kwargs return new func with kwargs
117125
if func is None:
118-
return functools.partial(final_decorator, **kwargs)
126+
return cast(FuncType, functools.partial(final_decorator, *args, **kwargs))
119127

120128
if not inspect.isfunction(func):
121129
# @custom_middleware(True) vs @custom_middleware(log_event=True)
@@ -124,9 +132,11 @@ def final_decorator(func: Optional[Callable] = None, **kwargs: Any):
124132
)
125133

126134
@functools.wraps(func)
127-
def wrapper(event, context, **handler_kwargs):
135+
def wrapper(*args: Any, **kwargs: Any) -> Any:
128136
try:
129-
middleware = functools.partial(decorator, func, event, context, **kwargs, **handler_kwargs)
137+
if decorator is None:
138+
raise ValueError("Decorator cannot be None")
139+
middleware = functools.partial(decorator, func, *args, **kwargs)
130140
if trace_execution:
131141
tracer = Tracer(auto_patch=False)
132142
with tracer.provider.in_subsegment(name=f"## {decorator.__qualname__}"):
@@ -135,9 +145,11 @@ def wrapper(event, context, **handler_kwargs):
135145
response = middleware()
136146
return response
137147
except Exception:
138-
logger.exception(f"Caught exception in {decorator.__qualname__}")
148+
logger.exception(
149+
f"Caught exception in {decorator.__qualname__ if decorator is not None else 'UnknownDecorator'}",
150+
)
139151
raise
140152

141-
return wrapper
153+
return cast(FuncType, wrapper)
142154

143155
return final_decorator

0 commit comments

Comments
 (0)