Commit 7f630812 authored by Vitja Makarov's avatar Vitja Makarov

Merge remote branch 'upstream/master'

Conflicts:
	Cython/Compiler/Nodes.py
parents 46bbbaba fd4f9c44
...@@ -1437,7 +1437,7 @@ class NameNode(AtomicExprNode): ...@@ -1437,7 +1437,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()
...@@ -2960,7 +2960,14 @@ class SimpleCallNode(CallNode): ...@@ -2960,7 +2960,14 @@ 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: if self.args[i].type.is_pyobject:
error(self.args[i].pos, error(self.args[i].pos,
......
...@@ -1459,7 +1459,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1459,7 +1459,7 @@ class FuncDefNode(StatNode, BlockNode):
# Decref any increfed args # Decref any increfed args
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_decref(entry) code.put_var_decref(entry)
if self.needs_closure and not self.is_generator: if self.needs_closure and not self.is_generator:
code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type) code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
...@@ -1527,13 +1527,14 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1527,13 +1527,14 @@ class FuncDefNode(StatNode, BlockNode):
import Buffer import Buffer
lenv = self.local_scope lenv = self.local_scope
acquire_gil = self.acquire_gil
self.generate_argument_parsing_code(env, code) self.generate_argument_parsing_code(env, code)
# If an argument is assigned to in the body, we must # If an argument is assigned to in the body, we must
# 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:
...@@ -3479,6 +3480,12 @@ class ExprStatNode(StatNode): ...@@ -3479,6 +3480,12 @@ class ExprStatNode(StatNode):
self.expr.result_is_used = False # hint that .result() may safely be left empty self.expr.result_is_used = False # hint that .result() may safely be left empty
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():
......
...@@ -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
......
...@@ -112,6 +112,7 @@ def handle_special_build(modname, pyxfilename): ...@@ -112,6 +112,7 @@ def handle_special_build(modname, pyxfilename):
return ext, setup_args return ext, setup_args
def handle_dependencies(pyxfilename): def handle_dependencies(pyxfilename):
testing = '_test_files' in globals()
dependfile = os.path.splitext(pyxfilename)[0] + PYXDEP_EXT dependfile = os.path.splitext(pyxfilename)[0] + PYXDEP_EXT
# by default let distutils decide whether to rebuild on its own # by default let distutils decide whether to rebuild on its own
...@@ -132,6 +133,7 @@ def handle_dependencies(pyxfilename): ...@@ -132,6 +133,7 @@ def handle_dependencies(pyxfilename):
files.extend(glob.glob(fullpath)) files.extend(glob.glob(fullpath))
# only for unit testing to see we did the right thing # only for unit testing to see we did the right thing
if testing:
_test_files[:] = [] #$pycheck_no _test_files[:] = [] #$pycheck_no
# if any file that the pyxfile depends upon is newer than # if any file that the pyxfile depends upon is newer than
...@@ -143,6 +145,7 @@ def handle_dependencies(pyxfilename): ...@@ -143,6 +145,7 @@ def handle_dependencies(pyxfilename):
print("Rebuilding because of ", file) print("Rebuilding because of ", file)
filetime = os.path.getmtime(file) filetime = os.path.getmtime(file)
os.utime(pyxfilename, (filetime, filetime)) os.utime(pyxfilename, (filetime, filetime))
if testing:
_test_files.append(file) _test_files.append(file)
def build_module(name, pyxfilename, pyxbuild_dir=None): def build_module(name, pyxfilename, pyxbuild_dir=None):
......
import pyximport; pyximport.install() import pyximport; pyximport.install(reload_support=True)
import os, sys import os, sys
import time, shutil import time, shutil
import tempfile import tempfile
...@@ -21,6 +21,7 @@ def on_remove_file_error(func, path, excinfo): ...@@ -21,6 +21,7 @@ def on_remove_file_error(func, path, excinfo):
print "You may want to delete this yourself when you get a chance." print "You may want to delete this yourself when you get a chance."
def test(): def test():
pyximport._test_files = []
tempdir = make_tempdir() tempdir = make_tempdir()
sys.path.append(tempdir) sys.path.append(tempdir)
filename = os.path.join(tempdir, "dummy.pyx") filename = os.path.join(tempdir, "dummy.pyx")
......
...@@ -82,20 +82,26 @@ def ticket_338(): ...@@ -82,20 +82,26 @@ def ticket_338():
for obj from 0 <= obj < 4: for obj from 0 <= obj < 4:
pass pass
def bare_pyvar_name(object x):
with nogil:
x
# For m(), the important thing is that there are errors on all lines in the range 23-69 # For m(), the important thing is that there are errors on all lines in the range 23-69
# except these: 34, 44, 56, 58, 60, 62-64 # except these: 29, 34, 44, 56, 58, 60, 62-64
_ERRORS = u""" _ERRORS = u"""
1:5: Function with Python return type cannot be declared nogil 1:5: Function with Python return type cannot be declared nogil
4:5: Function declared nogil has Python locals or temporaries 4:5: Function declared nogil has Python locals or temporaries
6:6: Assignment of Python object not allowed without gil 6:6: Assignment of Python object not allowed without gil
9:5: Discarding owned Python object not allowed without gil
11:5: Function with Python return type cannot be declared nogil 11:5: Function with Python return type cannot be declared nogil
15:5: Calling gil-requiring function not allowed without gil 15:5: Calling gil-requiring function not allowed without gil
24:9: Calling gil-requiring function not allowed without gil 24:9: Calling gil-requiring function not allowed without gil
26:12: Assignment of Python object not allowed without gil 26:12: Assignment of Python object not allowed without gil
28:8: Discarding owned Python object not allowed without gil
28:16: Constructing complex number not allowed without gil 28:16: Constructing complex number not allowed without gil
29:12: Accessing Python global or builtin not allowed without gil
30:8: Backquote expression not allowed without gil 30:8: Backquote expression not allowed without gil
30:8: Discarding owned Python object not allowed without gil
30:9: Operation not allowed without gil 30:9: Operation not allowed without gil
31:15: Assignment of Python object not allowed without gil 31:15: Assignment of Python object not allowed without gil
31:15: Operation not allowed without gil 31:15: Operation not allowed without gil
...@@ -105,20 +111,30 @@ _ERRORS = u""" ...@@ -105,20 +111,30 @@ _ERRORS = u"""
32:25: Constructing Python list not allowed without gil 32:25: Constructing Python list not allowed without gil
32:25: Operation not allowed without gil 32:25: Operation not allowed without gil
33:17: Iterating over Python object not allowed without gil 33:17: Iterating over Python object not allowed without gil
35:11: Discarding owned Python object not allowed without gil
35:11: Indexing Python object not allowed without gil 35:11: Indexing Python object not allowed without gil
36:11: Discarding owned Python object not allowed without gil
36:11: Slicing Python object not allowed without gil 36:11: Slicing Python object not allowed without gil
37:11: Constructing Python slice object not allowed without gil 37:11: Constructing Python slice object not allowed without gil
37:11: Discarding owned Python object not allowed without gil
37:11: Indexing Python object not allowed without gil 37:11: Indexing Python object not allowed without gil
37:13: Converting to Python object not allowed without gil 37:13: Converting to Python object not allowed without gil
37:15: Converting to Python object not allowed without gil 37:15: Converting to Python object not allowed without gil
37:17: Converting to Python object not allowed without gil 37:17: Converting to Python object not allowed without gil
38:11: Accessing Python attribute not allowed without gil 38:11: Accessing Python attribute not allowed without gil
39: 9: Constructing Python tuple not allowed without gil 38:11: Discarding owned Python object not allowed without gil
40: 8: Constructing Python list not allowed without gil 39:9: Constructing Python tuple not allowed without gil
41: 8: Constructing Python dict not allowed without gil 39:9: Discarding owned Python object not allowed without gil
40:8: Constructing Python list not allowed without gil
40:8: Discarding owned Python object not allowed without gil
41:8: Constructing Python dict not allowed without gil
41:8: Discarding owned Python object not allowed without gil
42:12: Discarding owned Python object not allowed without gil
42:12: Truth-testing Python object not allowed without gil 42:12: Truth-testing Python object not allowed without gil
43:13: Python type test not allowed without gil 43:13: Python type test not allowed without gil
45:10: Discarding owned Python object not allowed without gil
45:10: Operation not allowed without gil 45:10: Operation not allowed without gil
46:8: Discarding owned Python object not allowed without gil
46:8: Operation not allowed without gil 46:8: Operation not allowed without gil
47:10: Assignment of Python object not allowed without gil 47:10: Assignment of Python object not allowed without gil
47:14: Assignment of Python object not allowed without gil 47:14: Assignment of Python object not allowed without gil
......
cdef class Owner:
cdef object x
cdef call_me_with_owner(Owner owner, x):
owner.x = "def" # overwrite external reference
return x # crashes if x is not owned by function or caller
def test_ext_type_attr():
"""
>>> test_ext_type_attr()
'abc5'
"""
owner = Owner()
owner.x = ''.join("abc%d" % 5) # non-interned object
return call_me_with_owner(owner, owner.x)
cdef void call_me_without_gil(Owner owner, x) with gil:
owner.x = "def" # overwrite external reference
print x # crashes if x is not owned by function or caller
def test_ext_type_attr_nogil():
"""
>>> test_ext_type_attr_nogil()
abc5
"""
owner = Owner()
owner.x = ''.join("abc%d" % 5) # non-interned object
with nogil:
call_me_without_gil(owner, owner.x)
# the following isn't dangerous as long as index access uses temps
cdef call_me_with_list(list l, x):
l[:] = [(1,2), (3,4)] # overwrite external reference
return x # crashes if x is not owned by function or caller
def test_index():
"""
>>> test_index()
[3, 4]
"""
l = [[1,2],[3,4]]
return call_me_with_list(l, l[1])
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