Author: Armin Rigo <[email protected]>
Branch:
Changeset: r66777:ac6fb07dde4e
Date: 2013-09-03 09:18 +0200
http://bitbucket.org/pypy/pypy/changeset/ac6fb07dde4e/
Log: Import cffi/6fee32c68e45
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,5 +4,5 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "0.7"
-__version_info__ = (0, 7)
+__version__ = "0.7.2"
+__version_info__ = (0, 7, 2)
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -54,7 +54,8 @@
# _cffi_backend.so compiled.
import _cffi_backend as backend
from . import __version__
- assert backend.__version__ == __version__
+ assert (backend.__version__ == __version__ or
+ backend.__version__ == __version__[:3])
# (If you insist you can also try to pass the option
# 'backend=backend_ctypes.CTypesBackend()', but don't
# rely on it! It's probably not going to work well.)
diff --git a/lib_pypy/cffi/commontypes.py b/lib_pypy/cffi/commontypes.py
--- a/lib_pypy/cffi/commontypes.py
+++ b/lib_pypy/cffi/commontypes.py
@@ -30,7 +30,9 @@
elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
result = model.PrimitiveType(result)
else:
- assert commontype != result
+ if commontype == result:
+ raise api.FFIError("Unsupported type: %r. Please file a bug "
+ "if you think it should be." %
(commontype,))
result = resolve_common_type(result) # recursively
assert isinstance(result, model.BaseTypeByIdentity)
_CACHE[commontype] = result
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -290,13 +290,26 @@
# assume a primitive type. get it from .names, but reduce
# synonyms to a single chosen combination
names = list(type.names)
- if names == ['signed'] or names == ['unsigned']:
- names.append('int')
- if names[0] == 'signed' and names != ['signed', 'char']:
- names.pop(0)
- if (len(names) > 1 and names[-1] == 'int'
- and names != ['unsigned', 'int']):
- names.pop()
+ if names != ['signed', 'char']: # keep this unmodified
+ prefixes = {}
+ while names:
+ name = names[0]
+ if name in ('short', 'long', 'signed', 'unsigned'):
+ prefixes[name] = prefixes.get(name, 0) + 1
+ del names[0]
+ else:
+ break
+ # ignore the 'signed' prefix below, and reorder the others
+ newnames = []
+ for prefix in ('unsigned', 'short', 'long'):
+ for i in range(prefixes.get(prefix, 0)):
+ newnames.append(prefix)
+ if not names:
+ names = ['int'] # implicitly
+ if names == ['int']: # but kill it if 'short' or 'long'
+ if 'short' in prefixes or 'long' in prefixes:
+ names = []
+ names = newnames + names
ident = ' '.join(names)
if ident == 'void':
return model.void_type
@@ -500,8 +513,8 @@
self._partial_length = True
return None
#
- raise api.FFIError("unsupported non-constant or "
- "not immediately constant expression")
+ raise api.FFIError("unsupported expression: expected a "
+ "simple numeric constant")
def _build_enum_type(self, explicit_name, decls):
if decls is not None:
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
@@ -61,7 +61,9 @@
def load_library(self):
# import it with the CFFI backend
backend = self.ffi._backend
- module = backend.load_library(self.verifier.modulefilename)
+ # needs to make a path that contains '/', on Posix
+ filename = os.path.join(os.curdir, self.verifier.modulefilename)
+ module = backend.load_library(filename)
#
# call loading_gen_struct() to get the struct layout inferred by
# the C compiler
diff --git a/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py
b/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py
--- a/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py
@@ -199,6 +199,9 @@
typerepr = self.TypeRepr
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { short a, b, c; };")
+ p = ffi.cast("short unsigned int", 0)
+ assert repr(p) == "<cdata 'unsigned short' 0>"
+ assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
p = ffi.cast("unsigned short int", 0)
assert repr(p) == "<cdata 'unsigned short' 0>"
assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
@@ -535,13 +538,13 @@
for c_type, expected_size in [
('char', 1),
('unsigned int', 4),
- ('char *', SIZE_OF_LONG),
+ ('char *', SIZE_OF_PTR),
('int[5]', 20),
('struct foo', 12),
('union foo', 4),
]:
size = ffi.sizeof(c_type)
- assert size == expected_size
+ assert size == expected_size, (size, expected_size, ctype)
def test_sizeof_cdata(self):
ffi = FFI(backend=self.Backend())
diff --git a/pypy/module/test_lib_pypy/cffi_tests/callback_in_thread.py
b/pypy/module/test_lib_pypy/cffi_tests/callback_in_thread.py
--- a/pypy/module/test_lib_pypy/cffi_tests/callback_in_thread.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/callback_in_thread.py
@@ -27,6 +27,7 @@
seen = []
@ffi.callback('int(*)(int,int)')
def mycallback(x, y):
+ time.sleep(0.022)
seen.append((x, y))
return 0
lib.threaded_ballback_test(mycallback)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_function.py
b/pypy/module/test_lib_pypy/cffi_tests/test_function.py
--- a/pypy/module/test_lib_pypy/cffi_tests/test_function.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/test_function.py
@@ -382,3 +382,26 @@
sin100 = my_decorator(m.sin)
x = sin100(1.23)
assert x == math.sin(1.23) + 100
+
+ def test_free_callback_cycle(self):
+ if self.Backend is CTypesBackend:
+ py.test.skip("seems to fail with the ctypes backend on windows")
+ import weakref
+ def make_callback(data):
+ container = [data]
+ callback = ffi.callback('int()', lambda: len(container))
+ container.append(callback)
+ # Ref cycle: callback -> lambda (closure) -> container -> callback
+ return callback
+
+ class Data(object):
+ pass
+ ffi = FFI(backend=self.Backend())
+ data = Data()
+ callback = make_callback(data)
+ wr = weakref.ref(data)
+ del callback, data
+ for i in range(3):
+ if wr() is not None:
+ import gc; gc.collect()
+ assert wr() is None # 'data' does not leak
diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_version.py
b/pypy/module/test_lib_pypy/cffi_tests/test_version.py
--- a/pypy/module/test_lib_pypy/cffi_tests/test_version.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/test_version.py
@@ -8,6 +8,8 @@
BACKEND_VERSIONS = {
'0.4.2': '0.4', # did not change
+ '0.7.1': '0.7', # did not change
+ '0.7.2': '0.7', # did not change
}
def test_version():
@@ -22,7 +24,7 @@
content = open(p).read()
#
v = cffi.__version__
- assert ("version = '%s'\n" % v) in content
+ assert ("version = '%s'\n" % BACKEND_VERSIONS.get(v, v)) in content
assert ("release = '%s'\n" % v) in content
def test_doc_version_file():
@@ -45,4 +47,5 @@
v = cffi.__version__
p = os.path.join(parent, 'c', 'test_c.py')
content = open(p).read()
- assert ('assert __version__ == "%s"' % v) in content
+ assert (('assert __version__ == "%s"' % BACKEND_VERSIONS.get(v, v))
+ in content)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit