diff --git a/pyrightconfig.stricter.json b/pyrightconfig.stricter.json index be0163441020..a16607251715 100644 --- a/pyrightconfig.stricter.json +++ b/pyrightconfig.stricter.json @@ -98,6 +98,7 @@ "stubs/tqdm", "stubs/ttkthemes", "stubs/vobject", + "stubs/watchpoints", "stubs/workalendar", "stubs/wurlitzer", ], diff --git a/stubs/watchpoints/@tests/stubtest_allowlist.txt b/stubs/watchpoints/@tests/stubtest_allowlist.txt new file mode 100644 index 000000000000..5755d26ce61f --- /dev/null +++ b/stubs/watchpoints/@tests/stubtest_allowlist.txt @@ -0,0 +1 @@ +watchpoints.all diff --git a/stubs/watchpoints/METADATA.toml b/stubs/watchpoints/METADATA.toml new file mode 100644 index 000000000000..0d08dbc0d9da --- /dev/null +++ b/stubs/watchpoints/METADATA.toml @@ -0,0 +1,2 @@ +version = "0.2.5" +upstream_repository = "https://github.com/gaogaotiantian/watchpoints" diff --git a/stubs/watchpoints/watchpoints/__init__.pyi b/stubs/watchpoints/watchpoints/__init__.pyi new file mode 100644 index 000000000000..53f34b3a1610 --- /dev/null +++ b/stubs/watchpoints/watchpoints/__init__.pyi @@ -0,0 +1,10 @@ +from collections.abc import Callable +from typing import Final +from typing_extensions import LiteralString, Unpack + +from .watch import Watch + +__version__: Final[LiteralString] + +watch: Watch +unwatch: Final[Callable[[Unpack[tuple[object, ...]]], None]] diff --git a/stubs/watchpoints/watchpoints/ast_monkey.pyi b/stubs/watchpoints/watchpoints/ast_monkey.pyi new file mode 100644 index 000000000000..1409982075af --- /dev/null +++ b/stubs/watchpoints/watchpoints/ast_monkey.pyi @@ -0,0 +1,3 @@ +import ast + +def ast_parse_node(node: ast.expr) -> ast.Module: ... diff --git a/stubs/watchpoints/watchpoints/util.pyi b/stubs/watchpoints/watchpoints/util.pyi new file mode 100644 index 000000000000..37d456070dbc --- /dev/null +++ b/stubs/watchpoints/watchpoints/util.pyi @@ -0,0 +1,6 @@ +import ast +from collections.abc import Iterable +from types import FrameType + +def getline(frame: FrameType) -> str: ... +def getargnodes(frame: FrameType) -> Iterable[tuple[ast.expr, str]]: ... diff --git a/stubs/watchpoints/watchpoints/watch.pyi b/stubs/watchpoints/watchpoints/watch.pyi new file mode 100644 index 000000000000..320bc4afdbac --- /dev/null +++ b/stubs/watchpoints/watchpoints/watch.pyi @@ -0,0 +1,68 @@ +import threading +from _typeshed import SupportsWrite, TraceFunction +from collections.abc import Callable +from pdb import Pdb +from types import FrameType +from typing import Any, Literal, Protocol, TypeVar +from typing_extensions import TypeAlias + +from .watch_element import WatchElement + +_T = TypeVar("_T") + +# Alias used for fields that must always be valid identifiers +# A string `x` counts as a valid identifier if both the following are True +# (1) `x.isidentifier()` evaluates to `True` +# (2) `keyword.iskeyword(x)` evaluates to `False` +_Identifier: TypeAlias = str + +class Watch: + # User-defined callbacks passed to `__call__()` or `config()` set as instance variables have arguments of type `Any` to be + # compatible with more precisely-annotated signatures. + + custom_printer: Callable[[Any], None] | None + enable: bool + file: str | SupportsWrite[str] | None + pdb: Pdb | None + pdb_enable: bool + set_lock: threading.Lock + stack_limit: int | None + tracefunc_lock: threading.Lock + tracefunc_stack: list[TraceFunction | None] + watch_list: list[WatchElement] + + def __init__(self) -> None: ... + def __call__( + self, + *args: object, + alias: str = ..., + callback: Callable[[FrameType, WatchElement, tuple[str, str, int | None]], None] = ..., + cmp: Callable[[Any, Any], bool] = ..., # User-defined comparison callback; compares 2 arguments of any type + copy: Callable[[_T], _T] = ..., + # User-defined printing callback; writes a string representation of any object to a stream + custom_printer: Callable[[Any], None] = ..., + deepcopy: bool = False, + file: str | SupportsWrite[str] = ..., + stack_limit: int | None = 5, + track: Literal["object", "variable"] = ..., + when: Callable[[Any], bool] = ..., # User-defined callback for conditional watchpoints + ) -> None: ... + def config( + self, + *, + callback: Callable[[FrameType, WatchElement, tuple[str, str, int | None]], None] = ..., + pdb: Literal[True] = ..., + file: str | SupportsWrite[str] = ..., + stack_limit: int | None = 5, + custom_printer: Callable[[Any], None] = ..., # User-defined printing callback + ) -> None: ... + def install(self, func: _Identifier = "watch") -> None: ... + def restore(self) -> None: ... + def start_trace(self, frame: FrameType) -> None: ... + def stop_trace(self, frame: FrameType) -> None: ... + def tracefunc(self, frame: FrameType, event: str, arg: object) -> _TraceFunc: ... + def uninstall(self, func: _Identifier = "watch") -> None: ... + def unwatch(self, *args: object) -> None: ... + +class _TraceFunc(Protocol): + def __call__(self, frame: FrameType, event: str, arg: object) -> _TraceFunc: ... diff --git a/stubs/watchpoints/watchpoints/watch_element.pyi b/stubs/watchpoints/watchpoints/watch_element.pyi new file mode 100644 index 000000000000..b99f7e65f1c3 --- /dev/null +++ b/stubs/watchpoints/watchpoints/watch_element.pyi @@ -0,0 +1,56 @@ +import ast +from collections.abc import Callable, Iterable +from types import FrameType +from typing import Any, Literal, TypeVar +from typing_extensions import TypeAlias + +from .watch_print import WatchPrint + +_T = TypeVar("_T") +_TrackKind: TypeAlias = Literal["object", "variable"] | list[Literal["object", "variable"]] + +class WatchElement: + # User-defined callbacks passed to `__init__` set as instance variables have arguments of type `Any` to be + # compatible with more precisely-annotated signatures. These callbacks are passed from `watchpoints.watch.Watch`. + + alias: str | None + attr: str | None + cmp: Callable[[Any, Any], bool] | None + copy: Callable[[Any], object] | None # User-defined copy callback + default_alias: str | None + deepcopy: bool + exist: bool + frame: FrameType + localvar: str | None + obj: Any + parent: Any + prev_obj: Any + prev_obj_repr: str + subscr: Any + watch_print: WatchPrint + when: Callable[[Any], bool] | None + + def __init__( + self, + frame: FrameType, + node: ast.expr, + *, + alias: str | None = ..., + callback: Callable[[FrameType, WatchElement, tuple[str, str, int | None]], None] | None = ..., + cmp: Callable[[Any, Any], bool] | None = ..., # User-defined comparison callback + copy: Callable[[_T], _T] | None = ..., + deepcopy: bool = False, + default_alias: str | None = ..., + track: _TrackKind = ..., + watch_print: WatchPrint = ..., + when: Callable[[Any], bool] | None = ..., # User-defined callback for conditional watchpoints + ) -> None: ... + def belong_to(self, lst: Iterable[object]) -> bool: ... + def changed(self, frame: FrameType) -> tuple[bool, bool]: ... + def obj_changed(self, other: object) -> bool: ... + def same(self, other: object) -> bool: ... + @property + def track(self) -> _TrackKind: ... + @track.setter + def track(self, val: _TrackKind) -> None: ... + def update(self) -> None: ... diff --git a/stubs/watchpoints/watchpoints/watch_print.pyi b/stubs/watchpoints/watchpoints/watch_print.pyi new file mode 100644 index 000000000000..715d914daf07 --- /dev/null +++ b/stubs/watchpoints/watchpoints/watch_print.pyi @@ -0,0 +1,24 @@ +from _typeshed import SupportsWrite +from collections.abc import Callable +from types import FrameType +from typing import Any + +from .watch_element import WatchElement + +class WatchPrint: + # User-defined callbacks passed to `__init__` set as instance variables have arguments of type `Any` to be + # compatible with more precisely-annotated signatures. These callbacks are passed from `watchpoints.watch.Watch`. + + custom_printer: Callable[[Any], None] | None + file: str | SupportsWrite[str] | None + stack_limit: int | None + + def __init__( + self, + file: str | SupportsWrite[str] | None = ..., + stack_limit: int | None = ..., + custom_printer: Callable[[Any], None] | None = ..., # User-defined printing callback + ) -> None: ... + def __call__(self, frame: FrameType, elem: WatchElement, exec_info: tuple[str, str, int | None]) -> None: ... + def getsourceline(self, exec_info: tuple[str, str, int | None]) -> str: ... + def printer(self, obj: object) -> None: ...