|
15 | 15 | # |
16 | 16 | # You should have received a copy of the GNU General Public License |
17 | 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | + |
18 | 19 | import importlib |
19 | 20 | import inspect |
20 | 21 | import linecache |
21 | 22 | import os.path as osp |
22 | 23 | import re |
23 | 24 | import shlex |
24 | 25 | import sys |
25 | | -import tempfile |
26 | 26 | import traceback |
27 | 27 |
|
28 | 28 | # Note: the module name pre 3.2 is repr |
|
36 | 36 | import trepan.exception as Mexcept |
37 | 37 | import trepan.lib.display as Mdisplay |
38 | 38 | import trepan.lib.file as Mfile |
39 | | -import trepan.lib.stack as Mstack |
40 | 39 | import trepan.lib.thred as Mthread |
41 | 40 | import trepan.misc as Mmisc |
42 | | -import trepan.processor.complete as Mcomplete |
43 | 41 | from trepan.lib.bytecode import is_class_def, is_def_stmt |
44 | | -from trepan.processor import cmdfns |
45 | | -from trepan.processor.cmdfns import deparse_fn |
| 42 | +from trepan.processor.complete import completer |
| 43 | +from trepan.processor.print import print_location |
46 | 44 | from trepan.vprocessor import Processor |
47 | 45 |
|
48 | | -try: |
49 | | - from trepan.lib.deparse import deparse_and_cache |
50 | | - |
51 | | - have_deparse_and_cache = True |
52 | | -except ImportError: |
53 | | - have_deparse_and_cache = False |
54 | | - pass |
55 | | - |
56 | | -warned_file_mismatches = set() |
57 | | - |
58 | 46 |
|
59 | 47 | def get_srcdir() -> str: |
60 | 48 | filename = osp.normcase(osp.dirname(osp.abspath(__file__))) |
@@ -152,245 +140,6 @@ def resolve_name(obj, command_name) -> Optional[str]: |
152 | 140 | return |
153 | 141 |
|
154 | 142 |
|
155 | | -def print_source_line(msg, lineno, line, event_str=None): |
156 | | - """Print out a source line of text , e.g. the second |
157 | | - line in: |
158 | | - (/tmp.py:2): <module> |
159 | | - L -- 2 import sys,os |
160 | | - (trepan3k) |
161 | | -
|
162 | | - We define this method |
163 | | - specifically so it can be customized for such applications |
164 | | - like ipython.""" |
165 | | - |
166 | | - # We don't use the filename normally. ipython and other applications |
167 | | - # however might. |
168 | | - return msg("%s %d %s" % (event_str, lineno, line)) |
169 | | - |
170 | | - |
171 | | -def print_source_location_info( |
172 | | - print_fn, filename, lineno, fn_name=None, f_lasti=None, remapped_file=None |
173 | | -): |
174 | | - """Print out a source location , e.g. the first line in |
175 | | - line in: |
176 | | - (/tmp.py:2 @21): <module> |
177 | | - L -- 2 import sys,os |
178 | | - (trepan3k) |
179 | | - """ |
180 | | - if remapped_file and filename != remapped_file: |
181 | | - mess = f"({remapped_file}:{lineno} remapped {filename}" |
182 | | - else: |
183 | | - mess = f"({filename}:{lineno}" |
184 | | - if f_lasti and f_lasti != -1: |
185 | | - mess += " @%d" % f_lasti |
186 | | - pass |
187 | | - mess += "):" |
188 | | - if fn_name and fn_name != "?": |
189 | | - mess += f" {fn_name}" |
190 | | - pass |
191 | | - print_fn(mess) |
192 | | - return |
193 | | - |
194 | | - |
195 | | -def print_location(proc_obj): |
196 | | - """Show where we are. GUI's and front-end interfaces often |
197 | | - use this to update displays. So it is helpful to make sure |
198 | | - we give at least some place that's located in a file. |
199 | | - """ |
200 | | - i_stack = proc_obj.curindex |
201 | | - if i_stack is None or proc_obj.stack is None: |
202 | | - return False |
203 | | - core_obj = proc_obj.core |
204 | | - dbgr_obj = proc_obj.debugger |
205 | | - intf_obj = dbgr_obj.intf[-1] |
206 | | - |
207 | | - # Evaluation routines like "exec" don't show useful location |
208 | | - # info. In these cases, we will use the position before that in |
209 | | - # the stack. Hence the looping below which in practices loops |
210 | | - # once and sometimes twice. |
211 | | - remapped_file = None |
212 | | - source_text = None |
213 | | - while i_stack >= 0 and len(proc_obj.stack) > 0: |
214 | | - frame, lineno = proc_obj.stack[i_stack] |
215 | | - |
216 | | - # Before starting a program a location for a module with |
217 | | - # line number 0 may be reported. Treat that as though |
218 | | - # we were on the first line. |
219 | | - if frame.f_code.co_name == "<module>" and lineno == 0: |
220 | | - lineno = 1 |
221 | | - |
222 | | - i_stack -= 1 |
223 | | - |
224 | | - # # Next check to see that local variable breadcrumb exists and |
225 | | - # # has the magic dynamic value. |
226 | | - # # If so, it's us and we don't normally show this.a |
227 | | - # if 'breadcrumb' in frame.f_locals: |
228 | | - # if self.run == frame.f_locals['breadcrumb']: |
229 | | - # break |
230 | | - |
231 | | - filename = Mstack.frame2file(core_obj, frame, canonic=False) |
232 | | - if "<string>" == filename and dbgr_obj.eval_string: |
233 | | - remapped_file = filename |
234 | | - filename = pyficache.unmap_file(filename) |
235 | | - if "<string>" == filename: |
236 | | - remapped = cmdfns.source_tempfile_remap( |
237 | | - "eval_string", |
238 | | - dbgr_obj.eval_string, |
239 | | - tempdir=proc_obj.settings("tempdir"), |
240 | | - ) |
241 | | - pyficache.remap_file(filename, remapped) |
242 | | - filename, lineno = pyficache.unmap_file_line(filename, lineno) |
243 | | - pass |
244 | | - pass |
245 | | - elif "<string>" == filename: |
246 | | - source_text = deparse_fn(frame.f_code) |
247 | | - filename = f"<string: '{source_text}'>" |
248 | | - pass |
249 | | - else: |
250 | | - m = re.search("^<frozen (.*)>", filename) |
251 | | - if m and m.group(1) in pyficache.file2file_remap: |
252 | | - remapped_file = pyficache.file2file_remap[m.group(1)] |
253 | | - pass |
254 | | - elif filename in pyficache.file2file_remap: |
255 | | - remapped_file = pyficache.file2file_remap[filename] |
256 | | - filename = remapped_file |
257 | | - pass |
258 | | - elif pyficache.main.remap_re_hash: |
259 | | - remapped_file = pyficache.remap_file_pat( |
260 | | - filename, pyficache.main.remap_re_hash |
261 | | - ) |
262 | | - elif m and m.group(1) in sys.modules: |
263 | | - remapped_file = m.group(1) |
264 | | - pyficache.remap_file(filename, remapped_file) |
265 | | - pass |
266 | | - |
267 | | - opts = { |
268 | | - "reload_on_change": proc_obj.settings("reload"), |
269 | | - "output": proc_obj.settings("highlight"), |
270 | | - } |
271 | | - |
272 | | - if proc_obj.debugger.settings.get("highlight", "plain") == "plain": |
273 | | - opts["style"] = "plain" |
274 | | - elif "style" in proc_obj.debugger.settings: |
275 | | - opts["style"] = proc_obj.settings("style") |
276 | | - |
277 | | - pyficache.update_cache(filename) |
278 | | - line = pyficache.getline(filename, lineno, opts) |
279 | | - if not line: |
280 | | - if ( |
281 | | - not source_text |
282 | | - and filename.startswith("<string: ") |
283 | | - and proc_obj.curframe.f_code |
284 | | - and have_deparse_and_cache |
285 | | - ): |
286 | | - # Deparse the code object into a temp file and remap the line from code |
287 | | - # into the corresponding line of the tempfile |
288 | | - co = proc_obj.curframe.f_code |
289 | | - tempdir = proc_obj.settings("tempdir") |
290 | | - temp_filename, name_for_code = deparse_and_cache( |
291 | | - co, proc_obj.errmsg, tempdir=tempdir |
292 | | - ) |
293 | | - lineno = 1 |
294 | | - # _, lineno = pyficache.unmap_file_line(temp_filename, lineno, True) |
295 | | - if temp_filename: |
296 | | - filename = temp_filename |
297 | | - pass |
298 | | - |
299 | | - else: |
300 | | - # FIXME: |
301 | | - if source_text: |
302 | | - lines = source_text.split("\n") |
303 | | - temp_name = "string-" |
304 | | - else: |
305 | | - # try with good ol linecache and consider fixing pyficache |
306 | | - lines = linecache.getlines(filename) |
307 | | - temp_name = filename |
308 | | - if lines: |
309 | | - # FIXME: DRY code with version in cmdproc.py print_location |
310 | | - prefix = osp.basename(temp_name).split(".")[0] |
311 | | - fd = tempfile.NamedTemporaryFile( |
312 | | - suffix=".py", |
313 | | - prefix=prefix, |
314 | | - delete=False, |
315 | | - dir=proc_obj.settings("tempdir"), |
316 | | - ) |
317 | | - with fd: |
318 | | - fd.write("".join(lines).encode("utf-8")) |
319 | | - remapped_file = fd.name |
320 | | - pyficache.remap_file(remapped_file, filename) |
321 | | - fd.close() |
322 | | - intf_obj.msg(f"remapped file {filename} to {remapped_file}") |
323 | | - |
324 | | - pass |
325 | | - line = linecache.getline(filename, lineno, proc_obj.curframe.f_globals) |
326 | | - if not line: |
327 | | - m = re.search("^<frozen (.*)>", filename) |
328 | | - if m and m.group(1): |
329 | | - remapped_file = m.group(1) |
330 | | - try_module = sys.modules.get(remapped_file) |
331 | | - if ( |
332 | | - try_module |
333 | | - and inspect.ismodule(try_module) |
334 | | - and hasattr(try_module, "__file__") |
335 | | - ): |
336 | | - remapped_file = sys.modules[remapped_file].__file__ |
337 | | - pyficache.remap_file(filename, remapped_file) |
338 | | - line = linecache.getline( |
339 | | - remapped_file, lineno, proc_obj.curframe.f_globals |
340 | | - ) |
341 | | - else: |
342 | | - remapped_file = m.group(1) |
343 | | - code = proc_obj.curframe.f_code |
344 | | - filename, line = cmdfns.deparse_getline( |
345 | | - code, remapped_file, lineno, opts |
346 | | - ) |
347 | | - pass |
348 | | - pass |
349 | | - |
350 | | - try: |
351 | | - match, reason = Mstack.check_path_with_frame(frame, filename) |
352 | | - if not match: |
353 | | - if filename not in warned_file_mismatches: |
354 | | - proc_obj.errmsg(reason) |
355 | | - warned_file_mismatches.add(filename) |
356 | | - except Exception: |
357 | | - pass |
358 | | - |
359 | | - fn_name = frame.f_code.co_name |
360 | | - last_i = frame.f_lasti |
361 | | - print_source_location_info( |
362 | | - intf_obj.msg, |
363 | | - filename, |
364 | | - lineno, |
365 | | - fn_name, |
366 | | - remapped_file=remapped_file, |
367 | | - f_lasti=last_i, |
368 | | - ) |
369 | | - if line and len(line.strip()) != 0: |
370 | | - if proc_obj.event: |
371 | | - print_source_line( |
372 | | - intf_obj.msg, lineno, line, proc_obj.event2short[proc_obj.event] |
373 | | - ) |
374 | | - pass |
375 | | - if "<string>" != filename: |
376 | | - break |
377 | | - pass |
378 | | - |
379 | | - if proc_obj.event in ["return", "exception"]: |
380 | | - val = proc_obj.event_arg |
381 | | - intf_obj.msg(f"R=> {proc_obj._saferepr(val)}") |
382 | | - pass |
383 | | - elif ( |
384 | | - proc_obj.event == "call" |
385 | | - and proc_obj.curframe.f_locals.get("__name__", "") != "__main__" |
386 | | - ): |
387 | | - try: |
388 | | - proc_obj.commands["info"].run(["info", "locals"]) |
389 | | - except Exception: |
390 | | - pass |
391 | | - return True |
392 | | - |
393 | | - |
394 | 143 | # Default settings for command processor method call |
395 | 144 | DEFAULT_PROC_OPTS = { |
396 | 145 | # A list of debugger initialization files to read on first command |
@@ -432,7 +181,7 @@ def get_option_fn(key): |
432 | 181 | # command name before alias or macro resolution |
433 | 182 | self.cmd_name = "" |
434 | 183 | self.cmd_queue = [] # Queued debugger commands |
435 | | - self.completer = lambda text, state: Mcomplete.completer(self, text, state) |
| 184 | + self.completer = lambda text, state: completer(self, text, state) |
436 | 185 | self.current_command = "" # Current command getting run |
437 | 186 | self.debug_nest = 1 |
438 | 187 | self.display_mgr = Mdisplay.DisplayMgr() |
|
0 commit comments