Author: Philip Jenvey <pjen...@underboss.org>
Branch: py3k
Changeset: r83725:df440f20d566
Date: 2016-04-17 17:51 -0700
http://bitbucket.org/pypy/pypy/changeset/df440f20d566/

Log:    merge default

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -111,23 +111,24 @@
   Simon Burton
   Martin Matusiak
   Konstantin Lopuhin
+  Stefano Rivera
   Wenzhu Man
   John Witulski
   Laurence Tratt
   Ivan Sichmann Freitas
   Greg Price
   Dario Bertini
-  Stefano Rivera
   Mark Pearse
   Simon Cross
+  Edd Barrett
   Andreas St&#252;hrk
-  Edd Barrett
   Jean-Philippe St. Pierre
   Guido van Rossum
   Pavel Vinogradov
+  Spenser Bauman
   Jeremy Thurgood
   Pawe&#322; Piotr Przeradowski
-  Spenser Bauman
+  Tobias Pape
   Paul deGrandis
   Ilya Osadchiy
   marky1991
@@ -139,7 +140,7 @@
   Georg Brandl
   Bert Freudenberg
   Stian Andreassen
-  Tobias Pape
+  Mark Young
   Wanja Saatkamp
   Gerald Klix
   Mike Blume
@@ -170,9 +171,9 @@
   Yichao Yu
   Rocco Moretti
   Gintautas Miliauskas
+  Devin Jeanpierre
   Michael Twomey
   Lucian Branescu Mihaila
-  Devin Jeanpierre
   Gabriel Lavoie
   Olivier Dormond
   Jared Grubb
@@ -183,6 +184,7 @@
   Victor Stinner
   Andrews Medina
   anatoly techtonik
+  Sergey Matyunin
   Stuart Williams
   Jasper Schulz
   Christian Hudon
@@ -217,7 +219,6 @@
   Arjun Naik
   Valentina Mukhamedzhanova
   Stefano Parmesan
-  Mark Young
   Alexis Daboville
   Jens-Uwe Mager
   Carl Meyer
@@ -225,7 +226,9 @@
   Pieter Zieschang
   Gabriel
   Lukas Vacek
+  Kunal Grover
   Andrew Dalke
+  Florin Papa
   Sylvain Thenault
   Jakub Stasiak
   Nathan Taylor
@@ -240,7 +243,6 @@
   Kristjan Valur Jonsson
   David Lievens
   Neil Blakey-Milner
-  Sergey Matyunin
   Lutz Paelike
   Lucio Torre
   Lars Wassermann
@@ -252,9 +254,11 @@
   Artur Lisiecki
   Sergey Kishchenko
   Ignas Mikalajunas
+  Alecsandru Patrascu
   Christoph Gerum
   Martin Blais
   Lene Wagner
+  Catalin Gabriel Manciu
   Tomo Cocoa
   Kim Jin Su
   Toni Mattis
@@ -291,6 +295,7 @@
   Akira Li
   Gustavo Niemeyer
   Stephan Busemann
+  florinpapa
   Rafa&#322; Ga&#322;czy&#324;ski
   Matt Bogosian
   Christian Muirhead
@@ -305,6 +310,7 @@
   Boglarka Vezer
   Chris Pressey
   Buck Golemon
+  Diana Popa
   Konrad Delong
   Dinu Gherman
   Chris Lambacher
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.5.2
+Version: 1.6.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.5.2"
-__version_info__ = (1, 5, 2)
+__version__ = "1.6.0"
+__version_info__ = (1, 6, 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.5.2"
+                               "\ncompiled with cffi version: 1.6.0"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -299,6 +299,23 @@
         """
         return self._backend.string(cdata, maxlen)
 
+    def unpack(self, cdata, length):
+        """Unpack an array of C data of the given length, 
+        returning a Python string/unicode/list.
+
+        If 'cdata' is a pointer to 'char', returns a byte string.
+        It does not stop at the first null.  This is equivalent to:
+        ffi.buffer(cdata, length)[:]
+
+        If 'cdata' is a pointer to 'wchar_t', returns a unicode string.
+        'length' is measured in wchar_t's; it is not the size in bytes.
+
+        If 'cdata' is a pointer to anything else, returns a list of
+        'length' items.  This is a faster equivalent to:
+        [cdata[i] for i in range(length)]
+        """
+        return self._backend.unpack(cdata, length)
+
     def buffer(self, cdata, size=-1):
         """Return a read-write buffer object that references the raw C data
         pointed to by the given 'cdata'.  The 'cdata' must be a pointer or
@@ -721,6 +738,26 @@
         raise ValueError("ffi.def_extern() is only available on API-mode FFI "
                          "objects")
 
+    def list_types(self):
+        """Returns the user type names known to this FFI instance.
+        This returns a tuple containing three lists of names:
+        (typedef_names, names_of_structs, names_of_unions)
+        """
+        typedefs = []
+        structs = []
+        unions = []
+        for key in self._parser._declarations:
+            if key.startswith('typedef '):
+                typedefs.append(key[8:])
+            elif key.startswith('struct '):
+                structs.append(key[7:])
+            elif key.startswith('union '):
+                unions.append(key[6:])
+        typedefs.sort()
+        structs.sort()
+        unions.sort()
+        return (typedefs, structs, unions)
+
 
 def _load_backend_lib(backend, name, flags):
     if name is None:
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -1231,7 +1231,7 @@
             if c == '\n': return '\\n'
             return '\\%03o' % ord(c)
         lines = []
-        for line in s.splitlines(True):
+        for line in s.splitlines(True) or ['']:
             lines.append('"%s"' % ''.join([_char_repr(c) for c in line]))
         return ' \\\n'.join(lines)
 
@@ -1319,7 +1319,9 @@
                 s = s.encode('ascii')
             super(NativeIO, self).write(s)
 
-def _make_c_or_py_source(ffi, module_name, preamble, target_file):
+def _make_c_or_py_source(ffi, module_name, preamble, target_file, verbose):
+    if verbose:
+        print("generating %s" % (target_file,))
     recompiler = Recompiler(ffi, module_name,
                             target_is_python=(preamble is None))
     recompiler.collect_type_table()
@@ -1331,6 +1333,8 @@
         with open(target_file, 'r') as f1:
             if f1.read(len(output) + 1) != output:
                 raise IOError
+        if verbose:
+            print("(already up-to-date)")
         return False     # already up-to-date
     except IOError:
         tmp_file = '%s.~%d' % (target_file, os.getpid())
@@ -1343,12 +1347,14 @@
             os.rename(tmp_file, target_file)
         return True
 
-def make_c_source(ffi, module_name, preamble, target_c_file):
+def make_c_source(ffi, module_name, preamble, target_c_file, verbose=False):
     assert preamble is not None
-    return _make_c_or_py_source(ffi, module_name, preamble, target_c_file)
+    return _make_c_or_py_source(ffi, module_name, preamble, target_c_file,
+                                verbose)
 
-def make_py_source(ffi, module_name, target_py_file):
-    return _make_c_or_py_source(ffi, module_name, None, target_py_file)
+def make_py_source(ffi, module_name, target_py_file, verbose=False):
+    return _make_c_or_py_source(ffi, module_name, None, target_py_file,
+                                verbose)
 
 def _modname_to_file(outputdir, modname, extension):
     parts = modname.split('.')
@@ -1438,7 +1444,8 @@
                 target = '*'
         #
         ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds)
