microsoft / pyright

Static Type Checker for Python
Other
13.04k stars 1.39k forks source link

TypedDict Not Accepting str Enum #8378

Closed kossyrev-bg closed 1 month ago

kossyrev-bg commented 1 month ago

Environment data

Code Snippet

from typing import TypedDict
from enum import Enum

class TestEnum(Enum):
    STR = "one"
    INT = "two"

MyTest = TypedDict('MyTest', {TestEnum.STR.value: str, TestEnum.INT.value: int})
my_dict: MyTest = {TestEnum.STR.value: "hello", TestEnum.INT.value: 1}

Expected behavior

No red squigglies.

Actual behavior

Red squigglies:

MyTest = TypedDict('MyTest', {TestEnum.STR.value: str, TestEnum.INT.value: int})
# Expected string literal for dictionary entry name
# (function) STR: Unknown

my_dict: MyTest = {TestEnum.STR.value: "hello", TestEnum.INT.value: 1}
# Expression of type "dict[str, str | int]" is incompatible with declared type "MyTest"
#  "one" is an undefined item in type "MyTest"
#  "two" is an undefined item in type "MyTest"

Note that code runs just fine when I copy-paste the above into a python terminal.

Logs

2024-07-11 13:16:24.479 [info] [Info  - 1:16:24 PM] Server process exited successfully
2024-07-11 13:16:24.983 [info] (Client) Pylance async client (2024.7.1) started with python extension (2024.10.0)
2024-07-11 13:16:25.249 [info] [Info  - 1:16:25 PM] (1187711) Pylance language server 2024.7.1 (pyright version 1.1.369, commit 1168be71) starting
2024-07-11 13:16:25.249 [info] [Info  - 1:16:25 PM] (1187711) Server root directory: file:///home/berkshiregrey.com/michael.kossyrev/.vscode/extensions/ms-python.vscode-pylance-2024.7.1/dist
2024-07-11 13:16:25.261 [info] [Info  - 1:16:25 PM] (1187711) Starting service instance "<default>"
2024-07-11 13:16:25.273 [info] [Info  - 1:16:25 PM] (1187711) Setting pythonPath for service "<default>": "/usr/bin/python3"
2024-07-11 13:16:25.273 [info] [Info  - 1:16:25 PM] (1187711) Setting environmentName for service "<default>": "3.10.12 (global)"
2024-07-11 13:16:25.273 [info] [Info  - 1:16:25 PM] (1187711) No include entries specified; assuming /<default workspace root>
2024-07-11 13:16:25.273 [info] [Info  - 1:16:25 PM] (1187711) Auto-excluding **/node_modules
2024-07-11 13:16:25.273 [info] [Info  - 1:16:25 PM] (1187711) Auto-excluding **/__pycache__
2024-07-11 13:16:25.273 [info] [Info  - 1:16:25 PM] (1187711) Auto-excluding **/.*
2024-07-11 13:16:25.288 [info] [Info  - 1:16:25 PM] (1187711) Assuming Python version 3.10.12.final.0
2024-07-11 13:16:25.322 [info] [Error - 1:16:25 PM] (1187711) File or directory "/<default workspace root>" does not exist.
2024-07-11 13:16:25.322 [info] [Info  - 1:16:25 PM] (1187711) No source files found.
2024-07-11 13:16:25.357 [info] [Info  - 1:16:25 PM] (1187711) Setting pythonPath for service "<default>": "/usr/bin/python3"
2024-07-11 13:16:25.357 [info] [Info  - 1:16:25 PM] (1187711) Setting environmentName for service "<default>": "3.10.12 (global)"
2024-07-11 13:16:25.357 [info] [Info  - 1:16:25 PM] (1187711) No include entries specified; assuming /<default workspace root>
2024-07-11 13:16:25.357 [info] [Info  - 1:16:25 PM] (1187711) Auto-excluding **/node_modules
2024-07-11 13:16:25.357 [info] [Info  - 1:16:25 PM] (1187711) Auto-excluding **/__pycache__
2024-07-11 13:16:25.357 [info] [Info  - 1:16:25 PM] (1187711) Auto-excluding **/.*
2024-07-11 13:16:25.357 [info] [Info  - 1:16:25 PM] (1187711) Assuming Python version 3.10.12.final.0
2024-07-11 13:16:25.385 [info] [Error - 1:16:25 PM] (1187711) File or directory "/<default workspace root>" does not exist.
2024-07-11 13:16:25.386 [info] [Info  - 1:16:25 PM] (1187711) No source files found.
2024-07-11 13:16:25.592 [info] [Info  - 1:16:25 PM] (1187711) Background analysis(1) root directory: file:///home/berkshiregrey.com/michael.kossyrev/.vscode/extensions/ms-python.vscode-pylance-2024.7.1/dist
2024-07-11 13:16:25.593 [info] [Info  - 1:16:25 PM] (1187711) Background analysis(1) started
kossyrev-bg commented 1 month ago

Ah maybe this isn't a bug, but rather a limitation of TypedDict in general: https://peps.python.org/pep-0589/#use-of-final-values-and-literal-types

If that's the case, then I apologize and you can close out this issue

erictraut commented 1 month ago

This behavior is correct. The TypedDict mechanism is created for static typing, and when you define a TypedDict, the keys need to be statically defined as string literals. You can't use dynamic expressions in a TypedDict. The key names must be string literals, like this:

MyTest = TypedDict("MyTest", {"one": str, "two": int})

Not surprisingly, mypy generates the same error in this case.

I was going to point you to the original PEP 589, but you already found it. :) Incidentally, the PEP has been superseded by the Python typing spec, which incorporates and builds upon all of the typing-related PEPs.