-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Feat/watchpoints #13248
base: main
Are you sure you want to change the base?
Feat/watchpoints #13248
Changes from 6 commits
59bc6cb
fa52c08
bb1bee3
9453cd8
700240d
54a3ee1
fcb9691
7ae5b5c
ec50c22
3a1f444
45e8f97
1a3d9ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
version = "0.2.5" | ||
upstream_repository = "https://github.com/gaogaotiantian/watchpoints" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from collections.abc import Callable | ||
from typing import Final, Literal | ||
from typing_extensions import LiteralString, Unpack | ||
|
||
from .watch import Watch | ||
|
||
__version__: Final[LiteralString] | ||
|
||
all: Final[list[Literal["watch", "unwatch"]]] | ||
watch: Watch | ||
unwatch: Final[Callable[[Unpack[tuple[object, ...]]], None]] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import ast | ||
|
||
def ast_parse_node(node: ast.expr) -> ast.Module: ... |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,5 @@ | ||||||
import ast | ||||||
from types import FrameType | ||||||
|
||||||
def getline(frame: FrameType) -> str: ... | ||||||
def getargnodes(frame: FrameType) -> zip[tuple[ast.expr, str]]: ... | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
It does return a zip object at runtime, but that's a bit too much of an implementation detail for my taste. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in ec50c22 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,64 @@ | ||||||
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: | ||||||
custom_printer: Callable[[Any], None] | None | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Several callback types this package have
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes sense, but please add a comment to the code explaining this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in fcb9691 |
||||||
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, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like these are unused, consider using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding of the library is that it inspects the expressions of positional-only arguments passed to Passing nothing will cause nothing to be watched, so I'm also tempted to enforce at least 1 argument to be passed here, but let me know if it's still desirable to use |
||||||
alias: str = ..., | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one and most of the others support None, since the runtime does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unlike in
Let me know if we'd still prefer |
||||||
callback: Callable[[FrameType, WatchElement, tuple[str, str, int | None]], None] = ..., | ||||||
cmp: Callable[[Any, Any], bool] = ..., | ||||||
copy: Callable[[_T], _T] = ..., | ||||||
custom_printer: Callable[[Any], None] = ..., | ||||||
deepcopy: bool = False, | ||||||
file: str | SupportsWrite[str] = ..., | ||||||
stack_limit: int | None = 5, | ||||||
track: Literal["object", "variable"] = ..., | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Or does it also support other kinds of Sequences? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The documentation describes |
||||||
when: Callable[[Any], bool] = ..., | ||||||
) -> 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] = ..., | ||||||
) -> 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: ... | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should these parameters be positional-only? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
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: | ||
alias: str | None | ||
attr: str | None | ||
cmp: Callable[[Any, Any], bool] | None | ||
copy: Callable[[Any], object] | None | ||
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 = ..., | ||
copy: Callable[[_T], _T] | None = ..., | ||
deepcopy: bool = False, | ||
default_alias: str | None = ..., | ||
track: _TrackKind = ..., | ||
watch_print: WatchPrint = ..., | ||
when: Callable[[Any], bool] | None = ..., | ||
) -> 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: ... |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from _typeshed import SupportsWrite | ||
from collections.abc import Callable | ||
from types import FrameType | ||
from typing import Any | ||
|
||
from .watch_element import WatchElement | ||
|
||
class WatchPrint: | ||
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 = ..., | ||
) -> 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: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is a typo for
__all__
, worth reporting as a bug to the runtime package.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 7ae5b5c - PR is also merged in the runtime package to change it to
__all__
, but I think that needs a new release before it can be added to typeshed.