Skip to content

Commit f0c7575

Browse files
committed
Replaced TypeAlias _ClassLevelWidgetT with descriptor _WidgetTypeOrInstance for Field.widget
1 parent 631b48a commit f0c7575

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

django-stubs/forms/fields.pyi

+14-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import datetime
22
from collections.abc import Collection, Iterator, Sequence
33
from decimal import Decimal
44
from 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
66
from uuid import UUID
77

88
from django.core.files import File
@@ -15,20 +15,24 @@ from django.utils.choices import CallableChoiceIterator, _ChoicesCallable, _Choi
1515
from django.utils.datastructures import _PropertyDescriptor
1616
from 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+
class _WidgetTypeOrInstance:
19+
def __init__(self, origin_type: type[Widget]) -> None: ...
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+
def __get__(self, instance: Field, owner: type[Field]) -> type[Widget] | Widget: ...
25+
@overload
26+
def __set__(self, instance: None, value: type[Widget]) -> None: ...
27+
@overload
28+
def __set__(self, instance: Field, value: Widget) -> None: ...
29+
def __set__(self, instance: Field, value: type[Widget] | Widget) -> None: ...
2630

2731
class Field:
2832
initial: Any
2933
label: _StrOrPromise | None
3034
required: bool
31-
widget: _ClassLevelWidgetT
35+
widget: _WidgetTypeOrInstance
3236
hidden_widget: type[Widget]
3337
default_validators: list[_ValidatorCallable]
3438
default_error_messages: ClassVar[_ErrorMessagesDict]

0 commit comments

Comments
 (0)