-
-
Notifications
You must be signed in to change notification settings - Fork 484
Used _ContextKeys for context like dicts #1298
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
Conversation
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 think dict[_ContextKeys, Any]
is the way to go 👍
Please, double check Mapping
case to be required.
Thanks!
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.
Other from a single comment - looks good to me!
@@ -35,6 +35,8 @@ from django.utils.functional import _StrOrPromise | |||
from django.utils.safestring import SafeString | |||
from typing_extensions import Literal, TypeAlias, TypedDict | |||
|
|||
from ...template.context import _ContextKeys |
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.
nit: please, use absolute import, ...
is hard to read.
@@ -33,6 +33,7 @@ from django.urls.resolvers import URLPattern | |||
from django.utils.datastructures import _ListOrTuple | |||
from django.utils.functional import _StrOrPromise | |||
from django.utils.safestring import SafeString | |||
from template.context import _ContextKeys |
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 template.context import _ContextKeys | |
from django.template.context import _ContextKeys |
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.
Thanks for the feedback. 👍
Hopefully I've captured them in the required style now 🤞
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.
Awesome! Just a single thing left and it is good to go. Thanks!
tests/typecheck/test_shortcuts.yml
Outdated
from django.http.request import HttpRequest | ||
|
||
TestContext = TypedDict("TestContext", {"user": Any}) | ||
TestContext = dict[Union[int, str, Node], Any] |
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 think that this test is here to be sure that custom TypedDict
instances are allowed. Because people can type their contexts with it.
Please, do not change it.
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 understand the use case. However, I'm not sure on the way forward here.
As far as I can tell TypedDict
only supports the use case where a dictionary object has a specific set of string keys
.
The change I'm proposing here is that the key could be int | str | Node
, and therefore the two are incompatible?
One option is not to change the type in the shortcut file. This would allow the test to pass, but I'm not sure it's the right solution.
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 think that typed dict {'user': anything}
must be compatible with dict[int | str | None, Any]
. But, if it is not - I am not surprised.
I've looked into the test history - it is quite old. I don't remember the history behind it. But, it is clear that we can break this use-case for user who already use it. But, using correct type annotations is also quite important.
I think people can go with cast()
when using typed dicts, so it is more important to have correct annotations 🤔
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 found TypedDict
not being compatible with dict
somewhat surprising. However, that's been discussed previously at #355 and so maybe we need to use Mapping
in place of Dict
throughout?
I'm also surprised that a typed dict is not compatible with a wider type definition. The same is true of dict
's too.
from typing import TypedDict, Any, Mapping
class MyContext(TypedDict):
user: Any
def str_mapping_function(context: Mapping[str, Any]) -> None:
pass
def multi_mapping_function(context: Mapping[str | int , Any]) -> None:
pass
ctx = MyContext(user="MyName")
str_mapping_function(ctx) # ok
multi_mapping_function(ctx) # error: Argument 1 to "multi_mapping_function" has incompatible type "MyContext"; expected "Mapping[Union[str, int], Any]"
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.
Can you please try Mapping
?
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 updated to mapping, and reverted the test. Just left with one error which I'm not sure how to resolve.
main:9: error: Argument 3 to "render" has incompatible type "TestContext"; expected "Optional[Mapping[Union[int, str, Node], Any]]" (diff)
I could add a cast()
like this, but this doesn't seem like a good answer to me.
test_context = cast(Mapping[Union[int, str, Node], Any], test_context)
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.
We can remove this test and recommend users to use cast(Any, typed_context)
for their code. If they use TypedDict
.
Sorry for the noise. I'll have to see about installing WSL so I can get the tests to run. It's a bit hard to see the wood through the trees running the test suite on Windows. |
No worries, thanks for the fix. |
Just came across this for Out of curiosity: What is the reasoning/advantage of using Update: Additional context: We use context = {'foo': 'bar'}
render_to_string('path/to/email.txt', context) mypy reports:
Adding a type hint According to the documentation |
This is causing tons of false positives in my code base. I think this is a release blocker. Simple code like this: from django.template.loader import get_template
template = get_template("bla.html")
context = {"title": "test", "number": 42}
template.render(context)
# Even using `Any` doesn't work:
context2: dict[str, Any] = {"title": "test", "number": 42}
template.render(context2)
|
To be frank, I don't understand what this PR is trying to achieve. Context dict is now assumed to be As I understand, context keys are usually names of attributes; these attribute names are then accessible in Django templates as What's the use case for using PS: The reason that this causes issues is that |
I notice that part of this PR was already reverted last week in #1306 and that has elicited no feedback here. I'm inclined to revert the rest as well, to unblock the release, unless there is a convincing explanation for this. |
I have made things!
I believe that
ContextKeys
should be allowed when using a dict "context". This updates for a few core items I came across but I've not yet done a full audit. That's a big task and there are many variations already, so thought best to get feedback first.django-stubs/django-stubs/template/context.pyi
Line 12 in 35eba6b
With these context like dicts, there are several different versions floating about. Even with the changes suggested here there is:
dict[str, Any]
dict[str, str]
Mapping[str, Any]
Further:
Context.flatten
returnsdict[_ContextKeys, dict[_ContextKeys, type[Any] | str] | int | str | None]
Variable.resolve
acceptsMapping[str, Mapping[str, Any]]
Is it worth trying to standardise? Maybe about
dict[_ContextKeys, Any]
?