mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Issue 8814: functools.wraps() did not copy __annotations__.
This commit is contained in:
parent
f56c9cd30d
commit
c6d80c1bef
5 changed files with 17 additions and 7 deletions
|
@ -66,9 +66,9 @@ The :mod:`functools` module defines the following functions:
|
||||||
attributes of the wrapper function are updated with the corresponding attributes
|
attributes of the wrapper function are updated with the corresponding attributes
|
||||||
from the original function. The default values for these arguments are the
|
from the original function. The default values for these arguments are the
|
||||||
module level constants *WRAPPER_ASSIGNMENTS* (which assigns to the wrapper
|
module level constants *WRAPPER_ASSIGNMENTS* (which assigns to the wrapper
|
||||||
function's *__name__*, *__module__* and *__doc__*, the documentation string) and
|
function's *__name__*, *__module__*, *__annotations__* and *__doc__*, the
|
||||||
*WRAPPER_UPDATES* (which updates the wrapper function's *__dict__*, i.e. the
|
documentation string) and *WRAPPER_UPDATES* (which updates the wrapper
|
||||||
instance dictionary).
|
function's *__dict__*, i.e. the instance dictionary).
|
||||||
|
|
||||||
The main intended use for this function is in :term:`decorator` functions which
|
The main intended use for this function is in :term:`decorator` functions which
|
||||||
wrap the decorated function and return the wrapper. If the wrapper function is
|
wrap the decorated function and return the wrapper. If the wrapper function is
|
||||||
|
|
|
@ -12,7 +12,7 @@ from _functools import partial, reduce
|
||||||
# update_wrapper() and wraps() are tools to help write
|
# update_wrapper() and wraps() are tools to help write
|
||||||
# wrapper functions that can handle naive introspection
|
# wrapper functions that can handle naive introspection
|
||||||
|
|
||||||
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
|
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__', '__annotations__')
|
||||||
WRAPPER_UPDATES = ('__dict__',)
|
WRAPPER_UPDATES = ('__dict__',)
|
||||||
def update_wrapper(wrapper,
|
def update_wrapper(wrapper,
|
||||||
wrapped,
|
wrapped,
|
||||||
|
@ -30,6 +30,7 @@ def update_wrapper(wrapper,
|
||||||
function (defaults to functools.WRAPPER_UPDATES)
|
function (defaults to functools.WRAPPER_UPDATES)
|
||||||
"""
|
"""
|
||||||
for attr in assigned:
|
for attr in assigned:
|
||||||
|
if hasattr(wrapped, attr):
|
||||||
setattr(wrapper, attr, getattr(wrapped, attr))
|
setattr(wrapper, attr, getattr(wrapped, attr))
|
||||||
for attr in updated:
|
for attr in updated:
|
||||||
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
|
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
|
||||||
|
|
|
@ -181,17 +181,19 @@ class TestUpdateWrapper(unittest.TestCase):
|
||||||
self.assertTrue(wrapped_attr[key] is wrapper_attr[key])
|
self.assertTrue(wrapped_attr[key] is wrapper_attr[key])
|
||||||
|
|
||||||
def test_default_update(self):
|
def test_default_update(self):
|
||||||
def f():
|
def f(a:'This is a new annotation'):
|
||||||
"""This is a test"""
|
"""This is a test"""
|
||||||
pass
|
pass
|
||||||
f.attr = 'This is also a test'
|
f.attr = 'This is also a test'
|
||||||
def wrapper():
|
def wrapper(b:'This is the prior annotation'):
|
||||||
pass
|
pass
|
||||||
functools.update_wrapper(wrapper, f)
|
functools.update_wrapper(wrapper, f)
|
||||||
self.check_wrapper(wrapper, f)
|
self.check_wrapper(wrapper, f)
|
||||||
self.assertEqual(wrapper.__name__, 'f')
|
self.assertEqual(wrapper.__name__, 'f')
|
||||||
self.assertEqual(wrapper.__doc__, 'This is a test')
|
self.assertEqual(wrapper.__doc__, 'This is a test')
|
||||||
self.assertEqual(wrapper.attr, 'This is also a test')
|
self.assertEqual(wrapper.attr, 'This is also a test')
|
||||||
|
self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation')
|
||||||
|
self.assertNotIn('b', wrapper.__annotations__)
|
||||||
|
|
||||||
def test_no_update(self):
|
def test_no_update(self):
|
||||||
def f():
|
def f():
|
||||||
|
@ -204,6 +206,7 @@ class TestUpdateWrapper(unittest.TestCase):
|
||||||
self.check_wrapper(wrapper, f, (), ())
|
self.check_wrapper(wrapper, f, (), ())
|
||||||
self.assertEqual(wrapper.__name__, 'wrapper')
|
self.assertEqual(wrapper.__name__, 'wrapper')
|
||||||
self.assertEqual(wrapper.__doc__, None)
|
self.assertEqual(wrapper.__doc__, None)
|
||||||
|
self.assertEqual(wrapper.__annotations__, {})
|
||||||
self.assertFalse(hasattr(wrapper, 'attr'))
|
self.assertFalse(hasattr(wrapper, 'attr'))
|
||||||
|
|
||||||
def test_selective_update(self):
|
def test_selective_update(self):
|
||||||
|
@ -230,6 +233,7 @@ class TestUpdateWrapper(unittest.TestCase):
|
||||||
functools.update_wrapper(wrapper, max)
|
functools.update_wrapper(wrapper, max)
|
||||||
self.assertEqual(wrapper.__name__, 'max')
|
self.assertEqual(wrapper.__name__, 'max')
|
||||||
self.assertTrue(wrapper.__doc__.startswith('max('))
|
self.assertTrue(wrapper.__doc__.startswith('max('))
|
||||||
|
self.assertEqual(wrapper.__annotations__, {})
|
||||||
|
|
||||||
class TestWraps(TestUpdateWrapper):
|
class TestWraps(TestUpdateWrapper):
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,7 @@ Steve Clift
|
||||||
Nick Coghlan
|
Nick Coghlan
|
||||||
Josh Cogliati
|
Josh Cogliati
|
||||||
Dave Cole
|
Dave Cole
|
||||||
|
Terrence Cole
|
||||||
Benjamin Collar
|
Benjamin Collar
|
||||||
Jeffery Collins
|
Jeffery Collins
|
||||||
Paul Colomiets
|
Paul Colomiets
|
||||||
|
|
|
@ -12,6 +12,10 @@ What's New in Python 3.1.3?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #8814: function annotations (the ``__annotations__`` attribute)
|
||||||
|
are now included in the set of attributes copied by default by
|
||||||
|
functools.wraps and functools.update_wrapper. Patch by Terrence Cole.
|
||||||
|
|
||||||
- Issue #83755: Implicit set-to-frozenset conversion was not thread-safe.
|
- Issue #83755: Implicit set-to-frozenset conversion was not thread-safe.
|
||||||
|
|
||||||
- Issue #9416: Fix some issues with complex formatting where the
|
- Issue #9416: Fix some issues with complex formatting where the
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue