Skip to content

Commit 3fb865b

Browse files
committed
Add set/show tempdir...
Allows us to set a tempdir which is useful in remote debugging so decompiled files can share a directory.
1 parent df9e5c1 commit 3fb865b

9 files changed

Lines changed: 141 additions & 54 deletions

File tree

trepan/cli.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
# -*- coding: iso-8859-1 -*-
3-
# Copyright (C) 2008-2010, 2013-2014, 2016-2017
3+
# Copyright (C) 2008-2010, 2013-2014, 2016-2017, 2021
44
# Rocky Bernstein <rocky@gnu.org>
55
#
66
# This program is free software: you can redistribute it and/or modify
@@ -118,19 +118,20 @@ def main(dbg=None, sys_argv=list(sys.argv)):
118118
raise IOError("Python file name embedded in code %s not found" % try_file)
119119
except:
120120
try:
121-
from uncompyle6 import uncompyle_file
121+
from uncompyle6 import decompile_file
122122
except ImportError:
123123
print("%s: Compiled python file '%s', but uncompyle6 not found"
124124
% (__title__, mainpyfile), file=sys.stderr)
125125
sys.exit(1)
126126
return
127127

128-
short_name = osp.basename(mainpyfile).strip('.pyc')
128+
short_name = osp.basename(mainpyfile).strip(".pyc")
129129
fd = tempfile.NamedTemporaryFile(suffix='.py',
130130
prefix=short_name + "_",
131+
dir=dbg.settings["tempdir"],
131132
delete=False)
132133
try:
133-
uncompyle_file(mainpyfile, fd)
134+
decompile_file(mainpyfile, outstream=fd)
134135
mainpyfile = fd.name
135136
fd.close()
136137
except:

trepan/lib/default.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2008-2009, 2013, 2015, 2017, 2020 Rocky Bernstein <rocky@gnu.org>
2+
# Copyright (C) 2008-2009, 2013, 2015, 2017, 2020-2021 Rocky Bernstein
3+
# <rocky@gnu.org>
34
#
45
# This program is free software: you can redistribute it and/or modify
56
# it under the terms of the GNU General Public License as published by
@@ -98,6 +99,9 @@
9899
"reload": False,
99100
# Stop at 'def' and 'class' statements?
100101
"skip": True,
102+
# Location to put temporary decompiled python files.
103+
# If value is None, use Python's defaults
104+
"tempdir": None,
101105
# print trace output?
102106
"trace": False,
103107
# The target maximum print length. Used for example in listing

trepan/lib/deparse.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
'''Deparsing Routines'''
2+
"""Deparsing Routines"""
33

44
import sys, tempfile
55
from StringIO import StringIO
@@ -12,8 +12,9 @@
1212

1313
deparse_cache = {}
1414

15-
def deparse_and_cache(co, errmsg_fn):
15+
def deparse_and_cache(co, errmsg_fn, tempdir=None):
1616
# co = proc_obj.curframe.f_code
17+
print("XXXX yo - rocky")
1718
out = StringIO()
1819
deparsed = deparse_cache.get(co, None)
1920
if not deparsed or not hasattr(deparsed, "source_linemap"):
@@ -36,6 +37,7 @@ def deparse_and_cache(co, errmsg_fn):
3637
name_for_code = sha1(co.co_code).hexdigest()[:6]
3738
prefix='deparsed-'
3839
fd = tempfile.NamedTemporaryFile(suffix='.py',
40+
dir=tempdir,
3941
prefix=prefix)
4042
fd.write(text.encode('utf-8'))
4143
map_line = "\n\n# %s" % linemap

