Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit