Debugger: Fix accessing cell variables in outer scopes
[cython.git] / Cython / Debugger / libcython.py
1 """
2 GDB extension that adds Cython support.
3 """
4
5 from __future__ import with_statement
6
7 import os
8 import sys
9 import textwrap
10 import operator
11 import traceback
12 import functools
13 import itertools
14 import collections
15
16 import gdb
17
18 try:
19   from lxml import etree
20   have_lxml = True
21 except ImportError:
22     have_lxml = False
23     try:
24         # Python 2.5
25         from xml.etree import cElementTree as etree
26     except ImportError:
27         try:
28             # Python 2.5
29             from xml.etree import ElementTree as etree
30         except ImportError:
31             try:
32                 # normal cElementTree install
33                 import cElementTree as etree
34             except ImportError:
35                 # normal ElementTree install
36                 import elementtree.ElementTree as etree
37
38 try:
39     import pygments.lexers
40     import pygments.formatters
41 except ImportError:
42     pygments = None
43     sys.stderr.write("Install pygments for colorized source code.\n")
44
45 if hasattr(gdb, 'string_to_argv'):
46     from gdb import string_to_argv
47 else:
48     from shlex import split as string_to_argv
49
50 from Cython.Debugger import libpython
51
52 # C or Python type
53 CObject = 'CObject'
54 PythonObject = 'PythonObject'
55
56 _data_types = dict(CObject=CObject, PythonObject=PythonObject)
57 _filesystemencoding = sys.getfilesystemencoding() or 'UTF-8'
58
59 # decorators
60
61 def dont_suppress_errors(function):
62     "*sigh*, readline"
63     @functools.wraps(function)
64     def wrapper(*args, **kwargs):
65         try:
66             return function(*args, **kwargs)
67         except Exception:
68             traceback.print_exc()
69             raise
70     
71     return wrapper
72
73 def default_selected_gdb_frame(err=True):
74     def decorator(function):
75         @functools.wraps(function)
76         def wrapper(self, frame=None, *args, **kwargs):
77             try:
78                 frame = frame or gdb.selected_frame()
79             except RuntimeError:
80                 raise gdb.GdbError("No frame is currently selected.")
81                 
82             if err and frame.name() is None:
83                 raise NoFunctionNameInFrameError()
84     
85             return function(self, frame, *args, **kwargs)
86         return wrapper
87     return decorator
88
89 def require_cython_frame(function):
90     @functools.wraps(function)
91     @require_running_program
92     def wrapper(self, *args, **kwargs):
93         frame = kwargs.get('frame') or gdb.selected_frame()
94         if not self.is_cython_function(frame):
95             raise gdb.GdbError('Selected frame does not correspond with a '
96                                'Cython function we know about.')
97         return function(self, *args, **kwargs)
98     return wrapper 
99
100 def dispatch_on_frame(c_command, python_command=None):
101     def decorator(function):
102         @functools.wraps(function)
103         def wrapper(self, *args, **kwargs):
104             is_cy = self.is_cython_function()
105             is_py = self.is_python_function()
106             
107             if is_cy or (is_py and not python_command):
108                 function(self, *args, **kwargs)
109             elif is_py:
110                 gdb.execute(python_command)
111             elif self.is_relevant_function():
112                 gdb.execute(c_command)
113             else:
114                 raise gdb.GdbError("Not a function cygdb knows about. "
115                                    "Use the normal GDB commands instead.")
116         
117         return wrapper
118     return decorator
119
120 def require_running_program(function):
121     @functools.wraps(function)
122     def wrapper(*args, **kwargs):
123         try:
124             gdb.selected_frame()
125         except RuntimeError:
126             raise gdb.GdbError("No frame is currently selected.")
127         
128         return function(*args, **kwargs)
129     return wrapper
130     
131
132 def gdb_function_value_to_unicode(function):
133     @functools.wraps(function)
134     def wrapper(self, string, *args, **kwargs):
135         if isinstance(string, gdb.Value):
136             string = string.string()
137
138         return function(self, string, *args, **kwargs)
139     return wrapper
140
141
142 # Classes that represent the debug information
143 # Don't rename the parameters of these classes, they come directly from the XML
144
145 class CythonModule(object):
146     def __init__(self, module_name, filename, c_filename):
147         self.name = module_name
148         self.filename = filename
149         self.c_filename = c_filename
150         self.globals = {}
151         # {cython_lineno: min(c_linenos)}
152         self.lineno_cy2c = {}
153         # {c_lineno: cython_lineno}
154         self.lineno_c2cy = {}
155         self.functions = {}
156         
157 class CythonVariable(object):
158
159     def __init__(self, name, cname, qualified_name, type, lineno):
160         self.name = name
161         self.cname = cname
162         self.qualified_name = qualified_name
163         self.type = type
164         self.lineno = int(lineno)
165
166 class CythonFunction(CythonVariable):
167     def __init__(self, 
168                  module, 
169                  name, 
170                  cname, 
171                  pf_cname,
172                  qualified_name, 
173                  lineno, 
174                  type=CObject,
175                  is_initmodule_function="False"):
176         super(CythonFunction, self).__init__(name, 
177                                              cname, 
178                                              qualified_name, 
179                                              type,
180                                              lineno)
181         self.module = module
182         self.pf_cname = pf_cname
183         self.is_initmodule_function = is_initmodule_function == "True"
184         self.locals = {}
185         self.arguments = []
186         self.step_into_functions = set()
187
188
189 # General purpose classes
190
191 class CythonBase(object):
192     
193     @default_selected_gdb_frame(err=False)
194     def is_cython_function(self, frame):
195         return frame.name() in self.cy.functions_by_cname
196
197     @default_selected_gdb_frame(err=False)
198     def is_python_function(self, frame):
199         """
200         Tells if a frame is associated with a Python function.
201         If we can't read the Python frame information, don't regard it as such.
202         """
203         if frame.name() == 'PyEval_EvalFrameEx':
204             pyframe = libpython.Frame(frame).get_pyop()
205             return pyframe and not pyframe.is_optimized_out()
206         return False
207         
208     @default_selected_gdb_frame()
209     def get_c_function_name(self, frame):
210         return frame.name()
211
212     @default_selected_gdb_frame()
213     def get_c_lineno(self, frame):
214         return frame.find_sal().line
215     
216     @default_selected_gdb_frame()
217     def get_cython_function(self, frame):
218         result = self.cy.functions_by_cname.get(frame.name())
219         if result is None:
220             raise NoCythonFunctionInFrameError()
221             
222         return result
223     
224     @default_selected_gdb_frame()
225     def get_cython_lineno(self, frame):
226         """
227         Get the current Cython line number. Returns 0 if there is no 
228         correspondence between the C and Cython code.
229         """
230         cyfunc = self.get_cython_function(frame)
231         return cyfunc.module.lineno_c2cy.get(self.get_c_lineno(frame), 0)
232     
233     @default_selected_gdb_frame()
234     def get_source_desc(self, frame):
235         filename = lineno = lexer = None
236         if self.is_cython_function(frame):
237             filename = self.get_cython_function(frame).module.filename
238             lineno = self.get_cython_lineno(frame)
239             if pygments:
240                 lexer = pygments.lexers.CythonLexer(stripall=False)
241         elif self.is_python_function(frame):
242             pyframeobject = libpython.Frame(frame).get_pyop()
243
244             if not pyframeobject:
245                 raise gdb.GdbError(
246                             'Unable to read information on python frame')
247
248             filename = pyframeobject.filename()
249             lineno = pyframeobject.current_line_num()
250             
251             if pygments:
252                 lexer = pygments.lexers.PythonLexer(stripall=False)
253         else:
254             symbol_and_line_obj = frame.find_sal()
255             if not symbol_and_line_obj or not symbol_and_line_obj.symtab:
256                 filename = None
257                 lineno = 0
258             else:
259                 filename = symbol_and_line_obj.symtab.fullname()
260                 lineno = symbol_and_line_obj.line
261                 if pygments:
262                     lexer = pygments.lexers.CLexer(stripall=False)
263             
264         return SourceFileDescriptor(filename, lexer), lineno
265
266     @default_selected_gdb_frame()
267     def get_source_line(self, frame):
268         source_desc, lineno = self.get_source_desc()
269         return source_desc.get_source(lineno)
270     
271     @default_selected_gdb_frame()
272     def is_relevant_function(self, frame):
273         """
274         returns whether we care about a frame on the user-level when debugging
275         Cython code
276         """
277         name = frame.name()
278         older_frame = frame.older()
279         if self.is_cython_function(frame) or self.is_python_function(frame):
280             return True
281         elif older_frame and self.is_cython_function(older_frame):
282             # direct C function call from a Cython function
283             cython_func = self.get_cython_function(older_frame)
284             return name in cython_func.step_into_functions
285
286         return False
287     
288     @default_selected_gdb_frame(err=False)
289     def print_stackframe(self, frame, index, is_c=False):
290         """
291         Print a C, Cython or Python stack frame and the line of source code
292         if available.
293         """
294         # do this to prevent the require_cython_frame decorator from
295         # raising GdbError when calling self.cy.cy_cvalue.invoke()
296         selected_frame = gdb.selected_frame()
297         frame.select()
298         
299         try:
300             source_desc, lineno = self.get_source_desc(frame)
301         except NoFunctionNameInFrameError:
302             print '#%-2d Unknown Frame (compile with -g)' % index
303             return
304
305         if not is_c and self.is_python_function(frame):
306             pyframe = libpython.Frame(frame).get_pyop()
307             if pyframe is None or pyframe.is_optimized_out():
308                 # print this python function as a C function
309                 return self.print_stackframe(frame, index, is_c=True)
310             
311             func_name = pyframe.co_name
312             func_cname = 'PyEval_EvalFrameEx'
313             func_args = []
314         elif self.is_cython_function(frame):
315             cyfunc = self.get_cython_function(frame)
316             f = lambda arg: self.cy.cy_cvalue.invoke(arg, frame=frame)
317             
318             func_name = cyfunc.name
319             func_cname = cyfunc.cname
320             func_args = [] # [(arg, f(arg)) for arg in cyfunc.arguments]
321         else:
322             source_desc, lineno = self.get_source_desc(frame)
323             func_name = frame.name()
324             func_cname = func_name
325             func_args = []
326         
327         try:
328             gdb_value = gdb.parse_and_eval(func_cname)
329         except RuntimeError:
330             func_address = 0
331         else:
332             # Seriously? Why is the address not an int?
333             func_address = int(str(gdb_value.address).split()[0], 0)
334         
335         a = ', '.join('%s=%s' % (name, val) for name, val in func_args)
336         print '#%-2d 0x%016x in %s(%s)' % (index, func_address, func_name, a),
337             
338         if source_desc.filename is not None:
339             print 'at %s:%s' % (source_desc.filename, lineno),
340         
341         print
342             
343         try:
344             print '    ' + source_desc.get_source(lineno)
345         except gdb.GdbError:
346             pass
347         
348         selected_frame.select()
349     
350     def get_remote_cython_globals_dict(self):
351         m = gdb.parse_and_eval('__pyx_m')
352         
353         try:
354             PyModuleObject = gdb.lookup_type('PyModuleObject')
355         except RuntimeError:
356             raise gdb.GdbError(textwrap.dedent("""\
357                 Unable to lookup type PyModuleObject, did you compile python 
358                 with debugging support (-g)?"""))
359             
360         m = m.cast(PyModuleObject.pointer())
361         return m['md_dict']
362         
363     
364     def get_cython_globals_dict(self):
365         """
366         Get the Cython globals dict where the remote names are turned into
367         local strings.
368         """
369         remote_dict = self.get_remote_cython_globals_dict()
370         pyobject_dict = libpython.PyObjectPtr.from_pyobject_ptr(remote_dict)
371         
372         result = {}
373         seen = set()
374         for k, v in pyobject_dict.iteritems():
375             result[k.proxyval(seen)] = v
376             
377         return result
378
379     def print_gdb_value(self, name, value, max_name_length=None, prefix=''):
380         if libpython.pretty_printer_lookup(value):
381             typename = ''
382         else:
383             typename = '(%s) ' % (value.type,)
384                 
385         if max_name_length is None:
386             print '%s%s = %s%s' % (prefix, name, typename, value)
387         else:
388             print '%s%-*s = %s%s' % (prefix, max_name_length, name, typename, 
389                                      value)
390
391     def is_initialized(self, cython_func, local_name):
392         islocal = local_name in cython_func.locals
393         if islocal:
394             cyvar = cython_func.locals[local_name]
395             if '->' in cyvar.cname:
396                 # Closed over free variable 
397                 try:
398                     gdb.parse_and_eval(cyvar.cname)
399                     return True
400                 except RuntimeError:
401                     return False
402         
403         cur_lineno = self.get_cython_lineno()
404         return (local_name in cython_func.arguments or
405                 (islocal and cur_lineno > cyvar.lineno))
406
407 class SourceFileDescriptor(object):
408     def __init__(self, filename, lexer, formatter=None):
409         self.filename = filename
410         self.lexer = lexer
411         self.formatter = formatter
412
413     def valid(self):
414         return self.filename is not None
415
416     def lex(self, code):
417         if pygments and self.lexer and parameters.colorize_code:
418             bg = parameters.terminal_background.value
419             if self.formatter is None:
420                 formatter = pygments.formatters.TerminalFormatter(bg=bg)
421             else:
422                 formatter = self.formatter
423
424             return pygments.highlight(code, self.lexer, formatter)
425
426         return code
427
428     def _get_source(self, start, stop, lex_source, mark_line, lex_entire):
429         with open(self.filename) as f:
430             # to provide "correct" colouring, the entire code needs to be
431             # lexed. However, this makes a lot of things terribly slow, so
432             # we decide not to. Besides, it's unlikely to matter.
433             
434             if lex_source and lex_entire:
435                 f = self.lex(f.read()).splitlines()
436             
437             slice = itertools.islice(f, start - 1, stop - 1)
438             
439             for idx, line in enumerate(slice):
440                 if start + idx == mark_line:
441                     prefix = '>'
442                 else:
443                     prefix = ' '
444                 
445                 if lex_source and not lex_entire:
446                     line = self.lex(line)
447
448                 yield '%s %4d    %s' % (prefix, start + idx, line.rstrip())
449
450     def get_source(self, start, stop=None, lex_source=True, mark_line=0, 
451                    lex_entire=False):
452         exc = gdb.GdbError('Unable to retrieve source code')
453         
454         if not self.filename:
455             raise exc
456         
457         start = max(start, 1)
458         if stop is None:
459             stop = start + 1
460
461         try:
462             return '\n'.join(
463                 self._get_source(start, stop, lex_source, mark_line, lex_entire))
464         except IOError:
465             raise exc
466
467
468 # Errors
469
470 class CyGDBError(gdb.GdbError):
471     """
472     Base class for Cython-command related erorrs
473     """
474     
475     def __init__(self, *args):
476         args = args or (self.msg,)
477         super(CyGDBError, self).__init__(*args)
478     
479 class NoCythonFunctionInFrameError(CyGDBError):
480     """
481     raised when the user requests the current cython function, which is 
482     unavailable
483     """
484     msg = "Current function is a function cygdb doesn't know about"
485
486 class NoFunctionNameInFrameError(NoCythonFunctionInFrameError):
487     """
488     raised when the name of the C function could not be determined 
489     in the current C stack frame
490     """
491     msg = ('C function name could not be determined in the current C stack '
492            'frame')
493
494
495 # Parameters
496
497 class CythonParameter(gdb.Parameter):
498     """
499     Base class for cython parameters
500     """
501     
502     def __init__(self, name, command_class, parameter_class, default=None):
503         self.show_doc = self.set_doc = self.__class__.__doc__
504         super(CythonParameter, self).__init__(name, command_class, 
505                                               parameter_class)
506         if default is not None:
507             self.value = default
508    
509     def __nonzero__(self):
510         return bool(self.value)
511     
512     __bool__ = __nonzero__ # python 3
513
514 class CompleteUnqualifiedFunctionNames(CythonParameter):
515     """
516     Have 'cy break' complete unqualified function or method names.
517     """ 
518
519 class ColorizeSourceCode(CythonParameter):
520     """
521     Tell cygdb whether to colorize source code.
522     """
523
524 class TerminalBackground(CythonParameter):
525     """
526     Tell cygdb about the user's terminal background (light or dark).
527     """
528
529 class CythonParameters(object):
530     """
531     Simple container class that might get more functionality in the distant
532     future (mostly to remind us that we're dealing with parameters).
533     """
534     
535     def __init__(self):
536         self.complete_unqualified = CompleteUnqualifiedFunctionNames(
537             'cy_complete_unqualified',
538             gdb.COMMAND_BREAKPOINTS,
539             gdb.PARAM_BOOLEAN,
540             True)
541         self.colorize_code = ColorizeSourceCode(
542             'cy_colorize_code',
543             gdb.COMMAND_FILES,
544             gdb.PARAM_BOOLEAN,
545             True)
546         self.terminal_background = TerminalBackground(
547             'cy_terminal_background_color',
548             gdb.COMMAND_FILES,
549             gdb.PARAM_STRING,
550             "dark")
551         
552 parameters = CythonParameters()
553
554
555 # Commands
556
557 class CythonCommand(gdb.Command, CythonBase):
558     """
559     Base class for Cython commands
560     """
561     
562     command_class = gdb.COMMAND_NONE
563     
564     @classmethod
565     def _register(cls, clsname, args, kwargs):
566         if not hasattr(cls, 'completer_class'):
567             return cls(clsname, cls.command_class, *args, **kwargs)
568         else:
569             return cls(clsname, cls.command_class, cls.completer_class, 
570                        *args, **kwargs)
571     
572     @classmethod
573     def register(cls, *args, **kwargs):
574         alias = getattr(cls, 'alias', None)
575         if alias:
576             cls._register(cls.alias, args, kwargs)
577             
578         return cls._register(cls.name, args, kwargs)
579
580
581 class CyCy(CythonCommand):
582     """
583     Invoke a Cython command. Available commands are:
584         
585         cy import
586         cy break
587         cy step
588         cy next
589         cy run
590         cy cont
591         cy finish
592         cy up
593         cy down
594         cy select
595         cy bt / cy backtrace
596         cy list
597         cy print
598         cy locals
599         cy globals
600         cy exec
601     """
602     
603     name = 'cy'
604     command_class = gdb.COMMAND_NONE
605     completer_class = gdb.COMPLETE_COMMAND
606     
607     def __init__(self, name, command_class, completer_class):
608         # keep the signature 2.5 compatible (i.e. do not use f(*a, k=v)
609         super(CythonCommand, self).__init__(name, command_class, 
610                                             completer_class, prefix=True)
611         
612         commands = dict(
613             import_ = CyImport.register(),
614             break_ = CyBreak.register(),
615             step = CyStep.register(),
616             next = CyNext.register(),
617             run = CyRun.register(),
618             cont = CyCont.register(),
619             finish = CyFinish.register(),
620             up = CyUp.register(),
621             down = CyDown.register(),
622             select = CySelect.register(),
623             bt = CyBacktrace.register(),
624             list = CyList.register(),
625             print_ = CyPrint.register(),
626             locals = CyLocals.register(),
627             globals = CyGlobals.register(),
628             exec_ = libpython.FixGdbCommand('cy exec', '-cy-exec'),
629             _exec = CyExec.register(),
630             cy_cname = CyCName('cy_cname'),
631             cy_cvalue = CyCValue('cy_cvalue'),
632             cy_lineno = CyLine('cy_lineno'),
633         )
634             
635         for command_name, command in commands.iteritems():
636             command.cy = self
637             setattr(self, command_name, command)
638         
639         self.cy = self
640         
641         # Cython module namespace
642         self.cython_namespace = {}
643         
644         # maps (unique) qualified function names (e.g. 
645         # cythonmodule.ClassName.method_name) to the CythonFunction object
646         self.functions_by_qualified_name = {}
647         
648         # unique cnames of Cython functions
649         self.functions_by_cname = {}
650         
651         # map function names like method_name to a list of all such 
652         # CythonFunction objects
653         self.functions_by_name = collections.defaultdict(list)
654
655
656 class CyImport(CythonCommand):
657     """
658     Import debug information outputted by the Cython compiler
659     Example: cy import FILE...
660     """
661     
662     name = 'cy import'
663     command_class = gdb.COMMAND_STATUS
664     completer_class = gdb.COMPLETE_FILENAME
665     
666     def invoke(self, args, from_tty):
667         args = args.encode(_filesystemencoding)
668         for arg in string_to_argv(args):
669             try:
670                 f = open(arg)
671             except OSError, e:
672                 raise gdb.GdbError('Unable to open file %r: %s' % 
673                                                 (args, e.args[1]))
674             
675             t = etree.parse(f)
676             
677             for module in t.getroot():
678                 cython_module = CythonModule(**module.attrib)
679                 self.cy.cython_namespace[cython_module.name] = cython_module
680                 
681                 for variable in module.find('Globals'):
682                     d = variable.attrib
683                     cython_module.globals[d['name']] = CythonVariable(**d)
684                 
685                 for function in module.find('Functions'):
686                     cython_function = CythonFunction(module=cython_module, 
687                                                      **function.attrib)
688
689                     # update the global function mappings
690                     name = cython_function.name
691                     qname = cython_function.qualified_name
692                     
693                     self.cy.functions_by_name[name].append(cython_function)
694                     self.cy.functions_by_qualified_name[
695                         cython_function.qualified_name] = cython_function
696                     self.cy.functions_by_cname[
697                         cython_function.cname] = cython_function
698                     
699                     d = cython_module.functions[qname] = cython_function
700                     
701                     for local in function.find('Locals'):
702                         d = local.attrib
703                         cython_function.locals[d['name']] = CythonVariable(**d)
704
705                     for step_into_func in function.find('StepIntoFunctions'):
706                         d = step_into_func.attrib
707                         cython_function.step_into_functions.add(d['name'])
708                     
709                     cython_function.arguments.extend(
710                         funcarg.tag for funcarg in function.find('Arguments'))
711
712                 for marker in module.find('LineNumberMapping'):
713                     cython_lineno = int(marker.attrib['cython_lineno'])
714                     c_linenos = map(int, marker.attrib['c_linenos'].split())
715                     cython_module.lineno_cy2c[cython_lineno] = min(c_linenos)
716                     for c_lineno in c_linenos:
717                         cython_module.lineno_c2cy[c_lineno] = cython_lineno
718
719
720 class CyBreak(CythonCommand):
721     """
722     Set a breakpoint for Cython code using Cython qualified name notation, e.g.:
723         
724         cy break cython_modulename.ClassName.method_name...
725     
726     or normal notation:
727         
728         cy break function_or_method_name...
729     
730     or for a line number:
731     
732         cy break cython_module:lineno...
733     
734     Set a Python breakpoint:
735         Break on any function or method named 'func' in module 'modname'
736             
737             cy break -p modname.func...
738         
739         Break on any function or method named 'func'
740             
741             cy break -p func...
742     """
743     
744     name = 'cy break'
745     command_class = gdb.COMMAND_BREAKPOINTS
746     
747     def _break_pyx(self, name):
748         modulename, _, lineno = name.partition(':')
749         lineno = int(lineno)
750         if modulename:
751             cython_module = self.cy.cython_namespace[modulename]
752         else:
753             cython_module = self.get_cython_function().module
754
755         if lineno in cython_module.lineno_cy2c:
756             c_lineno = cython_module.lineno_cy2c[lineno]
757             breakpoint = '%s:%s' % (cython_module.c_filename, c_lineno)
758             gdb.execute('break ' + breakpoint)
759         else:
760             raise GdbError("Not a valid line number. "
761                            "Does it contain actual code?")
762     
763     def _break_funcname(self, funcname):
764         func = self.cy.functions_by_qualified_name.get(funcname)
765         
766         if func and func.is_initmodule_function:
767             func = None
768         
769         break_funcs = [func]
770         
771         if not func:
772             funcs = self.cy.functions_by_name.get(funcname) or []
773             funcs = [f for f in funcs if not f.is_initmodule_function]
774             
775             if not funcs:
776                 gdb.execute('break ' + funcname)
777                 return
778             
779             if len(funcs) > 1:
780                 # multiple functions, let the user pick one
781                 print 'There are multiple such functions:'
782                 for idx, func in enumerate(funcs):
783                     print '%3d) %s' % (idx, func.qualified_name)
784                 
785                 while True:
786                     try:
787                         result = raw_input(
788                             "Select a function, press 'a' for all "
789                             "functions or press 'q' or '^D' to quit: ")
790                     except EOFError:
791                         return
792                     else:
793                         if result.lower() == 'q':
794                             return
795                         elif result.lower() == 'a':
796                             break_funcs = funcs
797                             break
798                         elif (result.isdigit() and 
799                             0 <= int(result) < len(funcs)):
800                             break_funcs = [funcs[int(result)]]
801                             break
802                         else:
803                             print 'Not understood...'
804             else:
805                 break_funcs = [funcs[0]]
806         
807         for func in break_funcs:
808             gdb.execute('break %s' % func.cname)
809             if func.pf_cname:
810                 gdb.execute('break %s' % func.pf_cname)
811     
812     def invoke(self, function_names, from_tty):
813         argv = string_to_argv(function_names.encode('UTF-8'))
814         if function_names.startswith('-p'):
815             argv = argv[1:]
816             python_breakpoints = True
817         else:
818             python_breakpoints = False
819         
820         for funcname in argv:
821             if python_breakpoints:
822                 gdb.execute('py-break %s' % funcname)
823             elif ':' in funcname:
824                 self._break_pyx(funcname)
825             else:
826                 self._break_funcname(funcname)
827     
828     @dont_suppress_errors
829     def complete(self, text, word):
830         # Filter init-module functions (breakpoints can be set using 
831         # modulename:linenumber).
832         names =  [n for n, L in self.cy.functions_by_name.iteritems() 
833                         if any(not f.is_initmodule_function for f in L)]
834         qnames = [n for n, f in self.cy.functions_by_qualified_name.iteritems()
835                         if not f.is_initmodule_function]
836         
837         if parameters.complete_unqualified:
838             all_names = itertools.chain(qnames, names)
839         else:
840             all_names = qnames
841
842         words = text.strip().split()
843         if not words or '.' not in words[-1]:
844             # complete unqualified
845             seen = set(text[:-len(word)].split())
846             return [n for n in all_names 
847                           if n.startswith(word) and n not in seen]
848         
849         # complete qualified name
850         lastword = words[-1]
851         compl = [n for n in qnames if n.startswith(lastword)]
852         
853         if len(lastword) > len(word):
854             # readline sees something (e.g. a '.') as a word boundary, so don't
855             # "recomplete" this prefix
856             strip_prefix_length = len(lastword) - len(word)
857             compl = [n[strip_prefix_length:] for n in compl]
858             
859         return compl
860
861
862 class CythonInfo(CythonBase, libpython.PythonInfo):
863     """
864     Implementation of the interface dictated by libpython.LanguageInfo.
865     """
866     
867     def lineno(self, frame):
868         # Take care of the Python and Cython levels. We need to care for both
869         # as we can't simply dispath to 'py-step', since that would work for
870         # stepping through Python code, but it would not step back into Cython-
871         # related code. The C level should be dispatched to the 'step' command.
872         if self.is_cython_function(frame):
873             return self.get_cython_lineno(frame)
874         return super(CythonInfo, self).lineno(frame)
875     
876     def get_source_line(self, frame):
877         try:
878             line = super(CythonInfo, self).get_source_line(frame)
879         except gdb.GdbError:
880             return None
881         else:
882             return line.strip() or None
883
884     def exc_info(self, frame):
885         if self.is_python_function:
886             return super(CythonInfo, self).exc_info(frame)
887
888     def runtime_break_functions(self):
889         if self.is_cython_function():
890             return self.get_cython_function().step_into_functions
891         return ()
892     
893     def static_break_functions(self):
894         result = ['PyEval_EvalFrameEx']
895         result.extend(self.cy.functions_by_cname)
896         return result
897
898
899 class CythonExecutionControlCommand(CythonCommand, 
900                                     libpython.ExecutionControlCommandBase):
901     
902     @classmethod
903     def register(cls):
904         return cls(cls.name, cython_info)
905
906
907 class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin):
908     "Step through Cython, Python or C code."
909     
910     name = 'cy -step'
911     stepinto = True
912     
913     def invoke(self, args, from_tty):
914         if self.is_python_function():
915             self.python_step(self.stepinto)
916         elif not self.is_cython_function():
917             if self.stepinto:
918                 command = 'step'
919             else:
920                 command = 'next'
921                 
922             self.finish_executing(gdb.execute(command, to_string=True))
923         else:
924             self.step(stepinto=self.stepinto)
925
926
927 class CyNext(CyStep):
928     "Step-over Cython, Python or C code."
929
930     name = 'cy -next'
931     stepinto = False
932
933
934 class CyRun(CythonExecutionControlCommand):
935     """
936     Run a Cython program. This is like the 'run' command, except that it 
937     displays Cython or Python source lines as well
938     """
939     
940     name = 'cy run'
941     
942     invoke = CythonExecutionControlCommand.run
943
944
945 class CyCont(CythonExecutionControlCommand):
946     """
947     Continue a Cython program. This is like the 'run' command, except that it 
948     displays Cython or Python source lines as well.
949     """
950     
951     name = 'cy cont'
952     invoke = CythonExecutionControlCommand.cont
953
954
955 class CyFinish(CythonExecutionControlCommand):
956     """
957     Execute until the function returns.
958     """
959     name = 'cy finish'
960
961     invoke = CythonExecutionControlCommand.finish
962
963
964 class CyUp(CythonCommand):
965     """
966     Go up a Cython, Python or relevant C frame.
967     """
968     name = 'cy up'
969     _command = 'up'
970     
971     def invoke(self, *args):
972         try:
973             gdb.execute(self._command, to_string=True)
974             while not self.is_relevant_function(gdb.selected_frame()):
975                 gdb.execute(self._command, to_string=True)
976         except RuntimeError, e:
977             raise gdb.GdbError(*e.args)
978         
979         frame = gdb.selected_frame()
980         index = 0
981         while frame:
982             frame = frame.older()
983             index += 1
984             
985         self.print_stackframe(index=index - 1)
986
987
988 class CyDown(CyUp):
989     """
990     Go down a Cython, Python or relevant C frame.
991     """
992     
993     name = 'cy down'
994     _command = 'down'
995
996
997 class CySelect(CythonCommand):
998     """
999     Select a frame. Use frame numbers as listed in `cy backtrace`.
1000     This command is useful because `cy backtrace` prints a reversed backtrace.
1001     """
1002     
1003     name = 'cy select'
1004     
1005     def invoke(self, stackno, from_tty):
1006         try:
1007             stackno = int(stackno)
1008         except ValueError:
1009             raise gdb.GdbError("Not a valid number: %r" % (stackno,))
1010         
1011         frame = gdb.selected_frame()
1012         while frame.newer():
1013             frame = frame.newer()
1014         
1015         stackdepth = libpython.stackdepth(frame)
1016         
1017         try:
1018             gdb.execute('select %d' % (stackdepth - stackno - 1,))
1019         except RuntimeError, e:
1020             raise gdb.GdbError(*e.args)
1021
1022
1023 class CyBacktrace(CythonCommand):
1024     'Print the Cython stack'
1025     
1026     name = 'cy bt'
1027     alias = 'cy backtrace'
1028     command_class = gdb.COMMAND_STACK
1029     completer_class = gdb.COMPLETE_NONE
1030     
1031     @require_running_program
1032     def invoke(self, args, from_tty):
1033         # get the first frame
1034         selected_frame = frame = gdb.selected_frame()
1035         while frame.older():
1036             frame = frame.older()
1037         
1038         print_all = args == '-a'
1039         
1040         index = 0
1041         while frame:
1042             is_c = False
1043             
1044             is_relevant = False
1045             try:
1046                 is_relevant = self.is_relevant_function(frame)
1047             except CyGDBError:
1048                 pass
1049                 
1050             if print_all or is_relevant:
1051                 self.print_stackframe(frame, index)
1052             
1053             index += 1
1054             frame = frame.newer()
1055         
1056         selected_frame.select()
1057
1058
1059 class CyList(CythonCommand):
1060     """
1061     List Cython source code. To disable to customize colouring see the cy_*
1062     parameters.
1063     """
1064     
1065     name = 'cy list'
1066     command_class = gdb.COMMAND_FILES
1067     completer_class = gdb.COMPLETE_NONE
1068     
1069     # @dispatch_on_frame(c_command='list')
1070     def invoke(self, _, from_tty):
1071         sd, lineno = self.get_source_desc()
1072         source = sd.get_source(lineno - 5, lineno + 5, mark_line=lineno, 
1073                                lex_entire=True)
1074         print source
1075
1076
1077 class CyPrint(CythonCommand):
1078     """
1079     Print a Cython variable using 'cy-print x' or 'cy-print module.function.x'
1080     """
1081     
1082     name = 'cy print'
1083     command_class = gdb.COMMAND_DATA
1084     
1085     def invoke(self, name, from_tty, max_name_length=None):
1086         if self.is_python_function():
1087             return gdb.execute('py-print ' + name)
1088         elif self.is_cython_function():
1089             value = self.cy.cy_cvalue.invoke(name.lstrip('*'))
1090             for c in name:
1091                 if c == '*':
1092                     value = value.dereference()
1093                 else:
1094                     break
1095                 
1096             self.print_gdb_value(name, value, max_name_length)
1097         else:
1098             gdb.execute('print ' + name)
1099         
1100     def complete(self):
1101         if self.is_cython_function():
1102             f = self.get_cython_function()
1103             return list(itertools.chain(f.locals, f.globals))
1104         else:
1105             return []
1106
1107
1108 sortkey = lambda (name, value): name.lower()
1109
1110 class CyLocals(CythonCommand):
1111     """
1112     List the locals from the current Cython frame.
1113     """
1114     
1115     name = 'cy locals'
1116     command_class = gdb.COMMAND_STACK
1117     completer_class = gdb.COMPLETE_NONE
1118     
1119     @dispatch_on_frame(c_command='info locals', python_command='py-locals')
1120     def invoke(self, args, from_tty):
1121         cython_function = self.get_cython_function()
1122         
1123         if cython_function.is_initmodule_function:
1124             self.cy.globals.invoke(args, from_tty)
1125             return
1126
1127         local_cython_vars = cython_function.locals
1128         max_name_length = len(max(local_cython_vars, key=len))
1129         for name, cyvar in sorted(local_cython_vars.iteritems(), key=sortkey):
1130             if self.is_initialized(self.get_cython_function(), cyvar.name):
1131                 value = gdb.parse_and_eval(cyvar.cname)
1132                 if not value.is_optimized_out:
1133                     self.print_gdb_value(cyvar.name, value, 
1134                                          max_name_length, '')
1135
1136
1137 class CyGlobals(CyLocals):
1138     """
1139     List the globals from the current Cython module.
1140     """
1141     
1142     name = 'cy globals'
1143     command_class = gdb.COMMAND_STACK
1144     completer_class = gdb.COMPLETE_NONE
1145     
1146     @dispatch_on_frame(c_command='info variables', python_command='py-globals')
1147     def invoke(self, args, from_tty):
1148         global_python_dict = self.get_cython_globals_dict()
1149         module_globals = self.get_cython_function().module.globals
1150         
1151         max_globals_len = 0
1152         max_globals_dict_len = 0
1153         if module_globals:
1154             max_globals_len = len(max(module_globals, key=len))
1155         if global_python_dict:
1156             max_globals_dict_len = len(max(global_python_dict))
1157             
1158         max_name_length = max(max_globals_len, max_globals_dict_len)
1159         
1160         seen = set()
1161         print 'Python globals:'
1162         for k, v in sorted(global_python_dict.iteritems(), key=sortkey):
1163             v = v.get_truncated_repr(libpython.MAX_OUTPUT_LEN)
1164             seen.add(k)
1165             print '    %-*s = %s' % (max_name_length, k, v)
1166         
1167         print 'C globals:'
1168         for name, cyvar in sorted(module_globals.iteritems(), key=sortkey):
1169             if name not in seen:
1170                 try:
1171                     value = gdb.parse_and_eval(cyvar.cname)
1172                 except RuntimeError:
1173                     pass
1174                 else:
1175                     if not value.is_optimized_out:
1176                         self.print_gdb_value(cyvar.name, value,
1177                                              max_name_length, '    ')
1178
1179
1180 class CyExec(CythonCommand, libpython.PyExec):
1181     """
1182     Execute Python code in the nearest Python or Cython frame.
1183     """
1184     
1185     name = '-cy-exec'
1186     command_class = gdb.COMMAND_STACK
1187     completer_class = gdb.COMPLETE_NONE
1188     
1189     def _fill_locals_dict(self, executor, local_dict_pointer):
1190         "Fill a remotely allocated dict with values from the Cython C stack"
1191         cython_func = self.get_cython_function()
1192         current_lineno = self.get_cython_lineno()
1193         
1194         for name, cyvar in cython_func.locals.iteritems():
1195             if (cyvar.type == PythonObject and 
1196                 self.is_initialized(cython_func, name)):
1197                 
1198                 try:
1199                     val = gdb.parse_and_eval(cyvar.cname)
1200                 except RuntimeError:
1201                     continue
1202                 else:
1203                     if val.is_optimized_out:
1204                         continue
1205                 
1206                 pystringp = executor.alloc_pystring(name)
1207                 code = '''
1208                     (PyObject *) PyDict_SetItem(
1209                         (PyObject *) %d,
1210                         (PyObject *) %d,
1211                         (PyObject *) %s)
1212                 ''' % (local_dict_pointer, pystringp, cyvar.cname)
1213
1214                 try:
1215                     if gdb.parse_and_eval(code) < 0:
1216                         gdb.parse_and_eval('PyErr_Print()')
1217                         raise gdb.GdbError("Unable to execute Python code.")
1218                 finally:
1219                     # PyDict_SetItem doesn't steal our reference
1220                     executor.decref(pystringp)
1221     
1222     def _find_first_cython_or_python_frame(self):
1223         frame = gdb.selected_frame()
1224         while frame:
1225             if (self.is_cython_function(frame) or 
1226                 self.is_python_function(frame)):
1227                 return frame
1228             
1229             frame = frame.older()
1230         
1231         raise gdb.GdbError("There is no Cython or Python frame on the stack.")
1232         
1233     def invoke(self, expr, from_tty):
1234         frame = self._find_first_cython_or_python_frame()
1235         if self.is_python_function(frame):
1236             libpython.py_exec.invoke(expr, from_tty)
1237             return
1238         
1239         expr, input_type = self.readcode(expr)
1240         executor = libpython.PythonCodeExecutor()
1241         
1242         with libpython.FetchAndRestoreError():
1243             # get the dict of Cython globals and construct a dict in the 
1244             # inferior with Cython locals
1245             global_dict = gdb.parse_and_eval(
1246                 '(PyObject *) PyModule_GetDict(__pyx_m)')
1247             local_dict = gdb.parse_and_eval('(PyObject *) PyDict_New()')
1248             
1249             cython_function = self.get_cython_function()
1250             
1251             try:
1252                 self._fill_locals_dict(executor, 
1253                                        libpython.pointervalue(local_dict))
1254                 executor.evalcode(expr, input_type, global_dict, local_dict)
1255             finally:
1256                 executor.decref(libpython.pointervalue(local_dict))
1257
1258
1259 # Functions
1260
1261 class CyCName(gdb.Function, CythonBase):
1262     """
1263     Get the C name of a Cython variable in the current context.
1264     Examples:
1265         
1266         print $cy_cname("function")
1267         print $cy_cname("Class.method")
1268         print $cy_cname("module.function")
1269     """
1270     
1271     @require_cython_frame
1272     @gdb_function_value_to_unicode
1273     def invoke(self, cyname, frame=None):
1274         frame = frame or gdb.selected_frame()
1275         cname = None
1276         
1277         if self.is_cython_function(frame):
1278             cython_function = self.get_cython_function(frame)
1279             if cyname in cython_function.locals:
1280                 cname = cython_function.locals[cyname].cname
1281             elif cyname in cython_function.module.globals:
1282                 cname = cython_function.module.globals[cyname].cname
1283             else:
1284                 qname = '%s.%s' % (cython_function.module.name, cyname)
1285                 if qname in cython_function.module.functions:
1286                     cname = cython_function.module.functions[qname].cname
1287             
1288         if not cname:
1289             cname = self.cy.functions_by_qualified_name.get(cyname)
1290             
1291         if not cname:
1292             raise gdb.GdbError('No such Cython variable: %s' % cyname)
1293         
1294         return cname
1295
1296
1297 class CyCValue(CyCName):
1298     """
1299     Get the value of a Cython variable.
1300     """
1301     
1302     @require_cython_frame
1303     @gdb_function_value_to_unicode
1304     def invoke(self, cyname, frame=None):
1305         try:
1306             cname = super(CyCValue, self).invoke(cyname, frame=frame)
1307             return gdb.parse_and_eval(cname)
1308         except (gdb.GdbError, RuntimeError), e:
1309             # variable exists but may not have been initialized yet, or may be
1310             # in the globals dict of the Cython module
1311             d = self.get_cython_globals_dict()
1312             if cyname in d:
1313                 return d[cyname]._gdbval
1314
1315             raise gdb.GdbError(str(e))
1316
1317
1318 class CyLine(gdb.Function, CythonBase):
1319     """
1320     Get the current Cython line.
1321     """
1322     
1323     @require_cython_frame
1324     def invoke(self):
1325         return self.get_cython_lineno()
1326
1327 cython_info = CythonInfo()
1328 cy = CyCy.register()
1329 cython_info.cy = cy
1330
1331 def register_defines():
1332     libpython.source_gdb_script(textwrap.dedent("""\
1333         define cy step
1334         cy -step
1335         end
1336         
1337         define cy next
1338         cy -next
1339         end
1340         
1341         document cy step
1342         %s
1343         end
1344         
1345         document cy next
1346         %s
1347         end
1348     """) % (CyStep.__doc__, CyNext.__doc__))
1349
1350 register_defines()