mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-128184: Fix display of signatures with ForwardRefs (#130815)
Co-authored-by: sobolevn <mail@sobolevn.me>
This commit is contained in:
parent
80e6d3ec49
commit
1d251b8339
5 changed files with 46 additions and 2 deletions
|
@ -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)
|
||||
|
|
|
@ -143,7 +143,7 @@ __all__ = [
|
|||
|
||||
|
||||
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 formatannotation(annotation, base_module=None, *, quote_annotation_strings=T
|
|||
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):
|
||||
|
|
|
@ -12,6 +12,7 @@ import builtins
|
|||
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 TestDocString(unittest.TestCase):
|
|||
|
||||
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):
|
||||
|
|
|
@ -1753,6 +1753,10 @@ class TestFormatAnnotation(unittest.TestCase):
|
|||
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 @@ class TestSignatureObject(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
|
||||
|
|
|
@ -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.
|
Loading…
Add table
Add a link
Reference in a new issue