Skip to content
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

Add type signatures to lru_cache using descriptor protocol (not ready to merge) #13043

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

alwaysmpe
Copy link

@alwaysmpe alwaysmpe commented Nov 18, 2024

This is an alternate approach to #13033 (appologies for multiple PRs, tricky problem).

That approach tries to solve the problem using multiple overloads but has some limitations, this has different limitations.

This changes lru_cache callable signature to use ParamSpec. Also provides descriptor protocol __get__ functions that match the behaviour of methods/classmethods/staticmethods as appropriate to bind the first parameter in the call signature. This is more robust/resistant to false positives because the first parameter should only be bindable as a method if it matches the type of object through which its accessed, likewise binding of classmethods. And a pure member variable should not use descriptor getters. This possibly depends on a very precise interpretation of the typing standard so I may be wrong.

So far from what I've found in pyright this works well with a few exceptions. overloads don't behave well with this cache. staticmethods that take as a first argument the type of the enclosing class have the first parameter bound when accessed through both the class and an instance. staticmethods that take as a first argument an instance of the enclosing class have the first parameter bound when accessed through an instance.

From what I've found in mypy, if cache is combined with property it causes a type error. Overloads cause problems. Likewise problem with staticmethod taking enclosing type or instance as first parameter.

The overload problem may be fixable in type checkers but I believe Eric from pyright has a proposal to clarify the typing spec for overloads, so nothing is likely to change before that. The staticmethod problem isn't very fixable.

Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

dacite (https://github.com/konradhalas/dacite)
+ dacite/types.py:19: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], type[Any]]"; expected "Never"  [arg-type]
+ dacite/types.py:27: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:29: error: "Never" not callable  [misc]
+ dacite/types.py:32: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[T] | type[None]], T]"; expected "Never"  [arg-type]
+ dacite/types.py:34: error: "Never" not callable  [misc]
+ dacite/types.py:41: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:46: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:48: error: "Never" not callable  [misc]
+ dacite/types.py:59: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:61: error: "Never" not callable  [misc]
+ dacite/types.py:64: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:69: error: "Never" not callable  [misc]
+ dacite/types.py:74: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:79: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], type[Any]]"; expected "Never"  [arg-type]
+ dacite/types.py:84: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:89: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], type[Any] | Any]"; expected "Never"  [arg-type]
+ dacite/types.py:106: error: "Never" not callable  [misc]
+ dacite/types.py:107: error: "Never" not callable  [misc]
+ dacite/types.py:108: error: "Never" not callable  [misc]
+ dacite/types.py:109: error: "Never" not callable  [misc]
+ dacite/types.py:112: error: "Never" not callable  [misc]
+ dacite/types.py:114: error: "Never" not callable  [misc]
+ dacite/types.py:115: error: "Never" not callable  [misc]
+ dacite/types.py:125: error: "Never" not callable  [misc]
+ dacite/types.py:130: error: "Never" not callable  [misc]
+ dacite/types.py:131: error: "Never" not callable  [misc]
+ dacite/types.py:132: error: "Never" not callable  [misc]
+ dacite/types.py:133: error: "Never" not callable  [misc]
+ dacite/types.py:134: error: "Never" not callable  [misc]
+ dacite/types.py:135: error: "Never" not callable  [misc]
+ dacite/types.py:136: error: "Never" not callable  [misc]
+ dacite/types.py:137: error: "Never" not callable  [misc]
+ dacite/types.py:138: error: "Never" not callable  [misc]
+ dacite/types.py:143: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:145: error: "Never" not callable  [misc]
+ dacite/types.py:147: error: "Never" not callable  [misc]
+ dacite/types.py:154: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any], tuple[Any, ...]], tuple[Any, ...]]"; expected "Never"  [arg-type]
+ dacite/types.py:166: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any], type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/types.py:168: error: "Never" not callable  [misc]
+ dacite/types.py:169: error: "Never" not callable  [misc]
+ dacite/types.py:176: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[Any]], bool]"; expected "Never"  [arg-type]
+ dacite/exceptions.py:6: error: "Never" not callable  [misc]
+ dacite/dataclasses.py:19: error: "Never" not callable  [misc]
+ dacite/dataclasses.py:24: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[T]], list[Field[Any]]]"; expected "Never"  [arg-type]
+ dacite/dataclasses.py:30: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[type[T]], bool]"; expected "Never"  [arg-type]
+ dacite/core.py:51: error: "Never" not callable  [misc]
+ dacite/core.py:51: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Callable[[object | Callable[..., Any] | FunctionType | BuiltinFunctionType | MethodType | Module | WrapperDescriptorType | MethodWrapperType | MethodDescriptorType, dict[str, Any] | None, Mapping[str, Any] | None, bool], dict[str, Any]]"; expected "Never"  [arg-type]
+ dacite/core.py:54: error: "Never" not callable  [misc]
+ dacite/core.py:79: error: "Never" not callable  [misc]
+ dacite/core.py:88: error: "Never" not callable  [misc]
+ dacite/core.py:89: error: "Never" not callable  [misc]
+ dacite/core.py:92: error: "Never" not callable  [misc]
+ dacite/core.py:94: error: "Never" not callable  [misc]
+ dacite/core.py:96: error: "Never" not callable  [misc]
+ dacite/core.py:98: error: "Never" not callable  [misc]
+ dacite/core.py:98: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type overloaded function; expected "Never"  [arg-type]
+ dacite/core.py:101: error: "Never" not callable  [misc]
+ dacite/core.py:102: error: "Never" not callable  [misc]
+ dacite/core.py:103: error: "Never" not callable  [misc]
+ dacite/core.py:111: error: "Never" not callable  [misc]
+ dacite/core.py:112: error: "Never" not callable  [misc]
+ dacite/core.py:140: error: "Never" not callable  [misc]
+ dacite/core.py:141: error: "Never" not callable  [misc]
+ dacite/core.py:143: error: "Never" not callable  [misc]
+ dacite/core.py:146: error: "Never" not callable  [misc]
+ dacite/core.py:152: error: "Never" not callable  [misc]
+ dacite/core.py:153: error: "Never" not callable  [misc]