-        updated = make_c_source(ffi, module_name, preamble, c_file)
+        updated = make_c_source(ffi, module_name, preamble, c_file,
+                                verbose=compiler_verbose)
         if call_c_compiler:
             patchlist = []
             cwd = os.getcwd()
@@ -1458,7 +1465,8 @@
     else:
         if c_file is None:
             c_file, _ = _modname_to_file(tmpdir, module_name, '.py')
-        updated = make_py_source(ffi, module_name, c_file)
+        updated = make_py_source(ffi, module_name, c_file,
+                                 verbose=compiler_verbose)
         if call_c_compiler:
             return c_file
         else:
@@ -1484,4 +1492,7 @@
     def typeof_disabled(*args, **kwds):
         raise NotImplementedError
     ffi._typeof = typeof_disabled
+    for name in dir(ffi):
+        if not name.startswith('_') and not hasattr(module.ffi, name):
+            setattr(ffi, name, NotImplemented)
     return module.lib
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -81,13 +81,13 @@
   Simon Burton
   Martin Matusiak
   Konstantin Lopuhin
+  Stefano Rivera
   Wenzhu Man
   John Witulski
   Laurence Tratt
   Ivan Sichmann Freitas
   Greg Price
   Dario Bertini
-  Stefano Rivera
   Mark Pearse
   Simon Cross
   Andreas St&#252;hrk
@@ -95,9 +95,10 @@
   Jean-Philippe St. Pierre
   Guido van Rossum
   Pavel Vinogradov
+  Spenser Bauman
   Jeremy Thurgood
   Pawe&#322; Piotr Przeradowski
-  Spenser Bauman
+  Tobias Pape
   Paul deGrandis
   Ilya Osadchiy
   marky1991
@@ -109,7 +110,7 @@
   Georg Brandl
   Bert Freudenberg
   Stian Andreassen
-  Tobias Pape
+  Mark Young
   Wanja Saatkamp
   Gerald Klix
   Mike Blume
@@ -140,9 +141,9 @@
   Yichao Yu
   Rocco Moretti
   Gintautas Miliauskas
+  Devin Jeanpierre
   Michael Twomey
   Lucian Branescu Mihaila
-  Devin Jeanpierre
   Gabriel Lavoie
   Olivier Dormond
   Jared Grubb
@@ -153,6 +154,7 @@
   Victor Stinner
   Andrews Medina
   anatoly techtonik
+  Sergey Matyunin
   Stuart Williams
   Jasper Schulz
   Christian Hudon
@@ -187,7 +189,6 @@
   Arjun Naik
   Valentina Mukhamedzhanova
   Stefano Parmesan
-  Mark Young
   Alexis Daboville
   Jens-Uwe Mager
   Carl Meyer
@@ -195,7 +196,9 @@
   Pieter Zieschang
   Gabriel
   Lukas Vacek
+  Kunal Grover
   Andrew Dalke
+  Florin Papa
   Sylvain Thenault
   Jakub Stasiak
   Nathan Taylor
@@ -210,7 +213,6 @@
   Kristjan Valur Jonsson
   David Lievens
   Neil Blakey-Milner
-  Sergey Matyunin
   Lutz Paelike
   Lucio Torre
   Lars Wassermann
@@ -222,9 +224,11 @@
   Artur Lisiecki
   Sergey Kishchenko
   Ignas Mikalajunas
+  Alecsandru Patrascu
   Christoph Gerum
   Martin Blais
   Lene Wagner
+  Catalin Gabriel Manciu
   Tomo Cocoa
   Kim Jin Su
   Toni Mattis
@@ -261,6 +265,7 @@
   Akira Li
   Gustavo Niemeyer
   Stephan Busemann
+  florinpapa
   Rafa&#322; Ga&#322;czy&#324;ski
   Matt Bogosian
   Christian Muirhead
@@ -275,6 +280,7 @@
   Boglarka Vezer
   Chris Pressey
   Buck Golemon
+  Diana Popa
   Konrad Delong
   Dinu Gherman
   Chris Lambacher
diff --git a/pypy/doc/release-5.1.0.rst b/pypy/doc/release-5.1.0.rst
--- a/pypy/doc/release-5.1.0.rst
+++ b/pypy/doc/release-5.1.0.rst
@@ -78,8 +78,6 @@
   * Try harder to not emit NEON instructions on ARM processors without NEON
     support
 
-  * Support glibc < 2.16 on ARM
-
   * Improve the rpython posix module system interaction function calls
 
   * Detect a missing class function implementation instead of calling a random
@@ -92,6 +90,8 @@
 
   * Fix JIT issue with unpack() on a Trace which contains half-written 
operations
 
+  * Fix sandbox startup (a regression in 5.0)
+
   * Issues reported with our previous release were resolved_ after reports 
from users on
     our issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at
     #pypy
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
@@ -5,3 +5,12 @@
 .. this is a revision shortly after release-5.1
 .. startrev: 2180e1eaf6f6
 
+.. branch: rposix-for-3
+
+Reuse rposix definition of TIMESPEC in rposix_stat, add wrapper for fstatat().
+This updates the underlying rpython functions with the ones needed for the 
+py3k branch
+ 
+.. branch: numpy_broadcast
+
+Add broadcast to micronumpy
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1051,6 +1051,9 @@
     def newlist_int(self, list_i):
         return self.newlist([self.wrap(i) for i in list_i])
 
+    def newlist_float(self, list_f):
+        return self.newlist([self.wrap(f) for f in list_f])
+
     def newlist_hint(self, sizehint):
         from pypy.objspace.std.listobject import make_empty_list_with_size
         return make_empty_list_with_size(self, sizehint)
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.5.2"
+VERSION = "1.6.0"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
@@ -48,7 +48,7 @@
         'from_buffer': 'func.from_buffer',
 
         'string': 'func.string',
-        'rawstring': 'func.rawstring',
+        'unpack': 'func.unpack',
         'buffer': 'cbuffer.buffer',
         'memmove': 'func.memmove',
 
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
@@ -323,14 +323,18 @@
         from pypy.module._cffi_backend import ctypearray
         ctype = self.ctype
         if isinstance(ctype, ctypearray.W_CTypeArray):
-            return ctype.ctitem.unpack_list_of_int_items(self)
+            length = self.get_array_length()
+            with self as ptr:
+                return ctype.ctitem.unpack_list_of_int_items(ptr, length)
         return None
 
     def unpackiterable_float(self, space):
         from pypy.module._cffi_backend import ctypearray
         ctype = self.ctype
         if isinstance(ctype, ctypearray.W_CTypeArray):
-            return ctype.ctitem.unpack_list_of_float_items(self)
+            length = self.get_array_length()
+            with self as ptr:
+                return ctype.ctitem.unpack_list_of_float_items(ptr, length)
         return None
 
     @specialize.argtype(1)
@@ -367,6 +371,25 @@
         with self as ptr:
             return W_CDataGCP(self.space, ptr, self.ctype, self, w_destructor)
 
+    def unpack(self, length):
+        from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
+        space = self.space
+        if not self.ctype.is_nonfunc_pointer_or_array:
+            raise oefmt(space.w_TypeError,
+                        "expected a pointer or array, got '%s'",
+                        self.ctype.name)
+        if length < 0:
+            raise oefmt(space.w_ValueError, "'length' cannot be negative")
+        ctype = self.ctype
+        assert isinstance(ctype, W_CTypePtrOrArray)
+        with self as ptr:
+            if not ptr:
+                raise oefmt(space.w_RuntimeError,
+                            "cannot use unpack() on %s",
+                            space.str_w(self.repr()))
+            w_result = ctype.ctitem.unpack_ptr(ctype, ptr, length)
+        return w_result
+
 
 class W_CDataMem(W_CData):
     """This is used only by the results of cffi.cast('int', x)
diff --git a/pypy/module/_cffi_backend/ctypearray.py 
b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -109,21 +109,6 @@
     def typeoffsetof_index(self, index):
         return self.ctptr.typeoffsetof_index(index)
 
-    def rawstring(self, w_cdata):
-        if isinstance(self.ctitem, ctypeprim.W_CTypePrimitive):
-            space = self.space
-            length = w_cdata.get_array_length()
-            if self.ctitem.size == rffi.sizeof(lltype.Char):
-                with w_cdata as ptr:
-                    s = rffi.charpsize2str(ptr, length)
-                return space.wrapbytes(s)
-            elif self.is_unichar_ptr_or_array():
-                with w_cdata as ptr:
-                    cdata = rffi.cast(rffi.CWCHARP, ptr)
-                    u = rffi.wcharpsize2unicode(cdata, length)
-                return space.wrap(u)
-        return W_CTypePtrOrArray.rawstring(self, w_cdata)
-
 
 class W_CDataIter(W_Root):
     _immutable_fields_ = ['ctitem', 'cdata', '_stop']    # but not '_next'
diff --git a/pypy/module/_cffi_backend/ctypeobj.py 
b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -49,10 +49,10 @@
     def is_unichar_ptr_or_array(self):
         return False
 
-    def unpack_list_of_int_items(self, cdata):
+    def unpack_list_of_int_items(self, ptr, length):
         return None
 
-    def unpack_list_of_float_items(self, cdata):
+    def unpack_list_of_float_items(self, ptr, length):
         return None
 
     def pack_list_of_items(self, cdata, w_ob):
@@ -127,11 +127,20 @@
         raise oefmt(space.w_TypeError,
                     "string(): unexpected cdata '%s' argument", self.name)
 
-    def rawstring(self, cdataobj):
+    def unpack_ptr(self, w_ctypeptr, ptr, length):
+        # generic implementation, when the type of items is not known to
+        # be one for which a fast-case exists
         space = self.space
-        raise oefmt(space.w_TypeError,
-                    "expected a 'char[]' or 'uint8_t[]' or 'int8_t[]' "
-                    "or 'wchar_t[]', got '%s'", self.name)
+        itemsize = self.size
+        if itemsize < 0:
+            raise oefmt(space.w_ValueError,
+                        "'%s' points to items of unknown size",
+                        w_ctypeptr.name)
+        result_w = [None] * length
+        for i in range(length):
+            result_w[i] = self.convert_to_object(ptr)
+            ptr = rffi.ptradd(ptr, itemsize)
+        return space.newlist(result_w)
 
     def add(self, cdata, i):
         space = self.space
diff --git a/pypy/module/_cffi_backend/ctypeprim.py 
b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -87,6 +87,13 @@
             return self.space.wrapbytes(s)
         return W_CType.string(self, cdataobj, maxlen)
 
+    def unpack_ptr(self, w_ctypeptr, ptr, length):
+        result = self.unpack_list_of_int_items(ptr, length)
+        if result is not None:
+            return self.space.newlist_int(result)
+        return W_CType.unpack_ptr(self, w_ctypeptr, ptr, length)
+
+
 class W_CTypePrimitiveCharOrUniChar(W_CTypePrimitive):
     _attrs_ = []
     is_primitive_integer = True
@@ -125,6 +132,10 @@
         value = self._convert_to_char(w_ob)
         cdata[0] = value
 
+    def unpack_ptr(self, w_ctypeptr, ptr, length):
+        s = rffi.charpsize2str(ptr, length)
+        return self.space.wrapbytes(s)
+
 
 # XXX explicitly use an integer type instead of lltype.UniChar here,
 # because for now the latter is defined as unsigned by RPython (even
@@ -171,6 +182,10 @@
         value = self._convert_to_unichar(w_ob)
         rffi.cast(rffi.CWCHARP, cdata)[0] = value
 
+    def unpack_ptr(self, w_ctypeptr, ptr, length):
+        u = rffi.wcharpsize2unicode(rffi.cast(rffi.CWCHARP, ptr), length)
+        return self.space.wrap(u)
+
 
 class W_CTypePrimitiveSigned(W_CTypePrimitive):
     _attrs_            = ['value_fits_long', 'value_smaller_than_long']
@@ -221,19 +236,16 @@
     def write_raw_integer_data(self, w_cdata, value):
         w_cdata.write_raw_signed_data(value)
 
-    def unpack_list_of_int_items(self, w_cdata):
+    def unpack_list_of_int_items(self, ptr, length):
         if self.size == rffi.sizeof(rffi.LONG):
             from rpython.rlib.rrawarray import populate_list_from_raw_array
             res = []
-            length = w_cdata.get_array_length()
-            with w_cdata as ptr:
-                buf = rffi.cast(rffi.LONGP, ptr)
-                populate_list_from_raw_array(res, buf, length)
+            buf = rffi.cast(rffi.LONGP, ptr)
+            populate_list_from_raw_array(res, buf, length)
             return res
         elif self.value_smaller_than_long:
-            res = [0] * w_cdata.get_array_length()
-            with w_cdata as ptr:
-                misc.unpack_list_from_raw_array(res, ptr, self.size)
+            res = [0] * length
+            misc.unpack_list_from_raw_array(res, ptr, self.size)
             return res
         return None
 
@@ -313,11 +325,10 @@
     def write_raw_integer_data(self, w_cdata, value):
         w_cdata.write_raw_unsigned_data(value)
 
-    def unpack_list_of_int_items(self, w_cdata):
+    def unpack_list_of_int_items(self, ptr, length):
         if self.value_fits_long:
-            res = [0] * w_cdata.get_array_length()
-            with w_cdata as ptr:
-                misc.unpack_unsigned_list_from_raw_array(res, ptr, self.size)
+            res = [0] * length
+            misc.unpack_unsigned_list_from_raw_array(res, ptr, self.size)
             return res
         return None
 
@@ -391,19 +402,16 @@
         value = space.float_w(space.float(w_ob))
         misc.write_raw_float_data(cdata, value, self.size)
 
-    def unpack_list_of_float_items(self, w_cdata):
+    def unpack_list_of_float_items(self, ptr, length):
         if self.size == rffi.sizeof(rffi.DOUBLE):
             from rpython.rlib.rrawarray import populate_list_from_raw_array
             res = []
-            length = w_cdata.get_array_length()
-            with w_cdata as ptr:
-                buf = rffi.cast(rffi.DOUBLEP, ptr)
-                populate_list_from_raw_array(res, buf, length)
+            buf = rffi.cast(rffi.DOUBLEP, ptr)
+            populate_list_from_raw_array(res, buf, length)
             return res
         elif self.size == rffi.sizeof(rffi.FLOAT):
-            res = [0.0] * w_cdata.get_array_length()
-            with w_cdata as ptr:
-                misc.unpack_cfloat_list_from_raw_array(res, ptr)
+            res = [0.0] * length
+            misc.unpack_cfloat_list_from_raw_array(res, ptr)
             return res
         return None
 
@@ -421,6 +429,12 @@
                 return True
         return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
 
+    def unpack_ptr(self, w_ctypeptr, ptr, length):
+        result = self.unpack_list_of_float_items(ptr, length)
+        if result is not None:
+            return self.space.newlist_float(result)
+        return W_CType.unpack_ptr(self, w_ctypeptr, ptr, length)
+
 
 class W_CTypePrimitiveLongDouble(W_CTypePrimitiveFloat):
     _attrs_ = []
diff --git a/pypy/module/_cffi_backend/ffi_obj.py 
b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -542,19 +542,23 @@
         return w_cdata.ctype.string(w_cdata, maxlen)
 
 
-    @unwrap_spec(w_cdata=W_CData)
-    def descr_rawstring(self, w_cdata):
-        """\
-Convert a cdata that is an array of 'char' or 'wchar_t' to
-a byte or unicode string.  Unlike ffi.string(), it does not stop
-at the first null.
+    @unwrap_spec(w_cdata=W_CData, length=int)
+    def descr_unpack(self, w_cdata, length):
+        """Unpack an array of C data of the given length,
+returning a Python string/unicode/list.
 
-Note that if you have a pointer and an explicit length, you
-can use 'p[0:length]' to make an array view.  This is similar to
-the construct 'list(p[0:length])', which returns a list of chars/
-unichars/ints/floats."""
+If 'cdata' is a pointer to 'char', returns a byte string.
+It does not stop at the first null.  This is equivalent to:
+ffi.buffer(cdata, length)[:]
+
+If 'cdata' is a pointer to 'wchar_t', returns a unicode string.
+'length' is measured in wchar_t's; it is not the size in bytes.
+
+If 'cdata' is a pointer to anything else, returns a list of
+'length' items.  This is a faster equivalent to:
+[cdata[i] for i in range(length)]"""
         #
-        return w_cdata.ctype.rawstring(w_cdata)
+        return w_cdata.unpack(length)
 
 
     def descr_sizeof(self, w_arg):
@@ -626,6 +630,38 @@
         return w_result
 
 
+    def descr_list_types(self):
+        """\
+Returns the user type names known to this FFI instance.
+This returns a tuple containing three lists of names:
+(typedef_names, names_of_structs, names_of_unions)"""
+        #
+        space = self.space
+        ctx = self.ctxobj.ctx
+
+        lst1_w = []
+        for i in range(rffi.getintfield(ctx, 'c_num_typenames')):
+            s = rffi.charp2str(ctx.c_typenames[i].c_name)
+            lst1_w.append(space.wrap(s))
+
+        lst2_w = []
+        lst3_w = []
+        for i in range(rffi.getintfield(ctx, 'c_num_struct_unions')):
+            su = ctx.c_struct_unions[i]
+            if su.c_name[0] == '$':
+                continue
+            s = rffi.charp2str(su.c_name)
+            if rffi.getintfield(su, 'c_flags') & cffi_opcode.F_UNION:
+                lst_w = lst3_w
+            else:
+                lst_w = lst2_w
+            lst_w.append(space.wrap(s))
+
+        return space.newtuple([space.newlist(lst1_w),
+                               space.newlist(lst2_w),
+                               space.newlist(lst3_w)])
+
+
     def descr_init_once(self, w_func, w_tag):
         """\
 init_once(function, tag): run function() once.  More precisely,
