Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: space-newtext
Changeset: r88080:ee5ad76cdf97
Date: 2016-11-02 14:11 +0100
http://bitbucket.org/pypy/pypy/changeset/ee5ad76cdf97/

Log:    merge default

diff too long, truncating to 2000 out of 3090 lines

diff --git a/lib-python/2.7/test/test_ssl.py b/lib-python/2.7/test/test_ssl.py
--- a/lib-python/2.7/test/test_ssl.py
+++ b/lib-python/2.7/test/test_ssl.py
@@ -26,6 +26,8 @@
 
 PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
 HOST = support.HOST
+IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
+IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
 
 def data_file(*name):
     return os.path.join(os.path.dirname(__file__), *name)
@@ -742,15 +744,15 @@
     def test_options(self):
         ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
         # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value
-        self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3,
-                         ctx.options)
+        default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
+        if not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0):
+            default |= ssl.OP_NO_COMPRESSION
+        self.assertEqual(default, ctx.options)
         ctx.options |= ssl.OP_NO_TLSv1
-        self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | 
ssl.OP_NO_TLSv1,
-                         ctx.options)
+        self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options)
         if can_clear_options():
-            ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1
-            self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
-                             ctx.options)
+            ctx.options = (ctx.options & ~ssl.OP_NO_TLSv1)
+            self.assertEqual(default, ctx.options)
             ctx.options = 0
             self.assertEqual(0, ctx.options)
         else:
@@ -2918,18 +2920,27 @@
                 client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
                 client_context.load_cert_chain(CERTFILE)
                 client_context.set_alpn_protocols(client_protocols)
-                stats = server_params_test(client_context, server_context,
-                                           chatty=True, connectionchatty=True)
-
-                msg = "failed trying %s (s) and %s (c).\n" \
-                      "was expecting %s, but got %%s from the %%s" \
-                          % (str(server_protocols), str(client_protocols),
-                             str(expected))
-                client_result = stats['client_alpn_protocol']
-                self.assertEqual(client_result, expected, msg % 
(client_result, "client"))
-                server_result = stats['server_alpn_protocols'][-1] \
-                    if len(stats['server_alpn_protocols']) else 'nothing'
-                self.assertEqual(server_result, expected, msg % 
(server_result, "server"))
+                try:
+                    stats = server_params_test(client_context, server_context,
+                                               chatty=True, 
connectionchatty=True)
+                except ssl.SSLError as e:
+                    stats = e
+
+                if expected is None and IS_OPENSSL_1_1:
+                    # OpenSSL 1.1.0 raises handshake error
+                    self.assertIsInstance(stats, ssl.SSLError)
+                else:
+                    msg = "failed trying %s (s) and %s (c).\n" \
+                          "was expecting %s, but got %%s from the %%s" \
+                              % (str(server_protocols), str(client_protocols),
+                                 str(expected))
+                    client_result = stats['client_alpn_protocol']
+                    self.assertEqual(client_result, expected,
+                                     msg % (client_result, "client"))
+                    server_result = stats['server_alpn_protocols'][-1] \
+                        if len(stats['server_alpn_protocols']) else 'nothing'
+                    self.assertEqual(server_result, expected,
+                                     msg % (server_result, "server"))
 
         def test_selected_npn_protocol(self):
             # selected_npn_protocol() is None unless NPN is used
diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py
--- a/lib_pypy/_collections.py
+++ b/lib_pypy/_collections.py
@@ -29,7 +29,7 @@
 class deque(object):
 
     def __new__(cls, iterable=(), *args, **kw):
-        self = super(deque, cls).__new__(cls, *args, **kw)
+        self = super(deque, cls).__new__(cls)
         self.clear()
         return self
 
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -229,7 +229,7 @@
     __metaclass__ = StructOrUnionMeta
 
     def __new__(cls, *args, **kwds):
-        self = super(_CData, cls).__new__(cls, *args, **kwds)
+        self = super(_CData, cls).__new__(cls)
         if '_abstract_' in cls.__dict__:
             raise TypeError("abstract class")
         if hasattr(cls, '_ffistruct_'):
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- 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.4
+Version: 1.9.0
 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
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.8.4"
-__version_info__ = (1, 8, 4)
+__version__ = "1.9.0"
+__version_info__ = (1, 9, 0)
 
 # 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/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@
         f = PySys_GetObject((char *)"stderr");
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.8.4"
+                               "\ncompiled with cffi version: 1.9.0"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
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
@@ -334,6 +334,8 @@
                         realtype, quals = self._get_type_and_quals(
                             decl.type, name=decl.name, partial_length_ok=True)
                     self._declare('typedef ' + decl.name, realtype, 
quals=quals)
+                elif decl.__class__.__name__ == 'Pragma':
+                    pass    # skip pragma, only in pycparser 2.15
                 else:
                     raise api.CDefError("unrecognized construct", decl)
         except api.FFIError as e:
diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py
--- a/lib_pypy/cffi/model.py
+++ b/lib_pypy/cffi/model.py
@@ -519,10 +519,18 @@
             smallest_value = min(self.enumvalues)
             largest_value = max(self.enumvalues)
         else:
-            raise api.CDefError("%r has no values explicitly defined: "
-                                "refusing to guess which integer type it is "
-                                "meant to be (unsigned/signed, int/long)"
-                % self._get_c_name())
+            import warnings
+            try:
+                # XXX!  The goal is to ensure that the warnings.warn()
+                # will not suppress the warning.  We want to get it
+                # several times if we reach this point several times.
+                __warningregistry__.clear()
+            except NameError:
+                pass
+            warnings.warn("%r has no values explicitly defined; "
+                          "guessing that it is equivalent to 'unsigned int'"
+                          % self._get_c_name())
+            smallest_value = largest_value = 0
         if smallest_value < 0:   # needs a signed type
             sign = 1
             candidate1 = PrimitiveType("int")
diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py
--- a/lib_pypy/cffi/setuptools_ext.py
+++ b/lib_pypy/cffi/setuptools_ext.py
@@ -1,4 +1,5 @@
 import os
+import sys
 
 try:
     basestring
@@ -74,8 +75,13 @@
     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.
+
+    CPython itself should ignore the flag in a debugging version
+    (by not listing .abi3.so in the extensions it supports), but
+    it doesn't so far, creating troubles.  That's why we check
+    for "not sys.flags.debug". (http://bugs.python.org/issue28401)
     """
-    if 'py_limited_api' not in kwds:
+    if 'py_limited_api' not in kwds and not sys.flags.debug:
         import setuptools
         try:
             setuptools_major_version = 
int(setuptools.__version__.partition('.')[0])
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -397,3 +397,13 @@
 in auto-generated C code, and at least some knowledge about the
 various components involved, from PyPy's own RPython source code to
 the GC and possibly the JIT.
+
+
+Why doesn't PyPy move to GitHub, Gitlab, ...?
+----------------------------------------------
+
+We've been quite happy with bitbucket.org. Moving version control systems and
+hosting is a lot of hard work: On the one hand, PyPy's mercurial history is
+long and gnarly. On the other hand, all our infrastructure (buildbots,
+benchmarking, etc) would have to be adapted. So unless somebody steps up and
+volunteers to do all that work, it will likely not happen.
diff --git a/pypy/doc/install.rst b/pypy/doc/install.rst
--- a/pypy/doc/install.rst
+++ b/pypy/doc/install.rst
@@ -1,8 +1,17 @@
 Downloading and Installing PyPy
 ===============================
 
+Using a packaged PyPy
+~~~~~~~~~~~~~~~~~~~~~
+
+Some Linux distributions provide a pypy package. Note that in order to
+install additional modules that require compilation, you may need to install
+additional packages such as pypy-dev. This will manifest as an error about
+"missing Python.h". Distributions do not as of yet supply many pypy-ready
+packages, if you require additional modules we recommend creating a virtualenv
+and using pip. 
+
 .. _prebuilt-pypy:
-
 Download a pre-built PyPy
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -38,6 +47,9 @@
 and not move the binary there, else PyPy would not be able to find its
 library.
 
+Installing more modules
+~~~~~~~~~~~~~~~~~~~~~~~
+
 If you want to install 3rd party libraries, the most convenient way is
 to install pip_ using ensurepip_ (unless you want to install virtualenv as 
 explained below; then you can directly use pip inside virtualenvs):
diff --git a/pypy/doc/release-pypy2.7-v5.6.0.rst 
b/pypy/doc/release-pypy2.7-v5.6.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-pypy2.7-v5.6.0.rst
@@ -0,0 +1,147 @@
+============
+PyPy2.7 v5.6
+============
+
+We have released PyPy2.7 v5.6, about two months after PyPy2.7 v5.4.
+This new PyPy2.7 release includes the upstream stdlib version 2.7.12.
+
+We continue to make incremental improvements to our C-API
+compatability layer (cpyext). We pass all but a few of the tests in the
+upstream numpy `test suite`_. 
+
+Work proceeds at a good pace on the PyPy3.5
+version due to a grant_ from the Mozilla Foundation, and some of those
+changes have been backported to PyPy2.7 where relevant
+
+We changed ``timeit`` to now report average +- standard deviation, which is
+better than the misleading minimum value reported in CPython.
+
+We now support building PyPy with OpenSSL 1.1 in our built-in _sll module, as
+well as maintaining support for previous versions.
+
+XXX
+
+As always, this release fixed many issues and bugs raised by the
+growing community of PyPy users. We strongly recommend updating.
+
+You can download the PyPy2.7 v5.6 release here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project.
+
+We would also like to thank our contributors and
+encourage new people to join the project. PyPy has many
+layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
+improvements, tweaking popular `modules`_ to run on pypy, or general `help`_
+with making RPython's JIT even better.
+
+.. _`test suite`: 
https://bitbucket.org/pypy/pypy/wiki/Adventures%20in%20cpyext%20compatibility
+.. _cffi: https://cffi.readthedocs.org
+.. _grant: 
https://morepypy.blogspot.com/2016/08/pypy-gets-funding-from-mozilla-for.html
+.. _`PyPy`: http://doc.pypy.org
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`modules`: 
http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly
+.. _`help`: http://doc.pypy.org/en/latest/project-ideas.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+This release supports: 
+
+  * **x86** machines on most common operating systems
+    (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
+  
+  * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+  
+  * big- and little-endian variants of **PPC64** running Linux,
+
+  * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://pypyjs.org
+
+Other Highlights (since 5.4 released Aug 31, 2016)
+=========================================================
+
+* New features
+  * Allow tests run with `-A` to find `libm.so` even if it is a script not a
+    dynamically loadable file
+  * Backport fixes to rposix on windows from py3.5
+  * Allow user-defined ``__getitem__`` on subclasses of ``str`` and ``unicode``
+  * Add ``inode`` to ``scandir()`` on posix systems
+  * Support more attributes on ``super``
+  * Issue #2386: non-latin1 unicode keys were ignored in 
``unicode.format(**d)``
+  * Restore the ability to translate with CPython
+  * Update to CFFI 1.8.4
+  * Support the new buffer protocol in cpyext and numpypy
+  * Add ``rposix.sync()``
+  * Support full-precision nanosecond times in os.stat()
+  * Add documentation about the assembler backends to RPYthon
+  * Search for the stdlibs from the libpypy shared object rather than the 
pypy-c exe,
+    changes downstream packaging requirments
+  * Add ``try_inline``, like ``always_inline`` and ``dont_inline`` to RPython
+  * Reject ``'a'.strip(buffer(' '))`` like cpython (the argument to strip must
+    be ``str`` or ``unicode``)
+  * Allow ``warning.warn(('something', 1), Warning)`` like on CPython
+  * Refactor ``rclock`` and add some more ``CLOCK_xxx`` constants on
+    relevant platforms
+  * Backport the ``'faulthandler`` module from py3.5
+  * Improve the error message when trying to call a method where the ``self``
+    parameter is missing in the definition
+  * Implement ``rposix.cpu_count``
+  * Support translation on FreeBSD running on PowerPC
+  * Implement ``__rmod__`` on ``str`` and ``unicode`` types
+  * Issue warnings for stricter handling of ``__new__``, ``__init__`` args
+  * When using ``struct.unpack('q', ...`` try harder to prefer int to long
+  * Support OpenSSL version 1.1 (in addition to version 1.0)
+
+* Bug Fixes
+  * Tweak a float comparison with 0 in `backendopt.inline` to avoid rounding 
errors
+  * Fix translation of the sandbox
+  * Fix for an issue where `unicode.decode('utf8', 'custom_replace')` messed up
+    the last byte of a unicode string sometimes
+  * fix some calls to functions through window's COM interface
+  * fix minor leak when the C call to socketpair() fails
+  * make sure (-1.0 + 0j).__hash__(), (-1.0).__hash__() returns -2
+  * Fix for an issue where PyBytesResize was called on a fresh pyobj
+  * Fix bug in codewriter about passing the ``exitswitch`` variable to a call
+  * Don't crash in ``merge_if_blocks`` if the values are symbolics
+  * Issue #2325/2361: __class__ assignment between two classes with the same
+    slots
+  * Issue #2409: don't leak the file descriptor when doing ``open('some-dir')``
+  * Windows fixes around vmprof
+  * Don't use ``sprintf()`` from inside a signal handler
+  * Test and fix bug from the ``guard_not_forced_2`` branch, which didn't
+    save the floating-point register
+  * ``_numpypy.add.reduce`` returns a scalar now
+
+* Performance improvements:
+  * Improve method calls on oldstyle classes
+  * Clean and refactor code for testing cpyext to allow sharing with py3.5
+  * Refactor a building the map of reflected ops in ``_numpypy``
+  * Improve merging of virtual states in the JIT in order to avoid jumping to 
the
+    preamble
+  * In JIT residual calls, if the called function starts with a fast-path like
+    ``if x.foo != 0: return x.foo``, then inline the check before doing the
+     ``CALL``.
+  * Ensure ``make_inputargs`` fails properly when given arguments with type 
+    information
+  * Makes ``optimiseopt`` iterative instead of recursive so it can be reasoned
+    about more easily and debugging is faster
+  * Refactor and remove dead code from ``optimizeopt``, ``resume``
+  
+
+.. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.6.0.html
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -80,3 +80,20 @@
 
 Improve support for new buffer interface in cpyext, bf_getbuffer on built-in
 types still missing
+
+.. branch: fix-struct-unpack-Q
+
+Improve compatibility with CPython in the ``struct`` module. In particular,
+``struct.unpack`` now returns an ``int`` whenever the returned value fits,
+while previously it always returned a ``long`` for certains format codes such
+as ``Q`` (and also ``I``, ``L`` and ``q`` on 32 bit)
+
+.. branch: newinitwarn
+
+Issue warnings for stricter handling of ``__new/init__`` args (that
+become TypeErrors in python 3)
+
+.. branch: openssl-1.1
+
+PyPy can now be translated on a machine where the newer OpenSSL 1.1 is
+installed.  Thanks tumbleweed!
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -72,10 +72,7 @@
             exc_typename = str(self.w_type)
             exc_value = str(w_value)
         else:
-            if space.is_w(space.type(self.w_type), space.w_str):
-                exc_typename = space.str_w(self.w_type)
-            else:
-                exc_typename = space.str_w(
+            exc_typename = space.str_w(
                     space.getattr(self.w_type, space.newtext('__name__')))
             if space.is_w(w_value, space.w_None):
                 exc_value = ""
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -610,7 +610,7 @@
 
 class StaticMethod(W_Root):
     """The staticmethod objects."""
-    _immutable_fields_ = ['w_function']
+    _immutable_fields_ = ['w_function?']
 
     def __init__(self, w_function):
         self.w_function = w_function
@@ -621,13 +621,16 @@
 
     def descr_staticmethod__new__(space, w_subtype, w_function):
         instance = space.allocate_instance(StaticMethod, w_subtype)
-        instance.__init__(w_function)
+        instance.__init__(space.w_None)
         return instance
 
+    def descr_init(self, space, w_function):
+        self.w_function = w_function
+
 
 class ClassMethod(W_Root):
     """The classmethod objects."""
-    _immutable_fields_ = ['w_function']
+    _immutable_fields_ = ['w_function?']
 
     def __init__(self, w_function):
         self.w_function = w_function
@@ -640,9 +643,12 @@
 
     def descr_classmethod__new__(space, w_subtype, w_function):
         instance = space.allocate_instance(ClassMethod, w_subtype)
-        instance.__init__(w_function)
+        instance.__init__(space.w_None)
         return instance
 
+    def descr_init(self, space, w_function):
+        self.w_function = w_function
+
 class FunctionWithFixedCode(Function):
     can_change_code = False
 
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -106,8 +106,10 @@
 # So we create a few interp-level subclasses of W_XxxObject, which add
 # some combination of features. This is done using mapdict.
 
-# we need two subclasses of the app-level type, one to add mapdict, and then 
one
-# to add del to not slow down the GC.
+# Note that nowadays, we need not "a few" but only one subclass.  It
+# adds mapdict, which flexibly allows all features.  We handle the
+# presence or absence of an app-level '__del__' by calling
+# register_finalizer() or not.
 
 @specialize.memo()
 def get_unique_interplevel_subclass(space, cls):
@@ -687,15 +689,17 @@
 (e.g. C().f()).  The instance is ignored except for its class.""",
     __get__ = interp2app(StaticMethod.descr_staticmethod_get),
     __new__ = interp2app(StaticMethod.descr_staticmethod__new__.im_func),
+    __init__=interp2app(StaticMethod.descr_init),
     __func__= interp_attrproperty_w('w_function', cls=StaticMethod),
     )
 
 ClassMethod.typedef = TypeDef(
     'classmethod',
-    __new__ = interp2app(ClassMethod.descr_classmethod__new__.im_func),
-    __get__ = interp2app(ClassMethod.descr_classmethod_get),
-    __func__= interp_attrproperty_w('w_function', cls=ClassMethod),
-    __doc__ = """classmethod(function) -> class method
+    __new__=interp2app(ClassMethod.descr_classmethod__new__.im_func),
+    __init__=interp2app(ClassMethod.descr_init),
+    __get__=interp2app(ClassMethod.descr_classmethod_get),
+    __func__=interp_attrproperty_w('w_function', cls=ClassMethod),
+    __doc__="""classmethod(function) -> class method
 
 Convert a function to be a class method.
 
diff --git a/pypy/module/__builtin__/test/test_descriptor.py 
b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -20,6 +20,12 @@
         x = Static(1)
         assert isinstance(x, Static)
 
+        class C(Static):
+            def __init__(self, callable):
+                super(C, self).__init__(callable)
+        y = C(1)
+        assert isinstance(y, C)
+
     def test_classmethod(self):
         class C(object):
             def f(cls, stuff):
@@ -41,8 +47,14 @@
         x = Classm(1)
         assert isinstance(x, Classm)
 
+        class C(Classm):
+            def __init__(self, callable):
+                super(C, self).__init__(callable)
+        y = C(1)
+        assert isinstance(y, C)
+
     def test_property_simple(self):
-        
+
         class a(object):
             def _get(self): return 42
             def _set(self, value): raise AttributeError
@@ -98,7 +110,7 @@
             assert message.startswith('super(type, obj): obj must be an 
instance or subtype of type')
 
     def test_super_various(self):
-        
+
         class A(object):
             def meth(self, a):
                 return "A(%r)" % a
@@ -352,10 +364,10 @@
 
     def test_property_subclass_with_init(self):
         l = []
-        
+
         def x(self):
             l.append('x')
-        
+
         class P(property):
             def __init__(self):
                 property.__init__(self, x)
diff --git a/pypy/module/_cffi_backend/__init__.py 
b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
 from rpython.rlib import rdynload, clibffi, entrypoint
 from rpython.rtyper.lltypesystem import rffi
 
-VERSION = "1.8.4"
+VERSION = "1.9.0"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
diff --git a/pypy/module/_cffi_backend/cbuffer.py 
b/pypy/module/_cffi_backend/cbuffer.py
--- a/pypy/module/_cffi_backend/cbuffer.py
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -2,6 +2,7 @@
 from pypy.interpreter.gateway import unwrap_spec, interp2app
 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
 from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypearray
+from pypy.module._cffi_backend import ctypestruct
 from pypy.objspace.std.bufferobject import W_Buffer
 
 from rpython.rlib.buffer import Buffer
@@ -71,7 +72,12 @@
     ctype = w_cdata.ctype
     if isinstance(ctype, ctypeptr.W_CTypePointer):
         if size < 0:
-            size = ctype.ctitem.size
+            structobj = w_cdata.get_structobj()
+            if (structobj is not None and
+                isinstance(structobj.ctype, ctypestruct.W_CTypeStructOrUnion)):
+                size = structobj._sizeof()
+            if size < 0:
+                size = ctype.ctitem.size
     elif isinstance(ctype, ctypearray.W_CTypeArray):
         if size < 0:
             size = w_cdata._sizeof()
diff --git a/pypy/module/_cffi_backend/cdataobj.py 
b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -329,7 +329,7 @@
     def getattr(self, w_attr):
         cfield = self.getcfield(w_attr)
         with self as ptr:
-            w_res = cfield.read(ptr)
+            w_res = cfield.read(ptr, self)
         return w_res
 
     def setattr(self, w_attr, w_value):
@@ -432,6 +432,9 @@
         lst = ct.cdata_dir()
         return space.newlist([space.wrap(s) for s in lst])
 
+    def get_structobj(self):
+        return None
+
 
 class W_CDataMem(W_CData):
     """This is used only by the results of cffi.cast('int', x)
@@ -453,28 +456,36 @@
     by newp().  They create and free their own memory according to an
     allocator."""
 
-    # the 'length' is either >= 0 for arrays, or -1 for pointers.
-    _attrs_ = ['length']
-    _immutable_fields_ = ['length']
+    # the 'allocated_length' is >= 0 for arrays; for var-sized
+    # structures it is the total size in bytes; otherwise it is -1.
+    _attrs_ = ['allocated_length']
+    _immutable_fields_ = ['allocated_length']
 
     def __init__(self, space, cdata, ctype, length=-1):
         W_CData.__init__(self, space, cdata, ctype)
-        self.length = length
+        self.allocated_length = length
 
     def _repr_extra(self):
         return self._repr_extra_owning()
 
     def _sizeof(self):
         ctype = self.ctype
-        if self.length >= 0:
+        if self.allocated_length >= 0:
             from pypy.module._cffi_backend import ctypearray
-            assert isinstance(ctype, ctypearray.W_CTypeArray)
-            return self.length * ctype.ctitem.size
+            if isinstance(ctype, ctypearray.W_CTypeArray):
+                return self.allocated_length * ctype.ctitem.size
+            else:
+                return self.allocated_length    # var-sized struct size
         else:
             return ctype.size
 
     def get_array_length(self):
-        return self.length
+        from pypy.module._cffi_backend import ctypearray
+        assert isinstance(self.ctype, ctypearray.W_CTypeArray)
+        return self.allocated_length
+
+    def get_structobj(self):
+        return self
 
 
 class W_CDataNewStd(W_CDataNewOwning):
@@ -508,12 +519,19 @@
         self.structobj = structobj
 
     def _repr_extra(self):
-        return self._repr_extra_owning()
+        return self.structobj._repr_extra_owning()
 
     def _do_getitem(self, ctype, i):
         assert i == 0
         return self.structobj
 
+    def get_structobj(self):
+        structobj = self.structobj
+        if isinstance(structobj, W_CDataNewOwning):
+            return structobj
+        else:
+            return None
+
 
 class W_CDataSliced(W_CData):
     """Subclass with an explicit length, for slices."""
diff --git a/pypy/module/_cffi_backend/ctypeptr.py 
b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -211,13 +211,16 @@
             # a W_CDataPtrToStruct object which has a strong reference
             # to a W_CDataNewOwning that really contains the structure.
             #
-            if not space.is_w(w_init, space.w_None):
-                ctitem.force_lazy_struct()
-                if ctitem._with_var_array:
+            varsize_length = -1
+            ctitem.force_lazy_struct()
+            if ctitem._with_var_array:
+                if not space.is_w(w_init, space.w_None):
                     datasize = ctitem.convert_struct_from_object(
                         lltype.nullptr(rffi.CCHARP.TO), w_init, datasize)
+                varsize_length = datasize
             #
-            cdatastruct = allocator.allocate(space, datasize, ctitem)
+            cdatastruct = allocator.allocate(space, datasize, ctitem,
+                                             length=varsize_length)
             ptr = cdatastruct.unsafe_escaping_ptr()
             cdata = cdataobj.W_CDataPtrToStructOrUnion(space, ptr,
                                                        self, cdatastruct)
diff --git a/pypy/module/_cffi_backend/ctypestruct.py 
b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -210,7 +210,7 @@
         return W_CField(self.ctype, offset + self.offset,
                         self.bitshift, self.bitsize, self.flags | fflags)
 
-    def read(self, cdata):
+    def read(self, cdata, w_cdata):
         cdata = rffi.ptradd(cdata, self.offset)
         if self.bitshift == self.BS_REGULAR:
             return self.ctype.convert_to_object(cdata)
@@ -218,6 +218,14 @@
             from pypy.module._cffi_backend import ctypearray
             ctype = self.ctype
             assert isinstance(ctype, ctypearray.W_CTypeArray)
+            structobj = w_cdata.get_structobj()
+            if structobj is not None:
+                # variable-length array
+                size = structobj.allocated_length - self.offset
+                if size >= 0:
+                    arraylen = size // ctype.ctitem.size
+                    return cdataobj.W_CDataSliced(ctype.space, cdata, ctype,
+                                                  arraylen)
             return cdataobj.W_CData(ctype.space, cdata, ctype.ctptr)
         else:
             return self.convert_bitfield_to_object(cdata)
diff --git a/pypy/module/_cffi_backend/newtype.py 
b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -353,7 +353,7 @@
         if fbitsize < 0:
             # not a bitfield: common case
 
-            if isinstance(ftype, ctypearray.W_CTypeArray) and ftype.length==0:
+            if isinstance(ftype, ctypearray.W_CTypeArray) and ftype.length<=0:
                 bs_flag = ctypestruct.W_CField.BS_EMPTY_ARRAY
             else:
                 bs_flag = ctypestruct.W_CField.BS_REGULAR
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- 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.4", ("This test_c.py file is for testing a version"
+assert __version__ == "1.9.0", ("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,):
@@ -3161,17 +3161,19 @@
     assert d[1][0] == 'y'
     assert d[1][1].type is BArray
     assert d[1][1].offset == size_of_int()
-    assert d[1][1].bitshift == -1
+    assert d[1][1].bitshift == -2
     assert d[1][1].bitsize == -1
     #
     p = newp(new_pointer_type(BStruct))
     p.x = 42
     assert p.x == 42
-    assert typeof(p.y) is BIntP
+    assert typeof(p.y) is BArray
+    assert len(p.y) == 0
     assert p.y == cast(BIntP, p) + 1
     #
     p = newp(new_pointer_type(BStruct), [100])
     assert p.x == 100
+    assert len(p.y) == 0
     #
     # Tests for
     #    ffi.new("struct_with_var_array *", [field.., [the_array_items..]])
@@ -3186,6 +3188,10 @@
             p.y[0] = 200
             assert p.y[2] == 0
             p.y[2] = 400
+        assert len(p.y) == 3
+        assert len(p[0].y) == 3
+        assert len(buffer(p)) == sizeof(BInt) * 4
+        assert sizeof(p[0]) == sizeof(BInt) * 4
         plist.append(p)
     for i in range(20):
         p = plist[i]
@@ -3193,13 +3199,31 @@
         assert p.y[0] == 200
         assert p.y[1] == i
         assert p.y[2] == 400
-        assert list(p.y[0:3]) == [200, i, 400]
+        assert list(p.y) == [200, i, 400]
     #
     # the following assignment works, as it normally would, for any array field
-    p.y = [500, 600]
-    assert list(p.y[0:3]) == [500, 600, 400]
+    p.y = [501, 601]
+    assert list(p.y) == [501, 601, 400]
+    p[0].y = [500, 600]
+    assert list(p[0].y) == [500, 600, 400]
+    assert repr(p) == "<cdata 'foo *' owning %d bytes>" % (
+        sizeof(BStruct) + 3 * sizeof(BInt),)
+    assert repr(p[0]) == "<cdata 'foo' owning %d bytes>" % (
+        sizeof(BStruct) + 3 * sizeof(BInt),)
+    assert sizeof(p[0]) == sizeof(BStruct) + 3 * sizeof(BInt)
+    #
+    # from a non-owning pointer, we can't get the length
+    q = cast(new_pointer_type(BStruct), p)
+    assert q.y[0] == 500
+    assert q[0].y[0] == 500
+    py.test.raises(TypeError, len, q.y)
+    py.test.raises(TypeError, len, q[0].y)
+    assert typeof(q.y) is BIntP
+    assert typeof(q[0].y) is BIntP
+    assert sizeof(q[0]) == sizeof(BStruct)
     #
     # error cases
+    py.test.raises(IndexError, "p.y[4]")
     py.test.raises(TypeError, "p.y = cast(BIntP, 0)")
     py.test.raises(TypeError, "p.y = 15")
     py.test.raises(TypeError, "p.y = None")
@@ -3264,6 +3288,33 @@
         assert p.x[5] == 60
         assert p.x[6] == 70
 
+def test_struct_array_not_aligned():
+    # struct a { int x; char y; char z[]; };
+    # ends up of size 8, but 'z' is at offset 5
+    BChar = new_primitive_type("char")
+    BInt = new_primitive_type("int")
+    BCharP = new_pointer_type(BChar)
+    BArray = new_array_type(BCharP, None)
+    BStruct = new_struct_type("foo")
+    complete_struct_or_union(BStruct, [('x', BInt),
+                                       ('y', BChar),
+                                       ('z', BArray)])
+    assert sizeof(BStruct) == 2 * size_of_int()
+    def offsetof(BType, fieldname):
+        return typeoffsetof(BType, fieldname)[1]
+    base = offsetof(BStruct, 'z')
+    assert base == size_of_int() + 1
+    #
+    p = newp(new_pointer_type(BStruct), {'z': 3})
+    assert sizeof(p[0]) == base + 3
+    q = newp(new_pointer_type(BStruct), {'z': size_of_int()})
+    assert sizeof(q) == size_of_ptr()
+    assert sizeof(q[0]) == base + size_of_int()
+    assert len(p.z) == 3
+    assert len(p[0].z) == 3
+    assert len(q.z) == size_of_int()
+    assert len(q[0].z) == size_of_int()
+
 def test_ass_slice():
     BChar = new_primitive_type("char")
     BArray = new_array_type(new_pointer_type(BChar), None)
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py 
b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -408,11 +408,14 @@
             'test_misdeclared_field_1',
             "struct foo_s { int a[6]; };")
         assert ffi.sizeof("struct foo_s") == 24  # found by the actual C code
-        p = ffi.new("struct foo_s *")
-        # lazily build the fields and boom:
-        e = raises(ffi.error, getattr, p, "a")
-        assert str(e.value).startswith("struct foo_s: wrong size for field 'a' 
"
-                                       "(cdef says 20, but C compiler says 
24)")
+        try:
+            # lazily build the fields and boom:
+            p = ffi.new("struct foo_s *")
+            p.a
+            assert False, "should have raised"
+        except ffi.error as e:
+            assert str(e).startswith("struct foo_s: wrong size for field 'a' "
+                                     "(cdef says 20, but C compiler says 24)")
 
     def test_open_array_in_struct(self):
         ffi, lib = self.prepare(
@@ -420,8 +423,10 @@
             'test_open_array_in_struct',
             "struct foo_s { int b; int a[]; };")
         assert ffi.sizeof("struct foo_s") == 4
-        p = ffi.new("struct foo_s *", [5, [10, 20, 30]])
+        p = ffi.new("struct foo_s *", [5, [10, 20, 30, 40]])
         assert p.a[2] == 30
+        assert ffi.sizeof(p) == ffi.sizeof("void *")
+        assert ffi.sizeof(p[0]) == 5 * ffi.sizeof("int")
 
     def test_math_sin_type(self):
         ffi, lib = self.prepare(
@@ -954,6 +959,7 @@
             "struct foo_s { int x; int a[5][8]; int y; };")
         assert ffi.sizeof('struct foo_s') == 42 * ffi.sizeof('int')
         s = ffi.new("struct foo_s *")
+        assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
         assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int')
         assert s.a[4][7] == 0
         raises(IndexError, 's.a[4][8]')
@@ -961,6 +967,18 @@
         assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
         assert ffi.typeof(s.a[0]) == ffi.typeof("int[8]")
 
+    def test_struct_array_guess_length_3(self):
+        ffi, lib = self.prepare(
+            "struct foo_s { int a[][...]; };",
+            'test_struct_array_guess_length_3',
+            "struct foo_s { int x; int a[5][7]; int y; };")
+        assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int')
+        s = ffi.new("struct foo_s *")
+        assert ffi.typeof(s.a) == ffi.typeof("int[][7]")
+        assert s.a[4][6] == 0
+        raises(IndexError, 's.a[4][7]')
+        assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]")
+
     def test_global_var_array_2(self):
         ffi, lib = self.prepare(
             "int a[...][...];",
diff --git a/pypy/module/_hashlib/__init__.py b/pypy/module/_hashlib/__init__.py
--- a/pypy/module/_hashlib/__init__.py
+++ b/pypy/module/_hashlib/__init__.py
@@ -1,5 +1,6 @@
 from pypy.interpreter.mixedmodule import MixedModule
-from pypy.module._hashlib.interp_hashlib import algorithms, fetch_names
+from pypy.module._hashlib.interp_hashlib import (
+    algorithms, fetch_names, HAS_FAST_PKCS5_PBKDF2_HMAC)
 
 
 class Module(MixedModule):
@@ -13,6 +14,9 @@
     for name in algorithms:
         interpleveldefs['openssl_' + name] = 'interp_hashlib.new_' + name
 
+    if HAS_FAST_PKCS5_PBKDF2_HMAC:
+        interpleveldefs['pbkdf2_hmac'] = 'interp_hashlib.pbkdf2_hmac'
+
     def startup(self, space):
         w_meth_names = fetch_names(space)
         space.setattr(self, space.wrap('openssl_md_meth_names'), w_meth_names)
diff --git a/pypy/module/_hashlib/interp_hashlib.py 
b/pypy/module/_hashlib/interp_hashlib.py
--- a/pypy/module/_hashlib/interp_hashlib.py
+++ b/pypy/module/_hashlib/interp_hashlib.py
@@ -8,7 +8,7 @@
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.gateway import unwrap_spec, interp2app
+from pypy.interpreter.gateway import unwrap_spec, interp2app, WrappedDefault
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.module.thread.os_lock import Lock
 
@@ -58,23 +58,26 @@
     def __init__(self, space, name, copy_from=NULL_CTX):
         self.name = name
         digest_type = self.digest_type_by_name(space)
-        self.digest_size = rffi.getintfield(digest_type, 'c_md_size')
+        self.digest_size = ropenssl.EVP_MD_size(digest_type)
 
         # Allocate a lock for each HASH object.
         # An optimization would be to not release the GIL on small requests,
         # and use a custom lock only when needed.
         self.lock = Lock(space)
 
-        ctx = lltype.malloc(ropenssl.EVP_MD_CTX.TO, flavor='raw')
+        ctx = ropenssl.EVP_MD_CTX_new()
+        if ctx is None:
+            raise MemoryError
         rgc.add_memory_pressure(ropenssl.HASH_MALLOC_SIZE + self.digest_size)
         try:
             if copy_from:
-                ropenssl.EVP_MD_CTX_copy(ctx, copy_from)
+                if not ropenssl.EVP_MD_CTX_copy(ctx, copy_from):
+                    raise ValueError
             else:
                 ropenssl.EVP_DigestInit(ctx, digest_type)
             self.ctx = ctx
         except:
-            lltype.free(ctx, flavor='raw')
+            ropenssl.EVP_MD_CTX_free(ctx)
             raise
         self.register_finalizer(space)
 
@@ -82,8 +85,7 @@
         ctx = self.ctx
         if ctx:
             self.ctx = lltype.nullptr(ropenssl.EVP_MD_CTX.TO)
-            ropenssl.EVP_MD_CTX_cleanup(ctx)
-            lltype.free(ctx, flavor='raw')
+            ropenssl.EVP_MD_CTX_free(ctx)
 
     def digest_type_by_name(self, space):
         digest_type = ropenssl.EVP_get_digestbyname(self.name)
@@ -128,21 +130,26 @@
 
     def get_block_size(self, space):
         digest_type = self.digest_type_by_name(space)
-        block_size = rffi.getintfield(digest_type, 'c_block_size')
+        block_size = ropenssl.EVP_MD_block_size(digest_type)
         return space.wrap(block_size)
 
     def get_name(self, space):
         return space.wrap(self.name)
 
     def _digest(self, space):
-        with lltype.scoped_alloc(ropenssl.EVP_MD_CTX.TO) as ctx:
+        ctx = ropenssl.EVP_MD_CTX_new()
+        if ctx is None:
+            raise MemoryError
+        try:
             with self.lock:
-                ropenssl.EVP_MD_CTX_copy(ctx, self.ctx)
+                if not ropenssl.EVP_MD_CTX_copy(ctx, self.ctx):
+                    raise ValueError
             digest_size = self.digest_size
             with rffi.scoped_alloc_buffer(digest_size) as buf:
                 ropenssl.EVP_DigestFinal(ctx, buf.raw, None)
-                ropenssl.EVP_MD_CTX_cleanup(ctx)
                 return buf.str(digest_size)
+        finally:
+            ropenssl.EVP_MD_CTX_free(ctx)
 
 
 W_Hash.typedef = TypeDef(
@@ -177,3 +184,27 @@
 for _name in algorithms:
     _newname = 'new_%s' % (_name,)
     globals()[_newname] = make_new_hash(_name, _newname)
+
+
+HAS_FAST_PKCS5_PBKDF2_HMAC = ropenssl.PKCS5_PBKDF2_HMAC is not None
+if HAS_FAST_PKCS5_PBKDF2_HMAC:
+    @unwrap_spec(name=str, password=str, salt=str, rounds=int,
+                 w_dklen=WrappedDefault(None))
+    def pbkdf2_hmac(space, name, password, salt, rounds, w_dklen):
+        digest = ropenssl.EVP_get_digestbyname(name)
+        if not digest:
+            raise oefmt(space.w_ValueError, "unknown hash function")
+        if space.is_w(w_dklen, space.w_None):
+            dklen = ropenssl.EVP_MD_size(digest)
+        else:
+            dklen = space.int_w(w_dklen)
+        if dklen < 1:
+            raise oefmt(space.w_ValueError,
+                        "key length must be greater than 0.")
+        with rffi.scoped_alloc_buffer(dklen) as buf:
+            r = ropenssl.PKCS5_PBKDF2_HMAC(
+                password, len(password), salt, len(salt), rounds, digest,
+                dklen, buf.raw)
+            if not r:
+                raise ValueError
+            return space.wrap(buf.str(dklen))
diff --git a/pypy/module/_hashlib/test/test_hashlib.py 
b/pypy/module/_hashlib/test/test_hashlib.py
--- a/pypy/module/_hashlib/test/test_hashlib.py
+++ b/pypy/module/_hashlib/test/test_hashlib.py
@@ -15,17 +15,19 @@
 
     def test_attributes(self):
         import hashlib
-        for name, expected_size in {'md5': 16,
-                                    'sha1': 20,
-                                    'sha224': 28,
-                                    'sha256': 32,
-                                    'sha384': 48,
-                                    'sha512': 64,
-                                    }.items():
+        for name, (expected_size, expected_block_size) in {
+                'md5': (16, 64),
+                'sha1': (20, 64),
+                'sha224': (28, 64),
+                'sha256': (32, 64),
+                'sha384': (48, 128),
+                'sha512': (64, 128),
+                }.items():
             h = hashlib.new(name)
             assert h.name == name
             assert h.digest_size == expected_size
             assert h.digestsize == expected_size
+            assert h.block_size == expected_block_size
             #
             h.update('abc')
             h2 = h.copy()
@@ -46,6 +48,7 @@
             h = py_new(name)('')
             assert h.digest_size == expected_size
             assert h.digestsize == expected_size
+            assert h.block_size == expected_block_size
             #
             h.update('abc')
             h2 = h.copy()
@@ -108,3 +111,13 @@
             got.decode('hex')
             if expected is not None:
                 assert got == expected
+
+    def test_pbkdf2(self):
+        try:
+            from _hashlib import pbkdf2_hmac
+        except ImportError:
+            skip("Requires OpenSSL >= 1.1")
+        out = pbkdf2_hmac('sha1', 'password', 'salt', 1)
+        assert out == '0c60c80f961f0e71f3a9b524af6012062fe037a6'.decode('hex')
+        out = pbkdf2_hmac('sha1', 'password', 'salt', 2, None)
+        assert out == 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957'.decode('hex')
diff --git a/pypy/module/_socket/interp_socket.py 
b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -479,6 +479,14 @@
 
     @unwrap_spec(nbytes=int, flags=int)
     def recv_into_w(self, space, w_buffer, nbytes=0, flags=0):
+        """recv_into(buffer, [nbytes[, flags]]) -> nbytes_read
+
+        A version of recv() that stores its data into a buffer rather than 
creating
+        a new string.  Receive up to buffersize bytes from the socket.  If 
buffersize
+        is not specified (or 0), receive up to the size available in the given 
buffer.
+
+        See recv() for documentation about the flags.
+        """
         rwbuffer = space.getarg_w('w*', w_buffer)
         lgt = rwbuffer.getlength()
         if nbytes == 0 or nbytes > lgt:
@@ -490,6 +498,10 @@
 
     @unwrap_spec(nbytes=int, flags=int)
     def recvfrom_into_w(self, space, w_buffer, nbytes=0, flags=0):
+        """recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)
+
+        Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's 
address info.
+        """
         rwbuffer = space.getarg_w('w*', w_buffer)
         lgt = rwbuffer.getlength()
         if nbytes == 0:
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -33,9 +33,10 @@
 PY_SSL_CLIENT, PY_SSL_SERVER = 0, 1
 
 (PY_SSL_VERSION_SSL2, PY_SSL_VERSION_SSL3,
- PY_SSL_VERSION_SSL23, PY_SSL_VERSION_TLS1, PY_SSL_VERSION_TLS1_1,
+ PY_SSL_VERSION_TLS, PY_SSL_VERSION_TLS1, PY_SSL_VERSION_TLS1_1,
  PY_SSL_VERSION_TLS1_2) = range(6)
 
+
 SOCKET_IS_NONBLOCKING, SOCKET_IS_BLOCKING = 0, 1
 SOCKET_HAS_TIMED_OUT, SOCKET_HAS_BEEN_CLOSED = 2, 3
 SOCKET_TOO_LARGE_FOR_SELECT, SOCKET_OPERATION_OK = 4, 5
@@ -68,11 +69,12 @@
 constants["HAS_NPN"] = HAS_NPN
 constants["HAS_ALPN"] = HAS_ALPN
 
+constants["PROTOCOL_TLS"] = PY_SSL_VERSION_TLS
+constants["PROTOCOL_SSLv23"] = PY_SSL_VERSION_TLS  # Legacy name
 if not OPENSSL_NO_SSL2:
     constants["PROTOCOL_SSLv2"]  = PY_SSL_VERSION_SSL2
 if not OPENSSL_NO_SSL3:
     constants["PROTOCOL_SSLv3"]  = PY_SSL_VERSION_SSL3
-constants["PROTOCOL_SSLv23"] = PY_SSL_VERSION_SSL23
 constants["PROTOCOL_TLSv1"]  = PY_SSL_VERSION_TLS1
 if HAVE_TLSv1_2:
     constants["PROTOCOL_TLSv1_1"] = PY_SSL_VERSION_TLS1_1
@@ -111,7 +113,10 @@
         err_reason = libssl_ERR_GET_REASON(errcode)
         reason_str = ERROR_CODES_TO_NAMES.get((err_lib, err_reason), None)
         lib_str = LIBRARY_CODES_TO_NAMES.get(err_lib, None)
-        msg = rffi.charp2str(libssl_ERR_reason_error_string(errcode))
+        raw_msg = libssl_ERR_reason_error_string(errcode)
+        msg = None
+        if raw_msg:
+            msg = rffi.charp2str(raw_msg)
     if not msg:
         msg = "unknown error"
     if reason_str and lib_str:
@@ -637,9 +642,12 @@
         if not self.ssl:
             return space.w_None
         comp_method = libssl_SSL_get_current_compression(self.ssl)
-        if not comp_method or intmask(comp_method[0].c_type) == NID_undef:
+        if not comp_method:
             return space.w_None
-        short_name = libssl_OBJ_nid2sn(comp_method[0].c_type)
+        method_type = intmask(libssl_COMP_get_type(comp_method))
+        if method_type == NID_undef:
+            return space.w_None
+        short_name = libssl_COMP_get_name(comp_method)
         if not short_name:
             return space.w_None
         return space.wrap(rffi.charp2str(short_name))
@@ -795,7 +803,7 @@
     for index in range(entry_count):
         entry = libssl_X509_NAME_get_entry(xname, index)
         # check to see if we've gotten to a new RDN
-        entry_level = intmask(entry[0].c_set)
+        entry_level = intmask(libssl_X509_NAME_ENTRY_set(entry))
         if rdn_level >= 0:
             if rdn_level != entry_level:
                 # yes, new RDN
@@ -846,8 +854,9 @@
                                 "No method for internalizing subjectAltName!'")
 
             with lltype.scoped_alloc(rffi.CCHARPP.TO, 1) as p_ptr:
-                p_ptr[0] = ext[0].c_value.c_data
-                length = intmask(ext[0].c_value.c_length)
+                ext_value = libssl_X509_EXTENSION_get_data(ext)
+                p_ptr[0] = ext_value.c_data
+                length = intmask(ext_value.c_length)
                 null = lltype.nullptr(rffi.VOIDP.TO)
                 if method[0].c_it:
                     names = rffi.cast(GENERAL_NAMES, libssl_ASN1_item_d2i(
@@ -967,10 +976,8 @@
     if OPENSSL_VERSION_NUMBER >= 0x10001000:
         # Calls x509v3_cache_extensions and sets up crldp
         libssl_X509_check_ca(certificate)
-        dps = certificate[0].c_crldp
-    else:
-        dps = rffi.cast(stack_st_DIST_POINT, libssl_X509_get_ext_d2i(
-            certificate, NID_crl_distribution_points, None, None))
+    dps = rffi.cast(stack_st_DIST_POINT, libssl_X509_get_ext_d2i(
+        certificate, NID_crl_distribution_points, None, None))
     if not dps:
         return None
 
@@ -1268,14 +1275,14 @@
     @staticmethod
     @unwrap_spec(protocol=int)
     def descr_new(space, w_subtype, protocol):
-        if protocol == PY_SSL_VERSION_TLS1:
+        if protocol == PY_SSL_VERSION_TLS:
+            method = libssl_TLS_method()
+        elif protocol == PY_SSL_VERSION_TLS1:
             method = libssl_TLSv1_method()
         elif protocol == PY_SSL_VERSION_SSL3 and not OPENSSL_NO_SSL3:
             method = libssl_SSLv3_method()
         elif protocol == PY_SSL_VERSION_SSL2 and not OPENSSL_NO_SSL2:
             method = libssl_SSLv2_method()
-        elif protocol == PY_SSL_VERSION_SSL23:
-            method = libssl_SSLv23_method()
         elif protocol == PY_SSL_VERSION_TLS1_1 and HAVE_TLSv1_2:
             method = libssl_TLSv1_1_method()
         elif protocol == PY_SSL_VERSION_TLS1_2 and HAVE_TLSv1_2:
@@ -1303,6 +1310,7 @@
             # OpenSSL 1.0.2+), or use prime256v1 by default.
             # This is Apache mod_ssl's initialization
             # policy, so we should be safe.
+            # OpenSSL 1.1 has it enabled by default.
             if libssl_SSL_CTX_set_ecdh_auto:
                 libssl_SSL_CTX_set_ecdh_auto(self.ctx, 1)
             else:
@@ -1390,20 +1398,22 @@
 
     def descr_get_verify_flags(self, space):
         store = libssl_SSL_CTX_get_cert_store(self.ctx)
-        flags = libssl_X509_VERIFY_PARAM_get_flags(store[0].c_param)
+        param = libssl_X509_STORE_get0_param(store)
+        flags = libssl_X509_VERIFY_PARAM_get_flags(param)
         return space.wrap(flags)
 
     def descr_set_verify_flags(self, space, w_obj):
         new_flags = space.int_w(w_obj)
         store = libssl_SSL_CTX_get_cert_store(self.ctx)
-        flags = libssl_X509_VERIFY_PARAM_get_flags(store[0].c_param)
+        param = libssl_X509_STORE_get0_param(store)
+        flags = libssl_X509_VERIFY_PARAM_get_flags(param)
         flags_clear = flags & ~new_flags
         flags_set = ~flags & new_flags
         if flags_clear and not libssl_X509_VERIFY_PARAM_clear_flags(
-                store[0].c_param, flags_clear):
+                param, flags_clear):
             raise _ssl_seterror(space, None, 0)
         if flags_set and not libssl_X509_VERIFY_PARAM_set_flags(
-                store[0].c_param, flags_set):
+                param, flags_set):
             raise _ssl_seterror(space, None, 0)
 
     def descr_get_check_hostname(self, space):
@@ -1614,14 +1624,16 @@
         x509 = 0
         x509_ca = 0
         crl = 0
-        for i in range(libssl_sk_X509_OBJECT_num(store[0].c_objs)):
-            obj = libssl_sk_X509_OBJECT_value(store[0].c_objs, i)
-            if intmask(obj.c_type) == X509_LU_X509:
+        objs = libssl_X509_STORE_get0_objects(store)
+        for i in range(libssl_sk_X509_OBJECT_num(objs)):
+            obj = libssl_sk_X509_OBJECT_value(objs, i)
+            obj_type = intmask(libssl_X509_OBJECT_get_type(obj))
+            if obj_type == X509_LU_X509:
                 x509 += 1
                 if libssl_X509_check_ca(
-                        libssl_pypy_X509_OBJECT_data_x509(obj)):
+                        libssl_X509_OBJECT_get0_X509(obj)):
                     x509_ca += 1
-            elif intmask(obj.c_type) == X509_LU_CRL:
+            elif obj_type == X509_LU_CRL:
                 crl += 1
             else:
                 # Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
@@ -1660,13 +1672,14 @@
             binary_mode = False
         rlist = []
         store = libssl_SSL_CTX_get_cert_store(self.ctx)
-        for i in range(libssl_sk_X509_OBJECT_num(store[0].c_objs)):
-            obj = libssl_sk_X509_OBJECT_value(store[0].c_objs, i)
-            if intmask(obj.c_type) != X509_LU_X509:
+        objs = libssl_X509_STORE_get0_objects(store)
+        for i in range(libssl_sk_X509_OBJECT_num(objs)):
+            obj = libssl_sk_X509_OBJECT_value(objs, i)
+            if intmask(libssl_X509_OBJECT_get_type(obj)) != X509_LU_X509:
                 # not a x509 cert
                 continue
             # CA for any purpose
-            cert = libssl_pypy_X509_OBJECT_data_x509(obj)
+            cert = libssl_X509_OBJECT_get0_X509(obj)
             if not libssl_X509_check_ca(cert):
                 continue
             if binary_mode:
diff --git a/pypy/module/_ssl/test/test_ssl.py 
b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -77,7 +77,7 @@
         if sys.version_info < (2, 7, 9):
             ss = _ssl.sslwrap(s, 0)
         else:
-            ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+            ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
             ss = ctx._wrap_socket(s, 0)
             assert ss.context is ctx
         exc = raises(_socket.error, ss.do_handshake)
@@ -95,7 +95,7 @@
         if sys.version_info < (2, 7, 9):
             ss = _ssl.sslwrap(s, 0)
         else:
-            ss = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)._wrap_socket(s, 0)
+            ss = _ssl._SSLContext(_ssl.PROTOCOL_TLS)._wrap_socket(s, 0)
         s.close()
         exc = raises(_ssl.SSLError, ss.write, "data")
         assert exc.value.message == 'Underlying socket has been closed.'
@@ -123,13 +123,13 @@
 
     def test_context(self):
         import _ssl
-        s = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        s = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         raises(ValueError, _ssl._SSLContext, -1)
 
         assert type(s.options) is long
-        assert s.options & _ssl.OP_NO_SSLv2
-        s.options &= ~_ssl.OP_NO_SSLv2
-        assert not s.options & _ssl.OP_NO_SSLv2
+        assert s.options & _ssl.OP_NO_SSLv3
+        s.options &= ~_ssl.OP_NO_SSLv3
+        assert not s.options & _ssl.OP_NO_SSLv3
         raises(TypeError, "s.options = 2.5")
 
         assert not s.check_hostname
@@ -159,7 +159,7 @@
 
     def test_set_default_verify_paths(self):
         import _ssl
-        s = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        s = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         s.set_default_verify_paths()
 
 
@@ -253,13 +253,44 @@
         if not _ssl.HAS_NPN:
             skip("NPN requires OpenSSL 1.0.1 or greater")
 
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx._set_npn_protocols(b'\x08http/1.1\x06spdy/2')
         ss = ctx._wrap_socket(self.s._sock, True,
                               server_hostname="svn.python.org")
         self.s.close()
         del ss; gc.collect()
 
+    def test_peer_certificate(self):
+        import _ssl, gc
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
+        ss = ctx._wrap_socket(self.s._sock, False)
+        ss.do_handshake()
+        assert isinstance(ss.peer_certificate(der=True), bytes)
+        assert isinstance(ss.peer_certificate(), dict)
+        self.s.close()
+        del ss; gc.collect()
+
+    def test_peer_certificate_verify(self):
+        import _ssl, ssl, gc
+        paths = ssl.get_default_verify_paths()
+        if not paths.capath and not paths.cafile:
+            skip("ssl.get_default_verify_paths() failed to return any path")
+
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
+        ctx.verify_mode = _ssl.CERT_REQUIRED
+        ctx.load_verify_locations(capath=paths.capath, cafile=paths.cafile)
+
+        ss = ctx._wrap_socket(self.s._sock, False)
+        try:
+            ss.do_handshake()
+        except _ssl.SSLError as e:
+            if e.reason == 'CERTIFICATE_VERIFY_FAILED':
+                skip("Certificate verification failed. "
+                     "Most likely we just don't have any CA certificates.")
+        assert ss.peer_certificate()
+        self.s.close()
+        del ss; gc.collect()
+
     def test_tls_unique_cb(self):
         import ssl, sys, gc
         ss = ssl.wrap_socket(self.s)
@@ -325,7 +356,7 @@
 
     def test_load_cert_chain(self):
         import _ssl, errno
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.load_cert_chain(self.keycert)
         ctx.load_cert_chain(self.cert, self.key)
         exc = raises(IOError, ctx.load_cert_chain, "inexistent.pem")
@@ -344,11 +375,11 @@
 
     def test_load_verify_locations(self):
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.load_verify_locations(self.keycert)
         ctx.load_verify_locations(cafile=self.keycert, capath=None)
 
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         with open(self.keycert) as f:
             cacert_pem = f.read().decode('ascii')
         ctx.load_verify_locations(cadata=cacert_pem)
@@ -356,7 +387,7 @@
 
     def test_get_ca_certs(self):
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.load_verify_locations(self.keycert)
         assert ctx.get_ca_certs() == []
         ctx.load_verify_locations(self.python_org_cert)
@@ -370,7 +401,7 @@
 
     def test_cert_store_stats(self):
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         assert ctx.cert_store_stats() == {'x509_ca': 0, 'crl': 0, 'x509': 0}
         ctx.load_cert_chain(self.keycert)
         assert ctx.cert_store_stats() == {'x509_ca': 0, 'crl': 0, 'x509': 0}
@@ -379,7 +410,7 @@
 
     def test_load_dh_params(self):
         import _ssl, errno
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.load_dh_params(self.dh512)
         raises(TypeError, ctx.load_dh_params)
         raises(TypeError, ctx.load_dh_params, None)
@@ -389,7 +420,7 @@
 
     def test_set_ecdh_curve(self):
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.set_ecdh_curve("prime256v1")
         raises(ValueError, ctx.set_ecdh_curve, "foo")
 
@@ -434,7 +465,7 @@
     def test_lib_reason(self):
         # Test the library and reason attributes
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         exc = raises(_ssl.SSLError, ctx.load_dh_params, self.keycert)
         assert exc.value.library == 'PEM'
         assert exc.value.reason == 'NO_START_LINE'
@@ -445,7 +476,7 @@
         # Check that the appropriate SSLError subclass is raised
         # (this only tests one of them)
         import _ssl, _socket
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         s = _socket.socket()
         try:
             s.bind(("127.0.0.1", 0))
diff --git a/pypy/module/array/test/test_array.py 
b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -2,7 +2,18 @@
 import pytest
 
 
-class BaseArrayTests:
+class AppTestArray(object):
+    spaceconfig = {'usemodules': ['array', 'struct', '_rawffi', 'binascii']}
+
+    def setup_class(cls):
+        cls.w_array = cls.space.appexec([], """():
+            import array
+            return array.array
+        """)
+        cls.w_tempfile = cls.space.wrap(
+            str(pytest.ensuretemp('array').join('tmpfile')))
+        cls.w_maxint = cls.space.wrap(sys.maxint)
+
     def test_ctor(self):
         assert len(self.array('c')) == 0
         assert len(self.array('i')) == 0
@@ -22,8 +33,8 @@
         a = self.array('u')
         raises(TypeError, a.append, 7)
         raises(TypeError, a.append, u'hi')
-        a.append(unicode('h'))
-        assert a[0] == unicode('h')
+        a.append(u'h')
+        assert a[0] == u'h'
         assert type(a[0]) is unicode
         assert len(a) == 1
 
@@ -67,7 +78,7 @@
                            ('H', (     0, 56783, 65535),  int),
                            ('i', (-32768, 30535, 32767),  int),
                            ('I', (     0, 56783, 65535), long),
-                           ('l', (-2 ** 32 / 2, 34, 2 ** 32 / 2 - 1),  int),
+                           ('l', (-2 ** 32 // 2, 34, 2 ** 32 // 2 - 1),  int),
                            ('L', (0, 3523532, 2 ** 32 - 1), long),
                            ):
             a = self.array(tc, ok)
@@ -105,7 +116,7 @@
             assert a.tolist() == vals
 
             a = self.array(tc.lower())
-            vals = [-1 * (2 ** itembits) / 2,  (2 ** itembits) / 2 - 1]
+            vals = [-1 * (2 ** itembits) // 2,  (2 ** itembits) // 2 - 1]
             a.fromlist(vals)
             assert a.tolist() == vals
 
@@ -137,11 +148,11 @@
         for t in inttypes:
             a = self.array(t, [1, 2, 3])
             b = a.itemsize
-            for v in (-2 ** (8 * b) / 2, 2 ** (8 * b) / 2 - 1):
+            for v in (-2 ** (8 * b) // 2, 2 ** (8 * b) // 2 - 1):
                 a[1] = v
                 assert a[0] == 1 and a[1] == v and a[2] == 3
-            raises(OverflowError, a.append, -2 ** (8 * b) / 2 - 1)
-            raises(OverflowError, a.append, 2 ** (8 * b) / 2)
+            raises(OverflowError, a.append, -2 ** (8 * b) // 2 - 1)
+            raises(OverflowError, a.append, 2 ** (8 * b) // 2)
 
             a = self.array(t.upper(), [1, 2, 3])
             b = a.itemsize
@@ -175,42 +186,35 @@
                 raises(ValueError, a.fromstring, '\x00' * (a.itemsize + 1))
                 raises(ValueError, a.fromstring, '\x00' * (2 * a.itemsize - 1))
                 raises(ValueError, a.fromstring, '\x00' * (2 * a.itemsize + 1))
-            b = self.array(t, '\x00' * a.itemsize * 2)
+            b = self.array(t, b'\x00' * a.itemsize * 2)
             assert len(b) == 2 and b[0] == 0 and b[1] == 0
             if sys.version_info >= (2, 7, 11):
                 raises(ValueError, a.fromstring, a)
 
     def test_fromfile(self):
-
-        ## class myfile(object):
-        ##     def __init__(self, c, s):
-        ##         self.c = c
-        ##         self.s = s
-        ##     def read(self,n):
-        ##         return self.c*min(n,self.s)
         def myfile(c, s):
-            f = open(self.tempfile, 'w')
+            f = open(self.tempfile, 'wb')
             f.write(c * s)
             f.close()
-            return open(self.tempfile, 'r')
+            return open(self.tempfile, 'rb')
 
-        f = myfile('\x00', 100)
+        f = myfile(b'\x00', 100)
         for t in 'bBhHiIlLfd':
             a = self.array(t)
             a.fromfile(f, 2)
             assert len(a) == 2 and a[0] == 0 and a[1] == 0
 
         a = self.array('b')
-        a.fromfile(myfile('\x01', 20), 2)
+        a.fromfile(myfile(b'\x01', 20), 2)
         assert len(a) == 2 and a[0] == 1 and a[1] == 1
 
         a = self.array('h')
-        a.fromfile(myfile('\x01', 20), 2)
+        a.fromfile(myfile(b'\x01', 20), 2)
         assert len(a) == 2 and a[0] == 257 and a[1] == 257
 
         for i in (0, 1):
             a = self.array('h')
-            raises(EOFError, a.fromfile, myfile('\x01', 2 + i), 2)
+            raises(EOFError, a.fromfile, myfile(b'\x01', 2 + i), 2)
             assert len(a) == 1 and a[0] == 257
 
     def test_fromlist(self):
@@ -250,12 +254,12 @@
         assert repr(a) == "array('b', [1, 2, 1, 2])"
 
     def test_fromunicode(self):
-        raises(ValueError, self.array('i').fromunicode, unicode('hi'))
+        raises(ValueError, self.array('i').fromunicode, u'hi')
         a = self.array('u')
-        a.fromunicode(unicode('hi'))
+        a.fromunicode(u'hi')
         assert len(a) == 2 and a[0] == 'h' and a[1] == 'i'
 
-        b = self.array('u', unicode('hi'))
+        b = self.array('u', u'hi')
         assert len(b) == 2 and b[0] == 'h' and b[1] == 'i'
 
     def test_sequence(self):
@@ -357,23 +361,6 @@
                         except ValueError:
                             assert not ok
 
-    def test_reversingslice_pre26(self):
-        import sys
-        if sys.version_info >= (2, 6):
-            skip('arrays can handle more slice ops than lists in 2.6')
-
-        for a in range(-4, 5):
-            for b in range(-4, 5):
-                for c in [-4, -3, -2, -1, 1, 2, 3, 4]:
-                    lst = [1, 2, 3]
-                    arr = self.array('i', lst)
-                    for vals in ([4, 5], [6], []):
-                        try:
-                            lst[a:b:c] = vals
-                        except ValueError:
-                            raises(ValueError,
-                                   "arr[a:b:c]=self.array('i', vals)")
-
     def test_toxxx(self):
         a = self.array('i', [1, 2, 3])
         l = a.tolist()
@@ -405,7 +392,7 @@
                                ('BHILfd', (127, 0, 1, 7, 255, 169)),
                                ('hilHILfd', (32760, 30123, 3422, 23244))):
             for tc in tcodes:
-                values += ((2 ** self.array(tc).itemsize) / 2 - 1, )
+                values += ((2 ** self.array(tc).itemsize) // 2 - 1, )
                 s = self.array(tc, values).tostring()
                 a = unpack(tc * len(values), s)
                 assert a == values
@@ -420,8 +407,7 @@
         assert repr(a) == "array('c', 'hi')"
 
         raises(ValueError, self.array('i').tounicode)
-        assert self.array('u', unicode('hello')).tounicode() == \
-               unicode('hello')
+        assert self.array('u', u'hello').tounicode() == u'hello'
 
     def test_empty_tostring(self):
         a = self.array('l')
@@ -493,14 +479,14 @@
 
     def test_compare(self):
         class comparable(object):
-            def __cmp__(self, other):
-                return 0
+            def __eq__(self, other):
+                return True
         class incomparable(object):
             pass
 
         for v1, v2, tt in (([1, 2, 3], [1, 3, 2], 'bhilBHIL'),
                          ('abc', 'acb', 'c'),
-                         (unicode('abc'), unicode('acb'), 'u')):
+                         (u'abc', u'acb', 'u')):
             for t in tt:
                 a = self.array(t, v1)
                 b = self.array(t, v1)
@@ -767,16 +753,16 @@
                 self.height = height
                 return self
 
-            def _index(self, (x,y)):
+            def _index(self, x, y):
                 x = min(max(x, 0), self.width-1)
                 y = min(max(y, 0), self.height-1)
                 return y * self.width + x
 
             def __getitem__(self, i):
-                return array.__getitem__(self, self._index(i))
+                return array.__getitem__(self, self._index(*i))
 
             def __setitem__(self, i, val):
-                return array.__setitem__(self, self._index(i), val)
+                return array.__setitem__(self, self._index(*i), val)
 
         img = Image(5, 10, 'B')
         for y in range(10):
@@ -844,8 +830,8 @@
         assert repr(mya('i', (1, 2, 3))) == "array('i', [1, 2, 3])"
 
     def test_unicode_outofrange(self):
-        a = self.array('u', unicode(r'\x01\u263a\x00\ufeff', 'unicode-escape'))
-        b = self.array('u', unicode(r'\x01\u263a\x00\ufeff', 'unicode-escape'))
+        a = self.array('u', u'\x01\u263a\x00\ufeff')
+        b = self.array('u', u'\x01\u263a\x00\ufeff')
         b.byteswap()
         assert a != b
 
@@ -853,7 +839,7 @@
         import sys
         if sys.maxunicode == 0xffff:
             skip("test for 32-bit unicodes")
-        a = self.array('u', '\xff\xff\xff\xff')
+        a = self.array('u', b'\xff\xff\xff\xff')
         assert len(a) == 1
         assert repr(a[0]) == "u'\Uffffffff'"
         if sys.maxint == 2147483647:
@@ -954,28 +940,6 @@
         assert a[0] == u'b'
 
 
-class TestCPythonsOwnArray(BaseArrayTests):
-    def setup_class(cls):
-        import array
-        cls.array = array.array
-        import struct
-        cls.struct = struct
-        cls.tempfile = str(pytest.ensuretemp('array').join('tmpfile'))
-        cls.maxint = sys.maxint
-
-
-class AppTestArray(BaseArrayTests):
-    spaceconfig = {'usemodules': ['array', 'struct', '_rawffi', 'binascii']}
-
-    def setup_class(cls):
-        cls.w_array = cls.space.appexec([], """():
-            import array
-            return array.array
-        """)
-        cls.w_tempfile = cls.space.wrap(
-            str(pytest.ensuretemp('array').join('tmpfile')))
-        cls.w_maxint = cls.space.wrap(sys.maxint)
-
     def test_buffer_info(self):
         a = self.array('c', 'Hi!')
         bi = a.buffer_info()
diff --git a/pypy/module/array/test/test_array_old.py 
b/pypy/module/array/test/test_array_old.py
deleted file mode 100644
--- a/pypy/module/array/test/test_array_old.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# minimal tests.  See also lib-python/modified-2.4.1/test/test_array.
-
-import py
-from py.test import raises
-import struct
-
-
-class BaseArrayTests:
-    # XXX very incomplete
-
-    native_sizes = {'l': struct.calcsize('l')}
-
-    def test_attributes(self):
-        a = self.array.array('c')
-        assert a.typecode == 'c'
-        assert a.itemsize == 1
-        a = self.array.array('l')
-        assert a.typecode == 'l'
-        assert a.itemsize == self.native_sizes['l']
-
-    def test_imul(self):
-        a = self.array.array('i', [12, 34])
-        a *= 3
-        assert a.tolist() == [12, 34] * 3
-
-    def test_unicode(self):
-        a = self.array.array('u')
-        a.fromunicode(unichr(9999))
-        assert len(a) == 1
-        assert a.tolist() == [unichr(9999)]
-
-    def test_pickle(self):
-        import sys
-        if sys.version_info < (2, 5):
-            py.test.skip("array.array not picklable before python 2.5")
-        import pickle
-
-        for content in [[56, -12, 34], []]:
-            a = self.array.array('i', content)
-            a2 = pickle.loads(pickle.dumps(a))
-            assert type(a2) is self.array.array
-            assert list(a2) == content
-
-    def test_init_vs_new(self):
-        import sys
-        if sys.version_info < (2, 5):
-            py.test.skip("array.array constructor changed in 2.5")
-        class A(self.array.array):
-            def __init__(self, *args, **kwds):
-                self.args = args
-                self.kwds = kwds
-
-        a = A('c', foo='bar')
-        assert a.args == ('c',)
-        assert a.kwds == {'foo': 'bar'}
-        a = A('i', range(10), some=42)
-        assert a.args == ('i', range(10))
-        assert a.kwds == {'some': 42}
-        raises(TypeError, A)
-        raises(TypeError, A, 42)
-        raises(TypeError, A, 'i', [], [])
-        raises(TypeError, self.array.array, 'i', [], foo='bar')
-
-
-class TestCPythonsOwnArray(BaseArrayTests):
-
-    def setup_class(cls):
-        import array
-        cls.array = array
-
-
-## class TestArrayOnTopOfCPython(BaseArrayTests):
-
-##     def setup_class(cls):
-##         from pypy.tool.lib_pypy import LIB_PYPY
-##         if not hasattr(struct, 'pack_into'):
-##             py.test.skip("requires CPython >= 2.5")
-##         import new
-##         path = LIB_PYPY.join('array.py')
-##         myarraymodule = new.module('array')
-##         execfile(str(path), myarraymodule.__dict__)
-##         cls.array = myarraymodule
-
-##     def test_unicode(self):
-##         py.test.skip("no 'u' type code in CPython's struct module")
-
-##     def test_pickle(self):
-##         py.test.skip("pickle getting confused by the hack in setup_class()")
-
-
-class AppTestArray(BaseArrayTests):
-    spaceconfig = {'usemodules': ['struct', 'array', 'binascii']}
-
-    def setup_class(cls):
-        """Import the array module and make it available as self.array."""
-        cls.w_array = cls.space.getbuiltinmodule('array')
-        cls.w_native_sizes = cls.space.wrap(cls.native_sizes)
-
-
-## class AppTestArrayWithRawFFI(AppTestArray):
-##     """
-##     The same as the base class, but with a space that also includes the
-##     _rawffi module.  The array module internally uses it in this case.
-##     """
-##     spaceconfig = dict(usemodules=['struct', '_rawffi'])
-
-##     def test_buffer_info(self):
-##         a = self.array.array('l', [123, 456])
-##         assert a.itemsize == self.native_sizes['l']
-##         address, length = a.buffer_info()
-##         assert length == 2      # and not 2 * self.native_sizes['l']
-##         assert address != 0
-##         # should check the address via some unsafe peeking, but it's
-##         # not easy on top of py.py
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -79,11 +79,16 @@
 CONST_STRING = lltype.Ptr(lltype.Array(lltype.Char,
                                        hints={'nolength': True}),
                           use_cache=False)
+CONST_STRINGP = lltype.Ptr(lltype.Array(rffi.CCHARP,
+                                       hints={'nolength': True}),
+                          use_cache=False)
 CONST_WSTRING = lltype.Ptr(lltype.Array(lltype.UniChar,
                                         hints={'nolength': True}),
                            use_cache=False)
 assert CONST_STRING is not rffi.CCHARP
 assert CONST_STRING == rffi.CCHARP
+assert CONST_STRINGP is not rffi.CCHARPP
+assert CONST_STRINGP == rffi.CCHARPP
 assert CONST_WSTRING is not rffi.CWCHARP
 assert CONST_WSTRING == rffi.CWCHARP
 
@@ -1004,6 +1009,8 @@
     for i, argtype in enumerate(func.argtypes):
         if argtype is CONST_STRING:
             arg = 'const char *@'
+        elif argtype is CONST_STRINGP:
+            arg = 'const char **@'
         elif argtype is CONST_WSTRING:
             arg = 'const wchar_t *@'
         else:
diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py
--- a/pypy/module/cpyext/buffer.py
+++ b/pypy/module/cpyext/buffer.py
@@ -2,7 +2,6 @@
 from pypy.module.cpyext.api import (
     cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER)
 from pypy.module.cpyext.pyobject import PyObject
-from pypy.module.cpyext.bytesobject import PyBytesObject
 
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyObject_CheckBuffer(space, pyobj):
diff --git a/pypy/module/cpyext/memoryobject.py 
b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -1,6 +1,6 @@
 from pypy.module.cpyext.api import (cpython_api, Py_buffer, CANNOT_FAIL,
                          Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers, 
Py_ssize_tP)
-from pypy.module.cpyext.pyobject import PyObject, make_ref, incref
+from pypy.module.cpyext.pyobject import PyObject, make_ref, incref, from_ref
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rlib.rarithmetic import widen
 from pypy.objspace.std.memoryobject import W_MemoryView
@@ -132,11 +132,22 @@
 def PyMemoryView_FromObject(space, w_obj):
     return space.call_method(space.builtin, "memoryview", w_obj)
 
+@cpython_api([lltype.Ptr(Py_buffer)], PyObject)
+def PyMemoryView_FromBuffer(space, view):
+    """Create a memoryview object wrapping the given buffer-info structure 
view.
+    The memoryview object then owns the buffer, which means you shouldn't
+    try to release it yourself: it will be released on deallocation of the
+    memoryview object."""
+    w_obj = from_ref(space, view.c_obj)
+    if isinstance(w_obj, W_MemoryView):
+        return w_obj
+    return space.call_method(space.builtin, "memoryview", w_obj)
+
 @cpython_api([PyObject], PyObject)
 def PyMemoryView_GET_BASE(space, w_obj):
     # return the obj field of the Py_buffer created by PyMemoryView_GET_BUFFER
     # XXX needed for numpy on py3k
-    raise NotImplementedError('PyMemoryView_GET_BUFFER')
+    raise NotImplementedError('PyMemoryView_GET_BASE')
 
 @cpython_api([PyObject], lltype.Ptr(Py_buffer), error=CANNOT_FAIL)
 def PyMemoryView_GET_BUFFER(space, w_obj):
diff --git a/pypy/module/cpyext/methodobject.py 
b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -311,7 +311,7 @@
 def PyClassMethod_New(space, w_func):
     return space.wrap(ClassMethod(w_func))
 
-@cpython_api([PyObject, lltype.Ptr(PyMethodDef)], PyObject)
+@cpython_api([PyTypeObjectPtr, lltype.Ptr(PyMethodDef)], PyObject)
 def PyDescr_NewMethod(space, w_type, method):
     return space.wrap(W_PyCMethodObject(space, method, w_type))
 
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -3,7 +3,7 @@
     cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP,
     PyVarObject, Py_buffer, size_t,
     Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT,
-    Py_GE, CONST_STRING, FILEP, fwrite)
+    Py_GE, CONST_STRING, CONST_STRINGP, FILEP, fwrite)
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef,
     get_typedescr, _Py_NewReference)
@@ -429,7 +429,7 @@
     is active then NULL is returned but PyErr_Occurred() will return false."""
     return space.call_function(space.builtin.get('dir'), w_o)
 
-@cpython_api([PyObject, rffi.CCHARPP, Py_ssize_tP], rffi.INT_real, error=-1)
+@cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1)
 def PyObject_AsCharBuffer(space, obj, bufferp, sizep):
     """Returns a pointer to a read-only memory location usable as
     character-based input.  The obj argument must support the single-segment
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to