https://github.com/python/cpython/commit/1d251b8339a34a54e5d82d912d90bc0ca96e8757 commit: 1d251b8339a34a54e5d82d912d90bc0ca96e8757 branch: main author: Jelle Zijlstra <jelle.zijls...@gmail.com> committer: JelleZijlstra <jelle.zijls...@gmail.com> date: 2025-03-04T06:58:37-08:00 summary:
gh-128184: Fix display of signatures with ForwardRefs (#130815) Co-authored-by: sobolevn <m...@sobolevn.me> files: A Misc/NEWS.d/next/Library/2024-12-23-17-00-35.gh-issue-128184.cRQvgM.rst M Lib/dataclasses.py M Lib/inspect.py M Lib/test/test_dataclasses/__init__.py M Lib/test/test_inspect/test_inspect.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 7a24f8a9e5ccee..0f7dc9ae6b82f5 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1163,7 +1163,10 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, try: # In some cases fetching a signature is not possible. # But, we surely should not fail in this case. - text_sig = str(inspect.signature(cls)).replace(' -> None', '') + text_sig = str(inspect.signature( + cls, + annotation_format=annotationlib.Format.FORWARDREF, + )).replace(' -> None', '') except (TypeError, ValueError): text_sig = '' cls.__doc__ = (cls.__name__ + text_sig) diff --git a/Lib/inspect.py b/Lib/inspect.py index f143c89674b7b2..182c2eedbaba64 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -143,7 +143,7 @@ import abc -from annotationlib import Format +from annotationlib import Format, ForwardRef from annotationlib import get_annotations # re-exported import ast import dis @@ -1342,6 +1342,8 @@ def repl(match): if annotation.__module__ in ('builtins', base_module): return annotation.__qualname__ return annotation.__module__+'.'+annotation.__qualname__ + if isinstance(annotation, ForwardRef): + return annotation.__forward_arg__ return repr(annotation) def formatannotationrelativeto(object): diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 2e6c49e29ce828..8209374c36bca2 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -12,6 +12,7 @@ import types import weakref import traceback +import textwrap import unittest from unittest.mock import Mock from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol, DefaultDict @@ -2343,6 +2344,31 @@ class C: self.assertDocStrEqual(C.__doc__, "C(x:collections.deque=<factory>)") + def test_docstring_undefined_name(self): + @dataclass + class C: + x: undef + + self.assertDocStrEqual(C.__doc__, "C(x:undef)") + + def test_docstring_with_unsolvable_forward_ref_in_init(self): + # See: https://github.com/python/cpython/issues/128184 + ns = {} + exec( + textwrap.dedent( + """ + from dataclasses import dataclass + + @dataclass + class C: + def __init__(self, x: X, num: int) -> None: ... + """, + ), + ns, + ) + + self.assertDocStrEqual(ns['C'].__doc__, "C(x:X,num:int)") + def test_docstring_with_no_signature(self): # See https://github.com/python/cpython/issues/103449 class Meta(type): diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 6a562108c3a34b..03f2bacb3a4e88 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -1753,6 +1753,10 @@ def test_typing_replacement(self): self.assertEqual(inspect.formatannotation(ann), 'Union[List[str], int]') self.assertEqual(inspect.formatannotation(ann1), 'Union[List[testModule.typing.A], int]') + def test_forwardref(self): + fwdref = ForwardRef('fwdref') + self.assertEqual(inspect.formatannotation(fwdref), 'fwdref') + class TestIsMethodDescriptor(unittest.TestCase): @@ -4587,6 +4591,11 @@ def foo(a: list[str]) -> Tuple[str, float]: self.assertEqual(str(inspect.signature(foo)), inspect.signature(foo).format()) + def foo(x: undef): + pass + sig = inspect.signature(foo, annotation_format=Format.FORWARDREF) + self.assertEqual(str(sig), '(x: undef)') + def test_signature_str_positional_only(self): P = inspect.Parameter S = inspect.Signature diff --git a/Misc/NEWS.d/next/Library/2024-12-23-17-00-35.gh-issue-128184.cRQvgM.rst b/Misc/NEWS.d/next/Library/2024-12-23-17-00-35.gh-issue-128184.cRQvgM.rst new file mode 100644 index 00000000000000..448dcfe5a7ccdb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-12-23-17-00-35.gh-issue-128184.cRQvgM.rst @@ -0,0 +1,4 @@ +Improve display of :class:`annotationlib.ForwardRef` object +within :class:`inspect.Signature` representations. +This also fixes a :exc:`NameError` that was raised when using +:func:`dataclasses.dataclass` on classes with unresolvable forward references. _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com