Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 33.9k
gh-85267: Improvements to inspect.signature __text_signature__ handling#98796
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
16ae02eb60fb02dd2e08fea41f407f9f257126b8c3fef9787File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2100,7 +2100,7 @@ def _signature_strip_non_python_syntax(signature): | ||
| self_parameter = None | ||
| last_positional_only = None | ||
| lines = [l.encode('ascii') for l in signature.split('\n')] | ||
| lines = [l.encode('ascii') for l in signature.split('\n') if l] | ||
| generator = iter(lines).__next__ | ||
| token_stream = tokenize.tokenize(generator) | ||
| @@ -2199,11 +2199,11 @@ def wrap_value(s): | ||
| try: | ||
| value = eval(s, sys_module_dict) | ||
| except NameError: | ||
| raise RuntimeError() | ||
| raise ValueError | ||
ContributorAuthor
| ||
| if isinstance(value, (str, int, float, bytes, bool, type(None))): | ||
| return ast.Constant(value) | ||
| raise RuntimeError() | ||
| raise ValueError | ||
| class RewriteSymbolics(ast.NodeTransformer): | ||
| def visit_Attribute(self, node): | ||
| @@ -2213,7 +2213,7 @@ def visit_Attribute(self, node): | ||
| a.append(n.attr) | ||
| n = n.value | ||
| if not isinstance(n, ast.Name): | ||
| raise RuntimeError() | ||
| raise ValueError | ||
| a.append(n.id) | ||
| value = ".".join(reversed(a)) | ||
| return wrap_value(value) | ||
| @@ -2223,14 +2223,29 @@ def visit_Name(self, node): | ||
| raise ValueError() | ||
| return wrap_value(node.id) | ||
| def visit_BinOp(self, node): | ||
hauntsaninja marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| # Support constant folding of a couple simple binary operations | ||
| # commonly used to define default values in text signatures | ||
| left = self.visit(node.left) | ||
| right = self.visit(node.right) | ||
| if not isinstance(left, ast.Constant) or not isinstance(right, ast.Constant): | ||
| raise ValueError | ||
| if isinstance(node.op, ast.Add): | ||
| return ast.Constant(left.value + right.value) | ||
| elif isinstance(node.op, ast.Sub): | ||
| return ast.Constant(left.value - right.value) | ||
| elif isinstance(node.op, ast.BitOr): | ||
| return ast.Constant(left.value | right.value) | ||
| raise ValueError | ||
| def p(name_node, default_node, default=empty): | ||
| name = parse_name(name_node) | ||
| if default_node and default_node is not _empty: | ||
| try: | ||
| default_node = RewriteSymbolics().visit(default_node) | ||
| default = ast.literal_eval(default_node) | ||
| except ValueError: | ||
| return None | ||
| raise ValueError("{!r} builtin has invalid signature".format(obj)) from None | ||
| parameters.append(Parameter(name, kind, default=default, annotation=empty)) | ||
| # non-keyword-only parameters | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2480,7 +2480,7 @@ def p(name): return signature.parameters[name].default | ||
| self.assertEqual(p('f'), False) | ||
| self.assertEqual(p('local'), 3) | ||
| self.assertEqual(p('sys'), sys.maxsize) | ||
| self.assertNotIn('exp', signature.parameters) | ||
| self.assertEqual(p('exp'), sys.maxsize - 1) | ||
| test_callable(object) | ||
| @@ -4246,10 +4246,29 @@ def func(*args, **kwargs): | ||
| sig = inspect.signature(func) | ||
| self.assertIsNotNone(sig) | ||
| self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)') | ||
| func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)' | ||
| sig = inspect.signature(func) | ||
| self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)') | ||
| func.__text_signature__ = '(self, a=1+2, b=4-3, c=1 | 3 | 16)' | ||
| sig = inspect.signature(func) | ||
| self.assertEqual(str(sig), '(self, a=3, b=1, c=19)') | ||
| func.__text_signature__ = '(self, a=1,\nb=2,\n\n\n c=3)' | ||
| sig = inspect.signature(func) | ||
| self.assertEqual(str(sig), '(self, a=1, b=2, c=3)') | ||
| func.__text_signature__ = '(self, x=does_not_exist)' | ||
| with self.assertRaises(ValueError): | ||
| inspect.signature(func) | ||
| func.__text_signature__ = '(self, x=sys, y=inspect)' | ||
| with self.assertRaises(ValueError): | ||
| inspect.signature(func) | ||
| func.__text_signature__ = '(self, 123)' | ||
| with self.assertRaises(ValueError): | ||
| inspect.signature(func) | ||
hauntsaninja marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| def test_base_class_have_text_signature(self): | ||
| # see issue 43118 | ||
| from test.ann_module7 import BufferedReader | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| Several improvements to :func:`inspect.signature`'s handling of ``__text_signature``. | ||
| - Fixes a case where :func:`inspect.signature` dropped parameters | ||
| - Fixes a case where :func:`inspect.signature` raised :exc:`tokenize.TokenError` | ||
| - Allows :func:`inspect.signature` to understand defaults involving binary operations of constants | ||
| - :func:`inspect.signature` is documented as only raising :exc:`TypeError` or :exc:`ValueError`, but sometimes raised :exc:`RuntimeError`. These cases now raise :exc:`ValueError` | ||
| - Removed a dead code path |
Uh oh!
There was an error while loading. Please reload this page.