Skip to content

Commit b224613

Browse files
committed
pp handles large objects better.
Try using decompyle3 on 3.7 and 3.8
2 parents b43a5b0 + 2d4259e commit b224613

8 files changed

Lines changed: 89 additions & 24 deletions

File tree

__pkginfo__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,16 @@
2323

2424
import sys
2525

26+
decompiler = "uncompyle6 >= 3.7.4"
27+
2628
SYS_VERSION = sys.version_info[0:2]
2729
if SYS_VERSION <= (3, 2):
2830
pygments_version = "== 1.6"
2931
else:
3032
pygments_version = ">= 2.2.0"
33+
if (3, 7) <= SYS_VERSION <= (3, 8):
34+
decompiler = "decompyle3 >= 3.7.4"
35+
3136

3237
# Python-version | package | last-version |
3338
# ------------------------------------------
@@ -78,7 +83,7 @@
7883
"spark_parser >= 1.8.9, <1.9.0",
7984
"tracer >= 0.3.2",
8085
"term-background >= 1.0.1",
81-
"uncompyle6 >= 3.7.4",
86+
decompiler,
8287
]
8388
license = "GPL3"
8489
mailing_list = "python-debugger@googlegroups.com"

trepan/__main__.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,18 @@ def main(dbg=None, sys_argv=list(sys.argv)):
145145
"Python file name embedded in code %s not found" % try_file
146146
)
147147
except IOError:
148+
decompiler = "uncompyle6"
148149
try:
149-
from uncompyle6 import decompile_file
150+
if 3.7 <= PYTHON_VERSION <= 3.8:
151+
from uncompyle6 import decompile_file
152+
else:
153+
from decompyle3 import decompile_file
154+
155+
decompiler = "decompyle3"
150156
except ImportError:
151157
print(
152-
"%s: Compiled python file '%s', but uncompyle6 not found"
153-
% (__title__, mainpyfile),
158+
"%s: Compiled python file '%s', but %s not found"
159+
% (__title__, mainpyfile, decompiler),
154160
file=sys.stderr,
155161
)
156162
sys.exit(1)

trepan/lib/deparse.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,15 @@
44
import sys, tempfile
55
from io import StringIO
66
from hashlib import sha1
7-
from uncompyle6.semantics.linemap import code_deparse_with_map
8-
from uncompyle6.semantics.fragments import deparsed_find, code_deparse
7+
from xdis import PYTHON_VERSION
8+
9+
if 3.7 <= PYTHON_VERSION <= 3.8:
10+
from decompyle3.semantics.linemap import code_deparse_with_map
11+
from decompyle3.semantics.fragments import deparsed_find, code_deparse
12+
else:
13+
from uncompyle6.semantics.linemap import code_deparse_with_map
14+
from uncompyle6.semantics.fragments import deparsed_find, code_deparse
15+
916
import pyficache
1017

1118
# FIXME remap filename to a short name.

trepan/lib/pp.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2009, 2013, 2015-2016, 2020 Rocky Bernstein
2+
# Copyright (C) 2009, 2013, 2015-2016, 2020-2021 Rocky Bernstein
33
#
44
# This program is free software: you can redistribute it and/or modify
55
# it under the terms of the GNU General Public License as published by
@@ -17,6 +17,42 @@
1717
import pprint
1818
from columnize import columnize
1919

20+
# Maximum length of strings
21+
MAX_PP_STRLEN = 100
22+
23+
# Maximum number of keys in dictionary
24+
MAX_PP_COUNT = 20
25+
26+
# Maximum total formatted string
27+
MAX_PP_LENGTH = 2000
28+
29+
30+
def truncate_length(obj, length=MAX_PP_COUNT):
31+
"""If `obj` is something that has more than `length` items,
32+
then truncate it to the first `length` items.
33+
"""
34+
if isinstance(obj, dict):
35+
new_obj = dict((k[:length], v) for k, v in sorted(obj.items()))
36+
# We hope zzz will be appear at the end of the sorted list.
37+
new_obj.update({"zzz...": "..."})
38+
return new_obj
39+
elif hasattr(obj, "__getitem__"):
40+
return list(obj[:length]) + ["..."]
41+
return obj
42+
43+
44+
class SafePP(pprint.PrettyPrinter):
45+
def _format(self, obj, *args, **kwargs):
46+
if isinstance(obj, str):
47+
if len(obj) > MAX_PP_STRLEN:
48+
obj = obj[:MAX_PP_STRLEN] + "..."
49+
pass
50+
pass
51+
elif hasattr(obj, "__len__") and len(obj) > MAX_PP_COUNT:
52+
obj = truncate_length(obj)
53+
54+
return pprint.PrettyPrinter._format(self, obj, *args, **kwargs)
55+
2056

