aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatti Picus <matti.picus@gmail.com>2016-09-04 17:55:23 +0300
committerMatti Picus <matti.picus@gmail.com>2016-09-04 17:55:23 +0300
commit3cbb0daa276653ce1574fe285326cb5ab9141fe4 (patch)
treed7c4ddaf3368e0ddad26806c067121f62095496a
parentMove the bit checking inside helpers, share it from the two places (diff)
downloadpypy-3cbb0daa276653ce1574fe285326cb5ab9141fe4.tar.gz
pypy-3cbb0daa276653ce1574fe285326cb5ab9141fe4.tar.bz2
pypy-3cbb0daa276653ce1574fe285326cb5ab9141fe4.zip
import cffi/b81ca61b6de6
(grafted from fdd46325fe3d2c1d29496931411c453c0af576a2)
-rw-r--r--lib_pypy/cffi.egg-info/PKG-INFO2
-rw-r--r--lib_pypy/cffi/__init__.py4
-rw-r--r--lib_pypy/cffi/_cffi_include.h16
-rw-r--r--lib_pypy/cffi/_embedding.h2
-rw-r--r--lib_pypy/cffi/api.py4
-rw-r--r--lib_pypy/cffi/backend_ctypes.py40
-rw-r--r--lib_pypy/cffi/ffiplatform.py9
-rw-r--r--lib_pypy/cffi/recompiler.py9
-rw-r--r--lib_pypy/cffi/setuptools_ext.py22
-rw-r--r--pypy/module/_cffi_backend/__init__.py2
-rw-r--r--pypy/module/_cffi_backend/test/_backend_test_c.py2
-rw-r--r--pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py1
-rw-r--r--pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py22
-rw-r--r--pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py6
14 files changed, 106 insertions, 35 deletions
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
index b9e935beb3..5efdefc077 100644
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: cffi
-Version: 1.8.0
+Version: 1.8.1
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
index 285b460675..02614644b3 100644
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@ __all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError',
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "1.8.0"
-__version_info__ = (1, 8, 0)
+__version__ = "1.8.1"
+__version_info__ = (1, 8, 1)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
index dee5e81306..cd0219f154 100644
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -1,4 +1,20 @@
#define _CFFI_
+
+/* We try to define Py_LIMITED_API before including Python.h.
+
+ Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and
+ Py_REF_DEBUG are not defined. This is a best-effort approximation:
+ we can learn about Py_DEBUG from pyconfig.h, but it is unclear if
+ the same works for the other two macros. Py_DEBUG implies them,
+ but not the other way around.
+*/
+#ifndef _CFFI_USE_EMBEDDING
+# include <pyconfig.h>
+# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
+# define Py_LIMITED_API
+# endif
+#endif
+
#include <Python.h>
#ifdef __cplusplus
extern "C" {
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
index a702c46fa3..eb7c7445b0 100644
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@ static int _cffi_initialize_python(void)
f = PySys_GetObject((char *)"stderr");
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.8.0"
+ "\ncompiled with cffi version: 1.8.1"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
index e4d7e39053..eda7209176 100644
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -652,7 +652,7 @@ class FFI(object):
recompile(self, module_name, source,
c_file=filename, call_c_compiler=False, **kwds)
- def compile(self, tmpdir='.', verbose=0, target=None):
+ def compile(self, tmpdir='.', verbose=0, target=None, debug=None):
"""The 'target' argument gives the final file name of the
compiled DLL. Use '*' to force distutils' choice, suitable for
regular CPython C API modules. Use a file name ending in '.*'
@@ -669,7 +669,7 @@ class FFI(object):
module_name, source, source_extension, kwds = self._assigned_source
return recompile(self, module_name, source, tmpdir=tmpdir,
target=target, source_extension=source_extension,
- compiler_verbose=verbose, **kwds)
+ compiler_verbose=verbose, debug=debug, **kwds)
def init_once(self, func, tag):
# Read _init_once_cache[tag], which is either (False, lock) if
diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py
index b2579b3ec1..d160fa7e6e 100644
--- a/lib_pypy/cffi/backend_ctypes.py
+++ b/lib_pypy/cffi/backend_ctypes.py
@@ -997,29 +997,37 @@ class CTypesBackend(object):
assert onerror is None # XXX not implemented
return BType(source, error)
+ _weakref_cache_ref = None
+
def gcp(self, cdata, destructor):
- BType = self.typeof(cdata)
+ if self._weakref_cache_ref is None:
+ import weakref
+ class MyRef(weakref.ref):
+ def __eq__(self, other):
+ myref = self()
+ return self is other or (
+ myref is not None and myref is other())
+ def __ne__(self, other):
+ return not (self == other)
+ self._weakref_cache_ref = {}, MyRef
+ weak_cache, MyRef = self._weakref_cache_ref
if destructor is None:
- if not (hasattr(BType, '_gcp_type') and
- BType._gcp_type is BType):
+ try:
+ del weak_cache[MyRef(cdata)]
+ except KeyError:
raise TypeError("Can remove destructor only on a object "
"previously returned by ffi.gc()")
- cdata._destructor = None
return None
- try:
- gcp_type = BType._gcp_type
- except AttributeError:
- class CTypesDataGcp(BType):
- __slots__ = ['_orig', '_destructor']
- def __del__(self):
- if self._destructor is not None:
- self._destructor(self._orig)
- gcp_type = BType._gcp_type = CTypesDataGcp
- new_cdata = self.cast(gcp_type, cdata)
- new_cdata._orig = cdata
- new_cdata._destructor = destructor
+ def remove(k):
+ cdata, destructor = weak_cache.pop(k, (None, None))
+ if destructor is not None:
+ destructor(cdata)
+
+ new_cdata = self.cast(self.typeof(cdata), cdata)
+ assert new_cdata is not cdata
+ weak_cache[MyRef(new_cdata, remove)] = (cdata, destructor)
return new_cdata
typeof = type
diff --git a/lib_pypy/cffi/ffiplatform.py b/lib_pypy/cffi/ffiplatform.py
index d2daa8e420..15e591ba4a 100644
--- a/lib_pypy/cffi/ffiplatform.py
+++ b/lib_pypy/cffi/ffiplatform.py
@@ -21,12 +21,12 @@ def get_extension(srcfilename, modname, sources=(), **kwds):
allsources.append(os.path.normpath(src))
return Extension(name=modname, sources=allsources, **kwds)
-def compile(tmpdir, ext, compiler_verbose=0):
+def compile(tmpdir, ext, compiler_verbose=0, debug=None):
"""Compile a C extension module using distutils."""
saved_environ = os.environ.copy()
try:
- outputfilename = _build(tmpdir, ext, compiler_verbose)
+ outputfilename = _build(tmpdir, ext, compiler_verbose, debug)
outputfilename = os.path.abspath(outputfilename)
finally:
# workaround for a distutils bugs where some env vars can
@@ -36,7 +36,7 @@ def compile(tmpdir, ext, compiler_verbose=0):
os.environ[key] = value
return outputfilename
-def _build(tmpdir, ext, compiler_verbose=0):
+def _build(tmpdir, ext, compiler_verbose=0, debug=None):
# XXX compact but horrible :-(
from distutils.core import Distribution
import distutils.errors, distutils.log
@@ -44,6 +44,9 @@ def _build(tmpdir, ext, compiler_verbose=0):
dist = Distribution({'ext_modules': [ext]})
dist.parse_config_files()
options = dist.get_option_dict('build_ext')
+ if debug is None:
+ debug = sys.flags.debug
+ options['debug'] = ('ffiplatform', debug)
options['force'] = ('ffiplatform', True)
options['build_lib'] = ('ffiplatform', tmpdir)
options['build_temp'] = ('ffiplatform', tmpdir)
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
index 8e66d1c0c1..7b0797d64d 100644
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -275,8 +275,8 @@ class Recompiler:
def write_c_source_to_f(self, f, preamble):
self._f = f
prnt = self._prnt
- if self.ffi._embedding is None:
- prnt('#define Py_LIMITED_API')
+ if self.ffi._embedding is not None:
+ prnt('#define _CFFI_USE_EMBEDDING')
#
# first the '#include' (actually done by inlining the file's content)
lines = self._rel_readlines('_cffi_include.h')
@@ -1431,7 +1431,7 @@ def _patch_for_target(patchlist, target):
def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True,
c_file=None, source_extension='.c', extradir=None,
- compiler_verbose=1, target=None, **kwds):
+ compiler_verbose=1, target=None, debug=None, **kwds):
if not isinstance(module_name, str):
module_name = module_name.encode('ascii')
if ffi._windows_unicode:
@@ -1467,7 +1467,8 @@ def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True,
if target != '*':
_patch_for_target(patchlist, target)
os.chdir(tmpdir)
- outputfilename = ffiplatform.compile('.', ext, compiler_verbose)
+ outputfilename = ffiplatform.compile('.', ext,
+ compiler_verbose, debug)
finally:
os.chdir(cwd)
_unpatch_meths(patchlist)
diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py
index 9c6436dfd6..24afddff6c 100644
--- a/lib_pypy/cffi/setuptools_ext.py
+++ b/lib_pypy/cffi/setuptools_ext.py
@@ -69,16 +69,36 @@ def add_cffi_module(dist, mod_spec):
else:
_add_c_module(dist, ffi, module_name, source, source_extension, kwds)
+def _set_py_limited_api(Extension, kwds):
+ """
+ Add py_limited_api to kwds if setuptools >= 26 is in use.
+ Do not alter the setting if it already exists.
+ Setuptools takes care of ignoring the flag on Python 2 and PyPy.
+ """
+ if 'py_limited_api' not in kwds:
+ import setuptools
+ try:
+ setuptools_major_version = int(setuptools.__version__.partition('.')[0])
+ if setuptools_major_version >= 26:
+ kwds['py_limited_api'] = True
+ except ValueError: # certain development versions of setuptools
+ # If we don't know the version number of setuptools, we
+ # try to set 'py_limited_api' anyway. At worst, we get a
+ # warning.
+ kwds['py_limited_api'] = True
+ return kwds
def _add_c_module(dist, ffi, module_name, source, source_extension, kwds):
from distutils.core import Extension
- from distutils.command.build_ext import build_ext
+ # We are a setuptools extension. Need this build_ext for py_limited_api.
+ from setuptools.command.build_ext import build_ext
from distutils.dir_util import mkpath
from distutils import log
from cffi import recompiler
allsources = ['$PLACEHOLDER']
allsources.extend(kwds.pop('sources', []))
+ kwds = _set_py_limited_api(Extension, kwds)
ext = Extension(name=module_name, sources=allsources, **kwds)
def make_mod(tmpdir, pre_run=None):
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
index 71ec6b2499..535c225b3b 100644
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@ from pypy.interpreter.mixedmodule import MixedModule
from rpython.rlib import rdynload, clibffi, entrypoint
from rpython.rtyper.lltypesystem import rffi
-VERSION = "1.8.0"
+VERSION = "1.8.1"
FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
try:
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
index 9297f8b2c4..f80e29a6b0 100644
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
# ____________________________________________________________
import sys
-assert __version__ == "1.8.0", ("This test_c.py file is for testing a version"
+assert __version__ == "1.8.1", ("This test_c.py file is for testing a version"
" of cffi that differs from the one that we"
" get from 'import _cffi_backend'")
if sys.version_info < (3,):
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
index e19a47d2fa..e64a6e056a 100644
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
@@ -1479,6 +1479,7 @@ class BackendTests:
assert p1[0] == 123
seen.append(1)
q = ffi.gc(p, destructor)
+ assert ffi.typeof(q) is ffi.typeof(p)
import gc; gc.collect()
assert seen == []
del q
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
index 9e78ec99f9..0a91652487 100644
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
@@ -149,3 +149,25 @@ class TestZIntegration(object):
p = snip_setuptools_verify2.C.getpwuid(0)
assert snip_setuptools_verify2.ffi.string(p.pw_name) == b"root"
''')
+
+ def test_set_py_limited_api(self):
+ from cffi.setuptools_ext import _set_py_limited_api
+ try:
+ import setuptools
+ orig_version = setuptools.__version__
+ setuptools.__version__ = '26.0.0'
+ from setuptools import Extension
+
+ kwds = _set_py_limited_api(Extension, {})
+ assert kwds['py_limited_api'] == True
+
+ setuptools.__version__ = '25.0'
+ kwds = _set_py_limited_api(Extension, {})
+ assert not kwds
+
+ setuptools.__version__ = 'development'
+ kwds = _set_py_limited_api(Extension, {})
+ assert kwds['py_limited_api'] == True
+
+ finally:
+ setuptools.__version__ = orig_version
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
index 1c9a59bda1..c5a042a72a 100644
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -1975,9 +1975,9 @@ def test_function_returns_union():
def test_function_returns_partial_struct():
ffi = FFI()
- ffi.cdef("struct a { int a; ...; }; struct a f1(int);")
+ ffi.cdef("struct aaa { int a; ...; }; struct aaa f1(int);")
lib = verify(ffi, "test_function_returns_partial_struct", """
- struct a { int b, a, c; };
- static struct a f1(int x) { struct a s = {0}; s.a = x; return s; }
+ struct aaa { int b, a, c; };
+ static struct aaa f1(int x) { struct aaa s = {0}; s.a = x; return s; }
""")
assert lib.f1(52).a == 52