dict: on retrieval, key allowed to be null
> uv run --with pyright pyright .\dict-none-key.py
e:\1work\CFF\dict-none-key.py
e:\1work\CFF\dict-none-key.py:4:12 - error: Argument of type "int | None" cannot be assigned to parameter "key" of type "int" in function "get"
Type "int | None" is not assignable to type "int"
"None" is not assignable to "int" (reportArgumentType)
But
> python -c "a = {'A': 1};b = {1: 'א'};k1 = a.get('A');k2 = b.get(k1);print('no runtime error')"
no runtime error
It just came to me that this might have been a design decision as:
a = {'A': 1}
b: dict[int | None, str] = {1: 'א'}
k1 = a.get('A')
k2 = b.get(k1)
gives:
> uv run --with pyright pyright .\dict-none-key.py
0 errors, 0 warnings, 0 informations
I searched manually, and with copilot and found no direct mention...
Is this PR acceptable in principal, which in that case I'll cross all the I's and dot all the T's
It's sort of questionable to me to treat None specially here. I think we've had someone before trying this (specifically for dict.get) and we rejected it, but can't immediately find it back. dict.get has seen a lot of efforts to change things: https://github.com/python/typeshed/pulls?q=is%3Apr+is%3Aclosed+dict.get+
dict.gethas seen a lot of efforts to change things:
I assumed so, but still somewhere there is an incongruency since:
a = {'A': 1}
b = {1: 'א'}
k1 = 'B'
kv1 = a.get(k1)
v1 = b.get(kv1)
print(f"'{k1}' -> '{kv1}' -> '{v1}'")
k2 = 'A'
kv2 = a.get(k2)
v2 = b.get(kv2)
print(f"'{k2}' -> '{kv2}' -> '{v2}'")
gets:
> python .\dict-none-key.py
'B' -> 'None' -> 'None'
'A' -> '1' -> 'א'
and IMHO is reasonable use case, where .get is used specifically for fall trough cascade
yet pyright and mypy report "error"
> uv run --with pyright pyright .\dict-none-key.py
dict-none-key.py
dict-none-key.py:6:12 - error: Argument of type "int | None" cannot be assigned to parameter "key" of type "int" in function "get"
Type "int | None" is not assignable to type "int"
"None" is not assignable to "int" (reportArgumentType)
dict-none-key.py:11:12 - error: Argument of type "int | None" cannot be assigned to parameter "key" of type "int" in function "get"
Type "int | None" is not assignable to type "int"
"None" is not assignable to "int" (reportArgumentType)
2 errors, 0 warnings, 0 informations
> uv run mypy .\dict-none-key.py
dict-none-key.py:6: error: Argument 1 to "get" of "dict" has incompatible type "int | None"; expected "int" [arg-type]
dict-none-key.py:11: error: Argument 1 to "get" of "dict" has incompatible type "int | None"; expected "int" [arg-type]
Found 2 errors in 1 file (checked 1 source file)
You could argue it's a mypy/pyright/jetbrains bug where they are being presumptuous in inferring the type of b as dict[int,str]
It's sort of questionable to me to treat
Nonespecially here. I think we've had someone before trying this (specifically fordict.get)
IMHO only .get and .pop should be treated this way.