@@ -746,13 +782,14 @@
         getctype    = interp2app(W_FFIObject.descr_getctype),
         init_once   = interp2app(W_FFIObject.descr_init_once),
         integer_const = interp2app(W_FFIObject.descr_integer_const),
+        list_types  = interp2app(W_FFIObject.descr_list_types),
         memmove     = interp2app(W_FFIObject.descr_memmove),
         new         = interp2app(W_FFIObject.descr_new),
         new_allocator = interp2app(W_FFIObject.descr_new_allocator),
         new_handle  = interp2app(W_FFIObject.descr_new_handle),
         offsetof    = interp2app(W_FFIObject.descr_offsetof),
-        rawstring   = interp2app(W_FFIObject.descr_rawstring),
         sizeof      = interp2app(W_FFIObject.descr_sizeof),
         string      = interp2app(W_FFIObject.descr_string),
         typeof      = interp2app(W_FFIObject.descr_typeof),
+        unpack      = interp2app(W_FFIObject.descr_unpack),
         **_extras)
diff --git a/pypy/module/_cffi_backend/func.py 
b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -78,9 +78,9 @@
 
 # ____________________________________________________________
 
-@unwrap_spec(w_cdata=cdataobj.W_CData)
-def rawstring(space, w_cdata):
-    return w_cdata.ctype.rawstring(w_cdata)
+@unwrap_spec(w_cdata=cdataobj.W_CData, length=int)
+def unpack(space, w_cdata, length):
+    return w_cdata.unpack(length)
 
 # ____________________________________________________________
 
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.5.2", ("This test_c.py file is for testing a version"
+assert __version__ == "1.6.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,):
@@ -3515,21 +3515,71 @@
     _get_common_types(d)
     assert d['bool'] == '_Bool'
 
-def test_rawstring():
+def test_unpack():
     BChar = new_primitive_type("char")
     BArray = new_array_type(new_pointer_type(BChar), 10)   # char[10]
-    p = newp(BArray, "abc\x00def")
-    assert rawstring(p) == "abc\x00def\x00\x00\x00"
-    assert rawstring(p[1:6]) == "bc\x00de"
+    p = newp(BArray, b"abc\x00def")
+    p0 = p
+    assert unpack(p, 10) == b"abc\x00def\x00\x00\x00"
+    assert unpack(p+1, 5) == b"bc\x00de"
     BWChar = new_primitive_type("wchar_t")
     BArray = new_array_type(new_pointer_type(BWChar), 10)   # wchar_t[10]
     p = newp(BArray, u"abc\x00def")
-    assert rawstring(p) == u"abc\x00def\x00\x00\x00"
-    assert rawstring(p[1:6]) == u"bc\x00de"
-    BChar = new_primitive_type("uint8_t")
-    BArray = new_array_type(new_pointer_type(BChar), 10)   # uint8_t[10]
-    p = newp(BArray, [65 + i for i in range(10)])
-    assert rawstring(p) == "ABCDEFGHIJ"
+    assert unpack(p, 10) == u"abc\x00def\x00\x00\x00"
+
+    for typename, samples in [
+            ("uint8_t",  [0, 2**8-1]),
+            ("uint16_t", [0, 2**16-1]),
+            ("uint32_t", [0, 2**32-1]),
+            ("uint64_t", [0, 2**64-1]),
+            ("int8_t",  [-2**7, 2**7-1]),
+            ("int16_t", [-2**15, 2**15-1]),
+            ("int32_t", [-2**31, 2**31-1]),
+            ("int64_t", [-2**63, 2**63-1]),
+            ("_Bool", [0, 1]),
+            ("float", [0.0, 10.5]),
+            ("double", [12.34, 56.78]),
+            ]:
+        BItem = new_primitive_type(typename)
+        BArray = new_array_type(new_pointer_type(BItem), 10)
+        p = newp(BArray, samples)
+        result = unpack(p, len(samples))
+        assert result == samples
+        for i in range(len(samples)):
+            assert result[i] == p[i] and type(result[i]) is type(p[i])
     #
-    py.test.raises(TypeError, rawstring, "foobar")
-    py.test.raises(TypeError, rawstring, p + 1)
+    BInt = new_primitive_type("int")
+    py.test.raises(TypeError, unpack, p)
+    py.test.raises(TypeError, unpack, b"foobar", 6)
+    py.test.raises(TypeError, unpack, cast(BInt, 42), 1)
+    #
+    BPtr = new_pointer_type(BInt)
+    random_ptr = cast(BPtr, -424344)
+    other_ptr = cast(BPtr, 54321)
+    BArray = new_array_type(new_pointer_type(BPtr), None)
+    lst = unpack(newp(BArray, [random_ptr, other_ptr]), 2)
+    assert lst == [random_ptr, other_ptr]
+    #
+    BFunc = new_function_type((BInt, BInt), BInt, False)
+    BFuncPtr = new_pointer_type(BFunc)
+    lst = unpack(newp(new_array_type(BFuncPtr, None), 2), 2)
+    assert len(lst) == 2
+    assert not lst[0] and not lst[1]
+    assert typeof(lst[0]) is BFunc
+    #
+    BStruct = new_struct_type("foo")
+    BStructPtr = new_pointer_type(BStruct)
+    e = py.test.raises(ValueError, unpack, cast(BStructPtr, 42), 5)
+    assert str(e.value) == "'foo *' points to items of unknown size"
+    complete_struct_or_union(BStruct, [('a1', BInt, -1),
+                                       ('a2', BInt, -1)])
+    array_of_structs = newp(new_array_type(BStructPtr, None), [[4,5], [6,7]])
+    lst = unpack(array_of_structs, 2)
+    assert typeof(lst[0]) is BStruct
+    assert lst[0].a1 == 4 and lst[1].a2 == 7
+    #
+    py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 0)
+    py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 10)
+    #
+    py.test.raises(ValueError, unpack, p0, -1)
+    py.test.raises(ValueError, unpack, p, -1)
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py 
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -477,15 +477,10 @@
             raises(ValueError, ffi.init_once, do_init, "tag")
             assert seen == [1] * (i + 1)
 
-    def test_rawstring(self):
+    def test_unpack(self):
         import _cffi_backend as _cffi1_backend
         ffi = _cffi1_backend.FFI()
-        p = ffi.new("char[]", "abc\x00def")
-        assert ffi.rawstring(p) == "abc\x00def\x00"
-        assert ffi.rawstring(p[1:6]) == "bc\x00de"
-        p = ffi.new("wchar_t[]", u"abc\x00def")
-        assert ffi.rawstring(p) == u"abc\x00def\x00"
-        assert ffi.rawstring(p[1:6]) == u"bc\x00de"
-        #
-        raises(TypeError, ffi.rawstring, "foobar")
-        raises(TypeError, ffi.rawstring, p + 1)
+        p = ffi.new("char[]", b"abc\x00def")
+        assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
+        p = ffi.new("int[]", [-123456789])
+        assert ffi.unpack(p, 1) == [-123456789]
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
@@ -1626,3 +1626,150 @@
         # a case where 'onerror' is not callable
         raises(TypeError, ffi.def_extern(name='bar', onerror=42),
                        lambda x: x)
+
+    def test_extern_python_stdcall(self):
+        ffi, lib = self.prepare("""
+            extern "Python" int __stdcall foo(int);
+            extern "Python" int WINAPI bar(int);
+            int (__stdcall * mycb1)(int);
+            int indirect_call(int);
+        """, 'test_extern_python_stdcall', """
+            #ifndef _MSC_VER
+            #  define __stdcall
+            #endif
+            static int (__stdcall * mycb1)(int);
+            static int indirect_call(int x) {
+                return mycb1(x);
+            }
+        """)
+        #
+        @ffi.def_extern()
+        def foo(x):
+            return x + 42
+        @ffi.def_extern()
+        def bar(x):
+            return x + 43
+        assert lib.foo(100) == 142
+        assert lib.bar(100) == 143
+        lib.mycb1 = lib.foo
+        assert lib.mycb1(200) == 242
+        assert lib.indirect_call(300) == 342
+
+    def test_introspect_function(self):
+        ffi, lib = self.prepare("""
+            float f1(double);
+        """, 'test_introspect_function', """
+            float f1(double x) { return x; }
+        """)
+        assert dir(lib) == ['f1']
+        FUNC = ffi.typeof(lib.f1)
+        assert FUNC.kind == 'function'
+        assert FUNC.args[0].cname == 'double'
+        assert FUNC.result.cname == 'float'
+        assert ffi.typeof(ffi.addressof(lib, 'f1')) is FUNC
+
+    def test_introspect_global_var(self):
+        ffi, lib = self.prepare("""
+            float g1;
+        """, 'test_introspect_global_var', """
+            float g1;
+        """)
+        assert dir(lib) == ['g1']
+        FLOATPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
+        assert FLOATPTR.kind == 'pointer'
+        assert FLOATPTR.item.cname == 'float'
+
+    def test_introspect_global_var_array(self):
+        ffi, lib = self.prepare("""
+            float g1[100];
+        """, 'test_introspect_global_var_array', """
+            float g1[100];
+        """)
+        assert dir(lib) == ['g1']
+        FLOATARRAYPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
+        assert FLOATARRAYPTR.kind == 'pointer'
+        assert FLOATARRAYPTR.item.kind == 'array'
+        assert FLOATARRAYPTR.item.length == 100
+        assert ffi.typeof(lib.g1) is FLOATARRAYPTR.item
+
+    def test_introspect_integer_const(self):
+        ffi, lib = self.prepare("#define FOO 42",
+                                'test_introspect_integer_const', """
+            #define FOO 42
+        """)
+        assert dir(lib) == ['FOO']
+        assert lib.FOO == ffi.integer_const('FOO') == 42
+
+    def test_introspect_typedef(self):
+        ffi, lib = self.prepare("typedef int foo_t;",
+                                'test_introspect_typedef', """
+            typedef int foo_t;
+        """)
+        assert ffi.list_types() == (['foo_t'], [], [])
+        assert ffi.typeof('foo_t').kind == 'primitive'
+        assert ffi.typeof('foo_t').cname == 'int'
+
+    def test_introspect_typedef_multiple(self):
+        ffi, lib = self.prepare("""
+            typedef signed char a_t, c_t, g_t, b_t;
+        """, 'test_introspect_typedef_multiple', """
+            typedef signed char a_t, c_t, g_t, b_t;
+        """)
+        assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'g_t'], [], [])
+
+    def test_introspect_struct(self):
+        ffi, lib = self.prepare("""
+            struct foo_s { int a; };
+        """, 'test_introspect_struct', """
+            struct foo_s { int a; };
+        """)
+        assert ffi.list_types() == ([], ['foo_s'], [])
+        assert ffi.typeof('struct foo_s').kind == 'struct'
+        assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
+
+    def test_introspect_union(self):
+        ffi, lib = self.prepare("""
+            union foo_s { int a; };
+        """, 'test_introspect_union', """
+            union foo_s { int a; };
+        """)
+        assert ffi.list_types() == ([], [], ['foo_s'])
+        assert ffi.typeof('union foo_s').kind == 'union'
+        assert ffi.typeof('union foo_s').cname == 'union foo_s'
+
+    def test_introspect_struct_and_typedef(self):
+        ffi, lib = self.prepare("""
+            typedef struct { int a; } foo_t;
+        """, 'test_introspect_struct_and_typedef', """
+            typedef struct { int a; } foo_t;
+        """)
+        assert ffi.list_types() == (['foo_t'], [], [])
+        assert ffi.typeof('foo_t').kind == 'struct'
+        assert ffi.typeof('foo_t').cname == 'foo_t'
+
+    def test_introspect_included_type(self):
+        SOURCE = """
+            typedef signed char schar_t;
+            struct sint_t { int x; };
+        """
+        ffi1, lib1 = self.prepare(SOURCE,
+            "test_introspect_included_type_parent", SOURCE)
+        ffi2, lib2 = self.prepare("",
+            "test_introspect_included_type", SOURCE,
+            includes=[ffi1])
+        assert ffi1.list_types() == ffi2.list_types() == (
+                ['schar_t'], ['sint_t'], [])
+
+    def test_introspect_order(self):
+        ffi, lib = self.prepare("""
+            union aaa { int a; }; typedef struct ccc { int a; } b;
+            union g   { int a; }; typedef struct cc  { int a; } bbb;
+            union aa  { int a; }; typedef struct a   { int a; } bb;
+        """, "test_introspect_order", """
+            union aaa { int a; }; typedef struct ccc { int a; } b;
+            union g   { int a; }; typedef struct cc  { int a; } bbb;
+            union aa  { int a; }; typedef struct a   { int a; } bb;
+        """)
+        assert ffi.list_types() == (['b', 'bb', 'bbb'],
+                                        ['a', 'cc', 'ccc'],
+                                        ['aa', 'aaa', 'g'])
diff --git a/pypy/module/micronumpy/__init__.py 
b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -32,6 +32,7 @@
         'set_string_function': 'appbridge.set_string_function',
         'typeinfo': 'descriptor.get_dtype_cache(space).w_typeinfo',
         'nditer': 'nditer.W_NDIter',
+        'broadcast': 'broadcast.W_Broadcast',
 
         'set_docstring': 'support.descr_set_docstring',
         'VisibleDeprecationWarning': 'support.W_VisibleDeprecationWarning',
diff --git a/pypy/module/micronumpy/broadcast.py 
b/pypy/module/micronumpy/broadcast.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/broadcast.py
@@ -0,0 +1,110 @@
+import pypy.module.micronumpy.constants as NPY
+from nditer import ConcreteIter, parse_op_flag, parse_op_arg
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.module.micronumpy import support
+from pypy.module.micronumpy.base import W_NDimArray, convert_to_array, 
W_NumpyObject
+from rpython.rlib import jit
+from strides import calculate_broadcast_strides, shape_agreement_multiple
+
+def descr_new_broadcast(space, w_subtype, __args__):
+    return W_Broadcast(space, __args__.arguments_w)
+
+class W_Broadcast(W_NumpyObject):
+    """
+    Implementation of numpy.broadcast.
+    This class is a simplified version of nditer.W_NDIter with fixed iteration 
for broadcasted arrays.
+    """
+
+    def __init__(self, space, args):
+        num_args = len(args)
+        if not (2 <= num_args <= NPY.MAXARGS):
+            raise oefmt(space.w_ValueError,
+                                 "Need at least two and fewer than (%d) array 
objects.", NPY.MAXARGS)
+
+        self.seq = [convert_to_array(space, w_elem)
+                    for w_elem in args]
+
+        self.op_flags = parse_op_arg(space, 'op_flags', space.w_None,
+                                     len(self.seq), parse_op_flag)
+
+        self.shape = shape_agreement_multiple(space, self.seq, shape=None)
+        self.order = NPY.CORDER
+
+        self.iters = []
+        self.index = 0
+
+        try:
+            self.size = support.product_check(self.shape)
+        except OverflowError as e:
+            raise oefmt(space.w_ValueError, "broadcast dimensions too large.")
+        for i in range(len(self.seq)):
+            it = self.get_iter(space, i)
+            it.contiguous = False
+            self.iters.append((it, it.reset()))
+
+        self.done = False
+        pass
+
+    def get_iter(self, space, i):
+        arr = self.seq[i]
+        imp = arr.implementation
+        if arr.is_scalar():
+            return ConcreteIter(imp, 1, [], [], [], self.op_flags[i], self)
+        shape = self.shape
+
+        backward = imp.order != self.order
+
+        r = calculate_broadcast_strides(imp.strides, imp.backstrides, 
imp.shape,
+                                        shape, backward)
+
+        iter_shape = shape
+        if len(shape) != len(r[0]):
+            # shape can be shorter when using an external loop, just return a 
view
+            iter_shape = imp.shape
+        return ConcreteIter(imp, imp.get_size(), iter_shape, r[0], r[1],
+                            self.op_flags[i], self)
+
+    def descr_iter(self, space):
+        return space.wrap(self)
+
+    def descr_get_shape(self, space):
+        return space.newtuple([space.wrap(i) for i in self.shape])
+
+    def descr_get_size(self, space):
+        return space.wrap(self.size)
+
+    def descr_get_index(self, space):
+        return space.wrap(self.index)
+
+    def descr_get_numiter(self, space):
+        return space.wrap(len(self.iters))
+
+    @jit.unroll_safe
+    def descr_next(self, space):
+        if self.index >= self.size:
+            self.done = True
+            raise OperationError(space.w_StopIteration, space.w_None)
+        self.index += 1
+        res = []
+        for i, (it, st) in enumerate(self.iters):
+            res.append(self._get_item(it, st))
+            self.iters[i] = (it, it.next(st))
+        if len(res) < 2:
+            return res[0]
+        return space.newtuple(res)
+
+    def _get_item(self, it, st):
+        return W_NDimArray(it.getoperand(st))
+
+
+W_Broadcast.typedef = TypeDef("numpy.broadcast",
+                              __new__=interp2app(descr_new_broadcast),
+                              __iter__=interp2app(W_Broadcast.descr_iter),
+                              next=interp2app(W_Broadcast.descr_next),
+                              
shape=GetSetProperty(W_Broadcast.descr_get_shape),
+                              size=GetSetProperty(W_Broadcast.descr_get_size),
+                              
index=GetSetProperty(W_Broadcast.descr_get_index),
+                              
numiter=GetSetProperty(W_Broadcast.descr_get_numiter),
+                              )
diff --git a/pypy/module/micronumpy/constants.py 
b/pypy/module/micronumpy/constants.py
--- a/pypy/module/micronumpy/constants.py
+++ b/pypy/module/micronumpy/constants.py
@@ -77,6 +77,8 @@
 WRAP = 1
 RAISE = 2
 
+MAXARGS = 32
+
 # These can be requested in constructor functions and tested for
 ARRAY_C_CONTIGUOUS = 0x0001
 ARRAY_F_CONTIGUOUS = 0x0002
diff --git a/pypy/module/micronumpy/test/test_broadcast.py 
b/pypy/module/micronumpy/test/test_broadcast.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_broadcast.py
@@ -0,0 +1,97 @@
+# -*- encoding: utf-8 -*-
+
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestArrayBroadcast(BaseNumpyAppTest):
+    def test_broadcast_for_row_and_column(self):
+        import numpy as np
+        x = np.array([[1], [2], [3]])
+        y = np.array([4, 5])
+        b = list(np.broadcast(x, y))
+        assert b == [(1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)]
+
+    def test_broadcast_properties(self):
+        import numpy as np
+        x = np.array([[1], [2], [3]])
+        y = np.array([4, 5])
+        b = np.broadcast(x, y)
+
+        assert b.shape == (3, 2)
+        assert b.size == 6
+        assert b.index == 0
+
+        b.next()
+        b.next()
+
+        assert b.shape == (3, 2)
+        assert b.size == 6
+        assert b.index == 2
+
+    def test_broadcast_from_doctest(self):
+        """
+        Test from numpy.broadcast doctest.
+        """
+        import numpy as np
+        x = np.array([[1], [2], [3]])
+        y = np.array([4, 5, 6])
+        reference = np.array([[5., 6., 7.],
+                              [6., 7., 8.],
+                              [7., 8., 9.]])
+
+        b = np.broadcast(x, y)
+        out = np.empty(b.shape)
+        out.flat = [u + v for (u, v) in b]
+
+        assert (reference == out).all()
+        assert out.dtype == reference.dtype
+        assert b.shape == reference.shape
+
+    def test_broadcast_linear(self):
+        import numpy as np
+        x = np.array([1, 2, 3])
+        y = np.array([4, 5, 6])
+        b = list(np.broadcast(x, y))
+        assert b == [(1, 4), (2, 5), (3, 6)]
+        assert b[0][0].dtype == x.dtype
+
+    def test_broadcast_failures(self):
+        import numpy as np
+        import sys
+        x = np.array([1, 2, 3])
+        y = np.array([4, 5])
+        raises(ValueError, np.broadcast, x, y)
+        a = np.empty(2**16,dtype='int8')
+        a = a.reshape(-1, 1, 1, 1)
+        b = a.reshape(1, -1, 1, 1)
+        c = a.reshape(1, 1, -1, 1)
+        d = a.reshape(1, 1, 1, -1)
+        exc = raises(ValueError, np.broadcast, a, b, c, d)
+        assert exc.value[0] == ('broadcast dimensions too large.')
+
+    def test_broadcast_3_args(self):
+        import numpy as np
+        x = np.array([[[1]], [[2]], [[3]]])
+        y = np.array([[[40], [50]]])
+        z = np.array([[[700, 800]]])
+
+        b = list(np.broadcast(x, y, z))
+
+        assert b == [(1, 40, 700), (1, 40, 800), (1, 50, 700), (1, 50, 800),
+                     (2, 40, 700), (2, 40, 800), (2, 50, 700), (2, 50, 800),
+                     (3, 40, 700), (3, 40, 800), (3, 50, 700), (3, 50, 800)]
+
+    def test_number_of_arguments(self):
+        """
+        Test from numpy unit tests.
+        """
+        import numpy as np
+        arr = np.empty((5,))
+        for j in range(35):
+            arrs = [arr] * j
+            if j < 2 or j > 32:
+                exc = raises(ValueError, np.broadcast, *arrs)
+                assert exc.value[0] == ('Need at least two and fewer than (32) 
array objects.')
+            else:
+                mit = np.broadcast(*arrs)
+                assert mit.numiter == j
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
@@ -424,3 +424,59 @@
     def test_ffi_def_extern(self):
         ffi = FFI()
         py.test.raises(ValueError, ffi.def_extern)
+
+    def test_introspect_typedef(self):
+        ffi = FFI()
+        ffi.cdef("typedef int foo_t;")
+        assert ffi.list_types() == (['foo_t'], [], [])
+        assert ffi.typeof('foo_t').kind == 'primitive'
+        assert ffi.typeof('foo_t').cname == 'int'
+        #
+        ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
+        assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'foo_t', 'g_t'],
+                                    [], [])
+
+    def test_introspect_struct(self):
+        ffi = FFI()
+        ffi.cdef("struct foo_s { int a; };")
+        assert ffi.list_types() == ([], ['foo_s'], [])
+        assert ffi.typeof('struct foo_s').kind == 'struct'
+        assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
+
+    def test_introspect_union(self):
+        ffi = FFI()
+        ffi.cdef("union foo_s { int a; };")
+        assert ffi.list_types() == ([], [], ['foo_s'])
+        assert ffi.typeof('union foo_s').kind == 'union'
+        assert ffi.typeof('union foo_s').cname == 'union foo_s'
+
+    def test_introspect_struct_and_typedef(self):
+        ffi = FFI()
+        ffi.cdef("typedef struct { int a; } foo_t;")
+        assert ffi.list_types() == (['foo_t'], [], [])
+        assert ffi.typeof('foo_t').kind == 'struct'
+        assert ffi.typeof('foo_t').cname == 'foo_t'
+
+    def test_introspect_included_type(self):
+        ffi1 = FFI()
+        ffi2 = FFI()
+        ffi1.cdef("typedef signed char schar_t; struct sint_t { int x; };")
+        ffi2.include(ffi1)
+        assert ffi1.list_types() == ffi2.list_types() == (
+            ['schar_t'], ['sint_t'], [])
+
+    def test_introspect_order(self):
+        ffi = FFI()
+        ffi.cdef("union aaa { int a; }; typedef struct ccc { int a; } b;")
+        ffi.cdef("union g   { int a; }; typedef struct cc  { int a; } bbb;")
+        ffi.cdef("union aa  { int a; }; typedef struct a   { int a; } bb;")
+        assert ffi.list_types() == (['b', 'bb', 'bbb'],
+                                    ['a', 'cc', 'ccc'],
+                                    ['aa', 'aaa', 'g'])
+
+    def test_unpack(self):
+        ffi = FFI()
+        p = ffi.new("char[]", b"abc\x00def")
+        assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
+        p = ffi.new("int[]", [-123456789])
+        assert ffi.unpack(p, 1) == [-123456789]
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
@@ -496,3 +496,10 @@
         assert i < 20
         time.sleep(0.51)
     assert seen == ['init!', 'oops'] * 3
