Author: Brian Kearns <[email protected]>
Branch: py3k
Changeset: r62245:17454c649f51
Date: 2013-03-08 14:56 -0500
http://bitbucket.org/pypy/pypy/changeset/17454c649f51/
Log: merge default
diff --git a/pypy/module/_cffi_backend/cdataobj.py
b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -92,15 +92,20 @@
cdata1 = self._cdata
other = space.interpclass_w(w_other)
if isinstance(other, W_CData):
+ if requires_ordering:
+ if (isinstance(self.ctype, W_CTypePrimitive) or
+ isinstance(other.ctype, W_CTypePrimitive)):
+ raise OperationError(space.w_TypeError,
+ space.wrap("cannot do comparison on a "
+ "primitive cdata"))
cdata2 = other._cdata
+ elif (misc.is_zero(space, w_other) and
+ not isinstance(self.ctype, W_CTypePrimitive)):
+ cdata2 = lltype.nullptr(rffi.CCHARP.TO)
else:
return space.w_NotImplemented
if requires_ordering:
- if (isinstance(self.ctype, W_CTypePrimitive) or
- isinstance(other.ctype, W_CTypePrimitive)):
- raise OperationError(space.w_TypeError,
- space.wrap("cannot do comparison on a primitive cdata"))
cdata1 = rffi.cast(lltype.Unsigned, cdata1)
cdata2 = rffi.cast(lltype.Unsigned, cdata2)
return space.newbool(op(cdata1, cdata2))
diff --git a/pypy/module/_cffi_backend/ctypeptr.py
b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -156,6 +156,10 @@
space = self.space
ob = space.interpclass_w(w_ob)
if not isinstance(ob, cdataobj.W_CData):
+ if misc.is_zero(space, w_ob):
+ NULL = lltype.nullptr(rffi.CCHARP.TO)
+ rffi.cast(rffi.CCHARPP, cdata)[0] = NULL
+ return
raise self._convert_error("cdata pointer", w_ob)
other = ob.ctype
if not isinstance(other, W_CTypePtrBase):
@@ -176,8 +180,8 @@
class W_CTypePointer(W_CTypePtrBase):
- _attrs_ = ['cache_array_type']
- _immutable_fields_ = ['cache_array_type?']
+ _attrs_ = ['is_file', 'cache_array_type']
+ _immutable_fields_ = ['is_file', 'cache_array_type?']
kind = "pointer"
cache_array_type = None
@@ -188,6 +192,8 @@
extra = "(*)" # obscure case: see test_array_add
else:
extra = " *"
+ self.is_file = (ctitem.name == "struct _IO_FILE" or
+ ctitem.name == "struct $FILE")
W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem)
def newp(self, w_init):
@@ -239,23 +245,53 @@
p = rffi.ptradd(cdata, i * self.ctitem.size)
return cdataobj.W_CData(space, p, self)
+ def cast(self, w_ob):
+ if self.is_file:
+ value = self.prepare_file(w_ob)
+ if value:
+ return cdataobj.W_CData(self.space, value, self)
+ return W_CTypePtrBase.cast(self, w_ob)
+
+ def prepare_file(self, w_ob):
+ from pypy.module._file.interp_file import W_File
+ from pypy.module._cffi_backend import ctypefunc
+ ob = self.space.interpclass_w(w_ob)
+ if isinstance(ob, W_File):
+ return prepare_file_argument(self.space, ob)
+ else:
+ return lltype.nullptr(rffi.CCHARP.TO)
+
def _prepare_pointer_call_argument(self, w_init, cdata):
space = self.space
- if (space.isinstance_w(w_init, space.w_list) or
+ if misc.is_zero(space, w_init):
+ # Convert 0 to NULL. Note that passing 0 is not ambigous,
+ # despite the potential confusion: as a 'T*' argument, 0 means
+ # NULL, but as a 'T[]' argument it would mean "array of size 0"
+ # --- except that we specifically refuse to interpret numbers
+ # as the array size when passing arguments.
+ rffi.cast(rffi.CCHARPP, cdata)[0] = lltype.nullptr(rffi.CCHARP.TO)
+ return 3
+ elif (space.isinstance_w(w_init, space.w_list) or
space.isinstance_w(w_init, space.w_tuple)):
length = space.int_w(space.len(w_init))
elif (space.isinstance_w(w_init, space.w_unicode) or
space.isinstance_w(w_init, space.w_bytes)):
# from a string, we add the null terminator
length = space.int_w(space.len(w_init)) + 1
+ elif self.is_file:
+ result = self.prepare_file(w_init)
+ if result:
+ rffi.cast(rffi.CCHARPP, cdata)[0] = result
+ return 2
+ return 0
else:
- return False
+ return 0
itemsize = self.ctitem.size
if itemsize <= 0:
if isinstance(self.ctitem, ctypevoid.W_CTypeVoid):
itemsize = 1
else:
- return False
+ return 0
try:
datasize = ovfcheck(length * itemsize)
except OverflowError:
@@ -269,7 +305,7 @@
lltype.free(result, flavor='raw')
raise
rffi.cast(rffi.CCHARPP, cdata)[0] = result
- return True
+ return 1
def convert_argument_from_object(self, cdata, w_ob):
from pypy.module._cffi_backend.ctypefunc import set_mustfree_flag
@@ -277,7 +313,7 @@
ob = space.interpclass_w(w_ob)
result = (not isinstance(ob, cdataobj.W_CData) and
self._prepare_pointer_call_argument(w_ob, cdata))
- if not result:
+ if result == 0:
self.convert_from_object(cdata, w_ob)
set_mustfree_flag(cdata, result)
return result
@@ -307,3 +343,36 @@
if attrchar == 'i': # item
return self.space.wrap(self.ctitem)
return W_CTypePtrBase._fget(self, attrchar)
+
+# ____________________________________________________________
+
+
+rffi_fdopen = rffi.llexternal("fdopen", [rffi.INT, rffi.CCHARP], rffi.CCHARP)
+rffi_setbuf = rffi.llexternal("setbuf", [rffi.CCHARP, rffi.CCHARP],
lltype.Void)
+rffi_fclose = rffi.llexternal("fclose", [rffi.CCHARP], rffi.INT)
+
+class CffiFileObj(object):
+ _immutable_ = True
+
+ def __init__(self, fd, mode):
+ self.llf = rffi_fdopen(fd, mode)
+ if not self.llf:
+ raise OSError(rposix.get_errno(), "fdopen failed")
+ rffi_setbuf(self.llf, lltype.nullptr(rffi.CCHARP.TO))
+
+ def close(self):
+ rffi_fclose(self.llf)
+
+
+def prepare_file_argument(space, fileobj):
+ fileobj.direct_flush()
+ if fileobj.cffi_fileobj is None:
+ fd = fileobj.direct_fileno()
+ if fd < 0:
+ raise OperationError(space.w_ValueError,
+ space.wrap("file has no OS file descriptor"))
+ try:
+ fileobj.cffi_fileobj = CffiFileObj(fd, fileobj.mode)
+ except OSError, e:
+ raise wrap_oserror(space, e)
+ return fileobj.cffi_fileobj.llf
diff --git a/pypy/module/_cffi_backend/misc.py
b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -209,6 +209,11 @@
neg_msg = "can't convert negative number to unsigned"
ovf_msg = "long too big to convert"
+def is_zero(space, w_ob):
+ return ((space.isinstance_w(w_ob, space.w_int) or
+ space.isinstance_w(w_ob, space.w_long))
+ and not space.is_true(w_ob))
+
# ____________________________________________________________
class _NotStandardObject(Exception):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -387,8 +387,19 @@
assert (x != None) is True
assert (x == ["hello"]) is False
assert (x != ["hello"]) is True
- y = cast(p, 0)
- assert (y == None) is False
+
+def test_cmp_pointer_with_0():
+ p = new_pointer_type(new_primitive_type("int"))
+ x = cast(p, 0)
+ assert (x == 0) is True
+ assert (x != 0) is False
+ assert (0 == x) is True
+ assert (0 != x) is False
+ y = cast(p, 42)
+ assert (y == 0) is False
+ assert (y != 0) is True
+ assert (0 == y) is False
+ assert (0 != y) is True
def test_invalid_indexing():
p = new_primitive_type("int")
@@ -768,7 +779,7 @@
assert s.a2 == 456
assert s.a3 == 0
assert s.p4 == cast(BVoidP, 0)
- assert s.p4 != 0
+ assert s.p4 == 0
#
s = newp(BStructPtr, {'a2': 41122, 'a3': -123})
assert s.a1 == 0
@@ -781,11 +792,14 @@
p = newp(BIntPtr, 14141)
s = newp(BStructPtr, [12, 34, 56, p])
assert s.p4 == p
- assert s.p4
+ s.p4 = 0
+ assert s.p4 == 0
#
s = newp(BStructPtr, [12, 34, 56, cast(BVoidP, 0)])
+ assert s.p4 == 0
+ #
+ s = newp(BStructPtr, [12, 34, 56, 0])
assert s.p4 == cast(BVoidP, 0)
- assert not s.p4
#
py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None])
@@ -1003,10 +1017,11 @@
f = cast(BFunc23, _testfunc(23))
res = f(b"foo")
assert res == 1000 * ord(b'f')
- res = f(cast(BVoidP, 0)) # NULL
+ res = f(0) # NULL
+ assert res == -42
+ res = f(long(0)) # NULL
assert res == -42
py.test.raises(TypeError, f, None)
- py.test.raises(TypeError, f, 0)
py.test.raises(TypeError, f, 0.0)
def test_call_function_23_bis():
@@ -2497,7 +2512,6 @@
pass # win32
def test_FILE():
- """FILE is not supported natively any more."""
if sys.platform == "win32":
py.test.skip("testing FILE not implemented")
#
@@ -2507,16 +2521,82 @@
BCharP = new_pointer_type(BChar)
BInt = new_primitive_type("int")
BFunc = new_function_type((BCharP, BFILEP), BInt, False)
+ BFunc2 = new_function_type((BFILEP, BCharP), BInt, True)
+ ll = find_and_load_library('c')
+ fputs = ll.load_function(BFunc, "fputs")
+ fscanf = ll.load_function(BFunc2, "fscanf")
+ #
+ import posix
+ fdr, fdw = posix.pipe()
+ fr1 = posix.fdopen(fdr, 'rb', 256)
+ fw1 = posix.fdopen(fdw, 'wb', 256)
+ #
+ fw1.write(b"X")
+ res = fputs(b"hello world\n", fw1)
+ assert res >= 0
+ fw1.flush() # should not be needed
+ #
+ p = newp(new_array_type(BCharP, 100), None)
+ res = fscanf(fr1, b"%s\n", p)
+ assert res == 1
+ assert string(p) == b"Xhello"
+ fr1.close()
+ fw1.close()
+
+def test_FILE_only_for_FILE_arg():
+ if sys.platform == "win32":
+ py.test.skip("testing FILE not implemented")
+ #
+ B_NOT_FILE = new_struct_type("NOT_FILE")
+ B_NOT_FILEP = new_pointer_type(B_NOT_FILE)
+ BChar = new_primitive_type("char")
+ BCharP = new_pointer_type(BChar)
+ BInt = new_primitive_type("int")
+ BFunc = new_function_type((BCharP, B_NOT_FILEP), BInt, False)
ll = find_and_load_library('c')
fputs = ll.load_function(BFunc, "fputs")
#
import posix
fdr, fdw = posix.pipe()
- fr1 = posix.fdopen(fdr, 'rb', 256)
+ fr1 = posix.fdopen(fdr, 'r')
+ fw1 = posix.fdopen(fdw, 'w')
+ #
+ e = py.test.raises(TypeError, fputs, b"hello world\n", fw1)
+ assert str(e.value).startswith(
+ "initializer for ctype 'struct NOT_FILE *' must "
+ "be a cdata pointer, not ")
+
+def test_FILE_object():
+ if sys.platform == "win32":
+ py.test.skip("testing FILE not implemented")
+ #
+ BFILE = new_struct_type("$FILE")
+ BFILEP = new_pointer_type(BFILE)
+ BChar = new_primitive_type("char")
+ BCharP = new_pointer_type(BChar)
+ BInt = new_primitive_type("int")
+ BFunc = new_function_type((BCharP, BFILEP), BInt, False)
+ BFunc2 = new_function_type((BFILEP,), BInt, False)
+ ll = find_and_load_library('c')
+ fputs = ll.load_function(BFunc, "fputs")
+ fileno = ll.load_function(BFunc2, "fileno")
+ #
+ import posix
+ fdr, fdw = posix.pipe()
fw1 = posix.fdopen(fdw, 'wb', 256)
- py.test.raises(TypeError, fputs, b"hello world\n", fw1)
- fr1.close()
+ #
+ fw1p = cast(BFILEP, fw1)
+ fw1.write(b"X")
+ fw1.flush()
+ res = fputs(b"hello\n", fw1p)
+ assert res >= 0
+ res = fileno(fw1p)
+ assert (res == fdw) == (sys.version_info < (3,))
fw1.close()
+ #
+ data = posix.read(fdr, 256)
+ assert data == b"Xhello\n"
+ posix.close(fdr)
def test_GetLastError():
if sys.platform != "win32":
@@ -2644,17 +2724,6 @@
c[1:3] = d
assert list(c) == [0, 40, 50, 30, 0]
-def test_FILE_forbidden():
- BFILE = new_struct_type("_IO_FILE")
- BFILEP = new_pointer_type(BFILE)
- BFunc = new_function_type((BFILEP,), BFILEP, False)
- func = cast(BFunc, 0)
- with open(__file__, "rb") as f:
- e = py.test.raises(TypeError, func, f)
- if '__pypy__' not in sys.builtin_module_names:
- assert ('note that you cannot pass Python files directly '
- 'any more since CFFI 0.6') in str(e.value)
-
def test_version():
# this test is here mostly for PyPy
assert __version__ == "0.6"
diff --git a/pypy/module/_cffi_backend/test/test_ztranslation.py
b/pypy/module/_cffi_backend/test/test_ztranslation.py
--- a/pypy/module/_cffi_backend/test/test_ztranslation.py
+++ b/pypy/module/_cffi_backend/test/test_ztranslation.py
@@ -1,7 +1,20 @@
from pypy.objspace.fake.checkmodule import checkmodule
+from pypy.module._cffi_backend import ctypeptr
+from rpython.rtyper.lltypesystem import lltype, rffi
# side-effect: FORMAT_LONGDOUBLE must be built before test_checkmodule()
from pypy.module._cffi_backend import misc
def test_checkmodule():
- checkmodule('_cffi_backend')
+ # prepare_file_argument() is not working without translating the _file
+ # module too
+ def dummy_prepare_file_argument(space, fileobj):
+ return lltype.nullptr(rffi.CCHARP.TO)
+ old = ctypeptr.prepare_file_argument
+ try:
+ ctypeptr.prepare_file_argument = dummy_prepare_file_argument
+ #
+ checkmodule('_cffi_backend')
+ #
+ finally:
+ ctypeptr.prepare_file_argument = old
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -4281,6 +4281,35 @@
"""
self.optimize_loop(ops, expected)
+ def test_add_sub_ovf_second_operation_regular(self):
+ py.test.skip("Smalltalk would like this to pass")
+ # This situation occurs in Smalltalk because it uses 1-based indexing.
+ # The below code is equivalent to a loop over an array.
+ ops = """
+ [i1]
+ i2 = int_sub(i1, 1)
+ escape(i2)
+ i3 = int_add_ovf(i1, 1)
+ guard_no_overflow() []
+ jump(i3)
+ """
+ preamble = """
+ [i1]
+ i2 = int_sub(i1, 1)
+ escape(i2)
+ i3 = int_add_ovf(i1, 1)
+ guard_no_overflow() []
+ jump(i3, i1)
+ """
+ expected = """
+ [i1, i2]
+ escape(i2)
+ i3 = int_add_ovf(i1, 1)
+ guard_no_overflow() []
+ jump(i3, i1)
+ """
+ self.optimize_loop(ops, expected, preamble)
+
def test_add_sub_ovf_virtual_unroll(self):
ops = """
[p15]
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit