mirror of https://github.com/python/cpython
bpo-38191: Turn warnings into errors in NamedTuple() and TypedDict(). (GH-16238)
This commit is contained in:
parent
2bf31ccab3
commit
8fc5839a9d
|
@ -3582,16 +3582,10 @@ class XMethBad2(NamedTuple):
|
|||
NamedTuple('Emp', [('name', str)], None)
|
||||
with self.assertRaises(ValueError):
|
||||
NamedTuple('Emp', [('_name', str)])
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
Emp = NamedTuple(typename='Emp', name=str, id=int)
|
||||
self.assertEqual(Emp.__name__, 'Emp')
|
||||
self.assertEqual(Emp._fields, ('name', 'id'))
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
Emp = NamedTuple('Emp', fields=[('name', str), ('id', int)])
|
||||
self.assertEqual(Emp.__name__, 'Emp')
|
||||
self.assertEqual(Emp._fields, ('name', 'id'))
|
||||
with self.assertRaises(TypeError):
|
||||
NamedTuple(typename='Emp', name=str, id=int)
|
||||
with self.assertRaises(TypeError):
|
||||
NamedTuple('Emp', fields=[('name', str), ('id', int)])
|
||||
|
||||
def test_pickle(self):
|
||||
global Emp # pickle wants to reference the class by name
|
||||
|
@ -3654,15 +3648,10 @@ class TypedDictTests(BaseTestCase):
|
|||
with self.assertRaises(TypeError):
|
||||
TypedDict('Emp', [('name', str)], None)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
Emp = TypedDict(_typename='Emp', name=str, id=int)
|
||||
self.assertEqual(Emp.__name__, 'Emp')
|
||||
self.assertEqual(Emp.__annotations__, {'name': str, 'id': int})
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
Emp = TypedDict('Emp', _fields={'name': str, 'id': int})
|
||||
self.assertEqual(Emp.__name__, 'Emp')
|
||||
self.assertEqual(Emp.__annotations__, {'name': str, 'id': int})
|
||||
with self.assertRaises(TypeError):
|
||||
TypedDict(_typename='Emp', name=str, id=int)
|
||||
with self.assertRaises(TypeError):
|
||||
TypedDict('Emp', _fields={'name': str, 'id': int})
|
||||
|
||||
def test_typeddict_errors(self):
|
||||
Emp = TypedDict('Emp', {'name': str, 'id': int})
|
||||
|
|
|
@ -1653,81 +1653,20 @@ class NamedTuple(metaclass=NamedTupleMeta):
|
|||
"""
|
||||
_root = True
|
||||
|
||||
def __new__(*args, **kwargs):
|
||||
if not args:
|
||||
raise TypeError('NamedTuple.__new__(): not enough arguments')
|
||||
cls, *args = args # allow the "cls" keyword be passed
|
||||
if args:
|
||||
typename, *args = args # allow the "typename" keyword be passed
|
||||
elif 'typename' in kwargs:
|
||||
typename = kwargs.pop('typename')
|
||||
import warnings
|
||||
warnings.warn("Passing 'typename' as keyword argument is deprecated",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
else:
|
||||
raise TypeError("NamedTuple.__new__() missing 1 required positional "
|
||||
"argument: 'typename'")
|
||||
if args:
|
||||
try:
|
||||
fields, = args # allow the "fields" keyword be passed
|
||||
except ValueError:
|
||||
raise TypeError(f'NamedTuple.__new__() takes from 2 to 3 '
|
||||
f'positional arguments but {len(args) + 2} '
|
||||
f'were given') from None
|
||||
elif 'fields' in kwargs and len(kwargs) == 1:
|
||||
fields = kwargs.pop('fields')
|
||||
import warnings
|
||||
warnings.warn("Passing 'fields' as keyword argument is deprecated",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
else:
|
||||
fields = None
|
||||
|
||||
def __new__(cls, typename, fields=None, /, **kwargs):
|
||||
if fields is None:
|
||||
fields = kwargs.items()
|
||||
elif kwargs:
|
||||
raise TypeError("Either list of fields or keywords"
|
||||
" can be provided to NamedTuple, not both")
|
||||
return _make_nmtuple(typename, fields)
|
||||
__new__.__text_signature__ = '($cls, typename, fields=None, /, **kwargs)'
|
||||
|
||||
|
||||
def _dict_new(*args, **kwargs):
|
||||
if not args:
|
||||
raise TypeError('TypedDict.__new__(): not enough arguments')
|
||||
cls, *args = args # allow the "cls" keyword be passed
|
||||
def _dict_new(cls, /, *args, **kwargs):
|
||||
return dict(*args, **kwargs)
|
||||
_dict_new.__text_signature__ = '($cls, _typename, _fields=None, /, **kwargs)'
|
||||
|
||||
|
||||
def _typeddict_new(*args, total=True, **kwargs):
|
||||
if not args:
|
||||
raise TypeError('TypedDict.__new__(): not enough arguments')
|
||||
cls, *args = args # allow the "cls" keyword be passed
|
||||
if args:
|
||||
typename, *args = args # allow the "_typename" keyword be passed
|
||||
elif '_typename' in kwargs:
|
||||
typename = kwargs.pop('_typename')
|
||||
import warnings
|
||||
warnings.warn("Passing '_typename' as keyword argument is deprecated",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
else:
|
||||
raise TypeError("TypedDict.__new__() missing 1 required positional "
|
||||
"argument: '_typename'")
|
||||
if args:
|
||||
try:
|
||||
fields, = args # allow the "_fields" keyword be passed
|
||||
except ValueError:
|
||||
raise TypeError(f'TypedDict.__new__() takes from 2 to 3 '
|
||||
f'positional arguments but {len(args) + 2} '
|
||||
f'were given') from None
|
||||
elif '_fields' in kwargs and len(kwargs) == 1:
|
||||
fields = kwargs.pop('_fields')
|
||||
import warnings
|
||||
warnings.warn("Passing '_fields' as keyword argument is deprecated",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
else:
|
||||
fields = None
|
||||
|
||||
def _typeddict_new(cls, typename, fields=None, /, *, total=True, **kwargs):
|
||||
if fields is None:
|
||||
fields = kwargs
|
||||
elif kwargs:
|
||||
|
@ -1742,7 +1681,6 @@ def _typeddict_new(*args, total=True, **kwargs):
|
|||
pass
|
||||
|
||||
return _TypedDictMeta(typename, (), ns)
|
||||
_typeddict_new.__text_signature__ = '($cls, _typename, _fields=None, /, *, total=True, **kwargs)'
|
||||
|
||||
|
||||
def _check_fails(cls, other):
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
Constructors of :class:`~typing.NamedTuple` and :class:`~typing.TypedDict`
|
||||
types now accept arbitrary keyword argument names, including "cls", "self",
|
||||
"typename", "_typename", "fields" and "_fields". Passing positional
|
||||
arguments by keyword is deprecated.
|
||||
"typename", "_typename", "fields" and "_fields".
|
||||
|
|
Loading…
Reference in New Issue