Simultaneous Python 2/3 compatibility.

This commit is contained in:
Bradley M. Froehle 2012-07-13 17:44:44 -07:00
parent b32b4e52d6
commit 605d9e1c2e
12 changed files with 92 additions and 43 deletions

View File

@ -35,9 +35,9 @@ def fermat(n):
if x**n + y**n == z**n:
yield x, y, z
print "SF", simple_func(10)
print("SF %s" % simple_func(10))
for i in fermat(2):
print i
print(i)
print "FINISHED"
print("FINISHED")

View File

@ -1,7 +1,7 @@
NUM_VERSION = (2012, 2, 1)
VERSION = ".".join(str(nv) for nv in NUM_VERSION)
from pudb.py3compat import raw_input
CURRENT_DEBUGGER = []
@ -46,14 +46,15 @@ def runscript(mainpyfile, args=None, pre_run="", steal_output=False):
from subprocess import call
retcode = call(pre_run, close_fds=True, shell=True)
if retcode:
print "*** WARNING: pre-run process exited with code %d." % retcode
print("*** WARNING: pre-run process exited with code %d." % retcode)
raw_input("[Hit Enter]")
status_msg = ""
try:
dbg._runscript(mainpyfile)
except SystemExit, se:
except SystemExit:
se = sys.exc_info()[1]
status_msg = "The debuggee exited normally with status code %s.\n\n" % se.code
except:
dbg.post_mortem = True
@ -149,4 +150,4 @@ def pm():
if __name__ == "__main__":
print "You now need to type 'python -m pudb.run'. Sorry."
print("You now need to type 'python -m pudb.run'. Sorry.")

View File

@ -4,14 +4,17 @@
from __future__ import division
import urwid
import bdb
import sys
from pudb.settings import load_config, save_config
CONFIG = load_config()
save_config(CONFIG)
from pudb.py3compat import PY3
if PY3:
_next = "__next__"
else:
_next = "next"
HELP_TEXT = """\
@ -124,7 +127,10 @@ class Debugger(bdb.Bdb):
if steal_output:
raise NotImplementedError("output stealing")
import sys
from cStringIO import StringIO
if PY3:
from io import StringIO
else:
from cStringIO import StringIO
self.stolen_output = sys.stderr = sys.stdout = StringIO()
sys.stdin = StringIO("") # avoid spurious hangs
@ -132,7 +138,7 @@ class Debugger(bdb.Bdb):
from pudb.settings import save_breakpoints
save_breakpoints([
bp
for fn, bp_lst in self.get_all_breaks().iteritems()
for fn, bp_lst in self.get_all_breaks().items()
for lineno in bp_lst
for bp in self.get_breaks(fn, lineno)
if not bp.temporary])
@ -280,7 +286,10 @@ class Debugger(bdb.Bdb):
# user_call for details).
self._wait_for_mainpyfile = 1
self.mainpyfile = self.canonic(filename)
statement = 'execfile( "%s")' % filename
if PY3:
statement = 'exec(compile(open("%s").read(), "%s", "exec"))' % (filename, filename)
else:
statement = 'execfile( "%s")' % filename
self.run(statement, globals=globals_, locals=locals_)
# }}}
@ -834,7 +843,7 @@ class DebuggerUI(FrameVarInfoKeeper):
self.update_breakpoints()
else:
raise RuntimeError, "no valid current file"
raise RuntimeError("no valid current file")
def pick_module(w, size, key):
from os.path import splitext
@ -1344,7 +1353,7 @@ class DebuggerUI(FrameVarInfoKeeper):
from pudb import VERSION
caption = [(None,
u"PuDB %s - ?:help n:next s:step into b:breakpoint o:output "
"PuDB %s - ?:help n:next s:step into b:breakpoint o:output "
"t:run to cursor !:python shell"
% VERSION)]
@ -1386,7 +1395,7 @@ class DebuggerUI(FrameVarInfoKeeper):
lines = getlines(fname)
from pudb.lowlevel import detect_encoding
source_enc, _ = detect_encoding(iter(lines).next)
source_enc, _ = detect_encoding(getattr(iter(lines), _next))
decoded_lines = []
for l in lines:
@ -1446,7 +1455,7 @@ class DebuggerUI(FrameVarInfoKeeper):
def _get_bp_list(self):
return [bp
for fn, bp_lst in self.debugger.get_all_breaks().iteritems()
for fn, bp_lst in self.debugger.get_all_breaks().items()
for lineno in bp_lst
for bp in self.debugger.get_breaks(fn, lineno)
if not bp.temporary]

View File

@ -24,7 +24,7 @@ def pudb_f_v10(self, arg):
"""
if not arg.strip():
print __doc__
print(__doc__)
return
from IPython.genutils import arg_split
@ -52,7 +52,7 @@ def pudb_f_v11(self, arg):
# Get the running instance
if not arg.strip():
print __doc__
print(__doc__)
return
from IPython.utils.process import arg_split

