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 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(),
142 DecoratorTransform(self),
143 AnalyseDeclarationsTransform(self),
144 AutoTestDictTransform(self),
145 EmbedSignature(self),
146 EarlyReplaceBuiltinCalls(self), ## Necessary?
147 MarkAssignments(self),
148 MarkOverflowingArithmetic(self),
149 TransformBuiltinMethods(self), ## Necessary?
150 IntroduceBufferAuxiliaryVars(self),
151 _check_c_declarations,
152 AnalyseExpressionsTransform(self),
153 CreateClosureClasses(self), ## After all lookups and type inference
154 ExpandInplaceOperators(self),
155 OptimizeBuiltinCalls(self), ## Necessary?
156 IterationTransform(),
158 DropRefcountingTransform(),
159 FinalOptimizePhase(self),
163 def create_pyx_pipeline(self, options, result, py=False):
164 def generate_pyx_code(module_node):
165 module_node.process_implementation(options, result)
166 result.compilation_source = module_node.compilation_source
169 def inject_pxd_code(module_node):
170 from textwrap import dedent
171 stats = module_node.body.stats
172 for name, (statlistnode, scope) in self.pxds.iteritems():
173 # Copy over function nodes to the module
174 # (this seems strange -- I believe the right concept is to split
175 # ModuleNode into a ModuleNode and a CodeGenerator, and tell that
176 # CodeGenerator to generate code both from the pyx and pxd ModuleNodes.
177 stats.append(statlistnode)
178 # Until utility code is moved to code generation phase everywhere,
179 # we need to copy it over to the main scope
180 module_node.scope.utility_code_list.extend(scope.utility_code_list)
184 if options.evaluate_tree_assertions:
185 from Cython.TestUtils import TreeAssertVisitor
186 test_support.append(TreeAssertVisitor())
188 if options.gdb_debug:
189 from Cython.Debugger import DebugWriter
190 from ParseTreeTransforms import DebugTransform
191 self.gdb_debug_outputwriter = DebugWriter.CythonDebugWriter(
193 debug_transform = [DebugTransform(self, options, result)]
197 return list(itertools.chain(
198 [create_parse(self)],
199 self.create_pipeline(pxd=False, py=py),
201 [inject_pxd_code, abort_on_errors],
203 [generate_pyx_code]))
205 def create_pxd_pipeline(self, scope, module_name):
206 def parse_pxd(source_desc):
207 tree = self.parse(source_desc, scope, pxd=True,
208 full_module_name=module_name)
213 from CodeGeneration import ExtractPxdCode
215 # The pxd pipeline ends up with a CCodeWriter containing the
216 # code of the pxd, as well as a pxd scope.
217 return [parse_pxd] + self.create_pipeline(pxd=True) + [
218 ExtractPxdCode(self),
221 def create_py_pipeline(self, options, result):
222 return self.create_pyx_pipeline(options, result, py=True)
225 def process_pxd(self, source_desc, scope, module_name):
226 pipeline = self.create_pxd_pipeline(scope, module_name)
227 result = self.run_pipeline(pipeline, source_desc)
230 def nonfatal_error(self, exc):
231 return Errors.report_error(exc)
233 def run_pipeline(self, pipeline, source):
238 for phase in pipeline:
239 if phase is not None:
240 if DebugFlags.debug_verbose_pipeline:
242 print "Entering pipeline phase %r" % phase
244 if DebugFlags.debug_verbose_pipeline:
245 print " %.3f seconds" % (time() - t)
246 except CompileError, err:
248 Errors.report_error(err)
250 except InternalError, err:
251 # Only raise if there was not an earlier error
252 if Errors.num_errors == 0:
255 except AbortError, err:
259 def find_module(self, module_name,
260 relative_to = None, pos = None, need_pxd = 1):
261 # Finds and returns the module scope corresponding to
262 # the given relative or absolute module name. If this
263 # is the first time the module has been requested, finds
264 # the corresponding .pxd file and process it.
265 # If relative_to is not None, it must be a module scope,
266 # and the module will first be searched for relative to
267 # that module, provided its name is not a dotted name.
268 debug_find_module = 0
269 if debug_find_module:
270 print("Context.find_module: module_name = %s, relative_to = %s, pos = %s, need_pxd = %s" % (
271 module_name, relative_to, pos, need_pxd))
275 if not module_name_pattern.match(module_name):
277 pos = (module_name, 0, 0)
278 raise CompileError(pos,
279 "'%s' is not a valid module name" % module_name)
280 if "." not in module_name and relative_to:
281 if debug_find_module:
282 print("...trying relative import")
283 scope = relative_to.lookup_submodule(module_name)
285 qualified_name = relative_to.qualify_name(module_name)
286 pxd_pathname = self.find_pxd_file(qualified_name, pos)
288 scope = relative_to.find_submodule(module_name)
290 if debug_find_module:
291 print("...trying absolute import")
293 for name in module_name.split("."):
294 scope = scope.find_submodule(name)
295 if debug_find_module:
296 print("...scope =", scope)
297 if not scope.pxd_file_loaded:
298 if debug_find_module:
299 print("...pxd not loaded")
300 scope.pxd_file_loaded = 1
302 if debug_find_module:
303 print("...looking for pxd file")
304 pxd_pathname = self.find_pxd_file(module_name, pos)
305 if debug_find_module:
306 print("......found ", pxd_pathname)
307 if not pxd_pathname and need_pxd:
308 package_pathname = self.search_include_directories(module_name, ".py", pos)
309 if package_pathname and package_pathname.endswith('__init__.py'):
312 error(pos, "'%s.pxd' not found" % module_name)
315 if debug_find_module:
316 print("Context.find_module: Parsing %s" % pxd_pathname)
317 rel_path = module_name.replace('.', os.sep) + os.path.splitext(pxd_pathname)[1]
318 if not pxd_pathname.endswith(rel_path):
319 rel_path = pxd_pathname # safety measure to prevent printing incorrect paths
320 source_desc = FileSourceDescriptor(pxd_pathname, rel_path)
321 err, result = self.process_pxd(source_desc, scope, module_name)
324 (pxd_codenodes, pxd_scope) = result
325 self.pxds[module_name] = (pxd_codenodes, pxd_scope)
330 def find_pxd_file(self, qualified_name, pos):
331 # Search include path for the .pxd file corresponding to the
332 # given fully-qualified module name.
333 # Will find either a dotted filename or a file in a
334 # package directory. If a source file position is given,
335 # the directory containing the source file is searched first
336 # for a dotted filename, and its containing package root
337 # directory is searched first for a non-dotted filename.
338 pxd = self.search_include_directories(qualified_name, ".pxd", pos)
339 if pxd is None: # XXX Keep this until Includes/Deprecated is removed
340 if (qualified_name.startswith('python') or
341 qualified_name in ('stdlib', 'stdio', 'stl')):
342 standard_include_path = os.path.abspath(os.path.normpath(
343 os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes')))
344 deprecated_include_path = os.path.join(standard_include_path, 'Deprecated')
345 self.include_directories.append(deprecated_include_path)
347 pxd = self.search_include_directories(qualified_name, ".pxd", pos)
349 self.include_directories.pop()
351 name = qualified_name
352 if name.startswith('python'):
353 warning(pos, "'%s' is deprecated, use 'cpython'" % name, 1)
354 elif name in ('stdlib', 'stdio'):
355 warning(pos, "'%s' is deprecated, use 'libc.%s'" % (name, name), 1)
356 elif name in ('stl'):
357 warning(pos, "'%s' is deprecated, use 'libcpp.*.*'" % name, 1)
360 def find_pyx_file(self, qualified_name, pos):
361 # Search include path for the .pyx file corresponding to the
362 # given fully-qualified module name, as for find_pxd_file().
363 return self.search_include_directories(qualified_name, ".pyx", pos)
365 def find_include_file(self, filename, pos):
366 # Search list of include directories for filename.
367 # Reports an error and returns None if not found.
368 path = self.search_include_directories(filename, "", pos,
371 error(pos, "'%s' not found" % filename)
374 def search_include_directories(self, qualified_name, suffix, pos,
376 # Search the list of include directories for the given
377 # file name. If a source file position is given, first
378 # searches the directory containing that file. Returns
379 # None if not found, but does not report an error.
380 # The 'include' option will disable package dereferencing.
381 dirs = self.include_directories
384 if not isinstance(file_desc, FileSourceDescriptor):
385 raise RuntimeError("Only file sources for code supported")
387 dirs = [os.path.dirname(file_desc.filename)] + dirs
389 dirs = [self.find_root_package_dir(file_desc.filename)] + dirs
391 dotted_filename = qualified_name
393 dotted_filename += suffix
395 names = qualified_name.split('.')
396 package_names = names[:-1]
397 module_name = names[-1]
398 module_filename = module_name + suffix
399 package_filename = "__init__" + suffix
402 path = os.path.join(dir, dotted_filename)
403 if Utils.path_exists(path):
406 package_dir = self.check_package_dir(dir, package_names)
407 if package_dir is not None:
408 path = os.path.join(package_dir, module_filename)
409 if Utils.path_exists(path):
411 path = os.path.join(dir, package_dir, module_name,
413 if Utils.path_exists(path):
417 def find_root_package_dir(self, file_path):
418 dir = os.path.dirname(file_path)
419 while self.is_package_dir(dir):
420 parent = os.path.dirname(dir)
426 def check_package_dir(self, dir, package_names):
427 for dirname in package_names:
428 dir = os.path.join(dir, dirname)
429 if not self.is_package_dir(dir):
433 def c_file_out_of_date(self, source_path):
434 c_path = Utils.replace_suffix(source_path, ".c")
435 if not os.path.exists(c_path):
437 c_time = Utils.modification_time(c_path)
438 if Utils.file_newer_than(source_path, c_time):
441 pxd_path = Utils.replace_suffix(source_path, ".pxd")
442 if os.path.exists(pxd_path) and Utils.file_newer_than(pxd_path, c_time):
444 for kind, name in self.read_dependency_file(source_path):
445 if kind == "cimport":
446 dep_path = self.find_pxd_file(name, pos)
447 elif kind == "include":
448 dep_path = self.search_include_directories(name, pos)
451 if dep_path and Utils.file_newer_than(dep_path, c_time):
455 def find_cimported_module_names(self, source_path):
456 return [ name for kind, name in self.read_dependency_file(source_path)
457 if kind == "cimport" ]
459 def is_package_dir(self, dir_path):
460 # Return true if the given directory is a package directory.
461 for filename in ("__init__.py",
464 path = os.path.join(dir_path, filename)
465 if Utils.path_exists(path):
468 def read_dependency_file(self, source_path):
469 dep_path = Utils.replace_suffix(source_path, ".dep")
470 if os.path.exists(dep_path):
471 f = open(dep_path, "rU")
472 chunks = [ line.strip().split(" ", 1)
473 for line in f.readlines()
474 if " " in line.strip() ]
480 def lookup_submodule(self, name):
481 # Look up a top-level module. Returns None if not found.
482 return self.modules.get(name, None)
484 def find_submodule(self, name):
485 # Find a top-level module, creating a new one if needed.
486 scope = self.lookup_submodule(name)
488 scope = ModuleScope(name,
489 parent_module = None, context = self)
490 self.modules[name] = scope
493 def parse(self, source_desc, scope, pxd, full_module_name):
494 if not isinstance(source_desc, FileSourceDescriptor):
495 raise RuntimeError("Only file sources for code supported")
496 source_filename = source_desc.filename
498 # Parse the given source file and return a parse tree.
500 f = Utils.open_source_file(source_filename, "rU")
503 s = PyrexScanner(f, source_desc, source_encoding = f.encoding,
504 scope = scope, context = self)
505 tree = Parsing.p_module(s, pxd, full_module_name)
508 except UnicodeDecodeError, msg:
510 #traceback.print_exc()
511 error((source_desc, 0, 0), "Decoding error, missing or incorrect coding=<encoding-name> at top of source (%s)" % msg)
512 if Errors.num_errors > 0:
516 def extract_module_name(self, path, options):
517 # Find fully_qualified module name from the full pathname
519 dir, filename = os.path.split(path)
520 module_name, _ = os.path.splitext(filename)
521 if "." in module_name:
523 if module_name == "__init__":
524 dir, module_name = os.path.split(dir)
525 names = [module_name]
526 while self.is_package_dir(dir):
527 parent, package_name = os.path.split(dir)
530 names.append(package_name)
533 return ".".join(names)
535 def setup_errors(self, options, result):
536 Errors.reset() # clear any remaining error state
537 if options.use_listing_file:
538 result.listing_file = Utils.replace_suffix(source, ".lis")
539 path = result.listing_file
542 Errors.open_listing_file(path=path,
543 echo_to_stderr=options.errors_to_stderr)
545 def teardown_errors(self, err, options, result):
546 source_desc = result.compilation_source.source_desc
547 if not isinstance(source_desc, FileSourceDescriptor):
548 raise RuntimeError("Only file sources for code supported")
549 Errors.close_listing_file()
550 result.num_errors = Errors.num_errors
551 if result.num_errors > 0:
553 if err and result.c_file:
555 Utils.castrate_file(result.c_file, os.stat(source_desc.filename))
556 except EnvironmentError:
560 def create_parse(context):
562 source_desc = compsrc.source_desc
563 full_module_name = compsrc.full_module_name
564 initial_pos = (source_desc, 1, 0)
565 scope = context.find_module(full_module_name, pos = initial_pos, need_pxd = 0)
566 tree = context.parse(source_desc, scope, pxd = 0, full_module_name = full_module_name)
567 tree.compilation_source = compsrc
573 def create_default_resultobj(compilation_source, options):
574 result = CompilationResult()
575 result.main_source_file = compilation_source.source_desc.filename
576 result.compilation_source = compilation_source
577 source_desc = compilation_source.source_desc
578 if options.output_file:
579 result.c_file = os.path.join(compilation_source.cwd, options.output_file)
585 result.c_file = Utils.replace_suffix(source_desc.filename, c_suffix)
588 def run_pipeline(source, options, full_module_name = None):
590 context = options.create_context()
592 # Set up source object
594 abs_path = os.path.abspath(source)
595 source_ext = os.path.splitext(source)[1]
596 full_module_name = full_module_name or context.extract_module_name(source, options)
597 if options.relative_path_in_code_position_comments:
598 rel_path = full_module_name.replace('.', os.sep) + source_ext
599 if not abs_path.endswith(rel_path):
600 rel_path = source # safety measure to prevent printing incorrect paths
603 source_desc = FileSourceDescriptor(abs_path, rel_path)
604 source = CompilationSource(source_desc, full_module_name, cwd)
606 # Set up result object
607 result = create_default_resultobj(source, options)
609 if options.annotate is None:
610 # By default, decide based on whether an html file already exists.
611 html_filename = os.path.splitext(result.c_file)[0] + ".html"
612 if os.path.exists(html_filename):
613 line = codecs.open(html_filename, "r", encoding="UTF-8").readline()
614 if line.startswith(u'<!-- Generated by Cython'):
615 options.annotate = True
618 if source_ext.lower() == '.py':
619 pipeline = context.create_py_pipeline(options, result)
621 pipeline = context.create_pyx_pipeline(options, result)
623 context.setup_errors(options, result)
624 err, enddata = context.run_pipeline(pipeline, source)
625 context.teardown_errors(err, options, result)
629 #------------------------------------------------------------------------
631 # Main Python entry points
633 #------------------------------------------------------------------------
635 class CompilationSource(object):
637 Contains the data necesarry to start up a compilation pipeline for
638 a single compilation unit.
640 def __init__(self, source_desc, full_module_name, cwd):
641 self.source_desc = source_desc
642 self.full_module_name = full_module_name
645 class CompilationOptions(object):
647 Options to the Cython compiler:
649 show_version boolean Display version number
650 use_listing_file boolean Generate a .lis file
651 errors_to_stderr boolean Echo errors to stderr when using .lis
652 include_path [string] Directories to search for include files
653 output_file string Name of generated .c file
654 generate_pxi boolean Generate .pxi file for public declarations
655 recursive boolean Recursively find and compile dependencies
656 timestamps boolean Only compile changed source files. If None,
657 defaults to true when recursive is true.
658 verbose boolean Always print source names being compiled
659 quiet boolean Don't print source names in recursive mode
660 compiler_directives dict Overrides for pragma options (see Options.py)
661 evaluate_tree_assertions boolean Test support: evaluate parse tree assertions
662 language_level integer The Python language level: 2 or 3
664 cplus boolean Compile as c++ code
667 def __init__(self, defaults = None, **kw):
668 self.include_path = []
670 if isinstance(defaults, CompilationOptions):
671 defaults = defaults.__dict__
673 defaults = default_options
674 self.__dict__.update(defaults)
675 self.__dict__.update(kw)
677 def create_context(self):
678 return Context(self.include_path, self.compiler_directives,
679 self.cplus, self.language_level)
682 class CompilationResult(object):
684 Results from the Cython compiler:
686 c_file string or None The generated C source file
687 h_file string or None The generated C header file
688 i_file string or None The generated .pxi file
689 api_file string or None The generated C API .h file
690 listing_file string or None File of error messages
691 object_file string or None Result of compiling the C file
692 extension_file string or None Result of linking the object file
693 num_errors integer Number of compilation errors
694 compilation_source CompilationSource
702 self.listing_file = None
703 self.object_file = None
704 self.extension_file = None
705 self.main_source_file = None
708 class CompilationResultSet(dict):
710 Results from compiling multiple Pyrex source files. A mapping
711 from source file paths to CompilationResult instances. Also
712 has the following attributes:
714 num_errors integer Total number of compilation errors
719 def add(self, source, result):
720 self[source] = result
721 self.num_errors += result.num_errors
724 def compile_single(source, options, full_module_name = None):
726 compile_single(source, options, full_module_name)
728 Compile the given Pyrex implementation file and return a CompilationResult.
729 Always compiles a single file; does not perform timestamp checking or
732 return run_pipeline(source, options, full_module_name)
735 def compile_multiple(sources, options):
737 compile_multiple(sources, options)
739 Compiles the given sequence of Pyrex implementation files and returns
740 a CompilationResultSet. Performs timestamp checking and/or recursion
741 if these are specified in the options.
743 context = options.create_context()
744 sources = [os.path.abspath(source) for source in sources]
746 results = CompilationResultSet()
747 recursive = options.recursive
748 timestamps = options.timestamps
749 if timestamps is None:
750 timestamps = recursive
751 verbose = options.verbose or ((recursive or timestamps) and not options.quiet)
752 for source in sources:
753 if source not in processed:
754 # Compiling multiple sources in one context doesn't quite
756 if not timestamps or context.c_file_out_of_date(source):
758 sys.stderr.write("Compiling %s\n" % source)
760 result = run_pipeline(source, options)
761 results.add(source, result)
762 processed.add(source)
764 for module_name in context.find_cimported_module_names(source):
765 path = context.find_pyx_file(module_name, [source])
770 "Cannot find .pyx file for cimported module '%s'\n" % module_name)
773 def compile(source, options = None, full_module_name = None, **kwds):
775 compile(source [, options], [, <option> = <value>]...)
777 Compile one or more Pyrex implementation files, with optional timestamp
778 checking and recursing on dependecies. The source argument may be a string
779 or a sequence of strings If it is a string and no recursion or timestamp
780 checking is requested, a CompilationResult is returned, otherwise a
781 CompilationResultSet is returned.
783 options = CompilationOptions(defaults = options, **kwds)
784 if isinstance(source, basestring) and not options.timestamps \
785 and not options.recursive:
786 return compile_single(source, options, full_module_name)
788 return compile_multiple(source, options)
790 #------------------------------------------------------------------------
792 # Main command-line entry point
794 #------------------------------------------------------------------------
795 def setuptools_main():
796 return main(command_line = 1)
798 def main(command_line = 0):
802 from CmdLine import parse_command_line
803 options, sources = parse_command_line(args)
805 options = CompilationOptions(default_options)
808 if options.show_version:
809 sys.stderr.write("Cython version %s\n" % Version.version)
810 if options.working_path!="":
811 os.chdir(options.working_path)
813 result = compile(sources, options)
814 if result.num_errors > 0:
816 except (EnvironmentError, PyrexError), e:
817 sys.stderr.write(str(e) + '\n')
824 #------------------------------------------------------------------------
826 # Set the default options depending on the platform
828 #------------------------------------------------------------------------
830 default_options = dict(
832 use_listing_file = 0,
833 errors_to_stderr = 1,
843 compiler_directives = {},
844 evaluate_tree_assertions = False,
845 emit_linenums = False,
846 relative_path_in_code_position_comments = True,
847 c_line_in_traceback = True,