-
Notifications
You must be signed in to change notification settings - Fork 421
fix(middleware_factory): ret type annotation for handler dec #1066
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #1066 +/- ##
========================================
Coverage 99.96% 99.96%
========================================
Files 119 119
Lines 5365 5365
Branches 612 612
========================================
Hits 5363 5363
Partials 2 2
Continue to review full report at Codecov.
|
Thanks a lot @huonw !! Question: Do we lose type signature with the current solution? e.g., create a decorator with a given type annotation on a key-value param, call it using an incorrect type and let mypy detect it. The way I solved this for Tracer (similar, not the same) on preserving the function signature types is using AnyCallableT - This Instead of using overload, could you try with |
I think this is an strict improvement over the current code (i.e. nothing is being lost): the middlewares used to be completely untyped, while now they're at least Are you proposing something like |
If your current Callable type is helping preserve the type signature (not being done today), then we should stop here and merge \o/! The AnyCallableT suggestion was for the first layer (like Tracer, Logger, Metrics decorators), it wouldn't work for the second one for reasons you called out - hence the thought to experiment as that wasn't the final solution. Let me know the answer to the types as I'm not entirely sure I understood. If types aren't being preserved with the latest commit, we can experiment other ways (typing from my phone again, need to think of other ways still) |
Ah, I see. I think that may be tricky and/or require manual casts at each use site of the decorator: from typing import Any, Callable, cast
AnyCallable = Callable[..., Any]
def base_decorator(f: AnyCallable) -> AnyCallable:
return f
@base_decorator
def my_decorator(g: AnyCallable) -> AnyCallable:
return g
my_decorator = cast(Callable[[AnyCallable], AnyCallable], my_decorator) There's quite a few downsides of this:
On balance, and especially because these decorators are designed for handlers (i.e. functions that typically aren't used elsewhere in library code), I feel the minimal |
Looking into this tomorrow ;-) Finished the other bits |
Just ran |
Nah, spent the last two hours and while I made headwinds towards identifying kwargs in a non-strict mode, I hit a dead end with Otherwise, I'll take this opportunity to fix a doc typo as part of this PR and then merge. Sample code used from typing import Any, Callable, Dict, List, Optional
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator
@lambda_handler_decorator
def obfuscate_sensitive_data(
handler: Callable[..., Any], event: Dict[str, Any], context: Any, fields: Optional[List[str]] = None
) -> Any:
# Obfuscate email before calling Lambda handler
if fields:
for field in fields:
if field in event:
event[field] = "REDACTED"
return handler(event, context)
@obfuscate_sensitive_data(fields=10)
def lambda_handler(event: Dict[str, Any], context: Any) -> Any:
... Mypy strict output against sample code blah.py:19:2: error: Unexpected keyword argument "fields" for "obfuscate_sensitive_data" [call-arg]
blah.py:19:2: error: Too few arguments for "obfuscate_sensitive_data" [call-arg]
Found 2 errors in 1 file (checked 1 source file) |
I have no further insight on that patch 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggesting a reword on return type comment, accepting, and merging.
Thanks again @huonw for taking the time, truly appreciate that. Hopefully, we will be able to solve this and other similar situations with typing_extensions in the future |
Woohoo, thanks for the tweak and then merging 👍 |
Issue #, if available: #1060
Description of changes:
This is two versions of typing
lambda_handler_decorator
more accurately for #1060, to ensure that middleware using it have a type. They end up with typeCallable[..., Any]
but that's better than nothing.The first commit 937e6fe tries to be more accurate via overloads and protocols, but it doesn't work as written, and I cannot quite work out why. The errors below demonstrate the issues. It's potentially resolvable with 3.10's
ParamSpec
(I'm not suretyping_extensions
depended upon for 3.8 and 3.8?):Errors
Checklist
Breaking change checklist
RFC issue #:
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.