5 import os, sys, re, codecs
6 if sys.version_info[:2] < (2, 3):
7 sys.stderr.write("Sorry, Cython requires Python 2.3 or later\n")
14 from sets import Set as set
21 # Do not import Parsing here, import it when needed, because Parsing imports
22 # Nodes, which globally needs debug command line options initialized to set a
23 # conditional metaclass. These options are processed by CmdLine called from
24 # main() in this file.
27 from Scanning import PyrexScanner, FileSourceDescriptor
28 from Errors import PyrexError, CompileError, InternalError, AbortError, error, warning
29 from Symtab import BuiltinScope, ModuleScope
30 from Cython import Utils
31 from Cython.Utils import open_new_file, replace_suffix
35 module_name_pattern = re.compile(r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$")
40 # For quick debugging in pipelines
44 def abort_on_errors(node):
45 # Stop the pipeline if there are any errors.
46 if Errors.num_errors != 0:
47 raise AbortError, "pipeline break"
50 class CompilationData(object):
51 # Bundles the information that is passed from transform to transform.
52 # (For now, this is only)
54 # While Context contains every pxd ever loaded, path information etc.,
55 # this only contains the data related to a single compilation pass
57 # pyx ModuleNode Main code tree of this compilation.
58 # pxds {string : ModuleNode} Trees for the pxds used in the pyx.
59 # codewriter CCodeWriter Where to output final code.
60 # options CompilationOptions
61 # result CompilationResult
64 class Context(object):
65 # This class encapsulates the context needed for compiling
66 # one or more Cython implementation files along with their
67 # associated and imported declaration files. It includes
68 # the root of the module import namespace and the list
69 # of directories to search for include files.
71 # modules {string : ModuleScope}
72 # include_directories [string]
73 # future_directives [object]
74 # language_level int currently 2 or 3 for Python 2/3
76 def __init__(self, include_directories, compiler_directives, cpp=False, language_level=2):
77 import Builtin, CythonScope
78 self.modules = {"__builtin__" : Builtin.builtin_scope}
79 self.modules["cython"] = CythonScope.create_cython_scope(self)
80 self.include_directories = include_directories
81 self.future_directives = set()
82 self.compiler_directives = compiler_directives
85 self.pxds = {} # full name -> node tree
87 standard_include_path = os.path.abspath(os.path.normpath(
88 os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes')))
89 self.include_directories = include_directories + [standard_include_path]
91 self.set_language_level(language_level)
93 self.gdb_debug_outputwriter = None
95 def set_language_level(self, level):
96 self.language_level = level
98 from Future import print_function, unicode_literals
99 self.future_directives.add(print_function)
100 self.future_directives.add(unicode_literals)
101 self.modules['builtins'] = self.modules['__builtin__']
103 def create_pipeline(self, pxd, py=False):
104 from Visitor import PrintTree
105 from ParseTreeTransforms import WithTransform, NormalizeTree, PostParse, PxdPostParse
106 from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform
107 from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
108 from ParseTreeTransforms import InterpretCompilerDirectives, TransformBuiltinMethods
109 from ParseTreeTransforms import ExpandInplaceOperators
110 from TypeInference import MarkAssignments, MarkOverflowingArithmetic
111 from ParseTreeTransforms import AlignFunctionDefinitions, GilCheck
112 from AnalysedTreeTransforms import AutoTestDictTransform
113 from AutoDocTransforms import EmbedSignature
114 from Optimize import FlattenInListTransform, SwitchTransform, IterationTransform
115 from Optimize import EarlyReplaceBuiltinCalls, OptimizeBuiltinCalls
116 from Optimize import ConstantFolding, FinalOptimizePhase
117 from Optimize import DropRefcountingTransform
118 from Buffer import IntroduceBufferAuxiliaryVars
119 from ModuleNode import check_c_declarations, check_c_declarations_pxd
122 _check_c_declarations = check_c_declarations_pxd
123 _specific_post_parse = PxdPostParse(self)
125 _check_c_declarations = check_c_declarations
126 _specific_post_parse = None
129 _align_function_definitions = AlignFunctionDefinitions(self)
131 _align_function_definitions = None
136 _specific_post_parse,
137 InterpretCompilerDirectives(self, self.compiler_directives),
138 MarkClosureVisitor(self),
139 _align_function_definitions,
141 FlattenInListTransform(),
143 DecoratorTransform(self),
144 AnalyseDeclarationsTransform(self),
145 AutoTestDictTransform(self),
146 EmbedSignature(self),
147 EarlyReplaceBuiltinCalls(self), ## Necessary?
148 MarkAssignments(self),
149 MarkOverflowingArithmetic(self),
150 TransformBuiltinMethods(self), ## Necessary?
151 IntroduceBufferAuxiliaryVars(self),
152 _check_c_declarations,
153 AnalyseExpressionsTransform(self),
154 CreateClosureClasses(self), ## After all lookups and type inference
155 ExpandInplaceOperators(self),
156 OptimizeBuiltinCalls(self), ## Necessary?
157 IterationTransform(),
159 DropRefcountingTransform(),
160 FinalOptimizePhase(self),
164 def create_pyx_pipeline(self, options, result, py=False):
165 def generate_pyx_code(module_node):
166 module_node.process_implementation(options, result)
167 result.compilation_source = module_node.compilation_source
170 def inject_pxd_code(module_node):
171 from textwrap import dedent
172 stats = module_node.body.stats
173 for name, (statlistnode, scope) in self.pxds.iteritems():
174 # Copy over function nodes to the module
175 # (this seems strange -- I believe the right concept is to split
176 # ModuleNode into a ModuleNode and a CodeGenerator, and tell that
177 # CodeGenerator to generate code both from the pyx and pxd ModuleNodes.
178 stats.append(statlistnode)
179 # Until utility code is moved to code generation phase everywhere,
180 # we need to copy it over to the main scope
181 module_node.scope.utility_code_list.extend(scope.utility_code_list)
185 if options.evaluate_tree_assertions:
186 from Cython.TestUtils import TreeAssertVisitor
187 test_support.append(TreeAssertVisitor())
189 if options.gdb_debug:
190 from Cython.Debugger import DebugWriter
191 from ParseTreeTransforms import DebugTransform
192 self.gdb_debug_outputwriter = DebugWriter.CythonDebugWriter(
194 debug_transform = [DebugTransform(self, options, result)]
198 return list(itertools.chain(
199 [create_parse(self)],
200 self.create_pipeline(pxd=False, py=py),
202 [inject_pxd_code, abort_on_errors],
204 [generate_pyx_code]))
206 def create_pxd_pipeline(self, scope, module_name):
207 def parse_pxd(source_desc):
208 tree = self.parse(source_desc, scope, pxd=True,
209 full_module_name=module_name)
214 from CodeGeneration import ExtractPxdCode
216 # The pxd pipeline ends up with a CCodeWriter containing the
217 # code of the pxd, as well as a pxd scope.
218 return [parse_pxd] + self.create_pipeline(pxd=True) + [
219 ExtractPxdCode(self),
222 def create_py_pipeline(self, options, result):
223 return self.create_pyx_pipeline(options, result, py=True)
226 def process_pxd(self, source_desc, scope, module_name):
227 pipeline = self.create_pxd_pipeline(scope, module_name)
228 result = self.run_pipeline(pipeline, source_desc)
231 def nonfatal_error(self, exc):
232 return Errors.report_error(exc)
234 def run_pipeline(self, pipeline, source):
239 for phase in pipeline:
240 if phase is not None:
241 if DebugFlags.debug_verbose_pipeline:
243 print "Entering pipeline phase %r" % phase
245 if DebugFlags.debug_verbose_pipeline:
246 print " %.3f seconds" % (time() - t)
247 except CompileError, err:
249 Errors.report_error(err)
251 except InternalError, err:
252 # Only raise if there was not an earlier error
253 if Errors.num_errors == 0:
256 except AbortError, err:
260 def find_module(self, module_name,
261 relative_to = None, pos = None, need_pxd = 1):
262 # Finds and returns the module scope corresponding to
263 # the given relative or absolute module name. If this
264 # is the first time the module has been requested, finds
265 # the corresponding .pxd file and process it.
266 # If relative_to is not None, it must be a module scope,
267 # and the module will first be searched for relative to
268 # that module, provided its name is not a dotted name.
269 debug_find_module = 0
270 if debug_find_module:
271 print("Context.find_module: module_name = %s, relative_to = %s, pos = %s, need_pxd = %s" % (
272 module_name, relative_to, pos, need_pxd))
276 if not module_name_pattern.match(module_name):
278 pos = (module_name, 0, 0)
279 raise CompileError(pos,
280 "'%s' is not a valid module name" % module_name)
281 if "." not in module_name and relative_to:
282 if debug_find_module:
283 print("...trying relative import")
284 scope = relative_to.lookup_submodule(module_name)
286 qualified_name = relative_to.qualify_name(module_name)
287 pxd_pathname = self.find_pxd_file(qualified_name, pos)
289 scope = relative_to.find_submodule(module_name)
291 if debug_find_module:
292 print("...trying absolute import")
294 for name in module_name.split("."):
295 scope = scope.find_submodule(name)
296 if debug_find_module:
297 print("...scope =", scope)
298 if not scope.pxd_file_loaded:
299 if debug_find_module:
300 print("...pxd not loaded")
301 scope.pxd_file_loaded = 1
303 if debug_find_module:
304 print("...looking for pxd file")
305 pxd_pathname = self.find_pxd_file(module_name, pos)
306 if debug_find_module:
307 print("......found ", pxd_pathname)
308 if not pxd_pathname and need_pxd:
309 package_pathname = self.search_include_directories(module_name, ".py", pos)
310 if package_pathname and package_pathname.endswith('__init__.py'):
313 error(pos, "'%s.pxd' not found" % module_name)
316 if debug_find_module:
317 print("Context.find_module: Parsing %s" % pxd_pathname)
318 rel_path = module_name.replace('.', os.sep) + os.path.splitext(pxd_pathname)[1]
319 if not pxd_pathname.endswith(rel_path):
320 rel_path = pxd_pathname # safety measure to prevent printing incorrect paths
321 source_desc = FileSourceDescriptor(pxd_pathname, rel_path)
322 err, result = self.process_pxd(source_desc, scope, module_name)
325 (pxd_codenodes, pxd_scope) = result
326 self.pxds[module_name] = (pxd_codenodes, pxd_scope)
331 def find_pxd_file(self, qualified_name, pos):
332 # Search include path for the .pxd file corresponding to the
333 # given fully-qualified module name.
334 # Will find either a dotted filename or a file in a
335 # package directory. If a source file position is given,
336 # the directory containing the source file is searched first
337 # for a dotted filename, and its containing package root
338 # directory is searched first for a non-dotted filename.
339 pxd = self.search_include_directories(qualified_name, ".pxd", pos)
340 if pxd is None: # XXX Keep this until Includes/Deprecated is removed
341 if (qualified_name.startswith('python') or
342 qualified_name in ('stdlib', 'stdio', 'stl')):
343 standard_include_path = os.path.abspath(os.path.normpath(
344 os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes')))
345 deprecated_include_path = os.path.join(standard_include_path, 'Deprecated')
346 self.include_directories.append(deprecated_include_path)
348 pxd = self.search_include_directories(qualified_name, ".pxd", pos)
350 self.include_directories.pop()
352 name = qualified_name
353 if name.startswith('python'):
354 warning(pos, "'%s' is deprecated, use 'cpython'" % name, 1)
355 elif name in ('stdlib', 'stdio'):
356 warning(pos, "'%s' is deprecated, use 'libc.%s'" % (name, name), 1)
357 elif name in ('stl'):
358 warning(pos, "'%s' is deprecated, use 'libcpp.*.*'" % name, 1)
361 def find_pyx_file(self, qualified_name, pos):
362 # Search include path for the .pyx file corresponding to the
363 # given fully-qualified module name, as for find_pxd_file().
364 return self.search_include_directories(qualified_name, ".pyx", pos)
366 def find_include_file(self, filename, pos):
367 # Search list of include directories for filename.
368 # Reports an error and returns None if not found.
369 path = self.search_include_directories(filename, "", pos,
372 error(pos, "'%s' not found" % filename)
375 def search_include_directories(self, qualified_name, suffix, pos,
377 # Search the list of include directories for the given
378 # file name. If a source file position is given, first
379 # searches the directory containing that file. Returns
380 # None if not found, but does not report an error.
381 # The 'include' option will disable package dereferencing.
382 dirs = self.include_directories
385 if not isinstance(file_desc, FileSourceDescriptor):
386 raise RuntimeError("Only file sources for code supported")
388 dirs = [os.path.dirname(file_desc.filename)] + dirs
390 dirs = [self.find_root_package_dir(file_desc.filename)] + dirs
392 dotted_filename = qualified_name
394 dotted_filename += suffix
396 names = qualified_name.split('.')
397 package_names = names[:-1]
398 module_name = names[-1]
399 module_filename = module_name + suffix
400 package_filename = "__init__" + suffix
403 path = os.path.join(dir, dotted_filename)
404 if Utils.path_exists(path):
407 package_dir = self.check_package_dir(dir, package_names)
408 if package_dir is not None:
409 path = os.path.join(package_dir, module_filename)
410 if Utils.path_exists(path):
412 path = os.path.join(dir, package_dir, module_name,
414 if Utils.path_exists(path):
418 def find_root_package_dir(self, file_path):
419 dir = os.path.dirname(file_path)
420 while self.is_package_dir(dir):
421 parent = os.path.dirname(dir)
427 def check_package_dir(self, dir, package_names):
428 for dirname in package_names:
429 dir = os.path.join(dir, dirname)
430 if not self.is_package_dir(dir):
434 def c_file_out_of_date(self, source_path):
435 c_path = Utils.replace_suffix(source_path, ".c")
436 if not os.path.exists(c_path):
438 c_time = Utils.modification_time(c_path)
439 if Utils.file_newer_than(source_path, c_time):
442 pxd_path = Utils.replace_suffix(source_path, ".pxd")
443 if os.path.exists(pxd_path) and Utils.file_newer_than(pxd_path, c_time):
445 for kind, name in self.read_dependency_file(source_path):
446 if kind == "cimport":
447 dep_path = self.find_pxd_file(name, pos)
448 elif kind == "include":
449 dep_path = self.search_include_directories(name, pos)
452 if dep_path and Utils.file_newer_than(dep_path, c_time):
456 def find_cimported_module_names(self, source_path):
457 return [ name for kind, name in self.read_dependency_file(source_path)
458 if kind == "cimport" ]
460 def is_package_dir(self, dir_path):
461 # Return true if the given directory is a package directory.
462 for filename in ("__init__.py",
465 path = os.path.join(dir_path, filename)
466 if Utils.path_exists(path):
469 def read_dependency_file(self, source_path):
470 dep_path = Utils.replace_suffix(source_path, ".dep")
471 if os.path.exists(dep_path):
472 f = open(dep_path, "rU")
473 chunks = [ line.strip().split(" ", 1)
474 for line in f.readlines()
475 if " " in line.strip() ]
481 def lookup_submodule(self, name):
482 # Look up a top-level module. Returns None if not found.
483 return self.modules.get(name, None)
485 def find_submodule(self, name):
486 # Find a top-level module, creating a new one if needed.
487 scope = self.lookup_submodule(name)
489 scope = ModuleScope(name,
490 parent_module = None, context = self)
491 self.modules[name] = scope
494 def parse(self, source_desc, scope, pxd, full_module_name):
495 if not isinstance(source_desc, FileSourceDescriptor):
496 raise RuntimeError("Only file sources for code supported")
497 source_filename = source_desc.filename
499 # Parse the given source file and return a parse tree.
501 f = Utils.open_source_file(source_filename, "rU")
504 s = PyrexScanner(f, source_desc, source_encoding = f.encoding,
505 scope = scope, context = self)
506 tree = Parsing.p_module(s, pxd, full_module_name)
509 except UnicodeDecodeError, msg:
511 #traceback.print_exc()
512 error((source_desc, 0, 0), "Decoding error, missing or incorrect coding=<encoding-name> at top of source (%s)" % msg)
513 if Errors.num_errors > 0:
517 def extract_module_name(self, path, options):
518 # Find fully_qualified module name from the full pathname
520 dir, filename = os.path.split(path)
521 module_name, _ = os.path.splitext(filename)
522 if "." in module_name:
524 if module_name == "__init__":
525 dir, module_name = os.path.split(dir)
526 names = [module_name]
527 while self.is_package_dir(dir):
528 parent, package_name = os.path.split(dir)
531 names.append(package_name)
534 return ".".join(names)
536 def setup_errors(self, options, result):
537 Errors.reset() # clear any remaining error state
538 if options.use_listing_file:
539 result.listing_file = Utils.replace_suffix(source, ".lis")
540 path = result.listing_file
543 Errors.open_listing_file(path=path,
544 echo_to_stderr=options.errors_to_stderr)
546 def teardown_errors(self, err, options, result):
547 source_desc = result.compilation_source.source_desc
548 if not isinstance(source_desc, FileSourceDescriptor):
549 raise RuntimeError("Only file sources for code supported")
550 Errors.close_listing_file()
551 result.num_errors = Errors.num_errors
552 if result.num_errors > 0:
554 if err and result.c_file:
556 Utils.castrate_file(result.c_file, os.stat(source_desc.filename))
557 except EnvironmentError:
561 def create_parse(context):
563 source_desc = compsrc.source_desc
564 full_module_name = compsrc.full_module_name
565 initial_pos = (source_desc, 1, 0)
566 scope = context.find_module(full_module_name, pos = initial_pos, need_pxd = 0)
567 tree = context.parse(source_desc, scope, pxd = 0, full_module_name = full_module_name)
568 tree.compilation_source = compsrc
574 def create_default_resultobj(compilation_source, options):
575 result = CompilationResult()
576 result.main_source_file = compilation_source.source_desc.filename
577 result.compilation_source = compilation_source
578 source_desc = compilation_source.source_desc
579 if options.output_file:
580 result.c_file = os.path.join(compilation_source.cwd, options.output_file)
586 result.c_file = Utils.replace_suffix(source_desc.filename, c_suffix)
589 def run_pipeline(source, options, full_module_name = None):
591 context = options.create_context()
593 # Set up source object
595 abs_path = os.path.abspath(source)
596 source_ext = os.path.splitext(source)[1]
597 full_module_name = full_module_name or context.extract_module_name(source, options)
598 if options.relative_path_in_code_position_comments:
599 rel_path = full_module_name.replace('.', os.sep) + source_ext
600 if not abs_path.endswith(rel_path):
601 rel_path = source # safety measure to prevent printing incorrect paths
604 source_desc = FileSourceDescriptor(abs_path, rel_path)
605 source = CompilationSource(source_desc, full_module_name, cwd)
607 # Set up result object
608 result = create_default_resultobj(source, options)
610 if options.annotate is None:
611 # By default, decide based on whether an html file already exists.
612 html_filename = os.path.splitext(result.c_file)[0] + ".html"
613 if os.path.exists(html_filename):
614 line = codecs.open(html_filename, "r", encoding="UTF-8").readline()
615 if line.startswith(u'<!-- Generated by Cython'):
616 options.annotate = True
619 if source_ext.lower() == '.py':
620 pipeline = context.create_py_pipeline(options, result)
622 pipeline = context.create_pyx_pipeline(options, result)
624 context.setup_errors(options, result)
625 err, enddata = context.run_pipeline(pipeline, source)
626 context.teardown_errors(err, options, result)
630 #------------------------------------------------------------------------
632 # Main Python entry points
634 #------------------------------------------------------------------------
636 class CompilationSource(object):
638 Contains the data necesarry to start up a compilation pipeline for
639 a single compilation unit.
641 def __init__(self, source_desc, full_module_name, cwd):
642 self.source_desc = source_desc
643 self.full_module_name = full_module_name
646 class CompilationOptions(object):
648 Options to the Cython compiler:
650 show_version boolean Display version number
651 use_listing_file boolean Generate a .lis file
652 errors_to_stderr boolean Echo errors to stderr when using .lis
653 include_path [string] Directories to search for include files
654 output_file string Name of generated .c file
655 generate_pxi boolean Generate .pxi file for public declarations
656 recursive boolean Recursively find and compile dependencies
657 timestamps boolean Only compile changed source files. If None,
658 defaults to true when recursive is true.
659 verbose boolean Always print source names being compiled
660 quiet boolean Don't print source names in recursive mode
661 compiler_directives dict Overrides for pragma options (see Options.py)
662 evaluate_tree_assertions boolean Test support: evaluate parse tree assertions
663 language_level integer The Python language level: 2 or 3
665 cplus boolean Compile as c++ code
668 def __init__(self, defaults = None, **kw):
669 self.include_path = []
671 if isinstance(defaults, CompilationOptions):
672 defaults = defaults.__dict__
674 defaults = default_options
675 self.__dict__.update(defaults)
676 self.__dict__.update(kw)
678 def create_context(self):
679 return Context(self.include_path, self.compiler_directives,
680 self.cplus, self.language_level)
683 class CompilationResult(object):
685 Results from the Cython compiler:
687 c_file string or None The generated C source file
688 h_file string or None The generated C header file
689 i_file string or None The generated .pxi file
690 api_file string or None The generated C API .h file
691 listing_file string or None File of error messages
692 object_file string or None Result of compiling the C file
693 extension_file string or None Result of linking the object file
694 num_errors integer Number of compilation errors
695 compilation_source CompilationSource
703 self.listing_file = None
704 self.object_file = None
705 self.extension_file = None
706 self.main_source_file = None
709 class CompilationResultSet(dict):
711 Results from compiling multiple Pyrex source files. A mapping
712 from source file paths to CompilationResult instances. Also
713 has the following attributes:
715 num_errors integer Total number of compilation errors
720 def add(self, source, result):
721 self[source] = result
722 self.num_errors += result.num_errors
725 def compile_single(source, options, full_module_name = None):
727 compile_single(source, options, full_module_name)
729 Compile the given Pyrex implementation file and return a CompilationResult.
730 Always compiles a single file; does not perform timestamp checking or
733 return run_pipeline(source, options, full_module_name)
736 def compile_multiple(sources, options):
738 compile_multiple(sources, options)
740 Compiles the given sequence of Pyrex implementation files and returns
741 a CompilationResultSet. Performs timestamp checking and/or recursion
742 if these are specified in the options.
744 context = options.create_context()
745 sources = [os.path.abspath(source) for source in sources]
747 results = CompilationResultSet()
748 recursive = options.recursive
749 timestamps = options.timestamps
750 if timestamps is None:
751 timestamps = recursive
752 verbose = options.verbose or ((recursive or timestamps) and not options.quiet)
753 for source in sources:
754 if source not in processed:
755 # Compiling multiple sources in one context doesn't quite
757 if not timestamps or context.c_file_out_of_date(source):
759 sys.stderr.write("Compiling %s\n" % source)
761 result = run_pipeline(source, options)
762 results.add(source, result)
763 processed.add(source)
765 for module_name in context.find_cimported_module_names(source):
766 path = context.find_pyx_file(module_name, [source])
771 "Cannot find .pyx file for cimported module '%s'\n" % module_name)
774 def compile(source, options = None, full_module_name = None, **kwds):
776 compile(source [, options], [, <option> = <value>]...)
778 Compile one or more Pyrex implementation files, with optional timestamp
779 checking and recursing on dependecies. The source argument may be a string
780 or a sequence of strings If it is a string and no recursion or timestamp
781 checking is requested, a CompilationResult is returned, otherwise a
782 CompilationResultSet is returned.
784 options = CompilationOptions(defaults = options, **kwds)
785 if isinstance(source, basestring) and not options.timestamps \
786 and not options.recursive:
787 return compile_single(source, options, full_module_name)
789 return compile_multiple(source, options)
791 #------------------------------------------------------------------------
793 # Main command-line entry point
795 #------------------------------------------------------------------------
796 def setuptools_main():
797 return main(command_line = 1)
799 def main(command_line = 0):
803 from CmdLine import parse_command_line
804 options, sources = parse_command_line(args)
806 options = CompilationOptions(default_options)
809 if options.show_version:
810 sys.stderr.write("Cython version %s\n" % Version.version)
811 if options.working_path!="":
812 os.chdir(options.working_path)
814 result = compile(sources, options)
815 if result.num_errors > 0:
817 except (EnvironmentError, PyrexError), e:
818 sys.stderr.write(str(e) + '\n')
825 #------------------------------------------------------------------------
827 # Set the default options depending on the platform
829 #------------------------------------------------------------------------
831 default_options = dict(
833 use_listing_file = 0,
834 errors_to_stderr = 1,
844 compiler_directives = {},
845 evaluate_tree_assertions = False,
846 emit_linenums = False,
847 relative_path_in_code_position_comments = True,
848 c_line_in_traceback = True,