Coverage for C:\leo.repo\leo-editor\leo\commands\debugCommands.py: 31%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2#@+leo-ver=5-thin
3#@+node:ekr.20150514040118.1: * @file ../commands/debugCommands.py
4#@@first
5"""Per-commander debugging class."""
6#@+<< debugCommands.py imports >>
7#@+node:ekr.20181006100818.1: ** << debugCommands.py imports >>
8import os
9import sys
10from leo.core import leoGlobals as g
11from leo.commands.baseCommands import BaseEditCommandsClass
12#@-<< debugCommands.py imports >>
14def cmd(name):
15 """Command decorator for the DebugCommandsClass class."""
16 return g.new_cmd_decorator(name, ['c', 'debugCommands',])
18class DebugCommandsClass(BaseEditCommandsClass):
19 #@+others
20 #@+node:ekr.20150514063305.104: ** debug.debug & helper
21 @cmd('debug')
22 def invoke_debugger(self, event=None):
23 """
24 Start an external debugger in another process to debug a script. The
25 script is the presently selected text or then entire tree's script.
26 """
27 c, p = self.c, self.c.p
28 python = sys.executable
29 script = g.getScript(c, p)
30 winpdb = self.findDebugger()
31 if not winpdb:
32 return
33 #check for doctest examples
34 try:
35 import doctest
36 parser = doctest.DocTestParser()
37 examples = parser.get_examples(script)
38 # if this is doctest, extract the examples as a script
39 if examples:
40 script = doctest.script_from_examples(script)
41 except ImportError:
42 pass
43 # Special case: debug code may include g.es("info string").
44 # insert code fragment to make this expression legal outside Leo.
45 hide_ges = "class G:\n def es(s,c=None):\n pass\ng = G()\n"
46 script = hide_ges + script
47 # Create a temp file from the presently selected node.
48 filename = c.writeScriptFile(script)
49 if not filename:
50 return
51 # Invoke the debugger, retaining the present environment.
52 os.chdir(g.app.loadDir)
53 args = [sys.executable, winpdb, '-t', filename]
54 os.spawnv(os.P_NOWAIT, python, args)
55 #@+node:ekr.20150514063305.105: *3* debug.findDebugger
56 def findDebugger(self):
57 """Find the winpdb debugger."""
58 c = self.c
59 pythonDir = g.os_path_dirname(sys.executable)
60 debugger_path = c.expand_path_expression(c.config.getString('debugger-path'))
61 debuggers = (
62 # #1431: only expand path expression in @string debugger-path.
63 debugger_path or '@string debugger-path',
64 g.os_path_join(pythonDir, 'Lib', 'site-packages', 'winpdb.py'), # winpdb 1.1.2 or newer.
65 g.os_path_join(pythonDir, 'scripts', '_winpdb.py'), # Older version.
66 )
67 for debugger in debuggers:
68 if debugger:
69 debugger = g.os_path_finalize(debugger)
70 if g.os_path_exists(debugger):
71 return debugger
72 # g.es_print('debugger does not exist:', debugger)
73 g.es_print('winpdb not found in...')
74 for z in debuggers:
75 print(z)
76 return None
77 #@+node:ekr.20170713112849.1: ** debug.dump-node
78 @cmd('dump-node')
79 def dumpNode(self, event=None):
80 """Dump c.p.v, including gnx, uA's, etc."""
81 p = self.c.p
82 if p:
83 g.es_print(f"gnx: {p.v.gnx} {p.v.h}")
84 if p.v.u:
85 g.es_print('uAs')
86 g.printDict(p.v.u)
87 else:
88 g.es_print('no uAs')
89 #@+node:ekr.20150514063305.103: ** debug.gc-collect-garbage
90 @cmd('gc-collect-garbage')
91 def collectGarbage(self, event=None):
92 """Run Python's Garbage Collector."""
93 import gc
94 gc.collect()
95 #@+node:ekr.20150514063305.106: ** debug.gc-dump-all-objects
96 @cmd('gc-dump-all-objects')
97 def dumpAllObjects(self, event=None):
98 """Print a summary of all existing Python objects."""
99 g.printGc()
100 #@+node:ekr.20150514063305.111: ** debug.gc-show-summary
101 @cmd('gc-show-summary')
102 def printGcSummary(self, event=None):
103 """Print a brief summary of all Python objects."""
104 g.printGcSummary()
105 #@+node:ekr.20170429154309.1: ** debug.kill-log-listener
106 @cmd('kill-log-listener')
107 @cmd('log-kill-listener')
108 def killLogListener(self, event=None):
109 """Kill the listener started by listen-for-log."""
110 if g.app.log_listener:
111 try:
112 g.app.log_listener.kill()
113 except Exception:
114 g.es_exception()
115 g.app.log_listener = None
116 g.es_print('killed log listener.')
117 else:
118 g.es_print('log listener not active.')
119 #@+node:ekr.20150514063305.109: ** debug.pdb
120 @cmd('pdb')
121 def pdb(self, event=None):
122 """Fall into pdb."""
123 g.pdb()
124 #@+node:ekr.20150514063305.110: ** debug.show-focus
125 @cmd('show-focus')
126 def printFocus(self, event=None):
127 """
128 Print information about the requested focus.
130 Doesn't work if the focus isn't in a pane with bindings!
131 """
132 c = self.c
133 # w = g.app.gui.get_focus()
134 g.es_print(
135 'c.requestedFocusWidget:',
136 c.widget_name(c.requestedFocusWidget))
137 g.es_print(
138 ' c.get_focus:',
139 c.widget_name(c.get_focus()))
140 #@-others
142#@@language python
143#@@tabwidth -4
144#@-leo