pylint (https://github.com/pycqa/pylint)
+ pylint/checkers/utils.py:2312: error: "_lru_cache_wrapper" expects 2 type arguments, but 1 given  [type-arg]
+ pylint/checkers/utils.py:2312: error: Missing type parameters for generic type "_lru_cache_wrapper"  [type-arg]

psycopg (https://github.com/psycopg/psycopg)
+ psycopg/psycopg/rows.py:143: error: Argument 2 to "__call__" of "_lru_cache_wrapper" has incompatible type "*Generator[bytes | None, None, None]"; expected "bytes"  [arg-type]
+ psycopg/psycopg/types/enum.py:153: error: Need type annotation for "loader"  [var-annotated]
+ psycopg/psycopg/types/enum.py:153: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:153: error: Argument 2 to "__call__" of "_lru_cache_wrapper" has incompatible type "type[E]"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:153: error: Argument 3 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[tuple[bytes, E], ...]"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:156: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:156: error: Argument 2 to "__call__" of "_lru_cache_wrapper" has incompatible type "type[E]"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:156: error: Argument 3 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[tuple[bytes, E], ...]"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:161: error: Need type annotation for "dumper"  [var-annotated]
+ psycopg/psycopg/types/enum.py:161: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "type[E]"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:161: error: Argument 2 to "__call__" of "_lru_cache_wrapper" has incompatible type "int"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:161: error: Argument 3 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[tuple[E, bytes], ...]"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:164: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "type[E]"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:164: error: Argument 2 to "__call__" of "_lru_cache_wrapper" has incompatible type "int"; expected "Never"  [arg-type]
+ psycopg/psycopg/types/enum.py:164: error: Argument 3 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[tuple[E, bytes], ...]"; expected "Never"  [arg-type]

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/settings/legacy.py:105: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "type[PrefectBaseSettings]"; expected "Hashable"  [arg-type]
- src/prefect/settings/legacy.py:105: note: Following member(s) of "PrefectBaseSettings" have conflicts:
- src/prefect/settings/legacy.py:105: note:     Expected:
- src/prefect/settings/legacy.py:105: note:         def __hash__() -> int
- src/prefect/settings/legacy.py:105: note:     Got:
- src/prefect/settings/legacy.py:105: note:         def __hash__(self: object) -> int
- src/prefect/settings/legacy.py:105: note:     Expected:
- src/prefect/settings/legacy.py:105: note:         def __hash__() -> int
- src/prefect/settings/legacy.py:105: note:     Got:
- src/prefect/settings/legacy.py:105: note:         def __hash__(self: object) -> int
- src/prefect/settings/legacy.py:136: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "type[PrefectBaseSettings]"; expected "Hashable"  [arg-type]
- src/prefect/settings/legacy.py:136: note: Following member(s) of "PrefectBaseSettings" have conflicts:
- src/prefect/settings/legacy.py:136: note:     Expected:
- src/prefect/settings/legacy.py:136: note:         def __hash__() -> int
- src/prefect/settings/legacy.py:136: note:     Got:
- src/prefect/settings/legacy.py:136: note:         def __hash__(self: object) -> int
- src/prefect/settings/legacy.py:136: note:     Expected:
- src/prefect/settings/legacy.py:136: note:         def __hash__() -> int
- src/prefect/settings/legacy.py:136: note:     Got:
- src/prefect/settings/legacy.py:136: note:         def __hash__(self: object) -> int

ibis (https://github.com/ibis-project/ibis)
+ ibis/backends/tests/test_temporal.py:2162: error: Argument "exclude" to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[str, str]"; expected "tuple[str]"  [arg-type]
+ ibis/backends/tests/test_temporal.py:2180: error: Argument "exclude" to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[str, str, str, str, str, str]"; expected "tuple[str]"  [arg-type]

pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/dtypes/cast.py:591: error: Unused "type: ignore" comment  [unused-ignore]
+ pandas/core/apply.py:1004: error: Unused "type: ignore" comment  [unused-ignore]

twine (https://github.com/pypa/twine)
+ twine/auth.py:93: error: Invalid self argument "Resolver" to attribute function "username" with type "Callable[[VarArg(Never), KwArg(Never)], Never]"  [misc]
+ twine/settings.py:135: error: Invalid self argument "Resolver" to attribute function "username" with type "Callable[[VarArg(Never), KwArg(Never)], Never]"  [misc]
+ twine/settings.py:140: error: Invalid self argument "Resolver" to attribute function "password" with type "Callable[[VarArg(Never), KwArg(Never)], Never]"  [misc]

jinja (https://github.com/pallets/jinja)
+ src/jinja2/environment.py:1190: error: Argument 2 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1191: error: Argument 3 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1192: error: Argument 4 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1193: error: Argument 5 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1194: error: Argument 6 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1195: error: Argument 7 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1196: error: Argument 8 to "__call__" of "_lru_cache_wrapper" has incompatible type "Optional[str]"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1197: error: Argument 9 to "__call__" of "_lru_cache_wrapper" has incompatible type "Optional[str]"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1198: error: Argument 10 to "__call__" of "_lru_cache_wrapper" has incompatible type "bool"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1199: error: Argument 11 to "__call__" of "_lru_cache_wrapper" has incompatible type "bool"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1200: error: Argument 12 to "__call__" of "_lru_cache_wrapper" has incompatible type "Literal['\n', '\r\n', '\r']"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1201: error: Argument 13 to "__call__" of "_lru_cache_wrapper" has incompatible type "bool"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1202: error: Argument 14 to "__call__" of "_lru_cache_wrapper" has incompatible type "FrozenSet[Union[str, Type[Extension]]]"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1203: error: Argument 15 to "__call__" of "_lru_cache_wrapper" has incompatible type "bool"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1205: error: Argument 17 to "__call__" of "_lru_cache_wrapper" has incompatible type "Optional[Callable[..., Any]]"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1206: error: Argument 18 to "__call__" of "_lru_cache_wrapper" has incompatible type "Union[bool, Callable[[Optional[str]], bool]]"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1207: error: Argument 19 to "__call__" of "_lru_cache_wrapper" has incompatible type "None"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1208: error: Argument 20 to "__call__" of "_lru_cache_wrapper" has incompatible type "int"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1209: error: Argument 21 to "__call__" of "_lru_cache_wrapper" has incompatible type "bool"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1210: error: Argument 22 to "__call__" of "_lru_cache_wrapper" has incompatible type "None"; expected "Never"  [arg-type]
+ src/jinja2/environment.py:1211: error: Argument 23 to "__call__" of "_lru_cache_wrapper" has incompatible type "bool"; expected "Never"  [arg-type]

jax (https://github.com/google/jax)
+ jax/_src/dtypes.py:385: error: Unused "type: ignore" comment  [unused-ignore]
+ jax/_src/dtypes.py:386: error: Unused "type: ignore" comment  [unused-ignore]

mitmproxy (https://github.com/mitmproxy/mitmproxy)
+ mitmproxy/connection.py:193: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ mitmproxy/utils/asyncio_utils.py:62: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Any | str"; expected "tuple[Any, ...] | None"  [arg-type]
+ mitmproxy/tools/console/common.py:811: error: Argument "error_message" to "__call__" of "_lru_cache_wrapper" has incompatible type "str | None"; expected "str"  [arg-type]
+ mitmproxy/tools/console/common.py:848: error: Incompatible types in assignment (expression has type "_lru_cache_wrapper[Callable[[NamedArg(RenderMode, 'render_mode'), NamedArg(bool, 'focused'), NamedArg(str, 'marked'), NamedArg(str | None, 'is_replay'), NamedArg(str, 'request_method'), NamedArg(str, 'request_scheme'), NamedArg(str, 'request_host'), NamedArg(str, 'request_path'), NamedArg(str, 'request_url'), NamedArg(str, 'request_http_version'), NamedArg(float, 'request_timestamp'), NamedArg(bool, 'request_is_push_promise'), NamedArg(bool, 'intercepted'), NamedArg(int | None, 'response_code'), NamedArg(str | None, 'response_reason'), NamedArg(int | None, 'response_content_length'), NamedArg(str | None, 'response_content_type'), NamedArg(float | None, 'duration'), NamedArg(str | None, 'error_message')], Any], Callable[[NamedArg(RenderMode, 'render_mode'), NamedArg(bool, 'focused'), NamedArg(str, 'marked'), NamedArg(str | None, 'is_replay'), NamedArg(str, 'request_method'), NamedArg(str, 'request_scheme'), NamedArg(str, 'request_host'), NamedArg(str, 'request_path'), NamedArg(str, 'request_url'), NamedArg(str, 'request_http_version'), NamedArg(float, 'request_timestamp'), NamedArg(bool, 'request_is_push_promise'), NamedArg(bool, 'intercepted'), NamedArg(int | None, 'response_code'), NamedArg(str | None, 'response_reason'), NamedArg(int | None, 'response_content_length'), NamedArg(str | None, 'response_content_type'), NamedArg(float | None, 'duration'), NamedArg(str | None, 'error_message')], Any]]", variable has type "_lru_cache_wrapper[Callable[[NamedArg(RenderMode, 'render_mode'), NamedArg(bool, 'focused'), NamedArg(str, 'marked'), NamedArg(bool, 'is_replay'), NamedArg(str, 'request_method'), NamedArg(str, 'request_scheme'), NamedArg(str, 'request_host'), NamedArg(str, 'request_path'), NamedArg(str, 'request_url'), NamedArg(str, 'request_http_version'), NamedArg(float, 'request_timestamp'), NamedArg(bool, 'request_is_push_promise'), NamedArg(bool, 'intercepted'), NamedArg(int | None, 'response_code'), NamedArg(str | None, 'response_reason'), NamedArg(int | None, 'response_content_length'), NamedArg(str | None, 'response_content_type'), NamedArg(float | None, 'duration'), NamedArg(str | None, 'error_message')], Any], Callable[[NamedArg(RenderMode, 'render_mode'), NamedArg(bool, 'focused'), NamedArg(str, 'marked'), NamedArg(bool, 'is_replay'), NamedArg(str, 'request_method'), NamedArg(str, 'request_scheme'), NamedArg(str, 'request_host'), NamedArg(str, 'request_path'), NamedArg(str, 'request_url'), NamedArg(str, 'request_http_version'), NamedArg(float, 'request_timestamp'), NamedArg(bool, 'request_is_push_promise'), NamedArg(bool, 'intercepted'), NamedArg(int | None, 'response_code'), NamedArg(str | None, 'response_reason'), NamedArg(int | None, 'response_content_length'), NamedArg(str | None, 'response_content_type'), NamedArg(float | None, 'duration'), NamedArg(str | None, 'error_message')], Any]]")  [assignment]
+ mitmproxy/tools/console/common.py:853: error: Argument "is_replay" to "__call__" of "_lru_cache_wrapper" has incompatible type "str | None"; expected "bool"  [arg-type]
+ mitmproxy/test/tflow.py:134: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ mitmproxy/test/tflow.py:235: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ mitmproxy/proxy/server.py:582: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ mitmproxy/proxy/mode_servers.py:115: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ mitmproxy/addons/clientplayback.py:98: error: Need type annotation for "mode"  [var-annotated]
+ mitmproxy/addons/proxyserver.py:109: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str"; expected "Never"  [arg-type]
+ mitmproxy/master.py:135: error: Need type annotation for "mode"  [var-annotated]

cki-lib (https://gitlab.com/cki-project/cki-lib)
+ cki_lib/gitlab.py:95: error: Too many arguments for "__call__" of "_lru_cache_wrapper"  [call-arg]
+ cki_lib/gitlab.py:95: note: Looks like the first special argument in a method is not named "self", "cls", or "mcs", maybe it is missing?

rich (https://github.com/Textualize/rich)
+ rich/progress_bar.py:145: error: Argument 3 to "__call__" of "_lru_cache_wrapper" has incompatible type "str | None"; expected "str"  [arg-type]

schemathesis (https://github.com/schemathesis/schemathesis)
+ src/schemathesis/stateful/state_machine.py: note: In class "APIStateMachine":
+ src/schemathesis/stateful/state_machine.py:68: error: Signature of "_to_test_case" incompatible with supertype "RuleBasedStateMachine"  [override]
+ src/schemathesis/stateful/state_machine.py:68: note:      Superclass:
+ src/schemathesis/stateful/state_machine.py:68: note:          _lru_cache_wrapper[Callable[[Type[RuleBasedStateMachine]], Any], Callable[[Type[RuleBasedStateMachine]], Any]]
+ src/schemathesis/stateful/state_machine.py:68: note:      Subclass:
+ src/schemathesis/stateful/state_machine.py:68: note:          _lru_cache_wrapper[Callable[[Type[APIStateMachine]], type], Callable[[Type[APIStateMachine]], type]]
+ src/schemathesis/specs/openapi/stateful/__init__.py: note: In function "create_state_machine":
+ src/schemathesis/specs/openapi/stateful/__init__.py:79: error: Argument 2 to "__call__" of "_lru_cache_wrapper" has incompatible type "Tuple[Any, ...]"; expected "Iterator[str]"  [arg-type]
+ src/schemathesis/specs/openapi/stateful/__init__.py:79: note: "tuple" is missing following "Iterator" protocol member:
+ src/schemathesis/specs/openapi/stateful/__init__.py:79: note:     __next__
+ src/schemathesis/specs/openapi/stateful/__init__.py: note: At top level:

pip (https://github.com/pypa/pip)
+ src/pip/_internal/index/package_finder.py:902: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str | None"; expected "str"  [arg-type]
+ src/pip/_internal/resolution/resolvelib/provider.py:242: error: Signature of "is_satisfied_by" incompatible with supertype "AbstractProvider"  [override]
+ src/pip/_internal/resolution/resolvelib/provider.py:242: note:      Superclass:
+ src/pip/_internal/resolution/resolvelib/provider.py:242: note:          def is_satisfied_by(self, requirement: Requirement, candidate: Candidate) -> bool
+ src/pip/_internal/resolution/resolvelib/provider.py:242: note:      Subclass:
+ src/pip/_internal/resolution/resolvelib/provider.py:242: note:          _lru_cache_wrapper[Callable[[PipProvider, Requirement, Candidate], bool], Callable[[PipProvider, Requirement, Candidate], bool]]

pydantic (https://github.com/pydantic/pydantic)
+ pydantic/v1/tools.py:37: error: Unused "type: ignore" comment  [unused-ignore]
- pydantic/networks.py:107: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "type[_BaseUrl]"; expected "Hashable"  [arg-type]
- pydantic/networks.py:107: note: Following member(s) of "_BaseUrl" have conflicts:
- pydantic/networks.py:107: note:     Expected:
- pydantic/networks.py:107: note:         def __hash__() -> int
- pydantic/networks.py:107: note:     Got:
- pydantic/networks.py:107: note:         def __hash__(self: object) -> int
- pydantic/networks.py:291: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "type[_BaseMultiHostUrl]"; expected "Hashable"  [arg-type]
- pydantic/networks.py:291: note: Following member(s) of "_BaseMultiHostUrl" have conflicts:
- pydantic/networks.py:291: note:     Expected:
- pydantic/networks.py:291: note:         def __hash__() -> int
- pydantic/networks.py:291: note:     Got:
- pydantic/networks.py:291: note:         def __hash__(self: object) -> int

manticore (https://github.com/trailofbits/manticore)
+ manticore/core/smtlib/solver.py:505: error: Signature of "can_be_true" incompatible with supertype "Solver"  [override]
+ manticore/core/smtlib/solver.py:505: note:      Superclass:
+ manticore/core/smtlib/solver.py:505: note:          def can_be_true(self, constraints: Any, expression: Any = ...) -> bool
+ manticore/core/smtlib/solver.py:505: note:      Subclass:
+ manticore/core/smtlib/solver.py:505: note:          _lru_cache_wrapper[Callable[[SMTLIBSolver, ConstraintSet, bool | Bool], bool], Callable[[SMTLIBSolver, ConstraintSet, bool | Bool], bool]]
+ manticore/core/smtlib/solver.py:605: error: Signature of "get_all_values" incompatible with supertype "Solver"  [override]
+ manticore/core/smtlib/solver.py:605: note:      Superclass:
+ manticore/core/smtlib/solver.py:605: note:          def get_all_values(self, constraints: Any, x: Any, maxcnt: Any = ..., silent: Any = ...) -> Any
+ manticore/core/smtlib/solver.py:605: note:      Subclass:
+ manticore/core/smtlib/solver.py:605: note:          _lru_cache_wrapper[Callable[[SMTLIBSolver, ConstraintSet, Any, int | None, bool], Any], Callable[[SMTLIBSolver, ConstraintSet, Any, int | None, bool], Any]]

core (https://github.com/home-assistant/core)
+ homeassistant/util/unit_conversion.py:387: error: Signature of "converter_factory" incompatible with supertype "BaseUnitConverter"  [override]
+ homeassistant/util/unit_conversion.py:387: note:      Superclass:
+ homeassistant/util/unit_conversion.py:387: note:          _lru_cache_wrapper[Callable[[type[BaseUnitConverter], str | None, str | None], Callable[[float], float]], Callable[[type[BaseUnitConverter], str | None, str | None], Callable[[float], float]]]
+ homeassistant/util/unit_conversion.py:387: note:      Subclass:
+ homeassistant/util/unit_conversion.py:387: note:          _lru_cache_wrapper[Callable[[type[SpeedConverter], str | None, str | None], Callable[[float], float]], Callable[[type[SpeedConverter], str | None, str | None], Callable[[float], float]]]
+ homeassistant/util/unit_conversion.py:401: error: Signature of "converter_factory_allow_none" incompatible with supertype "BaseUnitConverter"  [override]
+ homeassistant/util/unit_conversion.py:401: note:      Superclass:
+ homeassistant/util/unit_conversion.py:401: note:          _lru_cache_wrapper[Callable[[type[BaseUnitConverter], str | None, str | None], Callable[[float | None], float | None]], Callable[[type[BaseUnitConverter], str | None, str | None], Callable[[float | None], float | None]]]
+ homeassistant/util/unit_conversion.py:401: note:      Subclass:
+ homeassistant/util/unit_conversion.py:401: note:          _lru_cache_wrapper[Callable[[type[SpeedConverter], str | None, str | None], Callable[[float | None], float | None]], Callable[[type[SpeedConverter], str | None, str | None], Callable[[float | None], float | None]]]
+ homeassistant/util/unit_conversion.py:467: error: Signature of "converter_factory" incompatible with supertype "BaseUnitConverter"  [override]
+ homeassistant/util/unit_conversion.py:467: note:      Superclass:
+ homeassistant/util/unit_conversion.py:467: note:          _lru_cache_wrapper[Callable[[type[BaseUnitConverter], str | None, str | None], Callable[[float], float]], Callable[[type[BaseUnitConverter], str | None, str | None], Callable[[float], float]]]
+ homeassistant/util/unit_conversion.py:467: note:      Subclass:
+ homeassistant/util/unit_conversion.py:467: note:          _lru_cache_wrapper[Callable[[type[TemperatureConverter], str | None, str | None], Callable[[float], float]], Callable[[type[TemperatureConverter], str | None, str | None], Callable[[float], float]]]
+ homeassistant/util/unit_conversion.py:481: error: Signature of "converter_factory_allow_none" incompatible with supertype "BaseUnitConverter"  [override]
+ homeassistant/util/unit_conversion.py:481: note:      Superclass:
+ homeassistant/util/unit_conversion.py:481: note:          _lru_cache_wrapper[Callable[[type[BaseUnitConverter], str | None, str | None], Callable[[float | None], float | None]], Callable[[type[BaseUnitConverter], str | None, str | None], Callable[[float | None], float | None]]]
+ homeassistant/util/unit_conversion.py:481: note:      Subclass:
+ homeassistant/util/unit_conversion.py:481: note:          _lru_cache_wrapper[Callable[[type[TemperatureConverter], str | None, str | None], Callable[[float | None], float | None]], Callable[[type[TemperatureConverter], str | None, str | None], Callable[[float | None], float | None]]]
+ homeassistant/core.py:1511: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "EventType[_DataT] | str"; expected "Never"  [arg-type]
+ homeassistant/core.py:1529: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "EventType[_DataT] | str"; expected "Never"  [arg-type]
+ homeassistant/auth/__init__.py:655: error: Invalid self argument "_lru_cache_wrapper[partial[dict[str, Any]], partial[dict[str, Any]]]" to attribute function "__call__" with type "Callable[[_lru_cache_wrapper[Callable[_P, _R], _W], **_P], _R]"  [misc]
+ homeassistant/components/xiaomi_aqara/config_flow.py:216: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "str | None"; expected "str"  [arg-type]
+ homeassistant/helpers/llm.py:408: error: Invalid self argument "_lru_cache_wrapper[partial[str], partial[str]]" to attribute function "__call__" with type "Callable[[_lru_cache_wrapper[Callable[_P, _R], _W], **_P], _R]"  [misc]
+ homeassistant/components/mqtt_room/sensor.py:199: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "Any | None"; expected "str"  [arg-type]
+ homeassistant/components/esphome/update.py:63: error: "Never" has no attribute "get_entry_data"  [attr-defined]
+ homeassistant/components/esphome/update.py:63: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "HomeAssistant"; expected "Never"  [arg-type]
+ homeassistant/components/esphome/light.py:178: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:187: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:198: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:207: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:208: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:213: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:225: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:242: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:247: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:261: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/light.py:342: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "tuple[int, ...]"; expected "list[int]"  [arg-type]
+ homeassistant/components/esphome/__init__.py:61: error: Need type annotation for "domain_data"  [var-annotated]
+ homeassistant/components/esphome/__init__.py:61: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "HomeAssistant"; expected "Never"  [arg-type]
+ homeassistant/components/esphome/__init__.py:89: error: "Never" has no attribute "get_or_create_store"  [attr-defined]
+ homeassistant/components/esphome/__init__.py:89: error: Argument 1 to "__call__" of "_lru_cache_wrapper" has incompatible type "HomeAssistant"; expected "Never"  [arg-type]

Copy link
Author

@alwaysmpe alwaysmpe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have noted where this fails the tests I've added, may be something I've missed but tried quite hard to break it.

Comment on lines +137 to +146
# incorrect type error. If a static method
# takes the type of the enclosing class as
# the first argument there's a false positive.
CFnCls.st_fn_clst_arg(CFnCls)
CFnSubCls.st_fn_clst_arg(CFnSubCls)
# If a static method takes an instance of the
# enclosing class as its first argument,
# there's an error if accessed via an instance.
CFnSubCls.st_fn_self_t_arg(CFnSubCls())
CFnSubCls().st_fn_self_t_arg(CFnSubCls())
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably isn't fixable but may be acceptable. Error in both mypy & pyright.


if TYPE_CHECKING:
# This is not correctly rejected.
no_cache(Unhashable(), 2) # type: ignore[arg-type] # pyright: ignore[reportArgumentType]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach loses the previous hashable requirement so this is a false negative.

Comment on lines +203 to +204
assert_type(fn_overload(1), int)
assert_type(fn_overload("1"), str)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overloads don't work well with this change. In pyright types are resolved as int | str but cache_clear is correctly accessible.

Mypy correctly resolves return type but cache_clear isn't accessible.


def set_member(lhs: MemberVarBound[..., Any], rhs: MemberVarBound[..., Any]) -> None:
lhs.member_fn = rhs.equals
lhs.member_fn(rhs)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mypy doesn't resolve the callable type signature but pyright does, so this raises an error in mypy. Not sure why.

assert_type(cfn_inst.fn(1), int)
assert_type(CFnCls.st_fn(1), int)
assert_type(CFnCls.cls_fn(1), int)
assert_type(cfn_inst.prp_fn, int)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mypy is erroring on using property with cache. pyright is fine. Not sure why. There's also cached_property but this is a valid use case too.

@alwaysmpe
Copy link
Author

alwaysmpe commented Nov 18, 2024

Looking at primer output:

dacite errors are same as alternate approach, erroring because they're using a TypeVar bound to Callable without any type parameters, so the implicit type arguments are Never (the empty type), so I lean towards true positive error

pylint errors because the class template arguments have changed.

prefect errors lost because there's nolonger a hashable requirement.

twine is erroring because they're combining cache and property.

jinja seems to be a problem, they're using *args but only one parameter is accepted.

Not sure why mitmproxy/connection.py:193 is erroring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant