1 from __future__ import with_statement
14 from distutils import sysconfig
15 from distutils import ccompiler
18 import Cython.Distutils.extension
19 import Cython.Distutils.build_ext
20 from Cython.Debugger import Cygdb as cygdb
22 root = os.path.dirname(os.path.abspath(__file__))
23 codefile = os.path.join(root, 'codefile')
24 cfuncs_file = os.path.join(root, 'cfuncs.c')
25 with open(codefile) as f:
26 source_to_lineno = dict((line.strip(), i + 1) for i, line in enumerate(f))
28 # Cython.Distutils.__init__ imports build_ext from build_ext which means we
29 # can't access the module anymore. Get it from sys.modules instead.
30 build_ext = sys.modules['Cython.Distutils.build_ext']
32 class DebuggerTestCase(unittest.TestCase):
36 Run gdb and have cygdb import the debug information from the code
37 defined in TestParseTreeTransforms's setUp method
39 self.tempdir = tempfile.mkdtemp()
40 self.destfile = os.path.join(self.tempdir, 'codefile.pyx')
41 self.debug_dest = os.path.join(self.tempdir,
43 'cython_debug_info_codefile')
44 self.cfuncs_destfile = os.path.join(self.tempdir, 'cfuncs')
46 self.cwd = os.getcwd()
47 os.chdir(self.tempdir)
49 shutil.copy(codefile, self.destfile)
50 shutil.copy(cfuncs_file, self.cfuncs_destfile + '.c')
52 compiler = ccompiler.new_compiler()
53 compiler.compile(['cfuncs.c'], debug=True, extra_postargs=['-fPIC'])
56 test_directory=self.tempdir,
60 optimization_disabler = build_ext.Optimization()
61 optimization_disabler.disable_optimization()
63 cython_compile_testcase = runtests.CythonCompileTestCase(
65 # we clean up everything (not only compiled files)
66 cleanup_workdir=False,
70 cython_compile_testcase.run_cython(
71 targetdir=self.tempdir,
74 extra_compile_options={
76 'output_dir':self.tempdir,
81 cython_compile_testcase.run_distutils(
84 extra_extension_args={'extra_objects':['cfuncs.o']},
88 optimization_disabler.restore_state()
90 # ext = Cython.Distutils.extension.Extension(
94 # extra_objects=['cfuncs.o'])
96 # distutils.core.setup(
97 # script_args=['build_ext', '--inplace'],
99 # cmdclass=dict(build_ext=Cython.Distutils.build_ext)
104 shutil.rmtree(self.tempdir)
107 class GdbDebuggerTestCase(DebuggerTestCase):
110 super(GdbDebuggerTestCase, self).setUp()
112 prefix_code = textwrap.dedent('''\
119 def excepthook(type, value, tb):
120 traceback.print_exception(type, value, tb)
123 sys.excepthook = excepthook
125 # Have tracebacks end up on sys.stderr (gdb replaces sys.stderr
126 # with an object that calls gdb.write())
127 sys.stderr = sys.__stderr__
132 code = textwrap.dedent('''\
135 from Cython.Debugger.Tests import test_libcython_in_gdb
136 test_libcython_in_gdb.main(version=%r)
139 ''' % (sys.version_info[:2],))
141 self.gdb_command_file = cygdb.make_command_file(self.tempdir,
144 with open(self.gdb_command_file, 'a') as f:
147 args = ['gdb', '-batch', '-x', self.gdb_command_file, '-n', '--args',
148 sys.executable, '-c', 'import codefile']
151 path = os.environ.get('PYTHONPATH')
154 paths.append(os.path.dirname(os.path.dirname(
155 os.path.abspath(Cython.__file__))))
156 env = dict(os.environ, PYTHONPATH=os.pathsep.join(paths))
159 p = subprocess.Popen(['gdb', '-v'], stdout=subprocess.PIPE)
162 # gdb was not installed
165 gdb_version = p.stdout.read().decode('ascii')
170 # Based on Lib/test/test_gdb.py
171 regex = "^GNU gdb [^\d]*(\d+)\.(\d+)"
172 gdb_version_number = re.search(regex, gdb_version).groups()
174 # Be Python 3 compatible
175 if not have_gdb or list(map(int, gdb_version_number)) < [7, 2]:
177 warnings.warn('Skipping gdb tests, need gdb >= 7.2')
179 self.p = subprocess.Popen(
181 stdout=open(os.devnull, 'w'),
182 stderr=subprocess.PIPE,
186 super(GdbDebuggerTestCase, self).tearDown()
188 self.p.stderr.close()
190 os.remove(self.gdb_command_file)
193 class TestAll(GdbDebuggerTestCase):
199 out, err = self.p.communicate()
200 err = err.decode('UTF-8')
202 start = '%s v INSIDE GDB v %s' % (border, border)
203 end = '%s ^ INSIDE GDB ^ %s' % (border, border)
204 errmsg = '\n%s\n%s%s' % (start, err, end)
205 self.assertEquals(0, self.p.wait(), errmsg)
206 sys.stderr.write(err)
208 if __name__ == '__main__':