+
+def test_unpack():
+    ffi = _cffi1_backend.FFI()
+    p = ffi.new("char[]", b"abc\x00def")
+    assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
+    p = ffi.new("int[]", [-123456789])
+    assert ffi.unpack(p, 1) == [-123456789]
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -1744,3 +1744,125 @@
     lib.mycb1 = lib.foo
     assert lib.mycb1(200) == 242
     assert lib.indirect_call(300) == 342
+
+def test_introspect_function():
+    ffi = FFI()
+    ffi.cdef("float f1(double);")
+    lib = verify(ffi, 'test_introspect_function', """
+        float f1(double x) { return x; }
+    """)
+    assert dir(lib) == ['f1']
+    FUNC = ffi.typeof(lib.f1)
+    assert FUNC.kind == 'function'
+    assert FUNC.args[0].cname == 'double'
+    assert FUNC.result.cname == 'float'
+    assert ffi.typeof(ffi.addressof(lib, 'f1')) is FUNC
+
+def test_introspect_global_var():
+    ffi = FFI()
+    ffi.cdef("float g1;")
+    lib = verify(ffi, 'test_introspect_global_var', """
+        float g1;
+    """)
+    assert dir(lib) == ['g1']
+    FLOATPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
+    assert FLOATPTR.kind == 'pointer'
+    assert FLOATPTR.item.cname == 'float'
+
+def test_introspect_global_var_array():
+    ffi = FFI()
+    ffi.cdef("float g1[100];")
+    lib = verify(ffi, 'test_introspect_global_var_array', """
+        float g1[100];
+    """)
+    assert dir(lib) == ['g1']
+    FLOATARRAYPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
+    assert FLOATARRAYPTR.kind == 'pointer'
+    assert FLOATARRAYPTR.item.kind == 'array'
+    assert FLOATARRAYPTR.item.length == 100
+    assert ffi.typeof(lib.g1) is FLOATARRAYPTR.item
+
+def test_introspect_integer_const():
+    ffi = FFI()
+    ffi.cdef("#define FOO 42")
+    lib = verify(ffi, 'test_introspect_integer_const', """
+        #define FOO 42
+    """)
+    assert dir(lib) == ['FOO']
+    assert lib.FOO == ffi.integer_const('FOO') == 42
+
+def test_introspect_typedef():
+    ffi = FFI()
+    ffi.cdef("typedef int foo_t;")
+    lib = verify(ffi, 'test_introspect_typedef', """
+        typedef int foo_t;
+    """)
+    assert ffi.list_types() == (['foo_t'], [], [])
+    assert ffi.typeof('foo_t').kind == 'primitive'
+    assert ffi.typeof('foo_t').cname == 'int'
+
+def test_introspect_typedef_multiple():
+    ffi = FFI()
+    ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
+    lib = verify(ffi, 'test_introspect_typedef_multiple', """
+        typedef signed char a_t, c_t, g_t, b_t;
+    """)
+    assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'g_t'], [], [])
+
+def test_introspect_struct():
+    ffi = FFI()
+    ffi.cdef("struct foo_s { int a; };")
+    lib = verify(ffi, 'test_introspect_struct', """
+        struct foo_s { int a; };
+    """)
+    assert ffi.list_types() == ([], ['foo_s'], [])
+    assert ffi.typeof('struct foo_s').kind == 'struct'
+    assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
+
+def test_introspect_union():
+    ffi = FFI()
+    ffi.cdef("union foo_s { int a; };")
+    lib = verify(ffi, 'test_introspect_union', """
+        union foo_s { int a; };
+    """)
+    assert ffi.list_types() == ([], [], ['foo_s'])
+    assert ffi.typeof('union foo_s').kind == 'union'
+    assert ffi.typeof('union foo_s').cname == 'union foo_s'
+
+def test_introspect_struct_and_typedef():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int a; } foo_t;")
+    lib = verify(ffi, 'test_introspect_struct_and_typedef', """
+        typedef struct { int a; } foo_t;
+    """)
+    assert ffi.list_types() == (['foo_t'], [], [])
+    assert ffi.typeof('foo_t').kind == 'struct'
+    assert ffi.typeof('foo_t').cname == 'foo_t'
+
+def test_introspect_included_type():
+    SOURCE = """
+        typedef signed char schar_t;
+        struct sint_t { int x; };
+    """
+    ffi1 = FFI()
+    ffi1.cdef(SOURCE)
+    ffi2 = FFI()
+    ffi2.include(ffi1)
+    verify(ffi1, "test_introspect_included_type_parent", SOURCE)
+    verify(ffi2, "test_introspect_included_type", SOURCE)
+    assert ffi1.list_types() == ffi2.list_types() == (
+            ['schar_t'], ['sint_t'], [])
+
+def test_introspect_order():
+    ffi = FFI()
+    ffi.cdef("union aaa { int a; }; typedef struct ccc { int a; } b;")
+    ffi.cdef("union g   { int a; }; typedef struct cc  { int a; } bbb;")
+    ffi.cdef("union aa  { int a; }; typedef struct a   { int a; } bb;")
+    verify(ffi, "test_introspect_order", """
+        union aaa { int a; }; typedef struct ccc { int a; } b;
+        union g   { int a; }; typedef struct cc  { int a; } bbb;
+        union aa  { int a; }; typedef struct a   { int a; } bb;
+    """)
+    assert ffi.list_types() == (['b', 'bb', 'bbb'],
+                                    ['a', 'cc', 'ccc'],
+                                    ['aa', 'aaa', 'g'])
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
@@ -695,25 +695,14 @@
     assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
     assert ffi.string(ffi.cast('enum ee', -10)) == "EE3"
     #
