Author: Armin Rigo <[email protected]>
Branch:
Changeset: r77931:a24d38a16e74
Date: 2015-06-06 21:02 +0200
http://bitbucket.org/pypy/pypy/changeset/a24d38a16e74/
Log: import cffi/0a6cf359cc4a
diff --git a/lib_pypy/cffi/gc_weakref.py b/lib_pypy/cffi/gc_weakref.py
--- a/lib_pypy/cffi/gc_weakref.py
+++ b/lib_pypy/cffi/gc_weakref.py
@@ -2,18 +2,27 @@
class GcWeakrefs(object):
- # code copied and adapted from WeakKeyDictionary.
-
def __init__(self, ffi):
self.ffi = ffi
- self.data = data = {}
- def remove(k):
- destructor, cdata = data.pop(k)
- destructor(cdata)
- self.remove = remove
+ self.data = []
+ self.freelist = None
def build(self, cdata, destructor):
# make a new cdata of the same type as the original one
new_cdata = self.ffi.cast(self.ffi._backend.typeof(cdata), cdata)
- self.data[ref(new_cdata, self.remove)] = destructor, cdata
+ #
+ def remove(key):
+ assert self.data[index] is key
+ self.data[index] = self.freelist
+ self.freelist = index
+ destructor(cdata)
+ #
+ key = ref(new_cdata, remove)
+ index = self.freelist
+ if index is None:
+ index = len(self.data)
+ self.data.append(key)
+ else:
+ self.freelist = self.data[index]
+ self.data[index] = key
return new_cdata
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -775,7 +775,8 @@
try:
if ftype.is_integer_type() or fbitsize >= 0:
# accept all integers, but complain on float or double
- prnt(' (void)((p->%s) << 1);' % fname)
+ prnt(" (void)((p->%s) << 1); /* check that '%s.%s' is "
+ "an integer */" % (fname, cname, fname))
continue
# only accept exactly the type declared, except that '[]'
# is interpreted as a '*' and so will match any array length.
@@ -949,7 +950,7 @@
prnt('{')
prnt(' int n = (%s) <= 0;' % (name,))
prnt(' *o = (unsigned long long)((%s) << 0);'
- ' /* check that we get an integer */' % (name,))
+ ' /* check that %s is an integer */' % (name, name))
if check_value is not None:
if check_value > 0:
check_value = '%dU' % (check_value,)
@@ -1088,8 +1089,9 @@
self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index)
def _emit_bytecode_UnknownIntegerType(self, tp, index):
- s = '_cffi_prim_int(sizeof(%s), (((%s)-1) << 0) <= 0)' % (
- tp.name, tp.name)
+ s = ('_cffi_prim_int(sizeof(%s), (\n'
+ ' ((%s)-1) << 0 /* check that %s is an integer type
*/\n'
+ ' ) <= 0)' % (tp.name, tp.name, tp.name))
self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s)
def _emit_bytecode_RawFunctionType(self, tp, index):
diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py
--- a/lib_pypy/cffi/setuptools_ext.py
+++ b/lib_pypy/cffi/setuptools_ext.py
@@ -18,7 +18,9 @@
# __init__.py files may already try to import the file that
# we are generating.
with open(filename) as f:
- code = compile(f.read(), filename, 'exec')
+ src = f.read()
+ src += '\n' # Python 2.6 compatibility
+ code = compile(src, filename, 'exec')
exec(code, glob, glob)
diff --git a/lib_pypy/cffi/vengine_gen.py b/lib_pypy/cffi/vengine_gen.py
--- a/lib_pypy/cffi/vengine_gen.py
+++ b/lib_pypy/cffi/vengine_gen.py
@@ -402,12 +402,16 @@
else:
assert tp is not None
assert check_value is None
- prnt(tp.get_c_name(' %s(void)' % funcname, name),)
- prnt('{')
if category == 'var':
ampersand = '&'
else:
ampersand = ''
+ extra = ''
+ if category == 'const' and isinstance(tp, model.StructOrUnion):
+ extra = 'const *'
+ ampersand = '&'
+ prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name))
+ prnt('{')
prnt(' return (%s%s);' % (ampersand, name))
prnt('}')
prnt()
@@ -436,9 +440,14 @@
value += (1 << (8*self.ffi.sizeof(BLongLong)))
else:
assert check_value is None
- BFunc = self.ffi._typeof_locked(tp.get_c_name('(*)(void)',
name))[0]
+ fntypeextra = '(*)(void)'
+ if isinstance(tp, model.StructOrUnion):
+ fntypeextra = '*' + fntypeextra
+ BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra,
name))[0]
function = module.load_function(BFunc, funcname)
value = function()
+ if isinstance(tp, model.StructOrUnion):
+ value = value[0]
return value
def _loaded_gen_constant(self, tp, name, module, library):
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
@@ -1458,6 +1458,63 @@
import gc; gc.collect(); gc.collect(); gc.collect()
assert seen == [1]
+ def test_gc_2(self):
+ ffi = FFI(backend=self.Backend())
+ p = ffi.new("int *", 123)
+ seen = []
+ q1 = ffi.gc(p, lambda p: seen.append(1))
+ q2 = ffi.gc(q1, lambda p: seen.append(2))
+ import gc; gc.collect()
+ assert seen == []
+ del q1, q2
+ import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
+ assert seen == [2, 1]
+
+ def test_gc_3(self):
+ ffi = FFI(backend=self.Backend())
+ p = ffi.new("int *", 123)
+ r = ffi.new("int *", 123)
+ seen = []
+ seen_r = []
+ q1 = ffi.gc(p, lambda p: seen.append(1))
+ s1 = ffi.gc(r, lambda r: seen_r.append(4))
+ q2 = ffi.gc(q1, lambda p: seen.append(2))
+ s2 = ffi.gc(s1, lambda r: seen_r.append(5))
+ q3 = ffi.gc(q2, lambda p: seen.append(3))
+ import gc; gc.collect()
+ assert seen == []
+ assert seen_r == []
+ del q1, q2, q3, s2, s1
+ import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
+ assert seen == [3, 2, 1]
+ assert seen_r == [5, 4]
+
+ def test_gc_4(self):
+ ffi = FFI(backend=self.Backend())
+ p = ffi.new("int *", 123)
+ seen = []
+ q1 = ffi.gc(p, lambda p: seen.append(1))
+ q2 = ffi.gc(q1, lambda p: seen.append(2))
+ q3 = ffi.gc(q2, lambda p: seen.append(3))
+ import gc; gc.collect()
+ assert seen == []
+ del q1, q3 # q2 remains, and has a hard ref to q1
+ import gc; gc.collect(); gc.collect(); gc.collect()
+ assert seen == [3]
+
+ def test_gc_finite_list(self):
+ ffi = FFI(backend=self.Backend())
+ p = ffi.new("int *", 123)
+ keepalive = []
+ for i in range(10):
+ keepalive.append(ffi.gc(p, lambda p: None))
+ assert len(ffi.gc_weakrefs.data) == i + 1 #should be a private
attr
+ del keepalive[:]
+ import gc; gc.collect(); gc.collect()
+ for i in range(10):
+ keepalive.append(ffi.gc(p, lambda p: None))
+ assert len(ffi.gc_weakrefs.data) == 10
+
def test_CData_CType(self):
ffi = FFI(backend=self.Backend())
assert isinstance(ffi.cast("int", 0), ffi.CData)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py
@@ -2228,3 +2228,11 @@
ffi.cdef("static const int FOO = 123;")
e = py.test.raises(VerificationError, ffi.verify, "#define FOO 124")
assert str(e.value).endswith("FOO has the real value 124, not 123")
+
+def test_const_struct_global():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int x; ...; } T; const T myglob;")
+ lib = ffi.verify("typedef struct { double y; int x; } T;"
+ "const T myglob = { 0.1, 42 };")
+ assert ffi.typeof(lib.myglob) == ffi.typeof("T")
+ assert lib.myglob.x == 42
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
@@ -1,5 +1,5 @@
# Generated by pypy/tool/import_cffi.py
-import py
+import py, sys
import _cffi_backend as _cffi1_backend
@@ -66,6 +66,7 @@
ffi = _cffi1_backend.FFI()
p = ffi.new("char[]", init=b"foobar\x00baz")
assert ffi.string(p) == b"foobar"
+ assert ffi.string(cdata=p, maxlen=3) == b"foo"
def test_ffi_errno():
# xxx not really checking errno, just checking that we can read/write it
@@ -158,11 +159,18 @@
assert str(e.value) == ("undefined struct/union name\n"
"struct never_heard_of_s\n"
" ^")
+ e = py.test.raises(ffi.error, ffi.cast, "\t\n\x01\x1f~\x7f\x80\xff", 0)
+ assert str(e.value) == ("identifier expected\n"
+ " ??~???\n"
+ " ^")
+ e = py.test.raises(ffi.error, ffi.cast, "X" * 600, 0)
+ assert str(e.value) == ("undefined type name")
def test_ffi_buffer():
ffi = _cffi1_backend.FFI()
a = ffi.new("signed char[]", [5, 6, 7])
assert ffi.buffer(a)[:] == b'\x05\x06\x07'
+ assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06'
def test_ffi_from_buffer():
import array
@@ -179,3 +187,11 @@
ffi = _cffi1_backend.FFI()
assert isinstance(ffi.cast("int", 42), CData)
assert isinstance(ffi.typeof("int"), CType)
+
+def test_ffi_getwinerror():
+ if sys.platform != "win32":
+ py.test.skip("for windows")
+ ffi = _cffi1_backend.FFI()
+ n = (1 << 29) + 42
+ code, message = ffi.getwinerror(code=n)
+ assert code == n
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py
@@ -33,7 +33,9 @@
struct ab { int a, b; };
struct abc { int a, b, c; };
- enum foq { A0, B0, CC0, D0 };
+ /* don't use A0, B0, CC0, D0 because termios.h might be included
+ and it has its own #defines for these names */
+ enum foq { cffiA0, cffiB0, cffiCC0, cffiD0 };
enum bar { A1, B1=-2, CC1, D1, E1 };
enum baz { A2=0x1000, B2=0x2000 };
enum foo2 { A3, B3, C3, D3 };
@@ -879,9 +881,9 @@
def test_enum(self):
# enum foq { A0, B0, CC0, D0 };
- assert ffi.string(ffi.cast("enum foq", 0)) == "A0"
- assert ffi.string(ffi.cast("enum foq", 2)) == "CC0"
- assert ffi.string(ffi.cast("enum foq", 3)) == "D0"
+ assert ffi.string(ffi.cast("enum foq", 0)) == "cffiA0"
+ assert ffi.string(ffi.cast("enum foq", 2)) == "cffiCC0"
+ assert ffi.string(ffi.cast("enum foq", 3)) == "cffiD0"
assert ffi.string(ffi.cast("enum foq", 4)) == "4"
# enum bar { A1, B1=-2, CC1, D1, E1 };
assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
@@ -1408,6 +1410,47 @@
import gc; gc.collect(); gc.collect(); gc.collect()
assert seen == [1]
+ def test_gc_2(self):
+ p = ffi.new("int *", 123)
+ seen = []
+ q1 = ffi.gc(p, lambda p: seen.append(1))
+ q2 = ffi.gc(q1, lambda p: seen.append(2))
+ import gc; gc.collect()
+ assert seen == []
+ del q1, q2
+ import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
+ assert seen == [2, 1]
+
+ def test_gc_3(self):
+ p = ffi.new("int *", 123)
+ r = ffi.new("int *", 123)
+ seen = []
+ seen_r = []
+ q1 = ffi.gc(p, lambda p: seen.append(1))
+ s1 = ffi.gc(r, lambda r: seen_r.append(4))
+ q2 = ffi.gc(q1, lambda p: seen.append(2))
+ s2 = ffi.gc(s1, lambda r: seen_r.append(5))
+ q3 = ffi.gc(q2, lambda p: seen.append(3))
+ import gc; gc.collect()
+ assert seen == []
+ assert seen_r == []
+ del q1, q2, q3, s2, s1
+ import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
+ assert seen == [3, 2, 1]
+ assert seen_r == [5, 4]
+
+ def test_gc_4(self):
+ p = ffi.new("int *", 123)
+ seen = []
+ q1 = ffi.gc(p, lambda p: seen.append(1))
+ q2 = ffi.gc(q1, lambda p: seen.append(2))
+ q3 = ffi.gc(q2, lambda p: seen.append(3))
+ import gc; gc.collect()
+ assert seen == []
+ del q1, q3 # q2 remains, and has a hard ref to q1
+ import gc; gc.collect(); gc.collect(); gc.collect()
+ assert seen == [3]
+
def test_CData_CType(self):
assert isinstance(ffi.cast("int", 0), ffi.CData)
assert isinstance(ffi.new("int *"), ffi.CData)
@@ -1534,8 +1577,8 @@
assert p.a == -52525
#
p = ffi.cast("enum foq", 2)
- assert ffi.string(p) == "CC0"
- assert ffi2.sizeof("char[CC0]") == 2
+ assert ffi.string(p) == "cffiCC0"
+ assert ffi2.sizeof("char[cffiCC0]") == 2
#
p = ffi.new("anon_foo_t *", [-52526])
assert p.a == -52526
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
@@ -8,6 +8,7 @@
def setup_module(mod):
SRC = """
+ #include <string.h>
#define FOOBAR (-42)
static const int FOOBAZ = -43;
#define BIGPOS 420000000000L
@@ -54,6 +55,7 @@
struct foo_s;
typedef struct bar_s { int x; signed char a[]; } bar_t;
enum foo_e { AA, BB, CC };
+ int strlen(const char *);
""")
ffi.set_source('re_python_pysrc', None)
ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
@@ -82,10 +84,20 @@
def test_function_with_varargs():
import _cffi_backend
from re_python_pysrc import ffi
- lib = ffi.dlopen(extmod)
+ lib = ffi.dlopen(extmod, 0)
assert lib.add43(45, ffi.cast("int", -5)) == 45
assert type(lib.add43) is _cffi_backend.FFI.CData
+def test_dlopen_none():
+ import _cffi_backend
+ from re_python_pysrc import ffi
+ name = None
+ if sys.platform == 'win32':
+ import ctypes.util
+ name = ctypes.util.find_msvcrt()
+ lib = ffi.dlopen(name)
+ assert lib.strlen(b"hello") == 5
+
def test_dlclose():
import _cffi_backend
from re_python_pysrc import ffi
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -993,3 +993,13 @@
ffi.typeof('function_t*')
lib.function(ffi.NULL)
# assert did not crash
+
+def test_alignment_of_longlong():
+ ffi = FFI()
+ x1 = ffi.alignof('unsigned long long')
+ assert x1 in [4, 8]
+ ffi.cdef("struct foo_s { unsigned long long x; };")
+ lib = verify(ffi, 'test_alignment_of_longlong',
+ "struct foo_s { unsigned long long x; };")
+ assert ffi.alignof('unsigned long long') == x1
+ assert ffi.alignof('struct foo_s') == x1
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
@@ -2118,25 +2118,19 @@
try:
ffi1 = FFI()
ffi1.cdef("int foo_verify_dlopen_flags;")
-
- sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY)
+ sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_NOW)
lib1 = ffi1.verify("int foo_verify_dlopen_flags;")
- lib2 = get_second_lib()
-
- lib1.foo_verify_dlopen_flags = 42
- assert lib2.foo_verify_dlopen_flags == 42
- lib2.foo_verify_dlopen_flags += 1
- assert lib1.foo_verify_dlopen_flags == 43
finally:
sys.setdlopenflags(old)
-def get_second_lib():
- # Hack, using modulename makes the test fail
ffi2 = FFI()
- ffi2.cdef("int foo_verify_dlopen_flags;")
- lib2 = ffi2.verify("int foo_verify_dlopen_flags;",
- flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY)
- return lib2
+ ffi2.cdef("int *getptr(void);")
+ lib2 = ffi2.verify("""
+ extern int foo_verify_dlopen_flags;
+ static int *getptr(void) { return &foo_verify_dlopen_flags; }
+ """)
+ p = lib2.getptr()
+ assert ffi1.addressof(lib1, 'foo_verify_dlopen_flags') == p
def test_consider_not_implemented_function_type():
ffi = FFI()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
@@ -30,13 +30,17 @@
if hasattr(self, 'saved_cwd'):
os.chdir(self.saved_cwd)
- def run(self, args):
+ def run(self, args, cwd=None):
env = os.environ.copy()
- newpath = self.rootdir
- if 'PYTHONPATH' in env:
- newpath += os.pathsep + env['PYTHONPATH']
- env['PYTHONPATH'] = newpath
- subprocess.check_call([self.executable] + args, env=env)
+ # a horrible hack to prevent distutils from finding ~/.pydistutils.cfg
+ # (there is the --no-user-cfg option, but not in Python 2.6...)
+ env['HOME'] = '/this/path/does/not/exist'
+ if cwd is None:
+ newpath = self.rootdir
+ if 'PYTHONPATH' in env:
+ newpath += os.pathsep + env['PYTHONPATH']
+ env['PYTHONPATH'] = newpath
+ subprocess.check_call([self.executable] + args, cwd=cwd, env=env)
def _prepare_setuptools(self):
if hasattr(TestDist, '_setuptools_ready'):
@@ -45,8 +49,7 @@
import setuptools
except ImportError:
py.test.skip("setuptools not found")
- subprocess.check_call([self.executable, 'setup.py', 'egg_info'],
- cwd=self.rootdir)
+ self.run(['setup.py', 'egg_info'], cwd=self.rootdir)
TestDist._setuptools_ready = True
def check_produced_files(self, content, curdir=None):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit