gh-92062: inspect.Parameter checks whether name is a keyword (GH-92065)

Fixes #92062.
This commit is contained in:
Zac Hatfield-Dodds 2022-05-03 14:52:30 -06:00 committed by GitHub
parent 3a35b62ea0
commit 65f88a6ef7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 12 additions and 3 deletions

View file

@ -149,6 +149,7 @@ import token
import types import types
import functools import functools
import builtins import builtins
from keyword import iskeyword
from operator import attrgetter from operator import attrgetter
from collections import namedtuple, OrderedDict from collections import namedtuple, OrderedDict
@ -1645,7 +1646,7 @@ class Traceback(_Traceback):
instance = super().__new__(cls, filename, lineno, function, code_context, index) instance = super().__new__(cls, filename, lineno, function, code_context, index)
instance.positions = positions instance.positions = positions
return instance return instance
def __repr__(self): def __repr__(self):
return ('Traceback(filename={!r}, lineno={!r}, function={!r}, ' return ('Traceback(filename={!r}, lineno={!r}, function={!r}, '
'code_context={!r}, index={!r}, positions={!r})'.format( 'code_context={!r}, index={!r}, positions={!r})'.format(
@ -1683,7 +1684,7 @@ def getframeinfo(frame, context=1):
frame, *positions = (frame, lineno, *positions[1:]) frame, *positions = (frame, lineno, *positions[1:])
else: else:
frame, *positions = (frame, *positions) frame, *positions = (frame, *positions)
lineno = positions[0] lineno = positions[0]
if not isframe(frame): if not isframe(frame):
@ -2707,7 +2708,10 @@ class Parameter:
self._kind = _POSITIONAL_ONLY self._kind = _POSITIONAL_ONLY
name = 'implicit{}'.format(name[1:]) name = 'implicit{}'.format(name[1:])
if not name.isidentifier(): # It's possible for C functions to have a positional-only parameter
# where the name is a keyword, so for compatibility we'll allow it.
is_keyword = iskeyword(name) and self._kind is not _POSITIONAL_ONLY
if is_keyword or not name.isidentifier():
raise ValueError('{!r} is not a valid parameter name'.format(name)) raise ValueError('{!r} is not a valid parameter name'.format(name))
self._name = name self._name = name

View file

@ -3604,6 +3604,9 @@ class TestParameterObject(unittest.TestCase):
with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD) inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
inspect.Parameter('from', kind=inspect.Parameter.VAR_KEYWORD)
with self.assertRaisesRegex(TypeError, 'name must be a str'): with self.assertRaisesRegex(TypeError, 'name must be a str'):
inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD) inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)

View file

@ -0,0 +1,2 @@
:class:`inspect.Parameter` now raises :exc:`ValueError` if ``name`` is
a keyword, in addition to the existing check that it is an identifier.