-
Let's take a look at this function as an example of multiple things not working like I'd assume: from typing import TypeVar
T = TypeVar('T')
def cast_param_to_type(param_type: type[T], raw_param: str) -> T:
if param_type in {str, int, float}:
return param_type(raw_param) # Error: Expected no arguments to "object" constructor
elif param_type is datetime:
return datetime.fromisoformat(raw_param) # Error: Type "datetime" is incompatible with type "T@cast_param_to_type"
else:
raise ValueError('Unsupported type') I think the intention behind the implementation is clear: I want to pass a type to the method, and I want it to give me back an instance of it, created with the In my opinion, the function, written as is, should be correct, so let's break down the issues that confuse me:
I'm using Python 3.10 and Pylance v2024.8.2. I know there is a new syntax in 3.12 but I'm building a library and can't lock out so many users at the moment. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
In the first If you enable Unfortunately, it appears there's a bug in pyright that's causing it to narrow incorrectly in this case. I've logged a bug and will work on a fix for this issue. The reason this works if you change In the second |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for explaining the case so clearly. I like it when I dig deep into a topic nobody seems to talk about and it ends up improving the system. Since this is the third time that happened and I've interacted with you, I have to get slightly personal and say that I'm really inspired by your knowledge and constant desire to interact with the community. I don't know how you do it, but there aren't many open source projects with so many resolved issues as pyright. I'm sure I'll have something to report again and you'll answer/fix it in record time! With that out of the way, I do have a few follow-up questions:
I know you also do work on mypy so maybe you'd like to look at these too. |
Beta Was this translation helpful? Give feedback.
In the first
if
statement, the type of the expression{str, int, float}
evaluates to typeset[Unknown]
with pyright's default type inference settings. This means the statementparam_type in {str, int, float}
does not narrow the type ofparam_type
. For information about pyright's set expression inference rules, refer to this documentation. For more details about type narrowing and supported type guard patterns, refer to this documentation.If you enable
strictSetInference
(which is enabled by default in "strict" type checking mode), the type of{str, int, float}
will be inferred asset[type[str] | type[int] | type[float]]
, and thex in y
type guard pattern should apply, allowing pyright to…