-
Notifications
You must be signed in to change notification settings - Fork 233
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
Include contrib folder and pytorch stringifier #476
base: main
Are you sure you want to change the base?
Changes from all commits
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,13 @@ | ||
# Community contributed extensions for pudb | ||
|
||
Here the community can extend pudb with custom stringifiers, themes and shells. | ||
|
||
|
||
## How to contribute your stringifiers | ||
|
||
Simply add a new python module inside `contrib/stringifiers` that contains your custom stringifier. | ||
|
||
Then add your stringifier to the `CONTRIB_STRINGIFIERS` dict inside | ||
`contrib/stringifiers/__init__.py`. | ||
|
||
The new options should appear in the pudb settings pane after setting the `Enable community contributed content` option. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from pudb.contrib.stringifiers import CONTRIB_STRINGIFIERS |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from pudb.contrib.stringifiers.torch_stringifier import torch_stringifier_fn | ||
|
||
CONTRIB_STRINGIFIERS = { | ||
# User contributed stringifiers | ||
# Use the contrib prefix for all keys to avoid clashes with the core stringifiers | ||
# and make known to the user that this is community contributed code | ||
"contrib.pytorch": torch_stringifier_fn, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from typing import Any | ||
|
||
try: | ||
import torch | ||
|
||
HAVE_TORCH = 1 | ||
except: | ||
HAVE_TORCH = 0 | ||
|
||
import pudb.var_view as vv | ||
|
||
|
||
def torch_stringifier_fn(value: Any) -> str: | ||
if not HAVE_TORCH: | ||
# Fall back to default stringifier | ||
|
||
return vv.default_stringifier(value) | ||
|
||
if isinstance(value, torch.nn.Module): | ||
device: str = str(next(value.parameters()).device) | ||
params: int = sum([p.numel() for p in value.parameters() if p.requires_grad]) | ||
rep: str = value.__repr__() if len(value.__repr__()) < 55 else type( | ||
value | ||
).__name__ | ||
|
||
return "{}[{}] Params: {}".format(rep, device, params) | ||
elif isinstance(value, torch.Tensor): | ||
return "{}[{}][{}] {}".format( | ||
type(value).__name__, | ||
str(value.dtype).replace("torch.", ""), | ||
str(value.device), | ||
str(list(value.shape)), | ||
) | ||
else: | ||
# Fall back to default stringifier | ||
|
||
return vv.default_stringifier(value) |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -25,7 +25,6 @@ | |||||
|
||||||
import os | ||||||
import sys | ||||||
|
||||||
from configparser import ConfigParser | ||||||
from pudb.lowlevel import (lookup_module, get_breakpoint_invalid_reason, | ||||||
settings_log) | ||||||
|
@@ -123,6 +122,8 @@ def load_config(): | |||||
|
||||||
conf_dict.setdefault("hide_cmdline_win", "False") | ||||||
|
||||||
conf_dict.setdefault("enable_community_contributed_content", "False") | ||||||
|
||||||
def normalize_bool_inplace(name): | ||||||
try: | ||||||
if conf_dict[name].lower() in ["0", "false", "off"]: | ||||||
|
@@ -136,6 +137,7 @@ def normalize_bool_inplace(name): | |||||
normalize_bool_inplace("wrap_variables") | ||||||
normalize_bool_inplace("prompt_on_quit") | ||||||
normalize_bool_inplace("hide_cmdline_win") | ||||||
normalize_bool_inplace("enable_community_contributed_content") | ||||||
|
||||||
_config_[0] = conf_dict | ||||||
return conf_dict | ||||||
|
@@ -223,6 +225,11 @@ def _update_config(check_box, new_state, option_newvalue): | |||||
conf_dict.update(new_conf_dict) | ||||||
_update_hide_cmdline_win() | ||||||
|
||||||
elif option == "enable_community_contributed_content": | ||||||
new_conf_dict["enable_community_contributed_content"] = ( | ||||||
not check_box.get_state()) | ||||||
conf_dict.update(new_conf_dict) | ||||||
|
||||||
elif option == "current_stack_frame": | ||||||
# only activate if the new state of the radio button is 'on' | ||||||
if new_state: | ||||||
|
@@ -270,6 +277,14 @@ def _update_config(check_box, new_state, option_newvalue): | |||||
bool(conf_dict["hide_cmdline_win"]), on_state_change=_update_config, | ||||||
user_data=("hide_cmdline_win", None)) | ||||||
|
||||||
enable_community_contributed_content = urwid.CheckBox( | ||||||
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. All other settings in pudb act instantaneously. This one should, too. |
||||||
"Enable community contributed content. This will give you access to more " | ||||||
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
|
||||||
"stringifiers, shells and themes. \n" | ||||||
"Changing this setting requires a restart of PuDB.", | ||||||
bool(conf_dict["enable_community_contributed_content"]), | ||||||
on_state_change=_update_config, | ||||||
user_data=("enable_community_contributed_content", None)) | ||||||
|
||||||
# {{{ shells | ||||||
|
||||||
shell_info = urwid.Text("This is the shell that will be " | ||||||
|
@@ -345,8 +360,18 @@ def _update_config(check_box, new_state, option_newvalue): | |||||
# {{{ stringifier | ||||||
|
||||||
from pudb.var_view import STRINGIFIERS | ||||||
from pudb.contrib.stringifiers import CONTRIB_STRINGIFIERS | ||||||
stringifier_opts = list(STRINGIFIERS.keys()) | ||||||
if conf_dict["enable_community_contributed_content"]: | ||||||
stringifier_opts = ( | ||||||
list(STRINGIFIERS.keys()) + list(CONTRIB_STRINGIFIERS.keys())) | ||||||
known_stringifier = conf_dict["stringifier"] in stringifier_opts | ||||||
contrib_stringifier = conf_dict["stringifier"] in CONTRIB_STRINGIFIERS | ||||||
fallback_to_default_stringifier = (contrib_stringifier and not | ||||||
conf_dict["enable_community_contributed_content"]) | ||||||
use_default_stringifier = ((conf_dict["stringifier"] == "default") or | ||||||
fallback_to_default_stringifier) | ||||||
custom_stringifier = not (known_stringifier or contrib_stringifier) | ||||||
stringifier_rb_group = [] | ||||||
stringifier_edit = urwid.Edit(edit_text=conf_dict["custom_stringifier"]) | ||||||
stringifier_info = urwid.Text( | ||||||
|
@@ -357,15 +382,21 @@ def _update_config(check_box, new_state, option_newvalue): | |||||
"be slower than the default, type, or id stringifiers.\n") | ||||||
stringifier_edit_list_item = urwid.AttrMap(stringifier_edit, | ||||||
"input", "focused input") | ||||||
|
||||||
stringifier_rbs = [ | ||||||
urwid.RadioButton(stringifier_rb_group, "default", | ||||||
use_default_stringifier, | ||||||
on_state_change=_update_config, | ||||||
user_data=("stringifier", "default")) | ||||||
]+[ | ||||||
urwid.RadioButton(stringifier_rb_group, name, | ||||||
conf_dict["stringifier"] == name, | ||||||
on_state_change=_update_config, | ||||||
user_data=("stringifier", name)) | ||||||
for name in stringifier_opts | ||||||
for name in stringifier_opts if name != "default" | ||||||
]+[ | ||||||
urwid.RadioButton(stringifier_rb_group, "Custom:", | ||||||
not known_stringifier, on_state_change=_update_config, | ||||||
custom_stringifier, on_state_change=_update_config, | ||||||
user_data=("stringifier", None)), | ||||||
stringifier_edit_list_item, | ||||||
urwid.Text("\nTo use a custom stringifier, see " | ||||||
|
@@ -441,6 +472,7 @@ def _update_config(check_box, new_state, option_newvalue): | |||||
+ [cb_line_numbers] | ||||||
+ [cb_prompt_on_quit] | ||||||
+ [hide_cmdline_win] | ||||||
+ [enable_community_contributed_content] | ||||||
|
||||||
+ [urwid.AttrMap(urwid.Text("\nShell:\n"), "group head")] | ||||||
+ [shell_info] | ||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -47,7 +47,7 @@ | |||||
"Topic :: Terminals", | ||||||
"Topic :: Utilities", | ||||||
], | ||||||
packages=["pudb"], | ||||||
packages=["pudb", "pudb.contrib", "pudb.contrib.stringifiers"], | ||||||
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
Import from |
||||||
entry_points={ | ||||||
"console_scripts": [ | ||||||
# Deprecated. Should really use python -m pudb. | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
try: | ||
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. Could you have the CI install pytorch to make sure this code is tested? |
||
import torch | ||
HAVE_TORCH = True | ||
except ImportError: | ||
HAVE_TORCH = False | ||
|
||
from pudb.var_view import default_stringifier | ||
from pudb.contrib.stringifiers.torch_stringifier import torch_stringifier_fn | ||
|
||
def test_tensor(): | ||
if HAVE_TORCH: | ||
x = torch.randn(10, 5, 4) | ||
assert torch_stringifier_fn(x) == "Tensor[float32][cpu] [10, 5, 4]" | ||
|
||
|
||
def test_conv_module(): | ||
if HAVE_TORCH: | ||
x = torch.nn.Conv2d(20, 10, 3) | ||
assert torch_stringifier_fn(x) == "Conv2d(20, 10, kernel_size=(3, 3), stride=(1, 1))[cpu] Params: 1810" | ||
|
||
|
||
def test_linear_module(): | ||
if HAVE_TORCH: | ||
x = torch.nn.Linear(5, 2, bias=False) | ||
assert torch_stringifier_fn(x) == "Linear(in_features=5, out_features=2, bias=False)[cpu] Params: 10" | ||
|
||
|
||
def test_long_module_repr_should_revert_to_type(): | ||
if HAVE_TORCH: | ||
x = torch.nn.Transformer() | ||
assert torch_stringifier_fn(x) == "Transformer[cpu] Params: 44140544" | ||
|
||
|
||
def test_reverts_to_default_for_str(): | ||
x = "Everyone has his day, and some days last longer than others." | ||
assert torch_stringifier_fn(x) == default_stringifier(x) | ||
|
||
|
||
def test_reverts_to_default_for_dict(): | ||
x = {"a": 1, "b": 2, "c": 3} | ||
assert torch_stringifier_fn(x) == default_stringifier(x) | ||
|
||
|
||
def test_reverts_to_default_for_list(): | ||
x = list(range(1000)) | ||
assert torch_stringifier_fn(x) == default_stringifier(x) |
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.
This is heavyweight, and it should only happen if the stringifier is actually used, not unconditionally on every import.