Crash with variadic type variable
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
Hướng nghiên cứu
Tái hiện test.py được cung cấp bằng mypy --show-traceback, sau đó lần theo đường đi của lỗi từ checker.py:check_with_item qua checkexpr.py:visit_call_expr và visit_call_expr_inner. Traceback và báo cáo xác định đường đi của sự cố; hoàn tất khi ví dụ kiểu variadic này không còn tạo ra INTERNAL ERROR hoặc traceback.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Crash Report
I was writing some code in Colab and INTERNAL_ERROR showed up
This is the code:
%%mypy
from collections.abc import Callable, Mapping, MutableMapping, Iterator, Iterable
from typing import Any, Self, NoReturn, Concatenate, overload, TYPE_CHECKING, cast, TypeVar, final, Literal, Protocol
from typing_extensions import disjoint_base, TypeForm
from functools import wraps
from types import MethodType as method, TracebackType
import sys
@disjoint_base
class cached[**P, R]:
slots = ("_f", "_c")
def init(self, func: Callable[P, R]) -> None:
if not hasattr(self, "_f"):
self._f = func
self._c = {} # type: ignore[var-annotated]
@property
def cache(self) -> dict[tuple[tuple, frozenset[tuple[str, Any]]], R]:
return self._c
def call(self, *args: P.args, **kwargs: P.kwargs) -> R:
compd = (args, frozenset(kwargs.items()))
if compd in self._c:
return self._c[compd]
else:
result = self._f(*args, **kwargs)
self._c[compd] = result
return result
def repr(self) -> str:
return self._f.name
@disjoint_base
class cached_method[T, **P, R]:
slots = ("_f", "_c")
def init(self, func: Callable[Concatenate[T, P], R]) -> None:
if not hasattr(self, "_f"):
self._f = func
self._c = {} # type: ignore[var-annotated]
@property
def cache(self) -> dict[tuple[T, tuple[Any, ...], frozenset[tuple[str, Any]]], R]:
return self._c
def call(self, instance: T, /, *args: P.args, **kwargs: P.kwargs) -> R:
compd = (instance, args, frozenset(kwargs.items()))
if compd in self._c:
return self._c[compd]
else:
result = self._f(instance, *args, **kwargs)
self._c[compd] = result
return result
def repr(self) -> str:
return self._f.name
@overload
def get(self, instance: None, owner: type[T]) -> Self: ...
@overload
def get(self, instance: T, owner: type[T]) -> cached: ...
def get(self, instance: T | None, owner: type[T]):
@cached
def _cached_method_get(self, instance, owner):
if instance is None:
return self
else:
return cached(method(self._f, instance))
return _cached_method_get(self, instance, owner)
def notimplemented[**P](func: Callable[P, Any]) -> Callable[P, NoReturn]:
@wraps(func)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> NoReturn:
raise NotImplementedError
return wrapper
type _BinaryMethod[T, N] = Callable[[T, N], bool]
def typeguard[T](cls: type[T]) -> Callable[[_BinaryMethod[T, T]], BinaryMethod[T, object]]:
def dec(method: _BinaryMethod[T, T]) -> BinaryMethod[T, object]:
@wraps(method)
def wrapper(self_param, other: object) -> bool:
if not isinstance(other, cls):
return NotImplemented
else:
return method_(self_param, other)
return wrapper
return dec
@disjoint_base
class immutabledict[K, V]:
slots = ("_data",)
_data: dict[K, V]
def new(cls, dict_: Mapping[K, V] = {}, /) -> Self:
self = object.new(cls)
self.data = dict(dict)
return self
@property
def data(self, /) -> dict[K, V]:
return self._data
def contains(self, item: object) -> bool:
return self._data.contains(item)
def eq(self, other: object, /) -> bool:
@typeguard(immutabledict)
def wrapper(self_param, other: immutabledict, /) -> bool:
return self_param._data == other._data
return wrapper(self, other)
def getitem(self, item: K, /) -> V:
return self._data.getitem(item)
def hash(self, /) -> int:
return hash((frozenset(self._data.items()), 23*len(self), type)) ^ 2**20
def iter(self, /) -> Iterator[K]:
return iter(self._data)
def len(self, /) -> int:
return self._data.len()
def or(self, other: "immutabledict", /) -> Self:
return type(self)(self._data.or(other._data))
def reduce(self, /) -> tuple[type[Self], tuple[dict[K, V]]]:
return (type(self), (self._data,))
def repr(self, /) -> str:
return f"{type(self).name}({self._data!r})"
def reversed(self, /) -> Iterator[K]:
return self._data.reversed()
ror = or
def str(self) -> str:
return f"{type(self).name}({self._data})"
def copy(self, /) -> Self:
return self
@classmethod
def fromkeys(cls, iterable: Iterable[K], value: V, /) -> Self:
return cls(dict.fromkeys(iterable, value))
def get[_T](self, key: K, default: _T) -> V | _T:
if key in self._data:
return self._data.getitem(key)
else:
return default
def items(self, /) -> "immutabledict_items[K, V]":
return immutabledict_items(frozenset(self._data.items()))
def keys(self, /) -> "immutabledict_keys[K]":
return immutabledict_keys(frozenset(self._data.keys()))
def values(self, /) -> "immutabledict_values[V]":
return immutabledict_values(frozenset(self._data.values()))
@disjoint_base
class _immutabledict_view[T]:
slots = ("_data",)
_data: frozenset[T]
def new(cls, fset: frozenset[T], /) -> Self:
self = object.new(cls)
self._data = fset
return self
@property
def data(self) -> frozenset[T]:
return self._data
def and(self, other: Iterable, /) -> frozenset[T]:
return self._data & frozenset(other)
def contains(self, item: object, /):
return self._data.contains(item)
def eq(self, other: object, /) -> bool:
if isinstance(other, _immutabledict_view):
return self._data == other._data
else:
return NotImplemented
def hash(self, /) -> int:
return hash((frozenset(self._data), 34, len(self), object)) ^ 2**20
def len(self, /) -> int:
return self._data.len()
def iter(self, /) -> Iterator[T]:
return self._data.iter()
def or[_T](self, other: Iterable[_T], /) -> frozenset[T | _T]:
return self._data.or(frozenset(other))
rand = and
def repr(self) -> str:
return f"{type(self).name}({self._data!r})"
def rsub(self, other: Iterable, /) -> frozenset[T]:
return self._data.sub(frozenset(other))
def rxor[_T](self, other: Iterable[_T], /) -> frozenset[T | _T]:
return self._data.xor(frozenset(other))
ror = or
sub = rsub
xor = rxor
class immutabledict_items[K, V](_immutabledict_view[tuple[K, V]]):
pass
class immutabledict_keysK:
pass
class immutabledict_valuesV:
pass
class _exitE: BaseException, R:
@overload
def call(self, exc_tp: type[BaseException], exc: BaseException, tb: TracebackType, result: R, /) -> bool: ...
@overload
def call(self, exc_tp: None, exc: None, tb: None, result: R, /) -> bool: ...
@final
class contextmanager[**P, R]:
slots = ("_func", "exit")
_func: Callable[P, R]
exit: _exit[BaseException, R]
def new(cls, func: Callable[P, R]) -> Self:
self = object.new(cls)
self._func = func
def _exit_inner(
exc_tp: type[BaseException] | None,
exc: BaseException | None,
tb: TracebackType | None,
result: R,
/
) -> bool:
return False
self._exit_ = _exit_inner
return self
def call(self, *args: P.args, **kwargs: P.kwargs) -> "_contextmanager_cls[P, R]":
return _contextmanager_cls(self.exit, self._func(*args, **kwargs))
def exit(self, func: _exit[BaseException, R]) -> Self:
self.exit = func
return self
class _contextmanager_cls[**P, R]:
slots = ("_value", "exit")
_value: R
exit: _exit[BaseException, R]
def new(cls, exit: _exit[BaseException, R], value: R) -> Self:
self = object.new(cls)
self._value = value
self.exit = exit
return self
def enter(self) -> R:
return self._value
def exit(self, exc_tp: type[BaseException], exc: BaseException, tb: TracebackType) -> bool:
return self.exit(exc_tp, exc, tb, self._value)
Float = TypeVar("Float", int, float)
Complex = TypeVar("Complex", int, float, complex)
@contextmanager
def print_args[*Ts](*args: *Ts) -> tuple[*Ts]:
print("Function called with:", *args)
return args
@print_args.exit
def _(exc_tp, exc, tb, result):
if exc is not None:
print(f"Exception suppressed: {exc_tp.name}({exc})")
return True
with print_args(2) as n:
print(n, "in with block")
raise ValueError("hi")
Traceback
test.py:301: error: INTERNAL ERROR -- Please try using mypy master on GitHub:
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 2.4.0+dev.722047e369657c936851a349ebba6b4c5504b8e2
Traceback (most recent call last):
File "/usr/local/bin/mypy", line 8, in
sys.exit(console_entry())
File "/usr/local/lib/python3.12/dist-packages/mypy/main.py", line 16, in console_entry
main()
File "/usr/local/lib/python3.12/dist-packages/mypy/main.py", line 154, in main
res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
File "/usr/local/lib/python3.12/dist-packages/mypy/main.py", line 244, in run_build
res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
File "/usr/local/lib/python3.12/dist-packages/mypy/build.py", line 422, in build
result = build_inner(
File "/usr/local/lib/python3.12/dist-packages/mypy/build.py", line 537, in build_inner
graph = dispatch(sources, manager, stdout, connect_threads)
File "/usr/local/lib/python3.12/dist-packages/mypy/build.py", line 4150, in dispatch
process_graph(graph, manager)
File "/usr/local/lib/python3.12/dist-packages/mypy/build.py", line 4618, in process_graph
done, still_working, results = manager.wait_for_done(graph)
File "/usr/local/lib/python3.12/dist-packages/mypy/build.py", line 1484, in wait_for_done
process_stale_scc(graph, next_scc, self)
File "/usr/local/lib/python3.12/dist-packages/mypy/build.py", line 4793, in process_stale_scc
graph[id].type_check_first_pass()
File "/usr/local/lib/python3.12/dist-packages/mypy/build.py", line 3410, in type_check_first_pass
self.type_checker().check_first_pass(recurse_into_functions=recurse_into_functions)
File "/usr/local/lib/python3.12/dist-packages/mypy/checker.py", line 618, in check_first_pass
self.accept(d)
File "/usr/local/lib/python3.12/dist-packages/mypy/checker.py", line 765, in accept
stmt.accept(self)
File "/usr/local/lib/python3.12/dist-packages/mypy/nodes.py", line 2185, in accept
return visitor.visit_with_stmt(self)
File "/usr/local/lib/python3.12/dist-packages/mypy/checker.py", line 5902, in visit_with_stmt
exit_ret_type = self.check_with_item(expr, target, s.unanalyzed_type is None)
File "/usr/local/lib/python3.12/dist-packages/mypy/checker.py", line 5963, in check_with_item
ctx = echk.accept(expr)
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 6220, in accept
typ = self.accept_maybe_cache(node, type_context=type_context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 6255, in accept_maybe_cache
typ = node.accept(self)
^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/nodes.py", line 2545, in accept
return visitor.visit_call_expr(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 499, in visit_call_expr
return self.visit_call_expr_inner(e, allow_none_return=allow_none_return)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 630, in visit_call_expr_inner
ret_type = self.check_call_expr_with_callee_type(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 1498, in check_call_expr_with_callee_type
ret_type, callee_type = self.check_call(
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 1626, in check_call
result = self.check_call(
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 1591, in check_call
return self.check_callable_call(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 1793, in check_callable_call
callee = self.infer_function_type_arguments(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 2286, in infer_function_type_arguments
return self.apply_inferred_arguments(callee_type, inferred_args, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 2421, in apply_inferred_arguments
return self.apply_generic_arguments(callee_type, inferred_args, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/checkexpr.py", line 3424, in apply_generic_arguments
return applytype.apply_generic_arguments(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/applytype.py", line 147, in apply_generic_arguments
callable = expand_type(callable, id_to_type)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/expandtype.py", line 70, in expand_type
return typ.accept(ExpandTypeVisitor(env))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/types.py", line 2361, in accept
return visitor.visit_callable_type(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/expandtype.py", line 495, in visit_callable_type
ret_type=t.ret_type.accept(self),
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/types.py", line 1684, in accept
return visitor.visit_instance(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/expandtype.py", line 217, in visit_instance
args = self.expand_type_tuple_with_unpack(t.args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/expandtype.py", line 531, in expand_type_tuple_with_unpack
items.append(item.accept(self))
^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/types.py", line 2073, in accept
return visitor.visit_parameters(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/expandtype.py", line 403, in visit_parameters
return t.copy_modified(arg_types=self.expand_types(t.arg_types))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/expandtype.py", line 616, in expand_types
a.append(t.accept(self))
^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/types.py", line 1248, in accept
return visitor.visit_unpack_type(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/expandtype.py", line 380, in visit_unpack_type
return UnpackType(t.type.accept(self))
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/types.py", line 1007, in accept
return visitor.visit_type_var_tuple(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/mypy/expandtype.py", line 368, in visit_type_var_tuple
raise NotImplementedError
NotImplementedError
test.py:301: note: use --pdb to drop into pdb
To Reproduce
Setup:
!pip install git+https://github.com/python/mypy.git
from IPython.core.magic import register_cell_magic
from IPython import get_ipython
from mypy import api
@register_cell_magic
def mypy(line, cell):
mypy.api.run returns (stdout, stderr, exit_code)
stdout, stderr, exit_code = api.run(['-c', '\n' + cell] + line.split())
if stderr:
# If there's anything in stderr, it's usually an internal mypy error or argument error
raise TypeError(f"Mypy stderr:\n{stderr}")
if exit_code != 0:
# Mypy found type errors or exited with a non-zero status
if stdout:
raise TypeError(f"Mypy type errors:\n{stdout}")
else:
raise TypeError(f"Mypy exited with code {exit_code} but no output.")
If exit_code is 0 and no stderr, mypy passed, then run the cell
get_ipython().run_cell(cell)
Your Environment
Google colab, python 3.12
- Ngôn ngữ chính
- Python
- Star
- 20.6k
- Fork
- 3.3k
- Merge trung bình
- 1 ngày 18 giờ
- Pull request đã merge (30 ngày)
- 54
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của python/mypy
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
-
documentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
bug topic-configuration topic-error-reporting
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
qgis/QGIS-Documentation#11275 ·
-
bug priority:normal ready-for-dev
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
OpenHands/extensions#626 · 1 bình luận ·
-
Change observation tooltip text Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
CSCfi/sd-search-api#39 ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
-
please add to porn list Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
StevenBlack/hosts#3255 ·