diff options
author | Nikita Sobolev <mail@sobolevn.me> | 2023-09-01 11:18:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-01 01:18:15 -0700 |
commit | 044b8b3b6a65e6651b161e3badfa5d57c666db19 (patch) | |
tree | 144951a5304e451d52dff54042520cdfa02d019f | |
parent | 3edcf743e88b4ac4431d4b0f3a66048628cf5c70 (diff) | |
download | cpython-044b8b3b6a65e6651b161e3badfa5d57c666db19.tar.gz cpython-044b8b3b6a65e6651b161e3badfa5d57c666db19.zip |
gh-107805: Fix signatures of module-level generated functions in `turtle` (#107807)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
-rw-r--r-- | Lib/test/test_turtle.py | 20 | ||||
-rw-r--r-- | Lib/turtle.py | 43 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2023-08-09-13-49-37.gh-issue-107805.ezem0k.rst | 1 |
3 files changed, 45 insertions, 19 deletions
diff --git a/Lib/test/test_turtle.py b/Lib/test/test_turtle.py index 3f9f129a3dd..14121a590a5 100644 --- a/Lib/test/test_turtle.py +++ b/Lib/test/test_turtle.py @@ -461,5 +461,25 @@ class TestTPen(unittest.TestCase): self.assertTrue(tpen.isdown()) +class TestModuleLevel(unittest.TestCase): + def test_all_signatures(self): + import inspect + + known_signatures = { + 'teleport': + '(x=None, y=None, *, fill_gap: bool = False) -> None', + 'undo': '()', + 'goto': '(x, y=None)', + 'bgcolor': '(*args)', + 'pen': '(pen=None, **pendict)', + } + + for name in known_signatures: + with self.subTest(name=name): + obj = getattr(turtle, name) + sig = inspect.signature(obj) + self.assertEqual(str(sig), known_signatures[name]) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/turtle.py b/Lib/turtle.py index e542bc95689..6119b7a447e 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -3920,28 +3920,33 @@ def getmethparlist(ob): function definition and the second is suitable for use in function call. The "self" parameter is not included. """ - defText = callText = "" + orig_sig = inspect.signature(ob) # bit of a hack for methods - turn it into a function # but we drop the "self" param. # Try and build one for Python defined functions - args, varargs, varkw = inspect.getargs(ob.__code__) - items2 = args[1:] - realArgs = args[1:] - defaults = ob.__defaults__ or [] - defaults = ["=%r" % (value,) for value in defaults] - defaults = [""] * (len(realArgs)-len(defaults)) + defaults - items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)] - if varargs is not None: - items1.append("*" + varargs) - items2.append("*" + varargs) - if varkw is not None: - items1.append("**" + varkw) - items2.append("**" + varkw) - defText = ", ".join(items1) - defText = "(%s)" % defText - callText = ", ".join(items2) - callText = "(%s)" % callText - return defText, callText + func_sig = orig_sig.replace( + parameters=list(orig_sig.parameters.values())[1:], + ) + + call_args = [] + for param in func_sig.parameters.values(): + match param.kind: + case ( + inspect.Parameter.POSITIONAL_ONLY + | inspect.Parameter.POSITIONAL_OR_KEYWORD + ): + call_args.append(param.name) + case inspect.Parameter.VAR_POSITIONAL: + call_args.append(f'*{param.name}') + case inspect.Parameter.KEYWORD_ONLY: + call_args.append(f'{param.name}={param.name}') + case inspect.Parameter.VAR_KEYWORD: + call_args.append(f'**{param.name}') + case _: + raise RuntimeError('Unsupported parameter kind', param.kind) + call_text = f'({', '.join(call_args)})' + + return str(func_sig), call_text def _turtle_docrevise(docstr): """To reduce docstrings from RawTurtle class for functions diff --git a/Misc/NEWS.d/next/Library/2023-08-09-13-49-37.gh-issue-107805.ezem0k.rst b/Misc/NEWS.d/next/Library/2023-08-09-13-49-37.gh-issue-107805.ezem0k.rst new file mode 100644 index 00000000000..263df68f8e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-09-13-49-37.gh-issue-107805.ezem0k.rst @@ -0,0 +1 @@ +Fix signatures of module-level generated functions in :mod:`turtle`. |