Comments (4)
Yes, you can and you need to use the FunctionMaker class to do that. But there no examples in the docs for that. The function decorator.decorator
is signature-changing because it takes a function with arguments func, *args, **kw
and returns a function with a single argument func
, so the documentation is correct.
from decorator.
I see now. It IS (can acts as) a signature changing decorator. It cannot CREATE signature changing decorators. Now the docs make sense.
I'd love for that distinction to be made a little clearer in the docs, and to see a new easy to use function equivalent to decorator
that makes signature changing decorators.
While looking into this I discovered wrapt
which does support and document the creation of signature changing decorators (called "adaptors"), so I'll probably switch to that, although I prefer the decorator
syntax.
from decorator.
You may try this project https://github.com/smarie/python-makefun which is based on the decorator module.
from decorator.
Thanks @micheles for the redirection, yes I think that makefun
would be appropriate for this use case. It was entirely inspired by decorator
and relies on the same trick that decorator
uses, but it focuses solely on the function wrapping aspect so that it is de-coupled from the decorator creation problem.
Here is how you would create your decorator using makefun:
from inspect import signature, Parameter
from makefun import wraps, add_signature_parameters
def mydec(func):
"""
A decorator to add 2 keyword arguments to the decorated function.
:param func:
:return:
"""
# add parameters to the wrapped function signature
func_sig = signature(func)
new_kw_param = Parameter('new_kw', kind=Parameter.POSITIONAL_OR_KEYWORD, default=None)
another_new_kw_param = Parameter('another_new_kw', kind=Parameter.POSITIONAL_OR_KEYWORD, default=None)
new_sig = add_signature_parameters(func_sig, last=(new_kw_param, another_new_kw_param))
# create the new function with modified signature
@wraps(func, new_sig=new_sig)
def new_func(*args, **kwargs):
new_kw = kwargs.pop('new_kw')
another_new_kw = kwargs.pop('another_new_kw')
if new_kw:
print(new_kw)
return func(*args, **kwargs)
# return the new function
return new_func
# ------ Test
@mydec
def foo(a):
return a + 1
assert foo(1) == 2
assert foo(1, new_kw='bar') == 2 # prints 'bar'
print(help(foo)) # new signature
If you then wish to make the decorator creation step more easy, you can use decopatch
. This is particularly relevant if you wish your decorator to have arguments, including optional ones. This is how you can do it :
from inspect import signature, Parameter
from decopatch import function_decorator, DECORATED
from makefun import wraps, add_signature_parameters
@function_decorator
def mydec(func=DECORATED, msg_to_print="hello"):
"""
A decorator to add 2 keyword arguments to the decorated function.
:param msg_to_print: the message to print
:return:
"""
# add parameters to the wrapped function signature
func_sig = signature(func)
new_kw_param = Parameter('new_kw', kind=Parameter.POSITIONAL_OR_KEYWORD, default=None)
another_new_kw_param = Parameter('another_new_kw', kind=Parameter.POSITIONAL_OR_KEYWORD, default=None)
new_sig = add_signature_parameters(func_sig, last=(new_kw_param, another_new_kw_param))
# create the new function with modified signature
@wraps(func, new_sig=new_sig)
def new_func(*args, **kwargs):
new_kw = kwargs.pop('new_kw')
another_new_kw = kwargs.pop('another_new_kw')
if new_kw:
print("%s %s" % (msg_to_print, new_kw))
return func(*args, **kwargs)
# return the new function
return new_func
# ------ Test
@mydec # no parenthesis ! default behaviour
def foo(a):
return a + 1
assert foo(1) == 2
assert foo(1, new_kw='bar') == 2 # prints 'hello bar'
@mydec(msg_to_print="oops")
def foo2(a):
return a + 2
assert foo2(1) == 3
assert foo2(1, new_kw='bar') == 3 # prints 'oops bar'
Note: the helper function add_signature_parameters
is still a bit ugly but there are open tickets about this. Feel free to comment or propose other ideas: smarie/python-makefun#41 smarie/python-makefun#42 smarie/python-makefun#43
from decorator.
Related Issues (20)
- 5.0.9: sphinx 4.x warnings HOT 3
- pylint warning W1113: keyword-arg-before-vararg HOT 1
- Regression in 5.1.0 - decorator.contextmanager no longer compat with contextlib.contextmanager HOT 4
- `FunctionMaker.create()` fails when given a function definition with a return type annotation. HOT 1
- Functionmaker.create (from doc example) fails with kwarg-only functions HOT 6
- `FunctionMaker.create` raises unexpected SyntaxError when return is present as substring for async function
- How to make `@decorator` with other decorators? HOT 3
- TypeError: missing 1 required positional argument HOT 1
- <=3.4.2 can't be installed with modern setuptools HOT 2
- Continuous fuzzing by way of OSS-Fuzz
- compatibility issue with kwargs HOT 2
- Not preserving low level signature metadada HOT 1
- decorator whether to support decorator partial functions?
- Confusion about license using HOT 1
- Making __name__ optional attribute of decorated-function if underlying function is missing it. HOT 3
- Compatibility with Python 3.12 - RuntimeError: There is no current event loop in thread 'MainThread'.
- Unable to pull 4.4.2 from the repo only pulls in 4.2.1 HOT 1
- [BUG] kwargs are not respected HOT 3
- Create SECURITY.md
- Create a decorator for both sync and async function HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from decorator.