-
Notifications
You must be signed in to change notification settings - Fork 233
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
How to use arguments with default value? #277
Comments
For a start, you don't need the extra level of wrapping as you have. You should be able to write it as:
As to optional decorator arguments see: So you need something like:
|
Oh cool - i thought I read through all the docs but it seems i didn't catch this example! |
I think I got a fully working implementation. If you believe this is meaningful, I can update the docs with an even simpler example: def public_api(wrapped: Optional[Callable] = None, stage: Literal["alpha", "beta", "stable"] = "stable"):
"""Decorate public APIs with versioning.
Parameters
----------
stage : {'alpha', 'beta', 'stable'}, default='stable'
Stage of the API.
"""
logger = logging.getLogger(__name__)
_pub_api_tracker = threading.local()
def decorator(wrapped: Callable, stage: Literal["alpha", "beta", "stable"] = stage):
@wrapt.decorator
def wrapper(wrapped, _instance, args, kwargs):
if stage != "stable" and not hasattr(_pub_api_tracker, "used"):
logger.info(
f"{stage.title()} API: {wrapped.__module__}.{wrapped.__qualname__} "
f"is in {stage} stage and may have breaking changes."
)
_pub_api_tracker.used = True
if stage == "stable":
# Verify that the function or method is fully type annotated
sig = inspect.signature(wrapped)
for param in sig.parameters.values():
if param.annotation is param.empty:
raise TypeError(f"Parameter '{param.name}' in {wrapped.__name__} is missing a type annotation.")
if sig.return_annotation is sig.empty:
raise TypeError(f"Return type of {wrapped.__name__} is missing a type annotation.")
return wrapped(*args, **kwargs)
return wrapper(wrapped)
if wrapped is None:
return decorator
else:
return decorator(wrapped=wrapped, stage=stage)
``` |
Okay, you replaced use of |
BTW, if the
Just curious as to whether that makes a difference. The problem is that Since type hinting still not added in wrapt, all sorts of editor stuff like that may not work. I need to try and get onto adding type hints now that have dropped older Python versions, but can only do that sometime start of next year. |
This was the solution - keeps it nice and clean |
A docs update to the document link in question would probably help a future traveller |
What was the actual problem though, was it just that the popup from the editor wasn't giving useful information about arguments and giving warnings about type mismatch, or was there an actual runtime error? |
The signature was not being passed properly with partial. With your recent suggestion of object proxy, I now get the correct signature, but a runtime error (the decorator logic simply does not execute). |
So what I gave you as example was wrong. Should have been:
Change the return statement to:
|
Not sure if still need to use |
Yes, PartialCallableObjectProxy provides the appropriate signature/inspection. Using the final example you posted with the proxy meets all requirements. To summarize for future users, this is the way: def my_decorator(wrapped: Optional[Callable] = None, my_argument: str = "default_value"):
if wrapped is None:
return wrapt.PartialCallableObjectProxy(my_decorator, my_argument=my_argument)
@wrapt.decorator
def wrapper(wrapped, instance, args, kwargs):
# ... logic which uses the "my_argument"
return wrapped(*args, **kwargs)
return wrapper(wrapped)
@my_decorator # or @my_decorator() or @my_decorator("new_value") or @my_decorator(my_argument="new_value")
def my_function(x: int) -> int:
"""My function docstring."""
return x + 1 |
I am going to reopen this issue to remind me to look at updating the docs. |
If it's just that one-liner, I'm more than happy to submit a small PR |
Needs some explanation text about So the two code examples can be changed and just add a paragraph after second code example in that section saying something like.
If you want to create a PR for that would be much appreciated. |
You'll most likely see one tomorrow! |
Should be resolved by #278 |
I have a simple decorator constructed like so:
I can of course use the default argument of this decorator by applying it like so:
However, it does not behave well when used like this:
Is there a way to make the latter work as well without losing all of the clean typing on the decorator?
The text was updated successfully, but these errors were encountered: