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

Reply via email to