View File

@ -1,3 +1,5 @@
from pudb.py3compat import PY3
# breakpoint validity ---------------------------------------------------------
def generate_executable_lines_for_code(code):
l = code.co_firstlineno
@ -80,6 +82,8 @@ def lookup_module(filename):
import re
cookie_re = re.compile("^\s*#.*coding[:=]\s*([-\w.]+)")
from codecs import lookup, BOM_UTF8
if PY3:
BOM_UTF8 = BOM_UTF8.decode()
def detect_encoding(readline):
"""
@ -108,7 +112,10 @@ def detect_encoding(readline):
def find_cookie(line):
try:
line_string = line.decode('ascii')
if PY3:
line_string = line
else:
line_string = line.decode('ascii')
except UnicodeDecodeError:
return None

16
pudb/py3compat.py Normal file
View File

@ -0,0 +1,16 @@
import sys
PY3 = sys.version_info[0] >= 3
if PY3:
raw_input = input
xrange = range
integer_types = (int,)
string_types = (str,)
def execfile(fname, globs, locs=None):
exec(compile(open(fname).read(), fname, 'exec'), globs, locs or globs)
else:
raw_input = raw_input
xrange = xrange
integer_types = (int, long)
string_types = (basestring,)
execfile = execfile

View File

@ -19,7 +19,7 @@ def main():
mainpyfile = args[0]
from os.path import exists, dirname
if not exists(mainpyfile):
print 'Error:', mainpyfile, 'does not exist'
print('Error: %s does not exist' % mainpyfile)
sys.exit(1)
sys.argv = args

View File

@ -1,5 +1,11 @@
import os
from ConfigParser import ConfigParser
import sys
from pudb.py3compat import PY3
if PY3:
from configparser import ConfigParser
else:
from ConfigParser import ConfigParser
# minor LGPL violation: stolen from python-xdg
@ -20,7 +26,7 @@ def get_save_config_path(*resource):
assert not resource.startswith('/')
path = os.path.join(xdg_config_home, resource)
if not os.path.isdir(path):
os.makedirs(path, 0700)
os.makedirs(path, 448) # 0o700
return path
# end LGPL violation
@ -90,8 +96,8 @@ def save_config(conf_dict):
cparser = ConfigParser()
cparser.add_section(CONF_SECTION)
for key, val in conf_dict.iteritems():
cparser.set(CONF_SECTION, key, val)
for key, val in conf_dict.items():
cparser.set(CONF_SECTION, key, str(val))
try:
outf = open(join(get_save_config_path(),
@ -353,7 +359,7 @@ def parse_breakpoints(lines):
arg = arg[colon+1:].lstrip()
try:
lineno = int(arg)
except ValueError, msg:
except ValueError:
continue
else:
continue

View File

@ -28,13 +28,14 @@ class SourceLine(urwid.FlowWidget):
self.has_breakpoint = has_breakpoint
self._invalidate()
def rows(self, (maxcol,), focus=False):
def rows(self, size, focus=False):
return 1
def render(self, (maxcol,), focus=False):
def render(self, size, focus=False):
from pudb.debugger import CONFIG
render_line_nr = CONFIG["line_numbers"]
maxcol = size[0]
hscroll = self.dbg_ui.source_hscroll_start
attrs = []
if self.is_current:

View File

@ -1,7 +1,6 @@
THEMES = ["classic", "vim", "dark vim", "midnight"]
from pudb.py3compat import execfile, raw_input
def get_palette(may_use_fancy_formats, theme="classic"):
if may_use_fancy_formats:
@ -288,10 +287,10 @@ def get_palette(may_use_fancy_formats, theme="classic"):
from os.path import expanduser
execfile(expanduser(theme), symbols)
except:
print "Error when importing theme:"
print("Error when importing theme:")
from traceback import print_exc
print_exc()
raw_input("Hit enter:")
return [(key,)+value for key, value in palette_dict.iteritems()]
return [(key,)+value for key, value in palette_dict.items()]

View File

@ -103,10 +103,11 @@ class StackFrame(urwid.FlowWidget):
def selectable(self):
return True
def rows(self, (maxcol,), focus=False):
def rows(self, size, focus=False):
return 1
def render(self, (maxcol,), focus=False):
def render(self, size, focus=False):
maxcol = size[0]
if focus:
apfx = "focused "
else:
@ -143,10 +144,11 @@ class BreakpointFrame(urwid.FlowWidget):
def selectable(self):
return True
def rows(self, (maxcol,), focus=False):
def rows(self, size, focus=False):
return 1
def render(self, (maxcol,), focus=False):
def render(self, size, focus=False):
maxcol = size[0]
if focus:
apfx = "focused "
else:

View File

@ -2,6 +2,7 @@
# constants and imports -------------------------------------------------------
import urwid
import sys
try:
import numpy
@ -9,6 +10,13 @@ try:
except ImportError:
HAVE_NUMPY = 0
from pudb.py3compat import PY3, execfile, raw_input, xrange, \
integer_types, string_types
if PY3:
ELLIPSIS = ''
else:
ELLIPSIS = unicode('', 'utf-8')
from pudb.debugger import CONFIG
# data ------------------------------------------------------------------------
@ -179,7 +187,7 @@ class VariableWidget(urwid.FlowWidget):
for i in xrange(len(text)):
if len(text[i]) > maxcol:
text[i] = (unicode(text[i][:maxcol-1])
+ unicode(u'') + unicode(text[i][maxcol:]))
+ ELLIPSIS + unicode(text[i][maxcol:]))
# XXX: This doesn't work. It just gives a ?
# Strangely, the following does work (it gives the …
# three characters from the right):
@ -219,15 +227,15 @@ def get_stringifier(iinfo):
from os.path import expanduser
execfile(expanduser(iinfo.display_type), custom_stringifier_dict)
except:
print "Error when importing custom stringifier:"
print("Error when importing custom stringifier:")
from traceback import print_exc
print_exc()
raw_input("Hit enter:")
return lambda value: "ERROR: Invalid custom stringifier file."
else:
if "pudb_stringifier" not in custom_stringifier_dict:
print "%s does not contain " % iinfo.display_type
"a function named pudb_stringifier at the module level."
print("%s does not contain a function named pudb_stringifier at"
"the module level." % iinfo.display_type)
raw_input("Hit enter:")
return lambda value: ("ERROR: Invalid custom stringifier file: "
"pudb_stringifer not defined.")
@ -250,9 +258,9 @@ class ValueWalker:
iinfo = self.frame_var_info.get_inspect_info(id_path, read_only=True)
if isinstance(value, (int, float, long, complex)):
if isinstance(value, integer_types + (float, complex)):
self.add_item(prefix, label, repr(value), id_path, attr_prefix)
elif isinstance(value, (str, unicode)):
elif isinstance(value, string_types):
self.add_item(prefix, label, repr(value), id_path, attr_prefix)
else:
try:
@ -444,7 +452,7 @@ class TopAndMainVariableWalker(ValueWalker):
SEPARATOR = urwid.AttrMap(urwid.Text(""), "variable separator")
def make_var_view(frame_var_info, locals, globals):
vars = locals.keys()
vars = list(locals.keys())
vars.sort(key=lambda n: n.lower())
tmv_walker = TopAndMainVariableWalker(frame_var_info)