Skip to content

Commit 9a41aa6

Browse files
authored
Broaden type annotation for verbose_name(_plural) to accept lazystr. (#1139)
* Broaden type annotation for verbose_name(_plural) to accept lazystr. Fixes #1137. Signed-off-by: Zixuan James Li <[email protected]> * Broaden type annotation for help_text to accept lazystr. Signed-off-by: Zixuan James Li <[email protected]> * Broaden type annotation for ValidationError to accept lazystr. Signed-off-by: Zixuan James Li <[email protected]> * Broaden type annotation for label to accept lazystr. Signed-off-by: Zixuan James Li <[email protected]> * Add StrPromise and StrOrPromise aliases to django_stubs_ext. We make StrPromise and StrOrPromise available via django_stubs_ext so that conditional imports with TYPE_CHECKING is not required. These aliases fall back to Promise or Union[str, Promise] when not TYPE_CHECKING. Signed-off-by: Zixuan James Li <[email protected]> Signed-off-by: Zixuan James Li <[email protected]>
1 parent a2a3543 commit 9a41aa6

File tree

19 files changed

+138
-104
lines changed

19 files changed

+138
-104
lines changed

django-stubs/apps/config.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ from typing import Dict, Iterator, Optional, Type
33

44
from django.apps.registry import Apps
55
from django.db.models.base import Model
6+
from django.utils.functional import _StrOrPromise
67

78
MODELS_MODULE_NAME: str
89

@@ -11,7 +12,7 @@ class AppConfig:
1112
module: Optional[types.ModuleType] = ...
1213
apps: Optional[Apps] = ...
1314
label: str = ...
14-
verbose_name: str = ...
15+
verbose_name: _StrOrPromise = ...
1516
path: str = ...
1617
models_module: Optional[str] = ...
1718
models: Dict[str, Type[Model]] = ...

django-stubs/contrib/admin/options.pyi

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ from django.http.response import HttpResponse, HttpResponseRedirect, JsonRespons
4141
from django.template.response import _TemplateForResponseT
4242
from django.urls.resolvers import URLPattern
4343
from django.utils.datastructures import _ListOrTuple
44+
from django.utils.functional import _StrOrPromise
4445
from django.utils.safestring import SafeString
4546
from typing_extensions import Literal, TypedDict
4647

@@ -296,8 +297,8 @@ class InlineModelAdmin(Generic[_ChildModelT, _ParentModelT], BaseModelAdmin[_Chi
296297
min_num: Optional[int] = ...
297298
max_num: Optional[int] = ...
298299
template: str = ...
299-
verbose_name: Optional[str] = ...
300-
verbose_name_plural: Optional[str] = ...
300+
verbose_name: Optional[_StrOrPromise] = ...
301+
verbose_name_plural: Optional[_StrOrPromise] = ...
301302
can_delete: bool = ...
302303
show_change_link: bool = ...
303304
classes: Optional[Sequence[str]] = ...

django-stubs/contrib/admin/sites.pyi

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ from django.http.request import HttpRequest
1111
from django.http.response import HttpResponse
1212
from django.template.response import TemplateResponse
1313
from django.urls import URLPattern, URLResolver
14-
from django.utils.functional import LazyObject
14+
from django.utils.functional import LazyObject, _StrOrPromise
1515

1616
if sys.version_info >= (3, 9):
1717
from weakref import WeakSet
@@ -77,7 +77,7 @@ class AdminSite:
7777
def i18n_javascript(self, request: HttpRequest, extra_context: Optional[Dict[str, Any]] = ...) -> HttpResponse: ...
7878
def logout(self, request: HttpRequest, extra_context: Optional[Dict[str, Any]] = ...) -> TemplateResponse: ...
7979
def login(self, request: HttpRequest, extra_context: Optional[Dict[str, Any]] = ...) -> HttpResponse: ...
80-
def _build_app_dict(self, request: HttpRequest, label: Optional[str] = ...) -> Dict[str, Any]: ...
80+
def _build_app_dict(self, request: HttpRequest, label: Optional[_StrOrPromise] = ...) -> Dict[str, Any]: ...
8181
def get_app_list(self, request: HttpRequest) -> List[Any]: ...
8282
def index(self, request: HttpRequest, extra_context: Optional[Dict[str, Any]] = ...) -> TemplateResponse: ...
8383
def app_index(

django-stubs/contrib/admin/widgets.pyi

+7-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ from django.db.models.fields import _FieldChoices
77
from django.db.models.fields.reverse_related import ForeignObjectRel, ManyToManyRel, ManyToOneRel
88
from django.forms.models import ModelChoiceIterator
99
from django.forms.widgets import Media, _OptAttrs
10+
from django.utils.functional import _StrOrPromise
1011

1112
class FilteredSelectMultiple(forms.SelectMultiple):
12-
verbose_name: str = ...
13+
verbose_name: _StrOrPromise = ...
1314
is_stacked: bool = ...
1415
def __init__(
15-
self, verbose_name: str, is_stacked: bool, attrs: Optional[_OptAttrs] = ..., choices: _FieldChoices = ...
16+
self,
17+
verbose_name: _StrOrPromise,
18+
is_stacked: bool,
19+
attrs: Optional[_OptAttrs] = ...,
20+
choices: _FieldChoices = ...,
1621
) -> None: ...
1722

1823
class AdminDateWidget(forms.DateInput):

django-stubs/contrib/gis/db/models/fields.pyi

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ from typing import Any, Iterable, NamedTuple, Optional, Tuple, TypeVar, Union
22

33
from django.core.validators import _ValidatorCallable
44
from django.db.models.fields import Field, _ErrorMessagesT, _FieldChoices
5+
from django.utils.functional import _StrOrPromise
56

67
# __set__ value type
78
_ST = TypeVar("_ST")
@@ -19,7 +20,7 @@ def get_srid_info(srid: int, connection: Any) -> SRIDCacheEntry: ...
1920
class BaseSpatialField(Field[_ST, _GT]):
2021
def __init__(
2122
self,
22-
verbose_name: Optional[Union[str, bytes]] = ...,
23+
verbose_name: Optional[Union[_StrOrPromise, bytes]] = ...,
2324
srid: int = ...,
2425
spatial_index: bool = ...,
2526
*,
@@ -38,7 +39,7 @@ class BaseSpatialField(Field[_ST, _GT]):
3839
unique_for_month: Optional[str] = ...,
3940
unique_for_year: Optional[str] = ...,
4041
choices: Optional[_FieldChoices] = ...,
41-
help_text: str = ...,
42+
help_text: _StrOrPromise = ...,
4243
db_column: Optional[str] = ...,
4344
db_tablespace: Optional[str] = ...,
4445
validators: Iterable[_ValidatorCallable] = ...,
@@ -65,7 +66,7 @@ class GeometryField(BaseSpatialField):
6566
geography: Any = ...
6667
def __init__(
6768
self,
68-
verbose_name: Optional[Union[str, bytes]] = ...,
69+
verbose_name: Optional[Union[_StrOrPromise, bytes]] = ...,
6970
dim: int = ...,
7071
geography: bool = ...,
7172
*,
@@ -88,7 +89,7 @@ class GeometryField(BaseSpatialField):
8889
unique_for_month: Optional[str] = ...,
8990
unique_for_year: Optional[str] = ...,
9091
choices: Optional[_FieldChoices] = ...,
91-
help_text: str = ...,
92+
help_text: _StrOrPromise = ...,
9293
db_column: Optional[str] = ...,
9394
db_tablespace: Optional[str] = ...,
9495
validators: Iterable[_ValidatorCallable] = ...,

django-stubs/contrib/postgres/fields/array.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ from django.db.models import Field, Transform
55
from django.db.models.expressions import Combinable
66
from django.db.models.fields import _ErrorMessagesT, _FieldChoices
77
from django.db.models.fields.mixins import CheckFieldDefaultMixin
8+
from django.utils.functional import _StrOrPromise
89

910
# __set__ value type
1011
_ST = TypeVar("_ST")
@@ -42,7 +43,7 @@ class ArrayField(CheckFieldDefaultMixin, Field[_ST, _GT]):
4243
unique_for_month: Optional[str] = ...,
4344
unique_for_year: Optional[str] = ...,
4445
choices: Optional[_FieldChoices] = ...,
45-
help_text: str = ...,
46+
help_text: _StrOrPromise = ...,
4647
db_column: Optional[str] = ...,
4748
db_tablespace: Optional[str] = ...,
4849
validators: Iterable[_ValidatorCallable] = ...,

django-stubs/core/cache/backends/db.pyi

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from typing import Any, Dict
22

33
from django.core.cache.backends.base import BaseCache
4+
from django.utils.functional import _StrOrPromise
45

56
class Options:
67
db_table: str = ...
78
app_label: str = ...
89
model_name: str = ...
9-
verbose_name: str = ...
10-
verbose_name_plural: str = ...
10+
verbose_name: _StrOrPromise = ...
11+
verbose_name_plural: _StrOrPromise = ...
1112
object_name: str = ...
1213
abstract: bool = ...
1314
managed: bool = ...

django-stubs/core/exceptions.pyi

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
22

3+
from django.utils.functional import _StrPromise
34
from typing_extensions import Literal
45

56
class FieldDoesNotExist(Exception): ...
@@ -35,7 +36,7 @@ class ValidationError(Exception):
3536
def __init__(
3637
self,
3738
# Accepts arbitrarily nested data structure, mypy doesn't allow describing it accurately.
38-
message: Union[str, ValidationError, Dict[str, Any], List[Any]],
39+
message: Union[str, _StrPromise, ValidationError, Dict[str, Any], List[Any]],
3940
code: Optional[str] = ...,
4041
params: Optional[Dict[str, Any]] = ...,
4142
) -> None: ...

django-stubs/db/models/fields/__init__.pyi

+24-24
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ from django.db.models.query_utils import Q, RegisterLookupMixin
3030
from django.forms import Field as FormField
3131
from django.forms import Widget
3232
from django.utils.datastructures import DictWrapper
33-
from django.utils.functional import _Getter
33+
from django.utils.functional import _Getter, _StrOrPromise
3434
from typing_extensions import Protocol
3535

3636
class Empty: ...
@@ -120,7 +120,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
120120
_pyi_lookup_exact_type: Any
121121

122122
widget: Widget
123-
help_text: str
123+
help_text: _StrOrPromise
124124
attname: str
125125
auto_created: bool
126126
primary_key: bool
@@ -134,7 +134,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
134134
max_length: Optional[int]
135135
model: Type[Model]
136136
name: str
137-
verbose_name: str
137+
verbose_name: _StrOrPromise
138138
description: Union[str, _Getter[str]]
139139
blank: bool
140140
null: bool
@@ -158,7 +158,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
158158
non_db_attrs: Tuple[str, ...]
159159
def __init__(
160160
self,
161-
verbose_name: Optional[str] = ...,
161+
verbose_name: Optional[_StrOrPromise] = ...,
162162
name: Optional[str] = ...,
163163
primary_key: bool = ...,
164164
max_length: Optional[int] = ...,
@@ -174,7 +174,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
174174
unique_for_month: Optional[str] = ...,
175175
unique_for_year: Optional[str] = ...,
176176
choices: Optional[_FieldChoices] = ...,
177-
help_text: str = ...,
177+
help_text: _StrOrPromise = ...,
178178
db_column: Optional[str] = ...,
179179
db_tablespace: Optional[str] = ...,
180180
auto_created: bool = ...,
@@ -260,7 +260,7 @@ class DecimalField(Field[_ST, _GT]):
260260
decimal_places: int = ...
261261
def __init__(
262262
self,
263-
verbose_name: Optional[str] = ...,
263+
verbose_name: Optional[_StrOrPromise] = ...,
264264
name: Optional[str] = ...,
265265
max_digits: Optional[int] = ...,
266266
decimal_places: Optional[int] = ...,
@@ -275,7 +275,7 @@ class DecimalField(Field[_ST, _GT]):
275275
auto_created: bool = ...,
276276
serialize: bool = ...,
277277
choices: Optional[_FieldChoices] = ...,
278-
help_text: str = ...,
278+
help_text: _StrOrPromise = ...,
279279
db_column: Optional[str] = ...,
280280
db_tablespace: Optional[str] = ...,
281281
validators: Iterable[validators._ValidatorCallable] = ...,
@@ -289,7 +289,7 @@ class CharField(Field[_ST, _GT]):
289289
_pyi_lookup_exact_type: Any
290290
def __init__(
291291
self,
292-
verbose_name: Optional[str] = ...,
292+
verbose_name: Optional[_StrOrPromise] = ...,
293293
name: Optional[str] = ...,
294294
primary_key: bool = ...,
295295
max_length: Optional[int] = ...,
@@ -305,7 +305,7 @@ class CharField(Field[_ST, _GT]):
305305
unique_for_month: Optional[str] = ...,
306306
unique_for_year: Optional[str] = ...,
307307
choices: Optional[_FieldChoices] = ...,
308-
help_text: str = ...,
308+
help_text: _StrOrPromise = ...,
309309
db_column: Optional[str] = ...,
310310
db_tablespace: Optional[str] = ...,
311311
validators: Iterable[validators._ValidatorCallable] = ...,
@@ -319,7 +319,7 @@ class CommaSeparatedIntegerField(CharField[_ST, _GT]): ...
319319
class SlugField(CharField[_ST, _GT]):
320320
def __init__(
321321
self,
322-
verbose_name: Optional[str] = ...,
322+
verbose_name: Optional[_StrOrPromise] = ...,
323323
name: Optional[str] = ...,
324324
primary_key: bool = ...,
325325
unique: bool = ...,
@@ -333,7 +333,7 @@ class SlugField(CharField[_ST, _GT]):
333333
unique_for_month: Optional[str] = ...,
334334
unique_for_year: Optional[str] = ...,
335335
choices: Optional[_FieldChoices] = ...,
336-
help_text: str = ...,
336+
help_text: _StrOrPromise = ...,
337337
db_column: Optional[str] = ...,
338338
db_tablespace: Optional[str] = ...,
339339
validators: Iterable[validators._ValidatorCallable] = ...,
@@ -349,7 +349,7 @@ class EmailField(CharField[_ST, _GT]): ...
349349
class URLField(CharField[_ST, _GT]):
350350
def __init__(
351351
self,
352-
verbose_name: Optional[str] = ...,
352+
verbose_name: Optional[_StrOrPromise] = ...,
353353
name: Optional[str] = ...,
354354
*,
355355
primary_key: bool = ...,
@@ -366,7 +366,7 @@ class URLField(CharField[_ST, _GT]):
366366
unique_for_month: Optional[str] = ...,
367367
unique_for_year: Optional[str] = ...,
368368
choices: Optional[_FieldChoices] = ...,
369-
help_text: str = ...,
369+
help_text: _StrOrPromise = ...,
370370
db_column: Optional[str] = ...,
371371
db_tablespace: Optional[str] = ...,
372372
auto_created: bool = ...,
@@ -381,7 +381,7 @@ class TextField(Field[_ST, _GT]):
381381
_pyi_lookup_exact_type: Any
382382
def __init__(
383383
self,
384-
verbose_name: Optional[str] = ...,
384+
verbose_name: Optional[_StrOrPromise] = ...,
385385
name: Optional[str] = ...,
386386
primary_key: bool = ...,
387387
max_length: Optional[int] = ...,
@@ -397,7 +397,7 @@ class TextField(Field[_ST, _GT]):
397397
unique_for_month: Optional[str] = ...,
398398
unique_for_year: Optional[str] = ...,
399399
choices: Optional[_FieldChoices] = ...,
400-
help_text: str = ...,
400+
help_text: _StrOrPromise = ...,
401401
db_column: Optional[str] = ...,
402402
db_tablespace: Optional[str] = ...,
403403
validators: Iterable[validators._ValidatorCallable] = ...,
@@ -443,7 +443,7 @@ class GenericIPAddressField(Field[_ST, _GT]):
443443
auto_created: bool = ...,
444444
serialize: bool = ...,
445445
choices: Optional[_FieldChoices] = ...,
446-
help_text: str = ...,
446+
help_text: _StrOrPromise = ...,
447447
db_column: Optional[str] = ...,
448448
db_tablespace: Optional[str] = ...,
449449
validators: Iterable[validators._ValidatorCallable] = ...,
@@ -458,7 +458,7 @@ class DateField(DateTimeCheckMixin, Field[_ST, _GT]):
458458
_pyi_lookup_exact_type: Union[str, date]
459459
def __init__(
460460
self,
461-
verbose_name: Optional[str] = ...,
461+
verbose_name: Optional[_StrOrPromise] = ...,
462462
name: Optional[str] = ...,
463463
auto_now: bool = ...,
464464
auto_now_add: bool = ...,
@@ -474,7 +474,7 @@ class DateField(DateTimeCheckMixin, Field[_ST, _GT]):
474474
auto_created: bool = ...,
475475
serialize: bool = ...,
476476
choices: Optional[_FieldChoices] = ...,
477-
help_text: str = ...,
477+
help_text: _StrOrPromise = ...,
478478
db_column: Optional[str] = ...,
479479
db_tablespace: Optional[str] = ...,
480480
validators: Iterable[validators._ValidatorCallable] = ...,
@@ -486,7 +486,7 @@ class TimeField(DateTimeCheckMixin, Field[_ST, _GT]):
486486
_pyi_private_get_type: time
487487
def __init__(
488488
self,
489-
verbose_name: Optional[str] = ...,
489+
verbose_name: Optional[_StrOrPromise] = ...,
490490
name: Optional[str] = ...,
491491
auto_now: bool = ...,
492492
auto_now_add: bool = ...,
@@ -501,7 +501,7 @@ class TimeField(DateTimeCheckMixin, Field[_ST, _GT]):
501501
auto_created: bool = ...,
502502
serialize: bool = ...,
503503
choices: Optional[_FieldChoices] = ...,
504-
help_text: str = ...,
504+
help_text: _StrOrPromise = ...,
505505
db_column: Optional[str] = ...,
506506
db_tablespace: Optional[str] = ...,
507507
validators: Iterable[validators._ValidatorCallable] = ...,
@@ -518,7 +518,7 @@ class UUIDField(Field[_ST, _GT]):
518518
_pyi_private_get_type: uuid.UUID
519519
def __init__(
520520
self,
521-
verbose_name: Optional[str] = ...,
521+
verbose_name: Optional[_StrOrPromise] = ...,
522522
*,
523523
name: Optional[str] = ...,
524524
primary_key: bool = ...,
@@ -535,7 +535,7 @@ class UUIDField(Field[_ST, _GT]):
535535
unique_for_month: Optional[str] = ...,
536536
unique_for_year: Optional[str] = ...,
537537
choices: Optional[_FieldChoices] = ...,
538-
help_text: str = ...,
538+
help_text: _StrOrPromise = ...,
539539
db_column: Optional[str] = ...,
540540
db_tablespace: Optional[str] = ...,
541541
auto_created: bool = ...,
@@ -551,7 +551,7 @@ class FilePathField(Field[_ST, _GT]):
551551
allow_folders: bool = ...
552552
def __init__(
553553
self,
554-
verbose_name: Optional[str] = ...,
554+
verbose_name: Optional[_StrOrPromise] = ...,
555555
name: Optional[str] = ...,
556556
path: Union[str, Callable[..., str]] = ...,
557557
match: Optional[str] = ...,
@@ -570,7 +570,7 @@ class FilePathField(Field[_ST, _GT]):
570570
auto_created: bool = ...,
571571
serialize: bool = ...,
572572
choices: Optional[_FieldChoices] = ...,
573-
help_text: str = ...,
573+
help_text: _StrOrPromise = ...,
574574
db_column: Optional[str] = ...,
575575
db_tablespace: Optional[str] = ...,
576576
validators: Iterable[validators._ValidatorCallable] = ...,

0 commit comments

Comments
 (0)