Commit 8193f74a authored by Mark Florisson's avatar Mark Florisson
parents 76567d05 43a3dbea
...@@ -38,3 +38,4 @@ ef9d2c680684d0df7d81f529cda29e9e1741f575 cython-0.10.1 ...@@ -38,3 +38,4 @@ ef9d2c680684d0df7d81f529cda29e9e1741f575 cython-0.10.1
7fa84cb6d3d75eb3d015aeeb60bf8b642171fe93 0.14.beta2 7fa84cb6d3d75eb3d015aeeb60bf8b642171fe93 0.14.beta2
8412b39fbc3eb709a543e2f1e95c0c8881ea9ed4 0.14.beta2 8412b39fbc3eb709a543e2f1e95c0c8881ea9ed4 0.14.beta2
a6b9f0a6d02d23fc3d3a9d0587867faa3afb2fcd 0.14.rc0 a6b9f0a6d02d23fc3d3a9d0587867faa3afb2fcd 0.14.rc0
15bf34c9387444e262acb1de594405444dd571a4 0.14
...@@ -220,7 +220,11 @@ def parse_dependencies(source_filename): ...@@ -220,7 +220,11 @@ def parse_dependencies(source_filename):
# Actual parsing is way to slow, so we use regular expressions. # Actual parsing is way to slow, so we use regular expressions.
# The only catch is that we must strip comments and string # The only catch is that we must strip comments and string
# literals ahead of time. # literals ahead of time.
source = Utils.open_source_file(source_filename, "rU").read() fh = Utils.open_source_file(source_filename, "rU")
try:
source = fh.read()
finally:
fh.close()
distutils_info = DistutilsInfo(source) distutils_info = DistutilsInfo(source)
source, literals = strip_string_literals(source) source, literals = strip_string_literals(source)
source = source.replace('\\\n', ' ') source = source.replace('\\\n', ' ')
......
...@@ -52,9 +52,12 @@ def unbound_symbols(code, context=None): ...@@ -52,9 +52,12 @@ def unbound_symbols(code, context=None):
symbol_collector = AllSymbols() symbol_collector = AllSymbols()
symbol_collector(tree) symbol_collector(tree)
unbound = [] unbound = []
import __builtin__ try:
import builtins
except ImportError:
import __builtin__ as builtins
for name in symbol_collector.names: for name in symbol_collector.names:
if not tree.scope.lookup(name) and not hasattr(__builtin__, name): if not tree.scope.lookup(name) and not hasattr(builtins, name):
unbound.append(name) unbound.append(name)
return unbound return unbound
...@@ -79,7 +82,7 @@ def safe_type(arg, context=None): ...@@ -79,7 +82,7 @@ def safe_type(arg, context=None):
return 'numpy.ndarray[numpy.%s_t, ndim=%s]' % (arg.dtype.name, arg.ndim) return 'numpy.ndarray[numpy.%s_t, ndim=%s]' % (arg.dtype.name, arg.ndim)
else: else:
for base_type in py_type.mro(): for base_type in py_type.mro():
if base_type.__module__ == '__builtin__': if base_type.__module__ in ('__builtin__', 'builtins'):
return 'object' return 'object'
module = context.find_module(base_type.__module__, need_pxd=False) module = context.find_module(base_type.__module__, need_pxd=False)
if module: if module:
...@@ -125,7 +128,7 @@ def cython_inline(code, ...@@ -125,7 +128,7 @@ def cython_inline(code,
arg_names.sort() arg_names.sort()
arg_sigs = tuple([(get_type(kwds[arg], ctx), arg) for arg in arg_names]) arg_sigs = tuple([(get_type(kwds[arg], ctx), arg) for arg in arg_names])
key = code, arg_sigs, sys.version_info, sys.executable, Cython.__version__ key = code, arg_sigs, sys.version_info, sys.executable, Cython.__version__
module_name = "_cython_inline_" + hashlib.md5(str(key)).hexdigest() module_name = "_cython_inline_" + hashlib.md5(str(key).encode('utf-8')).hexdigest()
try: try:
if not os.path.exists(lib_dir): if not os.path.exists(lib_dir):
os.makedirs(lib_dir) os.makedirs(lib_dir)
...@@ -160,7 +163,11 @@ def __invoke(%(params)s): ...@@ -160,7 +163,11 @@ def __invoke(%(params)s):
for key, value in literals.items(): for key, value in literals.items():
module_code = module_code.replace(key, value) module_code = module_code.replace(key, value)
pyx_file = os.path.join(lib_dir, module_name + '.pyx') pyx_file = os.path.join(lib_dir, module_name + '.pyx')
open(pyx_file, 'w').write(module_code) fh = open(pyx_file, 'w')
try:
fh.write(module_code)
finally:
fh.close()
extension = Extension( extension = Extension(
name = module_name, name = module_name,
sources = [pyx_file], sources = [pyx_file],
......
...@@ -44,7 +44,7 @@ class AnnotationCCodeWriter(CCodeWriter): ...@@ -44,7 +44,7 @@ class AnnotationCCodeWriter(CCodeWriter):
if pos is not None: if pos is not None:
CCodeWriter.mark_pos(self, pos) CCodeWriter.mark_pos(self, pos)
if self.last_pos: if self.last_pos:
pos_code = self.code.setdefault(self.last_pos[0].get_description(),{}) pos_code = self.code.setdefault(self.last_pos[0].filename,{})
code = pos_code.get(self.last_pos[1], "") code = pos_code.get(self.last_pos[1], "")
pos_code[self.last_pos[1]] = code + self.annotation_buffer.getvalue() pos_code[self.last_pos[1]] = code + self.annotation_buffer.getvalue()
self.annotation_buffer = StringIO() self.annotation_buffer = StringIO()
......
...@@ -10,15 +10,15 @@ usage = """\ ...@@ -10,15 +10,15 @@ usage = """\
Cython (http://cython.org) is a compiler for code written in the Cython (http://cython.org) is a compiler for code written in the
Cython language. Cython is based on Pyrex by Greg Ewing. Cython language. Cython is based on Pyrex by Greg Ewing.
Usage: cython [options] sourcefile.pyx ... Usage: cython [options] sourcefile.{pyx,py} ...
Options: Options:
-V, --version Display version number of cython compiler -V, --version Display version number of cython compiler
-l, --create-listing Write error messages to a listing file -l, --create-listing Write error messages to a listing file
-I, --include-dir <directory> Search for include files in named directory -I, --include-dir <directory> Search for include files in named directory
(multiply include directories are allowed). (multiple include directories are allowed).
-o, --output-file <filename> Specify name of generated C file -o, --output-file <filename> Specify name of generated C file
-t, --timestamps Only compile newer source files (implied with -r) -t, --timestamps Only compile newer source files
-f, --force Compile all source files (overrides implied -t) -f, --force Compile all source files (overrides implied -t)
-q, --quiet Don't print module names in recursive mode -q, --quiet Don't print module names in recursive mode
-v, --verbose Be verbose, print file names on multiple compilation -v, --verbose Be verbose, print file names on multiple compilation
...@@ -30,11 +30,11 @@ Options: ...@@ -30,11 +30,11 @@ Options:
are searched from) are searched from)
--gdb Output debug information for cygdb --gdb Output debug information for cygdb
-D, --no-docstrings Remove docstrings. -D, --no-docstrings Strip docstrings from the compiled module.
-a, --annotate Produce a colorized HTML version of the source. -a, --annotate Produce a colorized HTML version of the source.
--line-directives Produce #line directives pointing to the .pyx source --line-directives Produce #line directives pointing to the .pyx source
--cplus Output a c++ rather than c file. --cplus Output a C++ rather than C file.
--embed Embed the Python interpreter in a main() method. --embed Generate a main() function that embeds the Python interpreter.
-2 Compile based on Python-2 syntax and code semantics. -2 Compile based on Python-2 syntax and code semantics.
-3 Compile based on Python-3 syntax and code semantics. -3 Compile based on Python-3 syntax and code semantics.
--fast-fail Abort the compilation on the first error --fast-fail Abort the compilation on the first error
...@@ -42,7 +42,7 @@ Options: ...@@ -42,7 +42,7 @@ Options:
""" """
# The following is broken http://trac.cython.org/cython_trac/ticket/379 # The following is broken http://trac.cython.org/cython_trac/ticket/379
# -r, --recursive Recursively find and compile dependencies # -r, --recursive Recursively find and compile dependencies (implies -t)
#The following experimental options are supported only on MacOSX: #The following experimental options are supported only on MacOSX:
...@@ -125,6 +125,8 @@ def parse_command_line(args): ...@@ -125,6 +125,8 @@ def parse_command_line(args):
options.language_level = 3 options.language_level = 3
elif option == "--fast-fail": elif option == "--fast-fail":
Options.fast_fail = True Options.fast_fail = True
elif option == "--disable-function-redefinition":
Options.disable_function_redefinition = True
elif option in ("-X", "--directive"): elif option in ("-X", "--directive"):
try: try:
options.compiler_directives = Options.parse_directive_list( options.compiler_directives = Options.parse_directive_list(
...@@ -141,6 +143,9 @@ def parse_command_line(args): ...@@ -141,6 +143,9 @@ def parse_command_line(args):
else: else:
sys.stderr.write("Unknown debug flag: %s\n" % option) sys.stderr.write("Unknown debug flag: %s\n" % option)
bad_usage() bad_usage()
elif option in ('-h', '--help'):
sys.stdout.write(usage)
sys.exit(0)
else: else:
sys.stderr.write("Unknown compiler flag: %s\n" % option) sys.stderr.write("Unknown compiler flag: %s\n" % option)
sys.exit(1) sys.exit(1)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
import cython import cython
cython.declare(re=object, Naming=object, Options=object, StringEncoding=object, cython.declare(re=object, Naming=object, Options=object, StringEncoding=object,
Utils=object, SourceDescriptor=object, StringIOTree=object, Utils=object, SourceDescriptor=object, StringIOTree=object,
DebugFlags=object, none_or_sub=object) DebugFlags=object, none_or_sub=object, basestring=object)
import re import re
import Naming import Naming
...@@ -19,9 +19,9 @@ import DebugFlags ...@@ -19,9 +19,9 @@ import DebugFlags
from Cython.Utils import none_or_sub from Cython.Utils import none_or_sub
try: try:
basestring from __builtin__ import basestring
except NameError: except ImportError:
basestring = str from builtins import str as basestring
class UtilityCode(object): class UtilityCode(object):
# Stores utility code to add during code generation. # Stores utility code to add during code generation.
......
...@@ -948,7 +948,8 @@ class BytesNode(ConstNode): ...@@ -948,7 +948,8 @@ class BytesNode(ConstNode):
# #
# value BytesLiteral # value BytesLiteral
type = PyrexTypes.c_char_ptr_type # start off as Python 'bytes' to support len() in O(1)
type = bytes_type
def compile_time_value(self, denv): def compile_time_value(self, denv):
return self.value return self.value
...@@ -969,11 +970,13 @@ class BytesNode(ConstNode): ...@@ -969,11 +970,13 @@ class BytesNode(ConstNode):
return len(self.value) == 1 return len(self.value) == 1
def coerce_to_boolean(self, env): def coerce_to_boolean(self, env):
# This is special because we start off as a C char*. Testing # This is special because testing a C char* for truth directly
# that for truth directly would yield the wrong result. # would yield the wrong result.
return BoolNode(self.pos, value=bool(self.value)) return BoolNode(self.pos, value=bool(self.value))
def coerce_to(self, dst_type, env): def coerce_to(self, dst_type, env):
if self.type == dst_type:
return self
if dst_type.is_int: if dst_type.is_int:
if not self.can_coerce_to_char_literal(): if not self.can_coerce_to_char_literal():
error(self.pos, "Only single-character string literals can be coerced into ints.") error(self.pos, "Only single-character string literals can be coerced into ints.")
...@@ -984,21 +987,20 @@ class BytesNode(ConstNode): ...@@ -984,21 +987,20 @@ class BytesNode(ConstNode):
return CharNode(self.pos, value=self.value) return CharNode(self.pos, value=self.value)
node = BytesNode(self.pos, value=self.value) node = BytesNode(self.pos, value=self.value)
if dst_type == PyrexTypes.c_char_ptr_type: if dst_type.is_pyobject:
node.type = PyrexTypes.c_char_ptr_type if dst_type in (py_object_type, Builtin.bytes_type):
node.type = Builtin.bytes_type
else:
self.check_for_coercion_error(dst_type, fail=True)
return node
elif dst_type == PyrexTypes.c_char_ptr_type:
node.type = dst_type
return node return node
elif dst_type == PyrexTypes.c_uchar_ptr_type: elif dst_type == PyrexTypes.c_uchar_ptr_type:
node.type = PyrexTypes.c_char_ptr_type node.type = PyrexTypes.c_char_ptr_type
return CastNode(node, PyrexTypes.c_uchar_ptr_type) return CastNode(node, PyrexTypes.c_uchar_ptr_type)
elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type):
if not self.type.is_pyobject: node.type = dst_type
if dst_type in (py_object_type, Builtin.bytes_type):
node.type = Builtin.bytes_type
elif dst_type.is_pyobject:
self.fail_assignment(dst_type)
return self
elif dst_type.is_pyobject and dst_type is not py_object_type:
self.check_for_coercion_error(dst_type, fail=True)
return node return node
# We still need to perform normal coerce_to processing on the # We still need to perform normal coerce_to processing on the
...@@ -1006,11 +1008,6 @@ class BytesNode(ConstNode): ...@@ -1006,11 +1008,6 @@ class BytesNode(ConstNode):
# in which case a type test node will be needed. # in which case a type test node will be needed.
return ConstNode.coerce_to(node, dst_type, env) return ConstNode.coerce_to(node, dst_type, env)
def as_py_string_node(self, env):
# Return a new BytesNode with the same value as this node
# but whose type is a Python type instead of a C type.
return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
def generate_evaluation_code(self, code): def generate_evaluation_code(self, code):
if self.type.is_pyobject: if self.type.is_pyobject:
self.result_code = code.get_py_string_const(self.value) self.result_code = code.get_py_string_const(self.value)
...@@ -1431,7 +1428,7 @@ class NameNode(AtomicExprNode): ...@@ -1431,7 +1428,7 @@ class NameNode(AtomicExprNode):
if self.is_used_as_rvalue: if self.is_used_as_rvalue:
entry = self.entry entry = self.entry
if entry.is_builtin: if entry.is_builtin:
# if not Options.cache_builtins: # cached builtins are ok if not Options.cache_builtins: # cached builtins are ok
self.gil_error() self.gil_error()
elif entry.is_pyglobal: elif entry.is_pyglobal:
self.gil_error() self.gil_error()
...@@ -2036,7 +2033,7 @@ class IndexNode(ExprNode): ...@@ -2036,7 +2033,7 @@ class IndexNode(ExprNode):
return None return None
def type_dependencies(self, env): def type_dependencies(self, env):
return self.base.type_dependencies(env) return self.base.type_dependencies(env) + self.index.type_dependencies(env)
def infer_type(self, env): def infer_type(self, env):
base_type = self.base.infer_type(env) base_type = self.base.infer_type(env)
...@@ -2605,6 +2602,7 @@ class SliceIndexNode(ExprNode): ...@@ -2605,6 +2602,7 @@ class SliceIndexNode(ExprNode):
self.start_code(), self.start_code(),
self.stop_code())) self.stop_code()))
self.generate_subexpr_disposal_code(code) self.generate_subexpr_disposal_code(code)
self.free_subexpr_temps(code)
def generate_slice_guard_code(self, code, target_size): def generate_slice_guard_code(self, code, target_size):
if not self.base.type.is_array: if not self.base.type.is_array:
...@@ -2952,11 +2950,23 @@ class SimpleCallNode(CallNode): ...@@ -2952,11 +2950,23 @@ class SimpleCallNode(CallNode):
# Coerce arguments # Coerce arguments
for i in range(min(max_nargs, actual_nargs)): for i in range(min(max_nargs, actual_nargs)):
formal_type = func_type.args[i].type formal_type = func_type.args[i].type
self.args[i] = self.args[i].coerce_to(formal_type, env) arg = self.args[i].coerce_to(formal_type, env)
if arg.type.is_pyobject and not env.nogil and (arg.is_attribute or not arg.is_simple):
# we do not own the argument's reference, but we must
# make sure it cannot be collected before we return
# from the function, so we create an owned temp
# reference to it
arg = arg.coerce_to_temp(env)
self.args[i] = arg
for i in range(max_nargs, actual_nargs): for i in range(max_nargs, actual_nargs):
if self.args[i].type.is_pyobject: arg = self.args[i]
if arg.type.is_pyobject:
arg_ctype = arg.type.default_coerced_ctype()
if arg_ctype is None:
error(self.args[i].pos, error(self.args[i].pos,
"Python object cannot be passed as a varargs parameter") "Python object cannot be passed as a varargs parameter")
else:
self.args[i] = arg.coerce_to(arg_ctype, env)
# Calc result type and code fragment # Calc result type and code fragment
if isinstance(self.function, NewExprNode): if isinstance(self.function, NewExprNode):
self.type = PyrexTypes.CPtrType(self.function.class_type) self.type = PyrexTypes.CPtrType(self.function.class_type)
...@@ -3401,7 +3411,7 @@ class AttributeNode(ExprNode): ...@@ -3401,7 +3411,7 @@ class AttributeNode(ExprNode):
return module_scope.lookup_type(self.attribute) return module_scope.lookup_type(self.attribute)
if not isinstance(self.obj, (UnicodeNode, StringNode, BytesNode)): if not isinstance(self.obj, (UnicodeNode, StringNode, BytesNode)):
base_type = self.obj.analyse_as_type(env) base_type = self.obj.analyse_as_type(env)
if base_type and hasattr(base_type, 'scope'): if base_type and hasattr(base_type, 'scope') and base_type.scope is not None:
return base_type.scope.lookup_type(self.attribute) return base_type.scope.lookup_type(self.attribute)
return None return None
...@@ -8182,17 +8192,17 @@ typedef struct { ...@@ -8182,17 +8192,17 @@ typedef struct {
PyCFunctionObject func; PyCFunctionObject func;
} %(binding_cfunc)s_object; } %(binding_cfunc)s_object;
PyTypeObject %(binding_cfunc)s_type; static PyTypeObject %(binding_cfunc)s_type;
PyTypeObject *%(binding_cfunc)s = NULL; static PyTypeObject *%(binding_cfunc)s = NULL;
PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */ static PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */
#define %(binding_cfunc)s_New(ml, self) %(binding_cfunc)s_NewEx(ml, self, NULL) #define %(binding_cfunc)s_New(ml, self) %(binding_cfunc)s_NewEx(ml, self, NULL)
int %(binding_cfunc)s_init(void); /* proto */ static int %(binding_cfunc)s_init(void); /* proto */
""" % Naming.__dict__, """ % Naming.__dict__,
impl=""" impl="""
PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) { static PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) {
%(binding_cfunc)s_object *op = PyObject_GC_New(%(binding_cfunc)s_object, %(binding_cfunc)s); %(binding_cfunc)s_object *op = PyObject_GC_New(%(binding_cfunc)s_object, %(binding_cfunc)s);
if (op == NULL) if (op == NULL)
return NULL; return NULL;
...@@ -8218,7 +8228,7 @@ static PyObject *%(binding_cfunc)s_descr_get(PyObject *func, PyObject *obj, PyOb ...@@ -8218,7 +8228,7 @@ static PyObject *%(binding_cfunc)s_descr_get(PyObject *func, PyObject *obj, PyOb
return PyMethod_New(func, obj, type); return PyMethod_New(func, obj, type);
} }
int %(binding_cfunc)s_init(void) { static int %(binding_cfunc)s_init(void) {
%(binding_cfunc)s_type = PyCFunction_Type; %(binding_cfunc)s_type = PyCFunction_Type;
%(binding_cfunc)s_type.tp_name = __Pyx_NAMESTR("cython_binding_builtin_function_or_method"); %(binding_cfunc)s_type.tp_name = __Pyx_NAMESTR("cython_binding_builtin_function_or_method");
%(binding_cfunc)s_type.tp_dealloc = (destructor)%(binding_cfunc)s_dealloc; %(binding_cfunc)s_type.tp_dealloc = (destructor)%(binding_cfunc)s_dealloc;
......
...@@ -74,7 +74,6 @@ class Context(object): ...@@ -74,7 +74,6 @@ class Context(object):
# language_level int currently 2 or 3 for Python 2/3 # language_level int currently 2 or 3 for Python 2/3
def __init__(self, include_directories, compiler_directives, cpp=False, language_level=2): def __init__(self, include_directories, compiler_directives, cpp=False, language_level=2):
#self.modules = {"__builtin__" : BuiltinScope()}
import Builtin, CythonScope import Builtin, CythonScope
self.modules = {"__builtin__" : Builtin.builtin_scope} self.modules = {"__builtin__" : Builtin.builtin_scope}
self.modules["cython"] = CythonScope.create_cython_scope(self) self.modules["cython"] = CythonScope.create_cython_scope(self)
...@@ -99,6 +98,7 @@ class Context(object): ...@@ -99,6 +98,7 @@ class Context(object):
from Future import print_function, unicode_literals from Future import print_function, unicode_literals
self.future_directives.add(print_function) self.future_directives.add(print_function)
self.future_directives.add(unicode_literals) self.future_directives.add(unicode_literals)
self.modules['builtins'] = self.modules['__builtin__']
def create_pipeline(self, pxd, py=False): def create_pipeline(self, pxd, py=False):
from Visitor import PrintTree from Visitor import PrintTree
...@@ -315,7 +315,10 @@ class Context(object): ...@@ -315,7 +315,10 @@ class Context(object):
try: try:
if debug_find_module: if debug_find_module:
print("Context.find_module: Parsing %s" % pxd_pathname) print("Context.find_module: Parsing %s" % pxd_pathname)
source_desc = FileSourceDescriptor(pxd_pathname) rel_path = module_name.replace('.', os.sep) + os.path.splitext(pxd_pathname)[1]
if not pxd_pathname.endswith(rel_path):
rel_path = pxd_pathname # safety measure to prevent printing incorrect paths
source_desc = FileSourceDescriptor(pxd_pathname, rel_path)
err, result = self.process_pxd(source_desc, scope, module_name) err, result = self.process_pxd(source_desc, scope, module_name)
if err: if err:
raise err raise err
...@@ -589,15 +592,23 @@ def run_pipeline(source, options, full_module_name = None): ...@@ -589,15 +592,23 @@ def run_pipeline(source, options, full_module_name = None):
# Set up source object # Set up source object
cwd = os.getcwd() cwd = os.getcwd()
source_desc = FileSourceDescriptor(os.path.join(cwd, source)) abs_path = os.path.abspath(source)
source_ext = os.path.splitext(source)[1]
full_module_name = full_module_name or context.extract_module_name(source, options) full_module_name = full_module_name or context.extract_module_name(source, options)
if options.relative_path_in_code_position_comments:
rel_path = full_module_name.replace('.', os.sep) + source_ext
if not abs_path.endswith(rel_path):
rel_path = source # safety measure to prevent printing incorrect paths
else:
rel_path = abs_path
source_desc = FileSourceDescriptor(abs_path, rel_path)
source = CompilationSource(source_desc, full_module_name, cwd) source = CompilationSource(source_desc, full_module_name, cwd)
# Set up result object # Set up result object
result = create_default_resultobj(source, options) result = create_default_resultobj(source, options)
# Get pipeline # Get pipeline
if source_desc.filename.endswith(".py"): if source_ext.lower() == '.py':
pipeline = context.create_py_pipeline(options, result) pipeline = context.create_py_pipeline(options, result)
else: else:
pipeline = context.create_pyx_pipeline(options, result) pipeline = context.create_pyx_pipeline(options, result)
...@@ -825,6 +836,7 @@ default_options = dict( ...@@ -825,6 +836,7 @@ default_options = dict(
compiler_directives = {}, compiler_directives = {},
evaluate_tree_assertions = False, evaluate_tree_assertions = False,
emit_linenums = False, emit_linenums = False,
relative_path_in_code_position_comments = True,
language_level = 2, language_level = 2,
gdb_debug = False, gdb_debug = False,
) )
...@@ -139,7 +139,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -139,7 +139,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
h_code.putln("") h_code.putln("")
h_code.putln("#endif") h_code.putln("#endif")
h_code.copyto(open_new_file(result.h_file)) f = open_new_file(result.h_file)
try:
h_code.copyto(f)
finally:
f.close()
def generate_public_declaration(self, entry, h_code, i_code): def generate_public_declaration(self, entry, h_code, i_code):
h_code.putln("%s %s;" % ( h_code.putln("%s %s;" % (
...@@ -222,7 +226,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -222,7 +226,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
h_code.putln("") h_code.putln("")
h_code.putln("#endif") h_code.putln("#endif")
h_code.copyto(open_new_file(result.api_file)) f = open_new_file(result.api_file)
try:
h_code.copyto(f)
finally:
f.close()
def generate_cclass_header_code(self, type, h_code): def generate_cclass_header_code(self, type, h_code):
h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % ( h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
...@@ -264,7 +272,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -264,7 +272,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code = globalstate['before_global_var'] code = globalstate['before_global_var']
code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name) code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name)
code.putln("int %s%s = 0;" % (Naming.module_is_main, self.full_module_name.replace('.', '__'))) code.putln("static int %s%s = 0;" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
code.putln("") code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name) code.putln("/* Implementation of %s */" % env.qualified_name)
...@@ -569,14 +577,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -569,14 +577,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#define PyBytes_Repr PyString_Repr #define PyBytes_Repr PyString_Repr
#define PyBytes_Concat PyString_Concat #define PyBytes_Concat PyString_Concat
#define PyBytes_ConcatAndDel PyString_ConcatAndDel #define PyBytes_ConcatAndDel PyString_ConcatAndDel
#endif
#if PY_VERSION_HEX < 0x02060000
#define PySet_Check(obj) PyObject_TypeCheck(obj, &PySet_Type) #define PySet_Check(obj) PyObject_TypeCheck(obj, &PySet_Type)
#define PyFrozenSet_Check(obj) PyObject_TypeCheck(obj, &PyFrozenSet_Type) #define PyFrozenSet_Check(obj) PyObject_TypeCheck(obj, &PyFrozenSet_Type)
#endif #endif
#ifndef PySet_CheckExact #ifndef PySet_CheckExact
# define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type)
#endif #endif
#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
#define PyIntObject PyLongObject #define PyIntObject PyLongObject
#define PyInt_Type PyLong_Type #define PyInt_Type PyLong_Type
...@@ -858,7 +870,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -858,7 +870,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
Naming.extern_c_macro, Naming.extern_c_macro,
name)) name))
elif entry.visibility == 'public': elif entry.visibility == 'public':
#code.putln("DL_EXPORT(PyTypeObject) %s;" % name)
code.putln("%s DL_EXPORT(PyTypeObject) %s;" % ( code.putln("%s DL_EXPORT(PyTypeObject) %s;" % (
Naming.extern_c_macro, Naming.extern_c_macro,
name)) name))
...@@ -1591,8 +1602,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1591,8 +1602,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if entry.visibility == 'public': if entry.visibility == 'public':
header = "DL_EXPORT(PyTypeObject) %s = {" header = "DL_EXPORT(PyTypeObject) %s = {"
else: else:
#header = "statichere PyTypeObject %s = {" header = "static PyTypeObject %s = {"
header = "PyTypeObject %s = {"
#code.putln(header % scope.parent_type.typeobj_cname) #code.putln(header % scope.parent_type.typeobj_cname)
code.putln(header % type.typeobj_cname) code.putln(header % type.typeobj_cname)
code.putln( code.putln(
...@@ -2041,12 +2051,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2041,12 +2051,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.error_goto_if_null(type.typeptr_cname, pos)) code.error_goto_if_null(type.typeptr_cname, pos))
self.use_type_import_utility_code(env) self.use_type_import_utility_code(env)
if type.vtabptr_cname: if type.vtabptr_cname:
code.putln(
"if (__Pyx_GetVtable(%s->tp_dict, &%s) < 0) %s" % (
type.typeptr_cname,
type.vtabptr_cname,
code.error_goto(pos)))
env.use_utility_code(Nodes.get_vtable_utility_code) env.use_utility_code(Nodes.get_vtable_utility_code)
code.putln("%s = (struct %s*)__Pyx_GetVtable(%s->tp_dict); %s" % (
type.vtabptr_cname,
type.vtabstruct_cname,
type.typeptr_cname,
code.error_goto_if_null(type.vtabptr_cname, pos)))
env.types_imported[type] = 1 env.types_imported[type] = 1
py3_type_name_map = {'str' : 'bytes', 'unicode' : 'str'} py3_type_name_map = {'str' : 'bytes', 'unicode' : 'str'}
...@@ -2099,24 +2109,24 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2099,24 +2109,24 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# a significant performance hit. (See trac #561.) # a significant performance hit. (See trac #561.)
for func in entry.type.scope.pyfunc_entries: for func in entry.type.scope.pyfunc_entries:
if func.is_special and Options.docstrings and func.wrapperbase_cname: if func.is_special and Options.docstrings and func.wrapperbase_cname:
code.putln("{"); code.putln("{")
code.putln( code.putln(
'PyObject *wrapper = __Pyx_GetAttrString((PyObject *)&%s, "%s"); %s' % ( 'PyObject *wrapper = __Pyx_GetAttrString((PyObject *)&%s, "%s"); %s' % (
typeobj_cname, typeobj_cname,
func.name, func.name,
code.error_goto_if_null('wrapper', entry.pos))); code.error_goto_if_null('wrapper', entry.pos)))
code.putln( code.putln(
"if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) {"); "if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) {")
code.putln( code.putln(
"%s = *((PyWrapperDescrObject *)wrapper)->d_base;" % ( "%s = *((PyWrapperDescrObject *)wrapper)->d_base;" % (
func.wrapperbase_cname)); func.wrapperbase_cname))
code.putln( code.putln(
"%s.doc = %s;" % (func.wrapperbase_cname, func.doc_cname)); "%s.doc = %s;" % (func.wrapperbase_cname, func.doc_cname))
code.putln( code.putln(
"((PyWrapperDescrObject *)wrapper)->d_base = &%s;" % ( "((PyWrapperDescrObject *)wrapper)->d_base = &%s;" % (
func.wrapperbase_cname)); func.wrapperbase_cname))
code.putln("}"); code.putln("}")
code.putln("}"); code.putln("}")
if type.vtable_cname: if type.vtable_cname:
code.putln( code.putln(
"if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % ( "if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % (
......
...@@ -1353,7 +1353,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1353,7 +1353,7 @@ class FuncDefNode(StatNode, BlockNode):
# incref it to properly keep track of refcounts. # incref it to properly keep track of refcounts.
for entry in lenv.arg_entries: for entry in lenv.arg_entries:
if entry.type.is_pyobject: if entry.type.is_pyobject:
if entry.assignments and not entry.in_closure: if (acquire_gil or entry.assignments) and not entry.in_closure:
code.put_var_incref(entry) code.put_var_incref(entry)
# ----- Initialise local variables # ----- Initialise local variables
for entry in lenv.var_entries: for entry in lenv.var_entries:
...@@ -1463,7 +1463,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1463,7 +1463,7 @@ class FuncDefNode(StatNode, BlockNode):
if entry.type.is_pyobject: if entry.type.is_pyobject:
if entry.in_closure: if entry.in_closure:
code.put_var_giveref(entry) code.put_var_giveref(entry)
elif entry.assignments: elif acquire_gil or entry.assignments:
code.put_var_decref(entry) code.put_var_decref(entry)
if self.needs_closure: if self.needs_closure:
code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type) code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
...@@ -1988,7 +1988,7 @@ class DefNode(FuncDefNode): ...@@ -1988,7 +1988,7 @@ class DefNode(FuncDefNode):
# staticmethod() was overridden - not much we can do here ... # staticmethod() was overridden - not much we can do here ...
self.is_staticmethod = False self.is_staticmethod = False
if self.name == '__new__': if self.name == '__new__' and env.is_py_class_scope:
self.is_staticmethod = 1 self.is_staticmethod = 1
self.analyse_argument_types(env) self.analyse_argument_types(env)
...@@ -2440,8 +2440,6 @@ class DefNode(FuncDefNode): ...@@ -2440,8 +2440,6 @@ class DefNode(FuncDefNode):
self.name, Naming.args_cname, self.error_value())) self.name, Naming.args_cname, self.error_value()))
code.putln("}") code.putln("}")
code.globalstate.use_utility_code(keyword_string_check_utility_code)
if self.starstar_arg: if self.starstar_arg:
if self.star_arg: if self.star_arg:
kwarg_check = "unlikely(%s)" % Naming.kwds_cname kwarg_check = "unlikely(%s)" % Naming.kwds_cname
...@@ -2450,6 +2448,7 @@ class DefNode(FuncDefNode): ...@@ -2450,6 +2448,7 @@ class DefNode(FuncDefNode):
else: else:
kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % ( kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
Naming.kwds_cname, Naming.kwds_cname) Naming.kwds_cname, Naming.kwds_cname)
code.globalstate.use_utility_code(keyword_string_check_utility_code)
code.putln( code.putln(
"if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % ( "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
kwarg_check, Naming.kwds_cname, self.name, kwarg_check, Naming.kwds_cname, self.name,
...@@ -2513,8 +2512,6 @@ class DefNode(FuncDefNode): ...@@ -2513,8 +2512,6 @@ class DefNode(FuncDefNode):
has_fixed_positional_count = not self.star_arg and \ has_fixed_positional_count = not self.star_arg and \
min_positional_args == max_positional_args min_positional_args == max_positional_args
code.globalstate.use_utility_code(raise_double_keywords_utility_code)
code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
if self.num_required_kw_args: if self.num_required_kw_args:
code.globalstate.use_utility_code(raise_keyword_required_utility_code) code.globalstate.use_utility_code(raise_keyword_required_utility_code)
...@@ -2605,6 +2602,7 @@ class DefNode(FuncDefNode): ...@@ -2605,6 +2602,7 @@ class DefNode(FuncDefNode):
if code.label_used(argtuple_error_label): if code.label_used(argtuple_error_label):
code.put_goto(success_label) code.put_goto(success_label)
code.put_label(argtuple_error_label) code.put_label(argtuple_error_label)
code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % ( code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
self.name, has_fixed_positional_count, self.name, has_fixed_positional_count,
min_positional_args, max_positional_args, min_positional_args, max_positional_args,
...@@ -2727,6 +2725,7 @@ class DefNode(FuncDefNode): ...@@ -2727,6 +2725,7 @@ class DefNode(FuncDefNode):
# kwargs) that were passed into positional # kwargs) that were passed into positional
# arguments up to this point # arguments up to this point
code.putln('else {') code.putln('else {')
code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % ( code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
self.name, has_fixed_positional_count, self.name, has_fixed_positional_count,
min_positional_args, max_positional_args, i)) min_positional_args, max_positional_args, i))
...@@ -3346,6 +3345,12 @@ class ExprStatNode(StatNode): ...@@ -3346,6 +3345,12 @@ class ExprStatNode(StatNode):
def analyse_expressions(self, env): def analyse_expressions(self, env):
self.expr.analyse_expressions(env) self.expr.analyse_expressions(env)
def nogil_check(self, env):
if self.expr.type.is_pyobject and self.expr.is_temp:
self.gil_error()
gil_message = "Discarding owned Python object"
def generate_execution_code(self, code): def generate_execution_code(self, code):
self.expr.generate_evaluation_code(code) self.expr.generate_evaluation_code(code)
if not self.expr.is_temp and self.expr.result(): if not self.expr.is_temp and self.expr.result():
...@@ -6094,7 +6099,8 @@ invalid_keyword: ...@@ -6094,7 +6099,8 @@ invalid_keyword:
bad: bad:
return -1; return -1;
} }
""") """,
requires=[raise_double_keywords_utility_code])
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
...@@ -6238,25 +6244,26 @@ bad: ...@@ -6238,25 +6244,26 @@ bad:
get_vtable_utility_code = UtilityCode( get_vtable_utility_code = UtilityCode(
proto = """ proto = """
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/ static void* __Pyx_GetVtable(PyObject *dict); /*proto*/
""", """,
impl = r""" impl = r"""
static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) { static void* __Pyx_GetVtable(PyObject *dict) {
void* ptr;
PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__"); PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
if (!ob) if (!ob)
goto bad; goto bad;
#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0) #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
*(void **)vtabptr = PyCapsule_GetPointer(ob, 0); ptr = PyCapsule_GetPointer(ob, 0);
#else #else
*(void **)vtabptr = PyCObject_AsVoidPtr(ob); ptr = PyCObject_AsVoidPtr(ob);
#endif #endif
if (!*(void **)vtabptr) if (!ptr && !PyErr_Occurred())
goto bad; PyErr_SetString(PyExc_RuntimeError, "invalid vtable found for imported type");
Py_DECREF(ob); Py_DECREF(ob);
return 0; return ptr;
bad: bad:
Py_XDECREF(ob); Py_XDECREF(ob);
return -1; return NULL;
} }
""") """)
......
...@@ -1110,8 +1110,9 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform): ...@@ -1110,8 +1110,9 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
def _function_is_builtin_name(self, function): def _function_is_builtin_name(self, function):
if not function.is_name: if not function.is_name:
return False return False
entry = self.current_env().lookup(function.name) env = self.current_env()
if entry and getattr(entry, 'scope', None) is not Builtin.builtin_scope: entry = env.lookup(function.name)
if entry is not env.builtin_scope().lookup_here(function.name):
return False return False
# if entry is None, it's at least an undeclared name, so likely builtin # if entry is None, it's at least an undeclared name, so likely builtin
return True return True
...@@ -1724,8 +1725,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -1724,8 +1725,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
# into a C function call (defined in the builtin scope) # into a C function call (defined in the builtin scope)
if not function.entry: if not function.entry:
return node return node
is_builtin = function.entry.is_builtin \ is_builtin = function.entry.is_builtin or \
or getattr(function.entry, 'scope', None) is Builtin.builtin_scope function.entry is self.current_env().builtin_scope().lookup_here(function.name)
if not is_builtin: if not is_builtin:
return node return node
function_handler = self._find_handler( function_handler = self._find_handler(
...@@ -1985,20 +1986,26 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -1985,20 +1986,26 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
test_nodes = [] test_nodes = []
env = self.current_env() env = self.current_env()
for test_type_node in types: for test_type_node in types:
if not test_type_node.entry: builtin_type = None
return node if isinstance(test_type_node, ExprNodes.NameNode):
if test_type_node.entry:
entry = env.lookup(test_type_node.entry.name) entry = env.lookup(test_type_node.entry.name)
if not entry or not entry.type or not entry.type.is_builtin_type: if entry and entry.type and entry.type.is_builtin_type:
return node builtin_type = entry.type
if builtin_type and builtin_type is not Builtin.type_type:
type_check_function = entry.type.type_check_function(exact=False) type_check_function = entry.type.type_check_function(exact=False)
if not type_check_function: type_check_args = [arg]
elif test_type_node.type is Builtin.type_type:
type_check_function = '__Pyx_TypeCheck'
type_check_args = [arg, test_type_node]
else:
return node return node
if type_check_function not in tests: if type_check_function not in tests:
tests.append(type_check_function) tests.append(type_check_function)
test_nodes.append( test_nodes.append(
ExprNodes.PythonCapiCallNode( ExprNodes.PythonCapiCallNode(
test_type_node.pos, type_check_function, self.Py_type_check_func_type, test_type_node.pos, type_check_function, self.Py_type_check_func_type,
args = [arg], args = type_check_args,
is_temp = True, is_temp = True,
)) ))
......
...@@ -51,6 +51,10 @@ c_line_in_traceback = 1 ...@@ -51,6 +51,10 @@ c_line_in_traceback = 1
# executes the body of this module. # executes the body of this module.
embed = False embed = False
# Disables function redefinition, allowing all functions to be declared at
# module creation time. For legacy code only.
disable_function_redefinition = False
# Declare compiler directives # Declare compiler directives
directive_defaults = { directive_defaults = {
......
...@@ -353,6 +353,10 @@ class PyObjectType(PyrexType): ...@@ -353,6 +353,10 @@ class PyObjectType(PyrexType):
def can_coerce_to_pyobject(self, env): def can_coerce_to_pyobject(self, env):
return True return True
def default_coerced_ctype(self):
"The default C type that this Python type coerces to, or None."
return None
def assignable_from(self, src_type): def assignable_from(self, src_type):
# except for pointers, conversion will be attempted # except for pointers, conversion will be attempted
return not src_type.is_ptr or src_type.is_string return not src_type.is_ptr or src_type.is_string
...@@ -404,6 +408,15 @@ class BuiltinObjectType(PyObjectType): ...@@ -404,6 +408,15 @@ class BuiltinObjectType(PyObjectType):
def __repr__(self): def __repr__(self):
return "<%s>"% self.cname return "<%s>"% self.cname
def default_coerced_ctype(self):
if self.name == 'bytes':
return c_char_ptr_type
elif self.name == 'bool':
return c_bint_type
elif self.name == 'float':
return c_double_type
return None
def assignable_from(self, src_type): def assignable_from(self, src_type):
if isinstance(src_type, BuiltinObjectType): if isinstance(src_type, BuiltinObjectType):
return src_type.name == self.name return src_type.name == self.name
...@@ -1371,10 +1384,10 @@ impl=""" ...@@ -1371,10 +1384,10 @@ impl="""
} }
#if %(is_float)s #if %(is_float)s
static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s z) { static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s z) {
#if HAVE_HYPOT #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
return hypot%(m)s(z.real, z.imag);
#else
return sqrt%(m)s(z.real*z.real + z.imag*z.imag); return sqrt%(m)s(z.real*z.real + z.imag*z.imag);
#else
return hypot%(m)s(z.real, z.imag);
#endif #endif
} }
static CYTHON_INLINE %(type)s __Pyx_c_pow%(m)s(%(type)s a, %(type)s b) { static CYTHON_INLINE %(type)s __Pyx_c_pow%(m)s(%(type)s a, %(type)s b) {
......
...@@ -166,8 +166,9 @@ class FileSourceDescriptor(SourceDescriptor): ...@@ -166,8 +166,9 @@ class FileSourceDescriptor(SourceDescriptor):
optional name argument and will be passed back when asking for optional name argument and will be passed back when asking for
the position()-tuple. the position()-tuple.
""" """
def __init__(self, filename): def __init__(self, filename, path_description=None):
filename = Utils.decode_filename(filename) filename = Utils.decode_filename(filename)
self.path_description = path_description or filename
self.filename = filename self.filename = filename
self.set_file_type_from_name(filename) self.set_file_type_from_name(filename)
self._cmp_name = filename self._cmp_name = filename
...@@ -180,7 +181,7 @@ class FileSourceDescriptor(SourceDescriptor): ...@@ -180,7 +181,7 @@ class FileSourceDescriptor(SourceDescriptor):
require_normalised_newlines=False) require_normalised_newlines=False)
def get_description(self): def get_description(self):
return self.filename return self.path_description
def get_filenametable_entry(self): def get_filenametable_entry(self):
return self.filename return self.filename
...@@ -199,6 +200,8 @@ class StringSourceDescriptor(SourceDescriptor): ...@@ -199,6 +200,8 @@ class StringSourceDescriptor(SourceDescriptor):
Instances of this class can be used instead of a filenames if the Instances of this class can be used instead of a filenames if the
code originates from a string object. code originates from a string object.
""" """
filename = None
def __init__(self, name, code): def __init__(self, name, code):
self.name = name self.name = name
#self.set_file_type_from_name(name) #self.set_file_type_from_name(name)
......
...@@ -526,7 +526,7 @@ class Scope(object): ...@@ -526,7 +526,7 @@ class Scope(object):
def declare_pyfunction(self, name, pos, allow_redefine=False, visibility='extern'): def declare_pyfunction(self, name, pos, allow_redefine=False, visibility='extern'):
# Add an entry for a Python function. # Add an entry for a Python function.
entry = self.lookup_here(name) entry = self.lookup_here(name)
if not allow_redefine: if not allow_redefine or Options.disable_function_redefinition:
return self._declare_pyfunction(name, pos, visibility=visibility, entry=entry) return self._declare_pyfunction(name, pos, visibility=visibility, entry=entry)
if entry: if entry:
if entry.type.is_unspecified: if entry.type.is_unspecified:
...@@ -733,6 +733,13 @@ class BuiltinScope(Scope): ...@@ -733,6 +733,13 @@ class BuiltinScope(Scope):
cname, type = definition cname, type = definition
self.declare_var(name, type, None, cname) self.declare_var(name, type, None, cname)
def lookup(self, name, language_level=None):
# 'language_level' is passed by ModuleScope
if language_level == 3:
if name == 'str':
name = 'unicode'
return Scope.lookup(self, name)
def declare_builtin(self, name, pos): def declare_builtin(self, name, pos):
if not hasattr(builtins, name): if not hasattr(builtins, name):
if self.outer_scope is not None: if self.outer_scope is not None:
...@@ -882,6 +889,12 @@ class ModuleScope(Scope): ...@@ -882,6 +889,12 @@ class ModuleScope(Scope):
def global_scope(self): def global_scope(self):
return self return self
def lookup(self, name):
entry = self.lookup_here(name)
if entry is not None:
return entry
return self.outer_scope.lookup(name, language_level = self.context.language_level)
def declare_builtin(self, name, pos): def declare_builtin(self, name, pos):
if not hasattr(builtins, name) and name != 'xrange': if not hasattr(builtins, name) and name != 'xrange':
# 'xrange' is special cased in Code.py # 'xrange' is special cased in Code.py
...@@ -1121,6 +1134,19 @@ class ModuleScope(Scope): ...@@ -1121,6 +1134,19 @@ class ModuleScope(Scope):
type.vtabslot_cname = "%s.%s" % ( type.vtabslot_cname = "%s.%s" % (
Naming.obj_base_cname, type.base_type.vtabslot_cname) Naming.obj_base_cname, type.base_type.vtabslot_cname)
elif type.scope and type.scope.cfunc_entries: elif type.scope and type.scope.cfunc_entries:
# one special case here: when inheriting from builtin
# types, the methods may also be built-in, in which
# case they won't need a vtable
entry_count = len(type.scope.cfunc_entries)
base_type = type.base_type
while base_type:
# FIXME: this will break if we ever get non-inherited C methods
if not base_type.scope or entry_count > len(base_type.scope.cfunc_entries):
break
if base_type.is_builtin_type:
# builtin base type defines all methods => no vtable needed
return
base_type = base_type.base_type
#print "...allocating vtabslot_cname because there are C methods" ### #print "...allocating vtabslot_cname because there are C methods" ###
type.vtabslot_cname = Naming.vtabslot_cname type.vtabslot_cname = Naming.vtabslot_cname
if type.vtabslot_cname: if type.vtabslot_cname:
...@@ -1535,9 +1561,8 @@ class CClassScope(ClassScope): ...@@ -1535,9 +1561,8 @@ class CClassScope(ClassScope):
if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'): if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'):
error(pos, "Special method %s must be implemented via __richcmp__" % name) error(pos, "Special method %s must be implemented via __richcmp__" % name)
if name == "__new__": if name == "__new__":
warning(pos, "__new__ method of extension type will change semantics " error(pos, "__new__ method of extension type will change semantics "
"in a future version of Pyrex and Cython. Use __cinit__ instead.") "in a future version of Pyrex and Cython. Use __cinit__ instead.")
name = EncodedString("__cinit__")
entry = self.declare_var(name, py_object_type, pos, visibility='extern') entry = self.declare_var(name, py_object_type, pos, visibility='extern')
special_sig = get_special_method_signature(name) special_sig = get_special_method_signature(name)
if special_sig: if special_sig:
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import re import re
from StringIO import StringIO from StringIO import StringIO
from Scanning import PyrexScanner, StringSourceDescriptor from Scanning import PyrexScanner, StringSourceDescriptor
from Symtab import BuiltinScope, ModuleScope from Symtab import ModuleScope
import Symtab import Symtab
import PyrexTypes import PyrexTypes
from Visitor import VisitorTransform from Visitor import VisitorTransform
......
...@@ -226,6 +226,8 @@ class build_ext(_build_ext.build_ext): ...@@ -226,6 +226,8 @@ class build_ext(_build_ext.build_ext):
if not self.inplace and (self.pyrex_c_in_temp if not self.inplace and (self.pyrex_c_in_temp
or getattr(extension, 'pyrex_c_in_temp', 0)): or getattr(extension, 'pyrex_c_in_temp', 0)):
target_dir = os.path.join(self.build_temp, "pyrex") target_dir = os.path.join(self.build_temp, "pyrex")
for package_name in extension.name.split('.')[:-1]:
target_dir = os.path.join(target_dir, package_name)
else: else:
target_dir = None target_dir = None
......
...@@ -49,9 +49,9 @@ cdef extern from "Python.h": ...@@ -49,9 +49,9 @@ cdef extern from "Python.h":
# 0 is returned on success and -1 on error. # 0 is returned on success and -1 on error.
void PyBuffer_Release(object obj, object view) void PyBuffer_Release(Py_buffer *view)
# Release the buffer view over obj. This should be called when the # Release the buffer view. This should be called when the buffer
# buffer is no longer being used as it may free memory from it. # is no longer being used as it may free memory from it.
void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices) void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices)
# ?? # ??
......
__version__ = "0.14.rc0" __version__ = "0.14+"
# Void cython.* directives (for case insensitive operating systems). # Void cython.* directives (for case insensitive operating systems).
from Cython.Shadow import * from Cython.Shadow import *
include MANIFEST.in README.txt INSTALL.txt ToDo.txt USAGE.txt include MANIFEST.in README.txt INSTALL.txt ToDo.txt USAGE.txt
include COPYING.txt LICENSE.txt PKG-INFO Makefile include COPYING.txt LICENSE.txt Makefile
include .hgrev include .hgrev
include setup.py include setup.py
include setupegg.py include setupegg.py
...@@ -15,16 +15,12 @@ include Demos/callback/* ...@@ -15,16 +15,12 @@ include Demos/callback/*
include Demos/embed/* include Demos/embed/*
include Demos/freeze/* include Demos/freeze/*
include Demos/libraries/* include Demos/libraries/*
include Demos/Setup.py
include Demos/Makefile* include Demos/Makefile*
recursive-include Tools * recursive-include Tools *
recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.BROKEN bugs.txt recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.BROKEN bugs.txt
recursive-include tests *_lib.cpp *.srctree recursive-include tests *_lib.cpp *.srctree
include runtests.py include runtests.py
include Cython/Mac/Makefile
include Cython/Mac/_Filemodule_patched.c
include Cython/Debugger/Tests/cfuncs.c include Cython/Debugger/Tests/cfuncs.c
include Cython/Debugger/Tests/codefile include Cython/Debugger/Tests/codefile
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment