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)
import abc
-from annotationlib import Format
+from annotationlib import Format, ForwardRef
from annotationlib import get_annotations # re-exported
import ast
import dis
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):
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
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):
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):
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
--- /dev/null
+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.