2157
def pp(val, display_width, msg_nocr, msg, prefix=None):
2258
if prefix is not None:
@@ -30,11 +66,11 @@ def pp(val, display_width, msg_nocr, msg, prefix=None):
3066
if isinstance(val, list) or isinstance(val, tuple):
3167
if not pprint_simple_array(val, display_width, msg_nocr, msg, " "):
3268
print("Can't print_simple_array")
33-
msg(" " + pprint.pformat(val))
69+
msg(" " + pprint.pformat(val)[:MAX_PP_LENGTH])
3470
pass
3571
pass
3672
else:
37-
msg(" " + pprint.pformat(val))
73+
msg(" " + SafePP().pformat(val)[:MAX_PP_LENGTH])
3874
pass
3975
return
4076

@@ -43,7 +79,7 @@ def pp(val, display_width, msg_nocr, msg, prefix=None):
4379
# Possibly some will go into columnize.
4480
def pprint_simple_array(val, displaywidth, msg_nocr, msg, lineprefix=""):
4581
"""Try to pretty print a simple case where a list is not nested.
46-
Return True if we can do it and False if not. """
82+
Return True if we can do it and False if not."""
4783

4884
if not (isinstance(val, list) or isinstance(val, tuple)):
4985
return False
@@ -88,8 +124,8 @@ def msg(m):
88124
pp(x, 20, msg_nocr, msg, "x = ")
89125
pp(x, 32, msg_nocr, msg, "x = ")
90126
x = [i for i in range(30)]
91-
l = locals().keys()
92-
for k in sorted(l):
127+
ll = locals().keys()
128+
for k in sorted(ll):
93129
pp(eval(k), 80, msg_nocr, msg, prefix="%s =" % k)
94130
pass
95131
pass

trepan/processor/cmdfns.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"""
2020
import os, sys, tempfile
2121
import pyficache
22-
from xdis import IS_PYPY
22+
from xdis import IS_PYPY, PYTHON_VERSION
2323

2424

2525
def source_tempfile_remap(prefix, text, tempdir=None):
@@ -35,9 +35,15 @@ def source_tempfile_remap(prefix, text, tempdir=None):
3535

3636
def deparse_fn(code):
3737
try:
38-
from uncompyle6.semanitcs.linemap import (
39-
deparse_code_with_fragments_and_map as deparse_code,
40-
)
38+
if 3.7 <= PYTHON_VERSION <= 3.8:
39+
from uncompyle6.semantics.linemap import (
40+
deparse_code_with_fragments_and_map as deparse_code,
41+
)
42+
else:
43+
from decompile3.semantics.linemap import (
44+
deparse_code_with_fragments_and_map as deparse_code,
45+
)
46+
4147
except ImportError:
4248
return None
4349
sys_version = sys.version[:5]

trepan/processor/command/base_cmd.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2009-2010, 2012-2013, 2015 Rocky Bernstein
2+
# Copyright (C) 2009-2010, 2012-2013, 2015, 2021 Rocky Bernstein
33
#
44
# This program is free software: you can redistribute it and/or modify
55
# it under the terms of the GNU General Public License as published by
@@ -98,10 +98,10 @@ def msg(self, msg, opts={}):
9898
pass
9999
return None
100100

101-
def msg_nocr(self, msg, opts={}):
101+
def msg_nocr(self, msg: str, opts={}):
102102
""" Convenience short-hand for self.debugger.intf[-1].msg_nocr """
103103
try:
104-
return self.debugger.intf[-1].msg_nocr(msg)
104+
return self.debugger.intf[-1].msg_nocr(msg[:1000])
105105
except EOFError:
106106
# FIXME: what do we do here?
107107
pass

trepan/processor/command/deparse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class DeparseCommand(DebuggerCommand):
5959
`disassemble`, `list`, and `set highlight`
6060
"""
6161

62-
short_help = "Deparse source via uncompyle6"
62+
short_help = "Deparse source via uncompyle6/decompyle3"
6363
DebuggerCommand.setup(locals(), category="data", max_args=10, need_stack=True)
6464

6565
def print_text(self, text):

trepan/processor/command/deval.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2017-2018, 2020 Rocky Bernstein
2+
# Copyright (C) 2017-2018, 2020-2021 Rocky Bernstein
33
#
44
# This program is free software: you can redistribute it and/or modify
55
# it under the terms of the GNU General Public License as published by
@@ -16,10 +16,15 @@
1616

1717
# Our local modules
1818
from sys import version_info
19+
from xdis import IS_PYPY, PYTHON_VERSION
1920
from trepan.processor.command.base_cmd import DebuggerCommand
20-
from uncompyle6.semantics.fragments import deparse_code
21-
from xdis import IS_PYPY
22-
from uncompyle6.semantics.fragments import deparsed_find
21+
22+
if 3.7 <= PYTHON_VERSION <= 3.8:
23+
from decompyle3.semantics.fragments import deparse_code
24+
from decompyle3.semantics.fragments import deparsed_find
25+
else:
26+
from uncompyle6.semantics.fragments import deparse_code
27+
from uncompyle6.semantics.fragments import deparsed_find
2328

2429

2530
class DEvalCommand(DebuggerCommand):

0 commit comments

Comments
 (0)