<div dir="auto"><div>The documentation for wrapt mentions:<div dir="auto"><br></div><div dir="auto"><h2 style="margin-top:0px;font-family:"roboto slab",ff-tisa-web-pro,georgia,arial,sans-serif;font-size:24px;color:rgb(64,64,64);background-color:rgb(252,252,252)">Decorators With Optional Arguments<a href="https://wrapt.readthedocs.io/en/latest/decorators.html#decorators-with-optional-arguments" style="color:rgb(155,89,182);text-decoration-line:none;display:inline-block;font-variant-numeric:normal;font-variant-east-asian:normal;font-weight:normal;font-stretch:normal;line-height:1;font-family:inherit;font-size:14px"></a></h2><p style="line-height:24px;margin:0px 0px 24px;font-size:16px;color:rgb(64,64,64);font-family:lato,proxima-nova,"helvetica neue",arial,sans-serif;background-color:rgb(252,252,252)">Although opinion can be mixed about whether the pattern is a good one, if the decorator arguments all have default values, it is also possible to implement decorators which have optional arguments. </p></div>As Graham hints in his docs, I think repurposing decorator factories as decorators is an antipattern. Explicit is better than implicit.</div><div dir="auto"><br></div><div dir="auto">While I *do* understands that what decotools and makefun do are technically independent, I'm not sure I ever want them independently in practice. I did write the book _Functional Programming in Python_, so I'm not entirely unfamiliar with function wrappers.<br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">On Tue, Mar 12, 2019, 10:18 AM David Mertz <<a href="mailto:mertz@gnosis.cx">mertz@gnosis.cx</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div>The wrapt module I linked to (not funtools.wraps) provides all the capabilities you mention since 2013. It allows mixed use of decorators as decorator factories. It has a flat style. </div><div dir="auto"><br></div><div dir="auto">There are some minor API difference between your libraries and wrapt, but the concept is very similar. Since yours is something new, I imagine you perceive some win over what wrapt does.<br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">On Tue, Mar 12, 2019, 9:52 AM Sylvain MARIE <<a href="mailto:sylvain.marie@se.com" target="_blank" rel="noreferrer">sylvain.marie@se.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">David, Steven,<br>
<br>
Thanks for your interest !<br>
<br>
As you probably know, decorators and function wrappers are *completely different concepts*. A decorator can directly return the decorated function (or class), it does not have to return a wrapper. Even more, it can entirely replace the decorated item with something else (not even a function or class!). Try it: it is possible to write a decorator to replace a function with an integer, even though it is probably not quite useful :)<br>
<br>
`decopatch` helps you write decorators, whatever they are. It "just" solves the annoying issue of having to handle the no-parenthesis and with-parenthesis calls. In addition as a 'goodie', it proposes two development styles: *nested* (you have to return a function) and *flat* (you directly write what will happen when the decorator is applied to something).<br>
--<br>
Now about creating signature-preserving function wrappers (in a decorator, or outside a decorator - again, that's not related). That use case is supposed to be covered by functools.wrapt. Unfortunately as explained here <a href="https://stackoverflow.com/questions/308999/what-does-functools-wraps-do/55102697#55102697" rel="noreferrer noreferrer noreferrer" target="_blank">https://stackoverflow.com/questions/308999/what-does-functools-wraps-do/55102697#55102697</a> this is not the case because with functools.wrapt:<br>
 - the wrapper code will execute even when the provided arguments are invalid.<br>
 - the wrapper code cannot easily access an argument using its name, from the received *args, **kwargs. Indeed one would have to handle all cases (positional, keyword, default) and therefore to use something like Signature.bind().<br>
<br>
For this reason I proposed a replacement in `makefun`: <a href="https://smarie.github.io/python-makefun/#signature-preserving-function-wrappers" rel="noreferrer noreferrer noreferrer" target="_blank">https://smarie.github.io/python-makefun/#signature-preserving-function-wrappers</a> <br>
--<br>
Now bridging the gap. Of course a very interesting use cases for decorators is to create decorators that create a signature-preserving wrapper. It is possible to combine decopatch and makefun for this: <a href="https://smarie.github.io/python-decopatch/#3-creating-function-wrappers" rel="noreferrer noreferrer noreferrer" target="_blank">https://smarie.github.io/python-decopatch/#3-creating-function-wrappers</a> .<br>
Decopatch even proposes a "double-flat" development style where you directly write the wrapper body, as explained in the doc.<br>
<br>
Did I answer your questions ?<br>
Thanks again for the quick feedback !<br>
Best,<br>
<br>
Sylvain <br>
<br>
-----Message d'origine-----<br>
De : Python-ideas <python-ideas-bounces+sylvain.marie=<a href="mailto:se.com@python.org" rel="noreferrer noreferrer" target="_blank">se.com@python.org</a>> De la part de Steven D'Aprano<br>
Envoyé : mardi 12 mars 2019 12:30<br>
À : <a href="mailto:python-ideas@python.org" rel="noreferrer noreferrer" target="_blank">python-ideas@python.org</a><br>
Objet : Re: [Python-ideas] Problems (and solutions?) in writing decorators<br>
<br>
[External email: Use caution with links and attachments]<br>
<br>
________________________________<br>
<br>
<br>
<br>
On Tue, Mar 12, 2019 at 09:36:41AM +0000, Sylvain MARIE via Python-ideas wrote:<br>
<br>
> I therefore proposed<br>
> <a href="https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsma" rel="noreferrer noreferrer noreferrer" target="_blank">https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsma</a><br>
> <a href="http://rie.github.io" rel="noreferrer noreferrer noreferrer" target="_blank">rie.github.io</a>%2Fpython-makefun%2F&amp;data=02%7C01%7Csylvain.marie%40s<br>
> <a href="http://e.com" rel="noreferrer noreferrer noreferrer" target="_blank">e.com</a>%7C579232e7e10e475314c708d6a6de9d23%7C6e51e1adc54b4b39b5980ffe9ae<br>
> 68fef%7C0%7C0%7C636879872385158085&amp;sdata=nB9p9V%2BJ7gk%2Fsc%2BA5%2<br>
> Fekk35bnYGvmEFJyCXaLDyLm9I%3D&amp;reserved=0 . In particular it <br>
> provides an equivalent of `@functools.wraps` that is truly <br>
> signature-preserving<br>
<br>
Tell us more about that please. I'm very interested in getting decorators preserve the original signature.<br>
<br>
<br>
--<br>
Steven<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" rel="noreferrer noreferrer" target="_blank">Python-ideas@python.org</a><br>
<a href="https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmail.python.org%2Fmailman%2Flistinfo%2Fpython-ideas&amp;data=02%7C01%7Csylvain.marie%40se.com%7C579232e7e10e475314c708d6a6de9d23%7C6e51e1adc54b4b39b5980ffe9ae68fef%7C0%7C0%7C636879872385158085&amp;sdata=XcYfEginmDF7kIpGGA0XxDZKpUn9e4p2zPFk7UAruYg%3D&amp;reserved=0" rel="noreferrer noreferrer noreferrer" target="_blank">https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmail.python.org%2Fmailman%2Flistinfo%2Fpython-ideas&amp;data=02%7C01%7Csylvain.marie%40se.com%7C579232e7e10e475314c708d6a6de9d23%7C6e51e1adc54b4b39b5980ffe9ae68fef%7C0%7C0%7C636879872385158085&amp;sdata=XcYfEginmDF7kIpGGA0XxDZKpUn9e4p2zPFk7UAruYg%3D&amp;reserved=0</a><br>
Code of Conduct: <a href="https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fpython.org%2Fpsf%2Fcodeofconduct%2F&amp;data=02%7C01%7Csylvain.marie%40se.com%7C579232e7e10e475314c708d6a6de9d23%7C6e51e1adc54b4b39b5980ffe9ae68fef%7C0%7C0%7C636879872385158085&amp;sdata=20ZrtVQZbpQ54c96veSXIOfEK7rKy0ggj0omTZg3ri8%3D&amp;reserved=0" rel="noreferrer noreferrer noreferrer" target="_blank">https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fpython.org%2Fpsf%2Fcodeofconduct%2F&amp;data=02%7C01%7Csylvain.marie%40se.com%7C579232e7e10e475314c708d6a6de9d23%7C6e51e1adc54b4b39b5980ffe9ae68fef%7C0%7C0%7C636879872385158085&amp;sdata=20ZrtVQZbpQ54c96veSXIOfEK7rKy0ggj0omTZg3ri8%3D&amp;reserved=0</a><br>
<br>
______________________________________________________________________<br>
This email has been scanned by the Symantec Email Security.cloud service.<br>
______________________________________________________________________<br>
</blockquote></div></div></div>
</blockquote></div></div></div>