-
-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Broaden type annotation for verbose_name(_plural) to accept lazystr. #1139
Conversation
Fixes typeddjango#1137. Signed-off-by: Zixuan James Li <p359101898@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way to make str
and Promise
compatible?
I did a quick search on GitHub and found that people use |
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
6ccb678
to
e95c760
Compare
I'm not following on why we need to type I mean, as a user of lazy/promise etc, you'll never need to know or directly consider that it's a Though the Union option suggested here looks a bit never ending, as it'll likely pop up quite a lot of cases where it'll have to be In addition to that, that's just to cover I think what I'm saying is that there have to be some |
Yeah, I agree with @flaeppe |
I agree that this is probably invasive in terms of the functions that might be affected within Django. If that's the issue we can try to implement method+function hooks ensuring that Django's functions/methods that accept However, it might be an overkill since it is unclear whether the
When using In fact, the documentation explicitly states the difference between a
We have already done something similar by typing the Passing
We did consider making a generic |
As an example of what can go wrong if we aren’t truthful to mypy, consider def maybe_decode(s: str | bytes) -> str:
if isinstance(s, str):
return s
else:
return s.decode()
maybe_decode(gettext_lazy("promise")) If we incorrectly told mypy that There would also be false positives, such an incorrect “error: Statement is unreachable” on this def force(s: str | Promise) -> str:
if isinstance(s, str):
return s
else:
return str(s)
force(gettext_lazy("foo")) Another reason that the user needs to care about the difference between |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't come up with any better idea really. But I'm curious if these changes could result in users prematurely evaluating lazy strings.
But I guess those cases could be mitigated by patching the stubs.
Suppose we'll notice in time
@@ -43,6 +43,7 @@ class _StrPromise(Promise, Sequence[str]): | |||
# Mypy requires this for the attribute hook to take effect | |||
def __getattribute__(self, __name: str) -> Any: ... | |||
|
|||
_StrOrPromise = Union[str, _StrPromise] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe _StrPromise
should be public? Since it'll be exposed to users, right?
So that one can do str | StrPromise
if passing around/accepting gettext_lazy
values
_StrOrPromise = Union[str, _StrPromise] | |
_StrOrPromise = Union[str, StrPromise] |
|
If we expect users to import and use Otherwise using them would be annoying, import would need |
d5178ed
to
15a0032
Compare
The PR is updated with aliases made available in |
15a0032
to
21ce4fe
Compare
StrOrPromise = StrOrPromise | ||
StrPromise = StrPromise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn’t how re-exports work in mypy.
But I think your initial inclination to use leading underscores in django-stubs/utils/functional.pyi
was correct, because these don’t exist in django.utils.functional
at runtime. We should use underscores in django-stubs
and re-export with no underscores here in django_stubs_ext
.
21ce4fe
to
159327e
Compare
StrOrPromise = _StrOrPromise | ||
StrPromise = _StrPromise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StrOrPromise = _StrOrPromise | |
StrPromise = _StrPromise |
else: | ||
from django.db.models.query import QuerySet | ||
from django.utils.functional import Promise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from django.utils.functional import Promise | |
from django.utils.functional import Promise as StrPromise |
59bfd6f
to
1ba1dfd
Compare
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 <p359101898@gmail.com>
1ba1dfd
to
a859de4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, any other comments?
Thanks for working on this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All good from my end
I have made things!
There might be other use cases of
lazystr
that need to be considered. It needs to be verified thatPromise
objects are actually expected for the callee. Right now we are following a conservative approach to first mark ones that do commonly acceptPromise
.Related issues