trepan/processor/cmdfns.py

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2013, 2015, 2017 Rocky Bernstein <rocky@gnu.org>
2+
# Copyright (C) 2013, 2015, 2017, 2021 Rocky Bernstein <rocky@gnu.org>
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,13 +17,14 @@
1717
counts, to parse a string for an integer, or check a string for an
1818
on/off setting value.
1919
'''
20-
import os, sys, tempfile
21-
import pyficache
20+
import sys, tempfile
2221

2322
def source_tempfile_remap(prefix, text):
23+
print("Hi rocky!")
2424
fd = tempfile.NamedTemporaryFile(suffix='.py',
2525
prefix=prefix,
26-
delete=False)
26+
delete=False,
27+
tempdir=None)
2728
with fd:
2829
fd.write(bytes(text, 'UTF-8'))
2930
fd.close()
@@ -43,26 +44,6 @@ def deparse_fn(code):
4344
raise
4445
return None
4546

46-
def deparse_getline(code, filename, line_number, opts):
47-
# Would love to figure out how to deparse the entire module
48-
# but with all many-time rewritten import stuff, I still
49-
# can't figure out how to get from "<frozen importlib>" to
50-
# the module's code.
51-
# So for now, we'll have to do this on a function by function
52-
# bases. Fortunately pyficache has the ability to remap line
53-
# numbers
54-
text = deparse_fn(code)
55-
if text:
56-
prefix = os.path.basename(filename) + "_"
57-
remapped_filename = source_tempfile_remap(prefix, text)
58-
lines = text.split("\n")
59-
first_line = code.co_firstlineno
60-
pyficache.remap_file_lines(filename, remapped_filename,
61-
range(first_line, first_line+len(lines)),
62-
1)
63-
return remapped_filename, pyficache.getline(filename, line_number, opts)
64-
return None, None
65-
6647
def get_an_int(errmsg, arg, msg_on_error, min_value=None, max_value=None):
6748
"""Another get_int() routine, this one simpler and less stylized
6849
than get_int(). We eval arg return it as an integer value or
@@ -207,28 +188,28 @@ def want_different_line(cmd, default):
207188
# Demo it
208189
if __name__ == '__main__':
209190
def errmsg(msg):
210-
print "** ", msg
191+
print("** ", msg)
211192
return
212193

213194
def msg(m):
214-
print m
215-
print get_int(errmsg, '1+2') # 3
216-
print get_int(errmsg, None) # 1
217-
print get_an_int(errmsg, '6*1', '6*1 is okay') # 6
218-
print get_an_int(errmsg, '0', '0 is too small', 1) # errmsg
219-
print get_an_int(errmsg, '5+a', '5+a is no good') # errmsg
195+
print(m)
196+
print(get_int(errmsg, '1+2')) # 3
197+
print(get_int(errmsg, None)) # 1
198+
print(get_an_int(errmsg, '6*1', '6*1 is okay')) # 6
199+
print(get_an_int(errmsg, '0', '0 is too small', 1)) # errmsg
200+
print(get_an_int(errmsg, '5+a', '5+a is no good')) # errmsg
220201
try:
221202
get_int(errmsg, 'pi')
222203
except ValueError:
223-
print "Good - 'pi' is not an integer"
204+
print("Good - 'pi' is not an integer")
224205
pass
225206

226207
import inspect
227208
curframe = inspect.currentframe()
228209

229-
print want_different_line("s+", False)
230-
print want_different_line("s-", True)
231-
print want_different_line("s", False)
232-
print want_different_line("s", True)
233-
print want_different_line("s", True)
210+
print(want_different_line("s+", False))
211+
print(want_different_line("s-", True))
212+
print(want_different_line("s", False))
213+
print(want_different_line("s", True))
214+
print(want_different_line("s", True))
234215
pass

trepan/processor/cmdproc.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2008-2010, 2013-2018, 2020 Rocky Bernstein <rocky@gnu.org>
2+
# Copyright (C) 2008-2010, 2013-2018, 2020-2021 Rocky Bernstein
3+
# <rocky@gnu.org>
34
#
45
# This program is free software: you can redistribute it and/or modify
56
# it under the terms of the GNU General Public License as published by
@@ -13,7 +14,7 @@
1314
#
1415
# You should have received a copy of the GNU General Public License
1516
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16-
import inspect, linecache, re, sys, shlex, tempfile, traceback, types
17+
import inspect, linecache, sys, shlex, tempfile, traceback, types
1718
import os.path as osp
1819
import pyficache
1920
from repr import Repr
@@ -192,7 +193,8 @@ def print_location(proc_obj):
192193
remapped_file = filename
193194
filename = pyficache.unmap_file(filename)
194195
if "<string>" == filename:
195-
remapped = source_tempfile_remap("eval_string", dbgr_obj.eval_string)
196+
remapped = source_tempfile_remap("eval_string", dbgr_obj.eval_string,
197+
tempdir=proc_obj.settings("tempdir"))
196198
pyficache.remap_file(filename, remapped)
197199
filename = remapped
198200
lineno = pyficache.unmap_file_line(filename, lineno)
@@ -203,7 +205,7 @@ def print_location(proc_obj):
203205
filename = "<string: '%s'>" % source_text
204206
pass
205207
elif filename in proc_obj.file2file_remap:
206-
remapped_file = self.file2file_remap[filename]
208+
remapped_file = proc_obj.file2file_remap[filename]
207209
elif filename in pyficache.file2file_remap:
208210
remapped_file = pyficache.unmap_file(filename)
209211
# FIXME: a remapped_file shouldn't be the same as its unmapped version
@@ -233,7 +235,9 @@ def print_location(proc_obj):
233235
# Deparse the code object into a temp file and remap the line from code
234236
# into the corresponding line of the tempfile
235237
co = proc_obj.curframe.f_code
236-
temp_filename, name_for_code = deparse_and_cache(co, proc_obj.errmsg)
238+
tempdir = proc_obj.settings("tempdir")
239+
temp_filename, name_for_code = deparse_and_cache(co, proc_obj.errmsg,
240+
tempdir=tempdir)
237241
lineno = 1
238242
# _, lineno = pyficache.unmap_file_line(temp_filename, lineno, True)
239243
if temp_filename:
@@ -253,7 +257,8 @@ def print_location(proc_obj):
253257
# FIXME: DRY code with version in cmdproc.py print_location
254258
prefix = osp.basename(temp_name).split(".")[0]
255259
fd = tempfile.NamedTemporaryFile(
256-
suffix=".py", prefix=prefix, delete=False
260+
suffix=".py", prefix=prefix, delete=False,
261+
dir=proc_obj.settings("tempdir"),
257262
)
258263
with fd:
259264
fd.write("".join(lines))

trepan/processor/command/deparse.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2015-2018, 2020 Rocky Bernstein
2+
# Copyright (C) 2015-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
@@ -117,7 +117,8 @@ def run(self, args):
117117
nodeInfo = None
118118

119119
if len(args) >= 1 and args[0] == ".":
120-
temp_filename, name_for_code = deparse_and_cache(co, self.errmsg)
120+
temp_filename, name_for_code = deparse_and_cache(co, self.errmsg,
121+
tempdir=self.settings["tempdir"])
121122
if not temp_filename:
122123
return
123124
self.print_text("".join(getlines(temp_filename)))

trepan/processor/command/list.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
# Copyright (C) 2009, 2012-2018 Rocky Bernstein
2+
# Copyright (C) 2009, 2012-2018, 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
@@ -96,7 +96,7 @@ def run(self, args):
9696
# Deparse the code object into a temp file and remap the line from code
9797
# into the corresponding line of the tempfile
9898
co = proc.curframe.f_code
99-
temp_filename, name_for_code = deparse_and_cache(co, proc.errmsg)
99+
temp_filename, name_for_code = deparse_and_cache(co, proc.errmsg, tempdir=self.settings["tempdir"])
100100
if temp_filename:
101101
filename = temp_filename
102102
show_marks = False
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (C) 2021 Rocky Bernstein
3+
#
4+
5+
import os
6+
# Our local modules
7+
from trepan.processor.command.base_subcmd import DebuggerSubcommand
8+
9+
10+
class SetTempdir(DebuggerSubcommand):
11+
"""**set tempdir** *directory*
12+
13+
Set the temporary directory for temporary decompiled python files.
14+
15+
This is sometimes useful remote debugging where you might set up a
16+
common shared location available between the debugged process and
17+
the front end client.
18+
Examples:
19+
---------
20+
21+
set tempdir /code/tmp # /code is a shared directory
22+
23+
See also:
24+
--------
25+
26+
`show tempdir`
27+
"""
28+
29+
in_list = True
30+
min_abbrev = len("temp")
31+
min_args = 1
32+
max_args = 1
33+
short_help = "Set a directory for storing decompiled Python"
34+
35+
def run(self, args):
36+
dirpath = args[0]
37+
if os.path.isdir(dirpath):
38+
self.debugger.settings[self.name] = dirpath
39+
else:
40+
self.errmsg("set tempdir: directory %s not found; not changed." % dirpath)
41+
return
42+
43+
pass
44+
45+
46+
# if __name__ == '__main__':
47+
# from trepan.processor.command.set.tempdir import __demo_helper__ as Mhelper
48+
# sub = Mhelper.demo_run(SetTempdir)
49+
# d = sub.proc.debugger
50+
# sub.run(['tempdir'])
51+
# print(d.settings['tempdir'])
52+
# pass
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (C) 2021 Rocky Bernstein
3+
#
4+
5+
# Our local modules
6+
from trepan.processor.command.base_subcmd import DebuggerSubcommand
7+
8+
9+
class ShowTempdir(DebuggerSubcommand):
10+
"""**show tempdir**
11+
12+
Show the temporary directory usind in decompiled python files.
13+
14+
See also:
15+
--------
16+
17+
`set tempdir`
18+
"""
19+
20+
in_list = True
21+
min_abbrev = len("temp")
22+
min_args = 0
23+
max_args = 0
24+
short_help = "Set a directory for storing decompiled Python"
25+
26+
def run(self, args):
27+
tempdir = self.debugger.settings.get(self.name, None)
28+
if tempdir:
29+
self.msg("tempdir is %s." % tempdir)
30+
else:
31+
self.msg("tempdir style not set; Python default is used.")
32+
return
33+
pass
34+
35+
if __name__ == "__main__":
36+
from trepan.processor.command.set_subcmd import __demo_helper__ as Mhelper
37+
38+
sub = Mhelper.demo_run(ShowTempdir)
39+
d = sub.proc.debugger
40+
sub.run(["show"])
41+
pass

0 commit comments

Comments
 (0)