From: Robert Bradshaw Date: Sat, 7 Jun 2008 00:46:37 +0000 (-0700) Subject: Merge -dagss and -devel X-Git-Tag: 0.9.8rc1~11^2~10^2~6 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=3e0a3b71c31a3dee3229742f19f9c560688d7114;p=cython.git Merge -dagss and -devel --- 3e0a3b71c31a3dee3229742f19f9c560688d7114 diff --cc Cython/Compiler/Main.py index 5d454087,c2348fce..d3084575 --- a/Cython/Compiler/Main.py +++ b/Cython/Compiler/Main.py @@@ -14,31 -14,15 +14,30 @@@ except NameError from sets import Set as set from time import time + import Code + import Errors + import Parsing import Version +from Scanning import PyrexScanner, FileSourceDescriptor - import Errors from Errors import PyrexError, CompileError, error - import Parsing -from Scanning import PyrexScanner from Symtab import BuiltinScope, ModuleScope - import Code - from Cython.Utils import replace_suffix from Cython import Utils -import Transform + +# Note: PHASES and TransformSet should be removed soon; but that's for +# another day and another commit. +PHASES = [ + 'before_analyse_function', # run in FuncDefNode.generate_function_definitions + 'after_analyse_function' # run in FuncDefNode.generate_function_definitions +] + +class TransformSet(dict): + def __init__(self): + for name in PHASES: + self[name] = [] + def run(self, name, node, **options): + assert name in self, "Transform phase %s not defined" % name + for transform in self[name]: + transform(node, phase=name, **options) verbose = 0 @@@ -140,17 -126,90 +142,93 @@@ class Context # None if not found, but does not report an error. dirs = self.include_directories if pos: - here_dir = os.path.dirname(pos[0]) + file_desc = pos[0] + if not isinstance(file_desc, FileSourceDescriptor): + raise RuntimeError("Only file sources for code supported") + here_dir = os.path.dirname(file_desc.filename) dirs = [here_dir] + dirs + + dotted_filename = qualified_name + suffix + if split_package: + names = qualified_name.split('.') + package_names = names[:-1] + module_name = names[-1] + module_filename = module_name + suffix + package_filename = "__init__" + suffix + for dir in dirs: - path = os.path.join(dir, filename) + path = os.path.join(dir, dotted_filename) if os.path.exists(path): return path + if split_package: + package_dir = self.check_package_dir(dir, package_names) + if package_dir is not None: + path = os.path.join(package_dir, module_filename) + if os.path.exists(path): + return path + path = os.path.join(dir, package_dir, module_name, + package_filename) + if os.path.exists(path): + return path return None + def check_package_dir(self, dir, package_names): + package_dir = os.path.join(dir, *package_names) + if not os.path.exists(package_dir): + return None + for dirname in package_names: + dir = os.path.join(dir, dirname) + package_init = os.path.join(dir, "__init__.py") + if not os.path.exists(package_init) and \ + not os.path.exists(package_init + "x"): # same with .pyx ? + return None + return package_dir + + def c_file_out_of_date(self, source_path): + c_path = Utils.replace_suffix(source_path, ".c") + if not os.path.exists(c_path): + return 1 + c_time = Utils.modification_time(c_path) + if Utils.file_newer_than(source_path, c_time): + return 1 + pos = [source_path] + pxd_path = Utils.replace_suffix(source_path, ".pxd") + if os.path.exists(pxd_path) and Utils.file_newer_than(pxd_path, c_time): + return 1 + for kind, name in self.read_dependency_file(source_path): + if kind == "cimport": + dep_path = self.find_pxd_file(name, pos) + elif kind == "include": + dep_path = self.search_include_directories(name, pos) + else: + continue + if dep_path and Utils.file_newer_than(dep_path, c_time): + return 1 + return 0 + + def find_cimported_module_names(self, source_path): + return [ name for kind, name in self.read_dependency_file(source_path) + if kind == "cimport" ] + + def is_package_dir(self, dir_path): + # Return true if the given directory is a package directory. + for filename in ("__init__.py", "__init__.pyx"): + path = os.path.join(dir_path, filename) + if os.path.exists(path): + return 1 + + def read_dependency_file(self, source_path): + dep_path = replace_suffix(source_path, ".dep") + if os.path.exists(dep_path): + f = open(dep_path, "rU") + chunks = [ line.strip().split(" ", 1) + for line in f.readlines() + if " " in line.strip() ] + f.close() + return chunks + else: + return () + def lookup_submodule(self, name): # Look up a top-level module. Returns None if not found. return self.modules.get(name, None) @@@ -218,20 -283,14 +304,21 @@@ c_suffix = ".cpp" else: c_suffix = ".c" - result.c_file = replace_suffix(source, c_suffix) - result.c_file = Utils.replace_suffix(source, c_suffix) ++ result.c_file = Utils .replace_suffix(source, c_suffix) + c_stat = None + if result.c_file: + try: + c_stat = os.stat(result.c_file) + except EnvironmentError: + pass - module_name = full_module_name # self.extract_module_name(source, options) + module_name = full_module_name or self.extract_module_name(source, options) + source = FileSourceDescriptor(source) initial_pos = (source, 1, 0) scope = self.find_module(module_name, pos = initial_pos, need_pxd = 0) errors_occurred = False try: - tree = self.parse(source, scope.type_names, pxd = 0, full_module_name = full_module_name) - tree = self.parse(source, scope, pxd = 0, ++ tree = self.parse(source, scope.type_names, pxd = 0, + full_module_name = full_module_name) tree.process_implementation(scope, options, result) except CompileError: errors_occurred = True @@@ -387,9 -516,13 +546,12 @@@ default_options = dict output_file = None, annotate = False, generate_pxi = 0, + transforms = TransformSet(), - working_path = "") - ++ working_path = "", + recursive = 0, + timestamps = None, + verbose = 0, - quiet = 0, - transforms = Transform.TransformSet(), - working_path = "") - ++ quiet = 0) if sys.platform == "mac": from Cython.Mac.MacSystem import c_compile, c_link, CCompilerError default_options['use_listing_file'] = 1 diff --cc Cython/Compiler/Nodes.py index c280caa5,1e5479fd..829c4ffb --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@@ -82,19 -106,58 +82,28 @@@ class Node(object) def __init__(self, pos, **kw): self.pos = pos self.__dict__.update(kw) - + + gil_message = "Operation" + + def gil_check(self, env): + if env.nogil: + self.gil_error() + + def gil_error(self): + error(self.pos, "%s not allowed without gil" % self.gil_message) + - def get_child_accessors(self): - """Returns an iterator over the children of the Node. Each member in the - iterated list is an object with get(), set(value), and name() methods, - which can be used to fetch and replace the child and query the name - the relation this node has with the child. For instance, for an - assignment node, this code: - - for child in assignment_node.get_child_accessors(): - print(child.name()) - child.set(i_node) - - will print "lhs", "rhs", and change the assignment statement to "i = i" - (assuming that i_node is a node able to represent the variable i in the - tree). - - Any kind of objects can in principle be returned, but the typical - candidates are either Node instances or lists of node instances. - - The object returned in each iteration stage can only be used until the - iterator is advanced to the next child attribute. (However, the objects - returned by the get() function can be kept). - - Typically, a Node instance will have other interesting and potentially - hierarchical attributes as well. These must be explicitly accessed -- this - method only provides access to attributes that are deemed to naturally - belong in the parse tree. - - Descandant classes can either specify child_attrs, override get_child_attrs, - or override this method directly in order to provide access to their - children. All descendants of Node *must* declare their children -- leaf nodes - should simply declare "child_attrs = []". - """ - attrnames = self.get_child_attrs() - if attrnames is None: - raise InternalError("Children access not implemented for %s" % \ - self.__class__.__name__) - return _AttributeIterator(self, attrnames) - - def get_child_attrs(self): - """Utility method for more easily implementing get_child_accessors. - If you override get_child_accessors then this method is not used.""" - return self.child_attrs + def clone_node(self): + """Clone the node. This is defined as a shallow copy, except for member lists + amongst the child attributes (from get_child_accessors) which are also + copied. Lists containing child nodes are thus seen as a way for the node + to hold multiple children directly; the list is not treated as a seperate + level in the tree.""" + result = copy.copy(self) + for attrname in result.child_attrs: + value = getattr(result, attrname) + if isinstance(value, list): + setattr(result, attrname, value) + return result # diff --cc Cython/Compiler/Parsing.py index 7bdfa4d2,74c670e8..32ecde7d --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@@ -3,9 -3,8 +3,8 @@@ # import os, re - from string import join, replace from types import ListType, TupleType -from Scanning import PyrexScanner +from Scanning import PyrexScanner, FileSourceDescriptor import Nodes import ExprNodes from ModuleNode import ModuleNode @@@ -1204,11 -1220,12 +1220,12 @@@ def p_include_statement(s, ctx) if s.compile_time_eval: include_file_path = s.context.find_include_file(include_file_name, pos) if include_file_path: + s.included_files.append(include_file_name) f = Utils.open_source_file(include_file_path, mode="rU") - s2 = PyrexScanner(f, include_file_path, parent_scanner = s, - source_encoding=f.encoding) + source_desc = FileSourceDescriptor(include_file_path) + s2 = PyrexScanner(f, source_desc, s, source_encoding=f.encoding) try: - tree = p_statement_list(s2, level) + tree = p_statement_list(s2, ctx) finally: f.close() return tree diff --cc Cython/Compiler/Scanning.py index 4ba1718c,39b89433..2e20d18a --- a/Cython/Compiler/Scanning.py +++ b/Cython/Compiler/Scanning.py @@@ -287,8 -213,7 +287,7 @@@ class PyrexScanner(Scanner) resword_dict = build_resword_dict() def __init__(self, file, filename, parent_scanner = None, - type_names = None, context = None, source_encoding=None): - scope = None, context = None, source_encoding=None): ++ type_names = None, context = None, source_encoding=None): Scanner.__init__(self, get_lexicon(), file, filename) if parent_scanner: self.context = parent_scanner.context diff --cc tests/run/big_indices.pyx index d8f3a765,0bf13916..7a787912 --- a/tests/run/big_indices.pyx +++ b/tests/run/big_indices.pyx @@@ -1,7 -1,7 +1,7 @@@ __doc__ = u""" >>> test() -- neg -1 -- pos 4294967294 ++ neg False ++ pos True neg pos neg @@@ -12,10 -12,10 +12,10 @@@ def test() cdef long neg = -1 cdef unsigned long pos = -2 # will be a large positive number - print "neg", neg - print "pos", pos - print u"neg", neg - print u"pos", pos ++ print "neg", neg > 0 ++ print "pos", pos > - - D = { neg: u'neg', pos: u'pos' } + D = { neg: 'neg', pos: 'pos' } print D[neg] print D[pos]