-    # try again
-    ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
-    assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
-    #
     assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': 
-10}
     assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
 
 def test_full_enum():
     ffi = FFI()
     ffi.cdef("enum ee { EE1, EE2, EE3 };")
-    ffi.verify("enum ee { EE1, EE2, EE3 };")
-    py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE2 };")
-    # disabled: for now, we always accept and fix transparently constant values
-    #e = py.test.raises(VerificationError, ffi.verify,
-    #                   "enum ee { EE1, EE3, EE2 };")
-    #assert str(e.value) == 'enum ee: EE2 has the real value 2, not 1'
-    # extra items cannot be seen and have no bad consequence anyway
-    lib = ffi.verify("enum ee { EE1, EE2, EE3, EE4 };")
-    assert lib.EE3 == 2
+    lib = ffi.verify("enum ee { EE1, EE2, EE3 };")
+    assert [lib.EE1, lib.EE2, lib.EE3] == [0, 1, 2]
 
 def test_enum_usage():
     ffi = FFI()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py 
b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
--- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
@@ -143,7 +143,7 @@
         env_extra[envname] = libpath
         for key, value in sorted(env_extra.items()):
             if os.environ.get(key) != value:
-                print '* setting env var %r to %r' % (key, value)
+                print('* setting env var %r to %r' % (key, value))
                 os.environ[key] = value
 
     def execute(self, name):
@@ -165,6 +165,9 @@
 
 
 class TestBasic(EmbeddingTests):
+    def test_empty(self):
+        empty_cffi = self.prepare_module('empty')
+
     def test_basic(self):
         add1_cffi = self.prepare_module('add1')
         self.compile('add1-test', [add1_cffi])
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -205,6 +205,12 @@
         storage = strategy.erase(list_i)
         return W_ListObject.from_storage_and_strategy(space, storage, strategy)
 
+    @staticmethod
+    def newlist_float(space, list_f):
+        strategy = space.fromcache(FloatListStrategy)
+        storage = strategy.erase(list_f)
+        return W_ListObject.from_storage_and_strategy(space, storage, strategy)
+
     def __repr__(self):
         """ representation for debugging purposes """
         return "%s(%s, %s)" % (self.__class__.__name__, self.strategy,
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -310,6 +310,9 @@
     def newlist_int(self, list_i):
         return W_ListObject.newlist_int(self, list_i)
 
+    def newlist_float(self, list_f):
+        return W_ListObject.newlist_float(self, list_f)
+
     def newdict(self, module=False, instance=False, kwargs=False,
                 strdict=False):
         return W_DictMultiObject.allocate_and_init_instance(
diff --git a/rpython/jit/backend/test/runner_test.py 
b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -4510,7 +4510,10 @@
                     continue
                 w = t[2].split()
                 if len(w) == 0:
-                    continue
+                    if '<UNDEFINED>' in line:
+                        w = ['UNDEFINED']
+                    else:
+                        continue
                 words.append(w[0] + ';')
                 print '[[%s]]' % (w[0],)
             text = ' '.join(words)
diff --git a/rpython/rlib/rposix_stat.py b/rpython/rlib/rposix_stat.py
--- a/rpython/rlib/rposix_stat.py
+++ b/rpython/rlib/rposix_stat.py
@@ -36,10 +36,9 @@
 # - ALL_STAT_FIELDS contains Float fields if the system can retrieve
 #   sub-second timestamps.
 # - TIMESPEC is defined when the "struct stat" contains st_atim field.
-
-try:
+if sys.platform.startswith('linux') or sys.platform.startswith('openbsd'):
     from rpython.rlib.rposix import TIMESPEC
-except ImportError:
+else:
     TIMESPEC = None
 
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to