-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Using variables as key of TypedDict #7178
Comments
We don't support that, no. I think it does work if The dynamic version we definitely won't be able to do useful typechecking of, I think. Best move is probably a |
I think |
Should, but doesn't :( In my case, I restrict possible keys for external API, e.g.: class DataType(TypedDict, total=False):
FIELD1: str
FIELD2: str
def send_to_external_api(data: DataType):
... And then use these keys in generic way: class MyGenericWay:
external_api_key: Final = 'FIELD1'
def send(self):
send_to_external_api({self.external_api_key: 'value'})
class AnotherClass:
external_api_key: Final = 'FIELD2'
... But mypy allows only in-place literal as keys and also restrict from mypy_extensions import TypedDict
from typing_extensions import Literal, Final
class MyDict(TypedDict):
field_name: int
d: MyDict
d = {'field_name': 1}
name_in_var = 'field_name'
d = {name_in_var: 1}
name_in_literal2: Literal['field_name'] = 'field_name'
d = {name_in_literal2: 1}
name_in_final: Final = 'field_name'
d = {name_in_final: 1}
Should I create a new issue, or @msullivan will reopen this? |
Looks like it needs to change a few lines in checkexpr::check_typeddict_call_with_dict: Lines 495 to 500 in bd00106
Add check for literal like this: if not isinstance(item_name_expr, StrExpr) or not (isinstance(item_name_expr, LiteralType) and isinstance(item_name_expr.value, str)): @ilevkivskyi What do you think? I can create a new PR for this issue if you think it's a good idea to implement and I use the right way to check |
This is problematic for us, since we use "constants" [0] like That said, I did find that setting What still doesn't work is something like the following:
[0] These are of course not real constants since that's not a thing, but they're variables that never change. |
Here's a workaround for you that might help: from typing import TypedDict, Sequence, Literal
class A(TypedDict):
key1: str
key2: str
a = A({KEY1: 'abc', KEY2: 'def'})
ALLOWED_KEYS: Sequence[Literal['key1', 'key2']] = (KEY1, KEY2)
for k in ALLOWED_KEYS:
print(a[k]) https://mypy-play.net/?mypy=latest&python=3.10&gist=4cf83edbe0afb7d5de7e4de44fb0c404 |
Thanks @AlexWaygood , appreciate the tip! Thought I can't shake the feeling that this level of verbosity is not justified here. Specifically, I can't execute
without first defining Either way, I think the above is maybe a bit of an edge case to the core issue outlined by OP. Though it would be nice if cases like these - which are quite unambiguously correct from a developer perspective - are handled properly by mypy. Otherwise it's easy to feel that we have to jump through hoops and make the code less readable just in order to satisfy mypy. |
Why is this closed? It's not resolved and it's very awkward when using TypedDicts. |
Furthermore, a common use case is converting dict -> tuple of a specific order (e.g., passing kwargs to position-only function): class D(TypeDict):
a: int
b: str
d: D = {"a": 0, "b": "foo"}
key_order = ("b", "a")
t = (d[k] for k in key_order) # error: TypedDict key must be a string literal; expected one of ("a", "b") |
Here's another example that I don't think should error:
I echo previous thoughts about this issue needing remain open as the problem is not resolved. |
As described on python/mypy#7178 (comment) isn't possible to use dynamic keys with TypedDict and the recommendation is to use `# type: ignore [misc]`.
* Fix error: Value of type "Optional[Match[Any]]" is not indexable mypy throws this error because the 2nd lambda function doesn't handle the case of re.search() returning None. The `get_key` function also requires two `assert` statements to provide more hints to mypy and keep the previous behaviour when: 1. `key_name` doesn't exist into `device` 2. re.search() will always find a group (`0`) * Fix error: Library stubs not installed for "requests" * Fix error: Need type annotation for "pie_data" * Fix error: Need type annotation for "report" * Fix error: Item "float"/"int" of "Union[float, str, int]" has no attribute "replace" * Ignore error: TypedDict key must be a string literal As described on python/mypy#7178 (comment) isn't possible to use dynamic keys with TypedDict and the recommendation is to use `# type: ignore [misc]`. * Fix error: Value of type variable "AnyStr" of "search" cannot be "Union[float,str]" * Ignore error: Value of type "Optional[Match[str]]" is not indexable If the result of re.search()[0] is not indexable (returns `None`) it will be handled by the try/except block, so it can be safely ignored. But maybe it could be rewritten to handle this in a clear way. * Fix error: Need type annotation for "seen" Add type annotation for `seen` variable.
Echoing the sentiment that this would be a helpful improvement. We use constants exactly as @svet-b described above. |
Same here. It's confusing and would be highly appreciated if fixed. |
I would also really like this to be adressed. I have two related problems:
Mypy should be able to figure out that |
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
Can't pull out image type because of <python/mypy#7178>.
+1 I would find this really useful if this can be address and fixed. |
Ref #7178 This code is used for some TypedDict errors, but `misc` was used for others. I make it more consistent. Also this code looks undocumented, so I add some basic docs.
Doesn't seem to have been fully fixed by #14621, (should be included in the latest mypy version 1.4.1) given this definiton:
I am getting And I need to add |
Can confirm it's not fixed in 1.4.1, even if the key is a known |
Given the amount and persistency of feedback, looks to me like a case of you're holding it wrong. Regardless of what's the right principled approach, there's obviously a usability issue. While we document how to define "constants", the behavior is apparently still unintuitive, should we consider solutions here? e.g.
|
Why is this actually closed? I can't find any hint of that being fixed now. |
With the following example I get an error.
Can mypy not figure out that
key
is set to a literal?In my own code im building up
key
dynamically to get a key from a TypedDict.mypy version: 0.711
The text was updated successfully, but these errors were encountered: