This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Incorrect reference to partial() in functools.wraps documentation
Type: enhancement Stage: resolved
Components: Documentation Versions: Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: ezio.melotti Nosy List: Dustin.Oprea, docs@python, ezio.melotti, python-dev, r.david.murray, rhettinger, terry.reedy
Priority: normal Keywords:

Created on 2014-07-07 00:05 by Dustin.Oprea, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg222426 - (view) Author: Dustin Oprea (Dustin.Oprea) Date: 2014-07-07 00:05
functools.wraps docs say "This is a convenience function for invoking partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated) as a function decorator when defining a wrapper function." The referenced function should be update_wrapper(), not partial().
msg222857 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2014-07-12 17:20
The docstring is correct, as this is how wraps is implemented (see Lib/functools.py#l73).
partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated) will return a partial version of update_wrapper() where only the wrapper argument is missing.  The missing argument is the function decorated with wraps().

For example, this code:

def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        return f(*args, **kwds)
    return wrapper

is equivalent to:

def my_decorator(f):
    def wrapper(*args, **kwds):
        return f(*args, **kwds)
    wrapper = wraps(f)(wrapper)
    return wrapper

Here wraps(f) creates a partial version of update_wrapper, with only the "wrapped" argument (i.e. f) set.  When the partial object returned by wrap(f) gets called, the missing "wrapper" argument is received, thus making wraps(f)(wrapper) equivalent to:

def my_decorator(f):
    def wrapper(*args, **kwds):
        return f(*args, **kwds)
    wrapper = update_wrapper(wrapper, f)
    return wrapper


That said, I agree that the sentence you quoted is not too clear/intuitive, but the following example is quite clear, so I'm not sure it's worth to removing/rephrasing the first part.

Maybe it could say something like "This is a convenience function for invoking update_wrapper() (by using partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)) as a function decorator when defining a wrapper function." instead?
msg223122 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-07-15 17:12
I would rewrite it as:

This is a convenience function for invoking update_wrapper() as a function decorator when defining a wrapper function.  It is equivalent to partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated).  For example:
msg224807 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2014-08-05 05:15
New changeset 9e3c367b45a1 by Ezio Melotti in branch '3.4':
#21928: clarify functools.wraps docs.
http://hg.python.org/cpython/rev/9e3c367b45a1

New changeset 5a58f6e793cc by Ezio Melotti in branch 'default':
#21928: merge with 3.4.
http://hg.python.org/cpython/rev/5a58f6e793cc

New changeset 6cbd08fbdf77 by Ezio Melotti in branch '2.7':
#21928: clarify functools.wraps docs.
http://hg.python.org/cpython/rev/6cbd08fbdf77
History
Date User Action Args
2022-04-11 14:58:05adminsetgithub: 66127
2014-08-05 05:16:30ezio.melottisetstatus: open -> closed
assignee: docs@python -> ezio.melotti
resolution: fixed
stage: resolved
2014-08-05 05:15:44python-devsetnosy: + python-dev
messages: + msg224807
2014-07-15 17:12:13r.david.murraysetstatus: pending -> open

messages: + msg223122
2014-07-12 17:20:50ezio.melottisetstatus: open -> pending
versions: + Python 3.5
nosy: + terry.reedy, rhettinger, ezio.melotti, r.david.murray

messages: + msg222857

type: enhancement
2014-07-07 00:05:51Dustin.Opreacreate