Skip to content

Commit

Permalink
Add saved settings, themes, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
inducer committed Feb 14, 2011
1 parent dd6daa3 commit 548d292
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 64 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
@@ -1,3 +1,4 @@
include debug_me.py
include ez_setup.py
include try-the-debugger.sh
include example-theme.py
3 changes: 3 additions & 0 deletions example-theme.py
@@ -0,0 +1,3 @@
palette.update({
"source": (add_setting("black", "underline"), "dark green"),
})
7 changes: 7 additions & 0 deletions pudb/__init__.py
Expand Up @@ -4,6 +4,13 @@



from pudb.settings import load_config, save_config
CONFIG = load_config()
save_config(CONFIG)




CURRENT_DEBUGGER = []
def _get_debugger():
if not CURRENT_DEBUGGER:
Expand Down
107 changes: 56 additions & 51 deletions pudb/debugger.py
Expand Up @@ -13,6 +13,8 @@
-------------------------------------------
Keys:
Ctrl-p - edit preferences
n - step over ("next")
s - step into
c - continue
Expand Down Expand Up @@ -135,7 +137,7 @@ def set_frame_index(self, index):
self.ui.set_current_line(lineno, self.curframe.f_code.co_filename)
self.ui.update_var_view()
self.ui.update_stack()

def move_up_frame(self):
if self.curindex > 0:
self.set_frame_index(self.curindex-1)
Expand Down Expand Up @@ -346,6 +348,9 @@ def change_var_state(w, size, key):
def edit_inspector_detail(w, size, key):
var, pos = self.var_list._w.get_focus()

if var is None:
return

fvi = self.get_frame_var_info(read_only=False)
iinfo = fvi.get_inspect_info(var.id_path, read_only=False)

Expand Down Expand Up @@ -465,7 +470,11 @@ def move_stack_down(w, size, key):

# stack listeners -----------------------------------------------------
def examine_breakpoint(w, size, key):
_, pos = self.bp_list._w.get_focus()
bp_entry, pos = self.bp_list._w.get_focus()

if bp_entry is None:
return

bp = self._get_bp_list()[pos]

if bp.cond is None:
Expand Down Expand Up @@ -870,50 +879,6 @@ def show_traceback(w, size, key):
self.message("No exception available.")

def run_shell(w, size, key):
import pudb.shell as shell

if shell.HAVE_IPYTHON and shell.USE_IPYTHON == "ask":
def ipython(w, size, key):
self.quit_event_loop = ["ipython"]
def classic(w, size, key):
self.quit_event_loop = ["classic"]
def cancel(w, size, key):
self.quit_event_loop = [False]

result = dbg.ui.dialog(
urwid.ListBox([urwid.Text(
"You've asked to enter a Python shell.\n\n"
"You appear to have IPython installed. If you wish to use it, "
"you may hit 'i' or select the corresponding button on the "
"right. If you prefer the 'classic' Python shell, hit '!' again or "
"select that button instead.\n\n"
"Sorry for bothering you, I won't ask again in this session."
)]),
[
("Classic", "classic"),
("IPython", "ipython"),
("Cancel", False),
],
focus_buttons=True,
bind_enter_esc=False,
title="Shell Requested",
extra_bindings=[
("!", classic),
("i", ipython),
("esc", cancel),
])

if result == False:
return
elif result == "ipython":
shell.USE_IPYTHON = use_ipython = True
elif result == "classic":
shell.USE_IPYTHON = use_ipython = False

elif shell.HAVE_IPYTHON and shell.USE_IPYTHON:
use_ipython = True
else:
use_ipython = False

self.screen.stop()

Expand All @@ -925,12 +890,14 @@ def cancel(w, size, key):

curframe = self.debugger.curframe

if use_ipython:
from pudb import CONFIG
import pudb.shell as shell
if shell.HAVE_IPYTHON and CONFIG["shell"] == "ipython":
runner = shell.run_ipython_shell
else:
runner = shell.run_classic_shell

runner(curframe.f_locals, curframe.f_globals,
runner(curframe.f_locals, curframe.f_globals,
first_shell_run)

self.screen.start()
Expand Down Expand Up @@ -965,9 +932,20 @@ def quit(w, size, key):
self.debugger.set_quit()
end()

def do_edit_config(w, size, key):
from pudb.settings import edit_config, save_config
from pudb import CONFIG
edit_config(self, CONFIG)
save_config(CONFIG)
self.setup_palette(self.screen)

for sl in self.source:
sl._invalidate()

def help(w, size, key):
self.message(HELP_TEXT, title="PuDB Help")


self.top.listen("o", show_output)
self.top.listen("!", run_shell)
self.top.listen("e", show_traceback)
Expand All @@ -979,6 +957,7 @@ def help(w, size, key):
self.top.listen("B", RHColumnFocuser(2))

self.top.listen("q", quit)
self.top.listen("ctrl p", do_edit_config)
self.top.listen("H", help)
self.top.listen("f1", help)
self.top.listen("?", help)
Expand Down Expand Up @@ -1068,8 +1047,10 @@ def setup_palette(screen):
may_use_fancy_formats = isinstance(screen, RawScreen) and \
not hasattr(urwid.escape, "_fg_attr_xterm")

from pudb import CONFIG
from pudb.theme import get_palette
screen.register_palette(get_palette(may_use_fancy_formats))
screen.register_palette(
get_palette(may_use_fancy_formats, CONFIG["theme"]))

# UI enter/exit -----------------------------------------------------------
def show(self):
Expand Down Expand Up @@ -1101,6 +1082,30 @@ def event_loop(self, toplevel=None):
self.message("Package 'pygments' not found. "
"Syntax highlighting disabled.")

from pudb import CONFIG
WELCOME_LEVEL = "b"
if CONFIG["seen_welcome"] < WELCOME_LEVEL:
CONFIG["seen_welcome"] = WELCOME_LEVEL
from pudb import VERSION
self.message("Welcome to PudB %s!\n\n"
"PuDB is a full-screen, console-based visual debugger for Python. "
" Its goal is to provide all the niceties of modern GUI-based "
"debuggers in a more lightweight and keyboard-friendly package. "
"PuDB allows you to debug code right where you write and test it--in "
"a terminal. If you've worked with the excellent (but nowadays "
"ancient) DOS-based Turbo Pascal or C tools, PuDB's UI might "
"look familiar.\n\n"
"New features in version 0.93:\n\n"
"- Stored preferences (no more pesky IPython prompt!)\n"
"- Themes\n"
"- Line numbers (optional)\n"
"\nHit Ctrl-P to set up PuDB.\n\n"
"If you're new here, welcome! The help screen (invoked by hitting "
"'?' after this message) should get you on your way." % VERSION)

from pudb.settings import save_config
save_config(CONFIG)

try:
if toplevel is None:
toplevel = self.top
Expand Down Expand Up @@ -1130,8 +1135,8 @@ def interaction(self, exc_tuple):

from pudb import VERSION
caption = [(None,
u"PuDB %s - The Python Urwid debugger - Hit ? for help"
u" - (C) Andreas Kloeckner 2009"
u"PuDB %s - ?:help, n:next, s:step into, b:breakpoint, o:console,"
"t:run to cursor, !:python shell"
% VERSION)]

if self.debugger.post_mortem:
Expand Down
145 changes: 145 additions & 0 deletions pudb/settings.py
@@ -0,0 +1,145 @@
import os
from ConfigParser import ConfigParser

# minor LGPL violation: stolen from python-xdg

_home = os.environ.get('HOME', '/')
xdg_data_home = os.environ.get('XDG_DATA_HOME',
os.path.join(_home, '.local', 'share'))

xdg_config_home = os.environ.get('XDG_CONFIG_HOME',
os.path.join(_home, '.config'))

xdg_config_dirs = [xdg_config_home] + \
os.environ.get('XDG_CONFIG_DIRS', '/etc/xdg').split(':')

def save_config_path(*resource):
resource = os.path.join(*resource)
assert not resource.startswith('/')
path = os.path.join(xdg_config_home, resource)
if not os.path.isdir(path):
os.makedirs(path, 0700)
return path

# end LGPL violation

CONF_SECTION = "pudb"

def load_config():
from os.path import join, isdir

cparser = ConfigParser()

conf_dict = {}
try:
cparser.read([
join(cdir, 'pudb', 'pudb.cfg')
for cdir in xdg_config_dirs if isdir(cdir)])

if cparser.has_section(CONF_SECTION):
conf_dict.update(dict(cparser.items(CONF_SECTION)))
except:
pass

conf_dict.setdefault("shell", "classic")
conf_dict.setdefault("theme", "classic")
conf_dict.setdefault("line_numbers", False)
conf_dict.setdefault("seen_welcome", "a")

def hack_bool(name):
try:
if conf_dict[name].lower() in ["0", "false", "off"]:
conf_dict[name] = False
except:
pass

hack_bool("line_numbers")

return conf_dict




def save_config(conf_dict):
from os.path import join

cparser = ConfigParser()
cparser.add_section(CONF_SECTION)

for key, val in conf_dict.iteritems():
cparser.set(CONF_SECTION, key, val)

try:
outf = open(join(save_config_path("pudb"), "pudb.cfg"), "w")
cparser.write(outf)
outf.close()
except:
pass





def edit_config(ui, conf_dict):
import urwid

cb_line_numbers = urwid.CheckBox("Show Line Numbers",
bool(conf_dict["line_numbers"]))

shells = ["classic", "ipython"]

shell_rb_grp = []
shell_rbs = [
urwid.RadioButton(shell_rb_grp, name,
conf_dict["shell"] == name)
for name in shells]

from pudb.theme import THEMES

known_theme = conf_dict["theme"] in THEMES

theme_rb_grp = []
theme_edit = urwid.Edit(edit_text=conf_dict["theme"])
theme_rbs = [
urwid.RadioButton(theme_rb_grp, name,
conf_dict["theme"] == name)
for name in THEMES]+[
urwid.RadioButton(theme_rb_grp, "Custom:",
not known_theme),
urwid.Padding(
urwid.AttrWrap(theme_edit, "value"),
left=4),

urwid.Text("\nTo use a custom theme, see example-theme.py in the "
"pudb distribution. Enter the full path to a file like it in the "
"box above."),
]

if ui.dialog(
urwid.ListBox(
[cb_line_numbers]
+ [urwid.Text("")]
+ [urwid.AttrWrap(urwid.Text("Shell:\n"), "group head")] + shell_rbs
+ [urwid.AttrWrap(urwid.Text("\nTheme:\n"), "group head")] + theme_rbs,
),
[
("OK", True),
("Cancel", False),
],
title="Edit Preferences"):
for shell, shell_rb in zip(shells, shell_rbs):
if shell_rb.get_state():
conf_dict["shell"] = shell

saw_theme = False
for theme, theme_rb in zip(THEMES, theme_rbs):
if theme_rb.get_state():
conf_dict["theme"] = theme
saw_theme = True

if not saw_theme:
conf_dict["theme"] = theme_edit.get_edit_text()

conf_dict["line_numbers"] = cb_line_numbers.get_state()


1 change: 0 additions & 1 deletion pudb/shell.py
Expand Up @@ -4,7 +4,6 @@
HAVE_IPYTHON = False
else:
HAVE_IPYTHON = True
USE_IPYTHON = "ask"



Expand Down

0 comments on commit 548d292

Please sign in to comment.