On Thu, Dec 2, 2021 at 7:36 PM Paul Moore <p.f.mo...@gmail.com> wrote: > > Actually, Chris - does functools.wraps work properly in your > implementation when wrapping functions with late-bound defaults? > > >>> def dec(f): > ... @wraps(f) > ... def inner(*args, **kw): > ... print("Calling") > ... return f(*args, **kw) > ... return inner > ... > >>> @dec > ... def g(a => []): > ... return len(a) >
Yes, it does. There are two things happening here which, from a technical standpoint, are actually orthogonal; the function *call* is simply using *a,**kw notation, so it's passing along all the positional and keyword parameters untouched; but the function *documentation* just says "hey look over there for the real signature". >>> g([1,2,3]) Calling 3 >>> g() Calling 0 (In your example there's no proof that it's late-bound, but it is.) >>> help(g) Help on function g in module __main__: g(a=>[]) >>> g.__wrapped__ <function g at 0x7fb5581efa00> >>> g <function g at 0x7fb5581efab0> When you do "inner = wraps(f)(inner)", what happens is that the function's name and qualname get updated, and then __wrapped__ gets added as a pointer saying "hey, assume that I have the signature of that guy over there". There's unfortunately no way to merge signatures (you can't do something like "def f(*a, timeout=500, **kw):" and then use the timeout parameter in your wrapper and pass the rest on - help(f) will just show the base function's signature), and nothing is actually aware of the underlying details. But on the plus side, this DOES work correctly. Documentation for late-bound defaults is done by a (compile-time) string snapshot of the AST that defined the default, so it's about as accurate as for early-bound defaults. One thing I'm not 100% happy with in the reference implementation is that the string for help() is stored on the function object, but the behaviour of the late-bound default is inherent to the code object. I'm not sure of a way around that, but it also doesn't seem terribly problematic in practice. ChrisA _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/TRDJLI24Z4BM3UCBVSV6E4FASDLT6CQY/ Code of Conduct: http://python.org/psf/codeofconduct/