Author: Armin Rigo <[email protected]>
Branch: release-1.11
Changeset: r3068:b6c9e34d098f
Date: 2018-01-11 21:43 +0100
http://bitbucket.org/cffi/cffi/changeset/b6c9e34d098f/
Log: hg merge default
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -2,7 +2,7 @@
#include <Python.h>
#include "structmember.h"
-#define CFFI_VERSION "1.11.2"
+#define CFFI_VERSION "1.11.3"
#ifdef MS_WIN32
#include <windows.h>
diff --git a/c/lib_obj.c b/c/lib_obj.c
--- a/c/lib_obj.c
+++ b/c/lib_obj.c
@@ -505,6 +505,7 @@
return x;
missing:
+ /*** ATTRIBUTEERROR IS SET HERE ***/
p = PyText_AsUTF8(name);
if (p == NULL)
return NULL;
@@ -534,6 +535,7 @@
#if PY_MAJOR_VERSION >= 3
if (strcmp(p, "__loader__") == 0 || strcmp(p, "__spec__") == 0) {
/* some more module-like behavior hacks */
+ PyErr_Clear();
Py_INCREF(Py_None);
return Py_None;
}
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -12,7 +12,7 @@
# ____________________________________________________________
import sys
-assert __version__ == "1.11.2", ("This test_c.py file is for testing a version"
+assert __version__ == "1.11.3", ("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/cffi/__init__.py b/cffi/__init__.py
--- a/cffi/__init__.py
+++ b/cffi/__init__.py
@@ -4,8 +4,8 @@
from .api import FFI
from .error import CDefError, FFIError, VerificationError, VerificationMissing
-__version__ = "1.11.2"
-__version_info__ = (1, 11, 2)
+__version__ = "1.11.3"
+__version_info__ = (1, 11, 3)
# 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/cffi/_cffi_include.h b/cffi/_cffi_include.h
--- a/cffi/_cffi_include.h
+++ b/cffi/_cffi_include.h
@@ -7,11 +7,38 @@
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.
+
+ Issue #350: more mess: on Windows, with _MSC_VER, we have to define
+ Py_LIMITED_API even before including pyconfig.h. In that case, we
+ guess what pyconfig.h will do to the macros above, and check our
+ guess after the #include.
*/
#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API)
-# include <pyconfig.h>
-# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
-# define Py_LIMITED_API
+# ifdef _MSC_VER
+# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) &&
!defined(Py_REF_DEBUG)
+# define Py_LIMITED_API
+# endif
+# include <pyconfig.h>
+ /* sanity-check: Py_LIMITED_API will cause crashes if any of these
+ are also defined. Normally, the Python file PC/pyconfig.h does not
+ cause any of these to be defined, with the exception that _DEBUG
+ causes Py_DEBUG. Double-check that. */
+# ifdef Py_LIMITED_API
+# if defined(Py_DEBUG)
+# error "pyconfig.h unexpectedly defines Py_DEBUG but _DEBUG is not set"
+# endif
+# if defined(Py_TRACE_REFS)
+# error "pyconfig.h unexpectedly defines Py_TRACE_REFS"
+# endif
+# if defined(Py_REF_DEBUG)
+# error "pyconfig.h unexpectedly defines Py_REF_DEBUG"
+# endif
+# endif
+# else
+# include <pyconfig.h>
+# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
+# define Py_LIMITED_API
+# endif
# endif
#endif
diff --git a/cffi/_embedding.h b/cffi/_embedding.h
--- a/cffi/_embedding.h
+++ b/cffi/_embedding.h
@@ -247,7 +247,7 @@
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.11.2"
+ "\ncompiled with cffi version: 1.11.3"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -295,8 +295,9 @@
base_module_name = self.module_name.split('.')[-1]
if self.ffi._embedding is not None:
prnt('#define _CFFI_MODULE_NAME "%s"' % (self.module_name,))
- prnt('#define _CFFI_PYTHON_STARTUP_CODE %s' %
- (self._string_literal(self.ffi._embedding),))
+ prnt('static const char _CFFI_PYTHON_STARTUP_CODE[] = {')
+ self._print_string_literal_in_array(self.ffi._embedding)
+ prnt('0 };')
prnt('#ifdef PYPY_VERSION')
prnt('# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s' % (
base_module_name,))
@@ -1271,17 +1272,18 @@
_generate_cpy_extern_python_plus_c_ctx = \
_generate_cpy_extern_python_ctx
- def _string_literal(self, s):
- def _char_repr(c):
- # escape with a '\' the characters '\', '"' or (for trigraphs) '?'
- if c in '\\"?': return '\\' + c
- if ' ' <= c < '\x7F': return c
- if c == '\n': return '\\n'
- return '\\%03o' % ord(c)
- lines = []
- for line in s.splitlines(True) or ['']:
- lines.append('"%s"' % ''.join([_char_repr(c) for c in line]))
- return ' \\\n'.join(lines)
+ def _print_string_literal_in_array(self, s):
+ prnt = self._prnt
+ prnt('// # NB. this is not a string because of a size limit in MSVC')
+ for line in s.splitlines(True):
+ prnt(('// ' + line).rstrip())
+ printed_line = ''
+ for c in line:
+ if len(printed_line) >= 76:
+ prnt(printed_line)
+ printed_line = ''
+ printed_line += '%d,' % (ord(c),)
+ prnt(printed_line)
# ----------
# emitting the opcodes for individual types
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -301,7 +301,6 @@
return suffixes
def _ensure_dir(filename):
- try:
- os.makedirs(os.path.dirname(filename))
- except OSError:
- pass
+ dirname = os.path.dirname(filename)
+ if dirname and not os.path.isdir(dirname):
+ os.makedirs(dirname)
diff --git a/doc/source/cdef.rst b/doc/source/cdef.rst
--- a/doc/source/cdef.rst
+++ b/doc/source/cdef.rst
@@ -701,7 +701,7 @@
-------------------------------
A few C libraries are actually hard to use correctly in a ``dlopen()``
-setting. This is because most C libraries are intented for, and tested
+setting. This is because most C libraries are intended for, and tested
with, a situation where they are *linked* with another program, using
either static linking or dynamic linking --- but from a program written
in C, at start-up, using the linker's capabilities instead of
diff --git a/doc/source/conf.py b/doc/source/conf.py
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -47,7 +47,7 @@
# The short X.Y version.
version = '1.11'
# The full version, including alpha/beta/rc tags.
-release = '1.11.2'
+release = '1.11.3'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/doc/source/installation.rst b/doc/source/installation.rst
--- a/doc/source/installation.rst
+++ b/doc/source/installation.rst
@@ -53,13 +53,13 @@
* https://pypi.python.org/pypi/cffi
-* Checksums of the "source" package version 1.11.2:
+* Checksums of the "source" package version 1.11.3:
- - MD5: a731487324b501c8295221b629d3f5f3
+ - MD5: ...
- - SHA: 04d2df85eb1921630b4f9206886737eb37200c19
+ - SHA: ...
- - SHA256: ab87dd91c0c4073758d07334c1e5f712ce8fe48f007b86f8238773963ee700a6
+ - SHA256: ...
* Or grab the most current version from the `Bitbucket page`_:
``hg clone https://bitbucket.org/cffi/cffi``
@@ -114,7 +114,7 @@
PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig pip install cffi
-Aternatively, **on OS/X 10.6** (Thanks Juraj Sukop for this)
+Alternatively, **on OS/X 10.6** (Thanks Juraj Sukop for this)
For building libffi you can use the default install path, but then, in
``setup.py`` you need to change::
diff --git a/doc/source/overview.rst b/doc/source/overview.rst
--- a/doc/source/overview.rst
+++ b/doc/source/overview.rst
@@ -45,8 +45,9 @@
there, %s!\n"``. In general it is ``somestring.encode(myencoding)``.
*Python 3 on Windows:* ``ffi.dlopen(None)`` does not work. This problem
-is messy and not really fixable. The example above could be fixed by
-calling another function from a specific DLL that exists on your system.
+is messy and not really fixable. The problem does not occur if you try
+to call a fucntion from a specific DLL that exists on your system: then
+you use ``ffi.dlopen("path.dll")``.
*This example does not call any C compiler. It works in the so-called
ABI mode, which means that it will crash if you call some function or
@@ -76,20 +77,27 @@
ffibuilder = FFI()
ffibuilder.set_source("_example",
- r""" // passed to the real C compiler
+ r""" // passed to the real C compiler,
+ // contains implementation of things declared in cdef()
#include <sys/types.h>
#include <pwd.h>
+
+ struct passwd *get_pw_for_root(void) {
+ return getpwuid(0);
+ }
""",
libraries=[]) # or a list of libraries to link with
# (more arguments like setup.py's Extension class:
# include_dirs=[..], extra_objects=[..], and so on)
- ffibuilder.cdef(""" // some declarations from the man page
+ ffibuilder.cdef("""
+ // declarations that are shared between Python and C
struct passwd {
char *pw_name;
...; // literally dot-dot-dot
};
- struct passwd *getpwuid(int uid);
+ struct passwd *getpwuid(int uid); // defined in <pwd.h>
+ struct passwd *get_pw_for_root(void); // defined in set_source()
""")
if __name__ == "__main__":
@@ -113,15 +121,18 @@
p = lib.getpwuid(0)
assert ffi.string(p.pw_name) == b'root'
+ p = lib.get_pw_for_root()
+ assert ffi.string(p.pw_name) == b'root'
Note that this works independently of the exact C layout of ``struct
passwd`` (it is "API level", as opposed to "ABI level"). It requires
a C compiler in order to run ``example_build.py``, but it is much more
portable than trying to get the details of the fields of ``struct
-passwd`` exactly right. Similarly, we declared ``getpwuid()`` as
-taking an ``int`` argument. On some platforms this might be slightly
-incorrect---but it does not matter. It is also faster than the ABI
-mode.
+passwd`` exactly right. Similarly, in the ``cdef()`` we declared
+``getpwuid()`` as taking an ``int`` argument; on some platforms this
+might be slightly incorrect---but it does not matter.
+
+Note also that at runtime, the API mode is faster than the ABI mode.
To integrate it inside a ``setup.py`` distribution with Setuptools:
diff --git a/doc/source/ref.rst b/doc/source/ref.rst
--- a/doc/source/ref.rst
+++ b/doc/source/ref.rst
@@ -401,7 +401,12 @@
nothing gets out of sync if the size estimates do not match. It only
makes the next GC start more or less early.
+Note that if you have several ``ffi.gc()`` objects, the corresponding
+destructors will be called in a random order. If you need a particular
+order, see the discussion in `issue 340`__.
+
.. __: http://bugs.python.org/issue31105
+.. __: https://bitbucket.org/cffi/cffi/issues/340/resources-release-issues
.. _ffi-new-handle:
diff --git a/doc/source/using.rst b/doc/source/using.rst
--- a/doc/source/using.rst
+++ b/doc/source/using.rst
@@ -28,7 +28,7 @@
*New in version 1.11:* in addition to ``wchar_t``, the C types
``char16_t`` and ``char32_t`` work the same but with a known fixed size.
In previous versions, this could be achieved using ``uint16_t`` and
-``int32_t`` but without automatic convertion to Python unicodes.
+``int32_t`` but without automatic conversion to Python unicodes.
Pointers, structures and arrays are more complex: they don't have an
obvious Python equivalent. Thus, they correspond to objects of type
diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst
--- a/doc/source/whatsnew.rst
+++ b/doc/source/whatsnew.rst
@@ -3,6 +3,23 @@
======================
+v1.11.3
+=======
+
+* Fix on CPython 3.x: reading the attributes ``__loader__`` or
+ ``__spec__`` from the cffi-generated lib modules gave a buggy
+ SystemError. (These attributes are always None, and provided only to
+ help compatibility with tools that expect them in all modules.)
+
+* More Windows fixes: workaround for MSVC not supporting large
+ literal strings in C code (from
+ ``ffi.embedding_init_code(large_string)``); and an issue with
+ ``Py_LIMITED_API`` linking with ``python35.dll/python36.dll`` instead
+ of ``python3.dll``.
+
+* Small documentation improvements.
+
+
v1.11.2
=======
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -186,7 +186,7 @@
`Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
""",
- version='1.11.2',
+ version='1.11.3',
packages=['cffi'] if cpython else [],
package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h',
'_embedding.h', '_cffi_errors.h']}
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -2270,7 +2270,7 @@
char32_t foo_4bytes(char32_t);
""")
lib = verify(ffi, "test_char16_char32_type" + no_cpp * "_nocpp", """
- #if !defined(__cplusplus) || __cplusplus < 201103L
+ #if !defined(__cplusplus) || (!defined(_LIBCPP_VERSION) && __cplusplus <
201103L)
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
#endif
@@ -2287,3 +2287,13 @@
def test_char16_char32_plain_c():
test_char16_char32_type(no_cpp=True)
+
+def test_loader_spec():
+ ffi = FFI()
+ lib = verify(ffi, "test_loader_spec", "")
+ if sys.version_info < (3,):
+ assert not hasattr(lib, '__loader__')
+ assert not hasattr(lib, '__spec__')
+ else:
+ assert lib.__loader__ is None
+ assert lib.__spec__ is None
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit