2
2
3
3
from __future__ import annotations
4
4
5
+ import dataclasses
5
6
import sys
6
7
import types
7
8
import typing
@@ -157,6 +158,7 @@ def get_type_hints(
157
158
obj : Any ,
158
159
globalns : dict [str , Any ] | None = None ,
159
160
localns : dict [str , Any ] | None = None ,
161
+ include_extras : bool = False ,
160
162
) -> dict [str , Any ]:
161
163
"""Return a dictionary containing type hints for a function, method, module or class
162
164
object.
@@ -167,7 +169,7 @@ def get_type_hints(
167
169
from sphinx .util .inspect import safe_getattr # lazy loading
168
170
169
171
try :
170
- return typing .get_type_hints (obj , globalns , localns )
172
+ return typing .get_type_hints (obj , globalns , localns , include_extras = include_extras )
171
173
except NameError :
172
174
# Failed to evaluate ForwardRef (maybe TYPE_CHECKING)
173
175
return safe_getattr (obj , '__annotations__' , {})
@@ -267,7 +269,20 @@ def restify(cls: Any, mode: _RestifyMode = 'fully-qualified-except-typing') -> s
267
269
return f':py:class:`{ module_prefix } { _INVALID_BUILTIN_CLASSES [cls ]} `'
268
270
elif _is_annotated_form (cls ):
269
271
args = restify (cls .__args__ [0 ], mode )
270
- meta = ', ' .join (map (repr , cls .__metadata__ ))
272
+ meta_args = []
273
+ for m in cls .__metadata__ :
274
+ if isinstance (m , type ):
275
+ meta_args .append (restify (m , mode ))
276
+ elif dataclasses .is_dataclass (m ):
277
+ # use restify for the repr of field values rather than repr
278
+ d_fields = ', ' .join ([
279
+ fr"{ f .name } =\ { restify (getattr (m , f .name ), mode )} "
280
+ for f in dataclasses .fields (m ) if f .repr
281
+ ])
282
+ meta_args .append (fr'{ restify (type (m ), mode )} \ ({ d_fields } )' )
283
+ else :
284
+ meta_args .append (repr (m ))
285
+ meta = ', ' .join (meta_args )
271
286
if sys .version_info [:2 ] <= (3 , 11 ):
272
287
# Hardcoded to fix errors on Python 3.11 and earlier.
273
288
return fr':py:class:`~typing.Annotated`\ [{ args } , { meta } ]'
@@ -510,7 +525,25 @@ def stringify_annotation(
510
525
return f'{ module_prefix } Literal[{ args } ]'
511
526
elif _is_annotated_form (annotation ): # for py39+
512
527
args = stringify_annotation (annotation_args [0 ], mode )
513
- meta = ', ' .join (map (repr , annotation .__metadata__ ))
528
+ meta_args = []
529
+ for m in annotation .__metadata__ :
530
+ if isinstance (m , type ):
531
+ meta_args .append (stringify_annotation (m , mode ))
532
+ elif dataclasses .is_dataclass (m ):
533
+ # use stringify_annotation for the repr of field values rather than repr
534
+ d_fields = ', ' .join ([
535
+ f"{ f .name } ={ stringify_annotation (getattr (m , f .name ), mode )} "
536
+ for f in dataclasses .fields (m ) if f .repr
537
+ ])
538
+ meta_args .append (f'{ stringify_annotation (type (m ), mode )} ({ d_fields } )' )
539
+ else :
540
+ meta_args .append (repr (m ))
541
+ meta = ', ' .join (meta_args )
542
+ if sys .version_info [:2 ] <= (3 , 9 ):
543
+ if mode == 'smart' :
544
+ return f'~typing.Annotated[{ args } , { meta } ]'
545
+ if mode == 'fully-qualified' :
546
+ return f'typing.Annotated[{ args } , { meta } ]'
514
547
if sys .version_info [:2 ] <= (3 , 11 ):
515
548
if mode == 'fully-qualified-except-typing' :
516
549
return f'Annotated[{ args } , { meta } ]'
0 commit comments