Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / cython / src / Cython / Debugger / Cygdb.py
blobb749b620c4baab20f717f74eba1a085875219840
1 #!/usr/bin/env python
3 """
4 The Cython debugger
6 The current directory should contain a directory named 'cython_debug', or a
7 path to the cython project directory should be given (the parent directory of
8 cython_debug).
10 Additional gdb args can be provided only if a path to the project directory is
11 given.
12 """
14 import os
15 import sys
16 import glob
17 import tempfile
18 import textwrap
19 import subprocess
20 import optparse
21 import logging
23 logger = logging.getLogger(__name__)
25 def make_command_file(path_to_debug_info, prefix_code='', no_import=False):
26 if not no_import:
27 pattern = os.path.join(path_to_debug_info,
28 'cython_debug',
29 'cython_debug_info_*')
30 debug_files = glob.glob(pattern)
32 if not debug_files:
33 sys.exit('%s.\nNo debug files were found in %s. Aborting.' % (
34 usage, os.path.abspath(path_to_debug_info)))
36 fd, tempfilename = tempfile.mkstemp()
37 f = os.fdopen(fd, 'w')
38 try:
39 f.write(prefix_code)
40 f.write('set breakpoint pending on\n')
41 f.write("set print pretty on\n")
42 f.write('python from Cython.Debugger import libcython, libpython\n')
44 if no_import:
45 # don't do this, this overrides file command in .gdbinit
46 # f.write("file %s\n" % sys.executable)
47 pass
48 else:
49 path = os.path.join(path_to_debug_info, "cython_debug", "interpreter")
50 interpreter_file = open(path)
51 try:
52 interpreter = interpreter_file.read()
53 finally:
54 interpreter_file.close()
55 f.write("file %s\n" % interpreter)
56 f.write('\n'.join('cy import %s\n' % fn for fn in debug_files))
57 f.write(textwrap.dedent('''\
58 python
59 import sys
60 try:
61 gdb.lookup_type('PyModuleObject')
62 except RuntimeError:
63 sys.stderr.write(
64 'Python was not compiled with debug symbols (or it was '
65 'stripped). Some functionality may not work (properly).\\n')
66 end
68 source .cygdbinit
69 '''))
70 finally:
71 f.close()
73 return tempfilename
75 usage = "Usage: cygdb [options] [PATH [-- GDB_ARGUMENTS]]"
77 def main(path_to_debug_info=None, gdb_argv=None, no_import=False):
78 """
79 Start the Cython debugger. This tells gdb to import the Cython and Python
80 extensions (libcython.py and libpython.py) and it enables gdb's pending
81 breakpoints.
83 path_to_debug_info is the path to the Cython build directory
84 gdb_argv is the list of options to gdb
85 no_import tells cygdb whether it should import debug information
86 """
87 parser = optparse.OptionParser(usage=usage)
88 parser.add_option("--gdb-executable",
89 dest="gdb", default='gdb',
90 help="gdb executable to use [default: gdb]")
91 parser.add_option("--verbose", "-v",
92 dest="verbosity", action="count", default=0,
93 help="Verbose mode. Multiple -v options increase the verbosity")
95 (options, args) = parser.parse_args()
96 if path_to_debug_info is None:
97 if len(args) > 1:
98 path_to_debug_info = args[0]
99 else:
100 path_to_debug_info = os.curdir
102 if gdb_argv is None:
103 gdb_argv = args[1:]
105 if path_to_debug_info == '--':
106 no_import = True
108 logging_level = logging.WARN
109 if options.verbosity == 1:
110 logging_level = logging.INFO
111 if options.verbosity == 2:
112 logging_level = logging.DEBUG
113 logging.basicConfig(level=logging_level)
115 logger.info("verbosity = %r", options.verbosity)
116 logger.debug("options = %r; args = %r", options, args)
117 logger.debug("Done parsing command-line options. path_to_debug_info = %r, gdb_argv = %r",
118 path_to_debug_info, gdb_argv)
120 tempfilename = make_command_file(path_to_debug_info, no_import=no_import)
121 logger.info("Launching %s with command file: %s and gdb_argv: %s",
122 options.gdb, tempfilename, gdb_argv)
123 logger.debug('Command file (%s) contains: """\n%s"""', tempfilename, open(tempfilename).read())
124 logger.info("Spawning %s...", options.gdb)
125 p = subprocess.Popen([options.gdb, '-command', tempfilename] + gdb_argv)
126 logger.info("Spawned %s (pid %d)", options.gdb, p.pid)
127 while True:
128 try:
129 logger.debug("Waiting for gdb (pid %d) to exit...", p.pid)
130 ret = p.wait()
131 logger.debug("Wait for gdb (pid %d) to exit is done. Returned: %r", p.pid, ret)
132 except KeyboardInterrupt:
133 pass
134 else:
135 break
136 logger.debug("Removing temp command file: %s", tempfilename)
137 os.remove(tempfilename)
138 logger.debug("Removed temp command file: %s", tempfilename)