gh-102378: don't bother stripping / from __text_signature__ (#102379)

This commit is contained in:
David Hewitt 2023-03-09 23:06:20 +00:00 committed by GitHub
parent c6858d1e7f
commit 71cf7c3ddd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 56 deletions

View file

@ -2106,26 +2106,21 @@ def _signature_strip_non_python_syntax(signature):
Private helper function. Takes a signature in Argument Clinic's
extended signature format.
Returns a tuple of three things:
* that signature re-rendered in standard Python syntax,
Returns a tuple of two things:
* that signature re-rendered in standard Python syntax, and
* the index of the "self" parameter (generally 0), or None if
the function does not have a "self" parameter, and
* the index of the last "positional only" parameter,
or None if the signature has no positional-only parameters.
the function does not have a "self" parameter.
"""
if not signature:
return signature, None, None
return signature, None
self_parameter = None
last_positional_only = None
lines = [l.encode('ascii') for l in signature.split('\n') if l]
generator = iter(lines).__next__
token_stream = tokenize.tokenize(generator)
delayed_comma = False
skip_next_comma = False
text = []
add = text.append
@ -2142,35 +2137,18 @@ def _signature_strip_non_python_syntax(signature):
if type == OP:
if string == ',':
if skip_next_comma:
skip_next_comma = False
else:
assert not delayed_comma
delayed_comma = True
current_parameter += 1
continue
if string == '/':
assert not skip_next_comma
assert last_positional_only is None
skip_next_comma = True
last_positional_only = current_parameter - 1
continue
current_parameter += 1
if (type == ERRORTOKEN) and (string == '$'):
assert self_parameter is None
self_parameter = current_parameter
continue
if delayed_comma:
delayed_comma = False
if not ((type == OP) and (string == ')')):
add(', ')
add(string)
if (string == ','):
add(' ')
clean_signature = ''.join(text)
return clean_signature, self_parameter, last_positional_only
return clean_signature, self_parameter
def _signature_fromstr(cls, obj, s, skip_bound_arg=True):
@ -2179,8 +2157,7 @@ def _signature_fromstr(cls, obj, s, skip_bound_arg=True):
"""
Parameter = cls._parameter_cls
clean_signature, self_parameter, last_positional_only = \
_signature_strip_non_python_syntax(s)
clean_signature, self_parameter = _signature_strip_non_python_syntax(s)
program = "def foo" + clean_signature + ": pass"
@ -2269,17 +2246,17 @@ def _signature_fromstr(cls, obj, s, skip_bound_arg=True):
parameters.append(Parameter(name, kind, default=default, annotation=empty))
# non-keyword-only parameters
args = reversed(f.args.args)
defaults = reversed(f.args.defaults)
iter = itertools.zip_longest(args, defaults, fillvalue=None)
if last_positional_only is not None:
kind = Parameter.POSITIONAL_ONLY
else:
kind = Parameter.POSITIONAL_OR_KEYWORD
for i, (name, default) in enumerate(reversed(list(iter))):
total_non_kw_args = len(f.args.posonlyargs) + len(f.args.args)
required_non_kw_args = total_non_kw_args - len(f.args.defaults)
defaults = itertools.chain(itertools.repeat(None, required_non_kw_args), f.args.defaults)
kind = Parameter.POSITIONAL_ONLY
for (name, default) in zip(f.args.posonlyargs, defaults):
p(name, default)
kind = Parameter.POSITIONAL_OR_KEYWORD
for (name, default) in zip(f.args.args, defaults):
p(name, default)
if i == last_positional_only:
kind = Parameter.POSITIONAL_OR_KEYWORD
# *args
if f.args.vararg:

View file

@ -4230,56 +4230,47 @@ class TestBoundArguments(unittest.TestCase):
class TestSignaturePrivateHelpers(unittest.TestCase):
def _strip_non_python_syntax(self, input,
clean_signature, self_parameter, last_positional_only):
clean_signature, self_parameter):
computed_clean_signature, \
computed_self_parameter, \
computed_last_positional_only = \
computed_self_parameter = \
inspect._signature_strip_non_python_syntax(input)
self.assertEqual(computed_clean_signature, clean_signature)
self.assertEqual(computed_self_parameter, self_parameter)
self.assertEqual(computed_last_positional_only, last_positional_only)
def test_signature_strip_non_python_syntax(self):
self._strip_non_python_syntax(
"($module, /, path, mode, *, dir_fd=None, " +
"effective_ids=False,\n follow_symlinks=True)",
"(module, path, mode, *, dir_fd=None, " +
"(module, /, path, mode, *, dir_fd=None, " +
"effective_ids=False, follow_symlinks=True)",
0,
0)
self._strip_non_python_syntax(
"($module, word, salt, /)",
"(module, word, salt)",
0,
2)
"(module, word, salt, /)",
0)
self._strip_non_python_syntax(
"(x, y=None, z=None, /)",
"(x, y=None, z=None)",
None,
2)
"(x, y=None, z=None, /)",
None)
self._strip_non_python_syntax(
"(x, y=None, z=None)",
"(x, y=None, z=None)",
None,
None)
self._strip_non_python_syntax(
"(x,\n y=None,\n z = None )",
"(x, y=None, z=None)",
None,
None)
self._strip_non_python_syntax(
"",
"",
None,
None)
self._strip_non_python_syntax(
None,
None,
None,
None)

View file

@ -0,0 +1 @@
Private helper method ``inspect._signature_strip_non_python_syntax`` will no longer strip ``/`` from the input string.