@@ -2,7 +2,7 @@ import datetime
22from collections .abc import Collection , Iterator , Sequence
33from decimal import Decimal
44from re import Pattern
5- from typing import Any , ClassVar , Protocol , TypeAlias , type_check_only
5+ from typing import Any , ClassVar , Protocol , overload , type_check_only
66from uuid import UUID
77
88from django .core .files import File
@@ -15,20 +15,22 @@ from django.utils.choices import CallableChoiceIterator, _ChoicesCallable, _Choi
1515from django .utils .datastructures import _PropertyDescriptor
1616from django .utils .functional import _StrOrPromise
1717
18- # Problem: attribute `widget` is always of type `Widget` after field instantiation.
19- # However, on class level it can be set to `Type[Widget]` too.
20- # If we annotate it as `Union[Widget, Type[Widget]]`, every code that uses field
21- # instances will not typecheck.
22- # If we annotate it as `Widget`, any widget subclasses that do e.g.
23- # `widget = Select` will not typecheck.
24- # `Any` gives too much freedom, but does not create false positives.
25- _ClassLevelWidgetT : TypeAlias = Any
18+ @type_check_only
19+ class _WidgetTypeOrInstance :
20+ @overload
21+ def __get__ (self , instance : None , owner : type [Field ]) -> type [Widget ] | Widget : ...
22+ @overload
23+ def __get__ (self , instance : Field , owner : type [Field ]) -> Widget : ...
24+ @overload
25+ def __set__ (self , instance : None , value : type [Widget ] | Widget ) -> None : ...
26+ @overload
27+ def __set__ (self , instance : Field , value : Widget ) -> None : ...
2628
2729class Field :
2830 initial : Any
2931 label : _StrOrPromise | None
3032 required : bool
31- widget : _ClassLevelWidgetT
33+ widget : _WidgetTypeOrInstance
3234 hidden_widget : type [Widget ]
3335 default_validators : list [_ValidatorCallable ]
3436 default_error_messages : ClassVar [_ErrorMessagesDict ]
0 commit comments