[pypy-commit] pypy py3k-memoryview: hg merge py3k

Manuel Jacob noreply at buildbot.pypy.org
Wed Jun 26 14:23:46 CEST 2013


Author: Manuel Jacob
Branch: py3k-memoryview
Changeset: r65003:3708c6a88a95
Date: 2013-06-26 14:20 +0200
http://bitbucket.org/pypy/pypy/changeset/3708c6a88a95/

Log:	hg merge py3k

diff too long, truncating to 2000 out of 7196 lines

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -6,6 +6,7 @@
 .idea
 .project
 .pydevproject
+__pycache__
 
 syntax: regexp
 ^testresult$
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -3,3 +3,6 @@
 d8ac7d23d3ec5f9a0fa1264972f74a010dbfd07f release-1.6
 ff4af8f318821f7f5ca998613a60fca09aa137da release-1.7
 07e08e9c885ca67d89bcc304e45a32346daea2fa release-2.0-beta-1
+9b623bc48b5950cf07184462a0e48f2c4df0d720 pypy-2.1-beta1-arm
+9b623bc48b5950cf07184462a0e48f2c4df0d720 pypy-2.1-beta1-arm
+ab0dd631c22015ed88e583d9fdd4c43eebf0be21 pypy-2.1-beta1-arm
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -218,6 +218,7 @@
     Impara, Germany
     Change Maker, Sweden 
     University of California Berkeley, USA
+    Google Inc.
 
 The PyPy Logo as used by http://speed.pypy.org and others was created
 by Samuel Reis and is distributed on terms of Creative Commons Share Alike
diff --git a/lib-python/2.7/logging/__init__.py b/lib-python/2.7/logging/__init__.py
--- a/lib-python/2.7/logging/__init__.py
+++ b/lib-python/2.7/logging/__init__.py
@@ -134,6 +134,11 @@
 DEBUG = 10
 NOTSET = 0
 
+# NOTE(flaper87): This is different from
+# python's stdlib module since pypy's
+# dicts are much faster when their
+# keys are all of the same type.
+# Introduced in commit 9de7b40c586f
 _levelToName = {
     CRITICAL: 'CRITICAL',
     ERROR: 'ERROR',
@@ -168,7 +173,11 @@
 
     Otherwise, the string "Level %s" % level is returned.
     """
-    return _levelToName.get(level, ("Level %s" % level))
+
+    # NOTE(flaper87): Check also in _nameToLevel
+    # if value is None.
+    return (_levelToName.get(level) or
+            _nameToLevel.get(level, ("Level %s" % level)))
 
 def addLevelName(level, levelName):
     """
diff --git a/lib-python/2.7/test/test_logging.py b/lib-python/2.7/test/test_logging.py
--- a/lib-python/2.7/test/test_logging.py
+++ b/lib-python/2.7/test/test_logging.py
@@ -278,6 +278,24 @@
     def test_invalid_name(self):
         self.assertRaises(TypeError, logging.getLogger, any)
 
+    def test_get_level_name(self):
+        """Test getLevelName returns level constant."""
+        # NOTE(flaper87): Bug #1517
+        self.assertEqual(logging.getLevelName('NOTSET'), 0)
+        self.assertEqual(logging.getLevelName('DEBUG'), 10)
+        self.assertEqual(logging.getLevelName('INFO'), 20)
+        self.assertEqual(logging.getLevelName('WARN'), 30)
+        self.assertEqual(logging.getLevelName('WARNING'), 30)
+        self.assertEqual(logging.getLevelName('ERROR'), 40)
+        self.assertEqual(logging.getLevelName('CRITICAL'), 50)
+
+        self.assertEqual(logging.getLevelName(0), 'NOTSET')
+        self.assertEqual(logging.getLevelName(10), 'DEBUG')
+        self.assertEqual(logging.getLevelName(20), 'INFO')
+        self.assertEqual(logging.getLevelName(30), 'WARNING')
+        self.assertEqual(logging.getLevelName(40), 'ERROR')
+        self.assertEqual(logging.getLevelName(50), 'CRITICAL')
+
 class BasicFilterTest(BaseTest):
 
     """Test the bundled Filter class."""
diff --git a/lib-python/3/logging/__init__.py b/lib-python/3/logging/__init__.py
--- a/lib-python/3/logging/__init__.py
+++ b/lib-python/3/logging/__init__.py
@@ -129,6 +129,11 @@
 DEBUG = 10
 NOTSET = 0
 
+# NOTE(flaper87): This is different from
+# python's stdlib module since pypy's
+# dicts are much faster when their
+# keys are all of the same type.
+# Introduced in commit 9de7b40c586f
 _levelToName = {
     CRITICAL: 'CRITICAL',
     ERROR: 'ERROR',
@@ -161,7 +166,11 @@
 
     Otherwise, the string "Level %s" % level is returned.
     """
-    return _levelToName.get(level, ("Level %s" % level))
+
+    # NOTE(flaper87): Check also in _nameToLevel
+    # if value is None.
+    return (_levelToName.get(level) or
+            _nameToLevel.get(level, ("Level %s" % level)))
 
 def addLevelName(level, levelName):
     """
diff --git a/lib-python/3/test/test_logging.py b/lib-python/3/test/test_logging.py
--- a/lib-python/3/test/test_logging.py
+++ b/lib-python/3/test/test_logging.py
@@ -299,6 +299,24 @@
     def test_invalid_name(self):
         self.assertRaises(TypeError, logging.getLogger, any)
 
+    def test_get_level_name(self):
+        """Test getLevelName returns level constant."""
+        # NOTE(flaper87): Bug #1517
+        self.assertEqual(logging.getLevelName('NOTSET'), 0)
+        self.assertEqual(logging.getLevelName('DEBUG'), 10)
+        self.assertEqual(logging.getLevelName('INFO'), 20)
+        self.assertEqual(logging.getLevelName('WARN'), 30)
+        self.assertEqual(logging.getLevelName('WARNING'), 30)
+        self.assertEqual(logging.getLevelName('ERROR'), 40)
+        self.assertEqual(logging.getLevelName('CRITICAL'), 50)
+
+        self.assertEqual(logging.getLevelName(0), 'NOTSET')
+        self.assertEqual(logging.getLevelName(10), 'DEBUG')
+        self.assertEqual(logging.getLevelName(20), 'INFO')
+        self.assertEqual(logging.getLevelName(30), 'WARNING')
+        self.assertEqual(logging.getLevelName(40), 'ERROR')
+        self.assertEqual(logging.getLevelName(50), 'CRITICAL')
+
 class BasicFilterTest(BaseTest):
 
     """Test the bundled Filter class."""
diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py
--- a/lib_pypy/_collections.py
+++ b/lib_pypy/_collections.py
@@ -431,5 +431,6 @@
 
            This API is used by pickle.py and copy.py.
         """
-        return (type(self), (self.default_factory,), None, None, self.items())
+        return (type(self), (self.default_factory,), None, None,
+                iter(self.items()))
 
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
@@ -20,7 +20,7 @@
                 or tp._type_ not in "iIhHbBlLqQ"):
                 #XXX: are those all types?
                 #     we just dont get the type name
-                #     in the interp levle thrown TypeError
+                #     in the interp level thrown TypeError
                 #     from rawffi if there are more
                 raise TypeError('bit fields not allowed for type ' + tp.__name__)
 
diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
--- a/lib_pypy/_curses.py
+++ b/lib_pypy/_curses.py
@@ -476,6 +476,15 @@
 def _chtype(ch):
     return int(ffi.cast("chtype", ch))
 
+def _texttype(text):
+    if isinstance(text, str):
+        return text
+    elif isinstance(text, unicode):
+        return str(text)   # default encoding
+    else:
+        raise TypeError("str or unicode expected, got a '%s' object"
+                        % (type(text).__name__,))
+
 
 def _extract_yx(args):
     if len(args) >= 2:
@@ -589,6 +598,7 @@
 
     @_argspec(1, 1, 2)
     def addstr(self, y, x, text, attr=None):
+        text = _texttype(text)
         if attr is not None:
             attr_old = lib.getattrs(self._win)
             lib.wattrset(self._win, attr)
@@ -602,6 +612,7 @@
 
     @_argspec(2, 1, 2)
     def addnstr(self, y, x, text, n, attr=None):
+        text = _texttype(text)
         if attr is not None:
             attr_old = lib.getattrs(self._win)
             lib.wattrset(self._win, attr)
@@ -780,6 +791,7 @@
 
     @_argspec(1, 1, 2)
     def insstr(self, y, x, text, attr=None):
+        text = _texttype(text)
         if attr is not None:
             attr_old = lib.getattrs(self._win)
             lib.wattrset(self._win, attr)
@@ -793,6 +805,7 @@
 
     @_argspec(2, 1, 2)
     def insnstr(self, y, x, text, n, attr=None):
+        text = _texttype(text)
         if attr is not None:
             attr_old = lib.getattrs(self._win)
             lib.wattrset(self._win, attr)
@@ -1197,6 +1210,7 @@
 
 
 def putp(text):
+    text = _texttype(text)
     return _check_ERR(lib.putp(text), "putp")
 
 
diff --git a/lib_pypy/_tkinter/__init__.py b/lib_pypy/_tkinter/__init__.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_tkinter/__init__.py
@@ -0,0 +1,48 @@
+# _tkinter package -- low-level interface to libtk and libtcl.
+#
+# This is an internal module, applications should "import Tkinter" instead.
+#
+# This version is based on cffi, and is a translation of _tkinter.c
+# from CPython, version 2.7.4.
+
+class TclError(Exception):
+    pass
+
+import cffi
+try:
+    from .tklib import tklib, tkffi
+except cffi.VerificationError:
+    raise ImportError("Tk headers and development libraries are required")
+
+from .app import TkApp
+
+TK_VERSION = tkffi.string(tklib.get_tk_version())
+TCL_VERSION = tkffi.string(tklib.get_tcl_version())
+
+READABLE = tklib.TCL_READABLE
+WRITABLE = tklib.TCL_WRITABLE
+EXCEPTION = tklib.TCL_EXCEPTION
+
+def create(screenName=None, baseName=None, className=None,
+           interactive=False, wantobjects=False, wantTk=True,
+           sync=False, use=None):
+    return TkApp(screenName, baseName, className,
+                 interactive, wantobjects, wantTk, sync, use)
+
+def _flatten(item):
+    def _flatten1(output, item, depth):
+        if depth > 1000:
+            raise ValueError("nesting too deep in _flatten")
+        if not isinstance(item, (list, tuple)):
+            raise TypeError("argument must be sequence")
+        # copy items to output tuple
+        for o in item:
+            if isinstance(o, (list, tuple)):
+                _flatten1(output, o, depth + 1)
+            elif o is not None:
+                output.append(o)
+
+    result = []
+    _flatten1(result, item, 0)
+    return tuple(result)
+    
diff --git a/lib_pypy/_tkinter/app.py b/lib_pypy/_tkinter/app.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_tkinter/app.py
@@ -0,0 +1,389 @@
+# The TkApp class.
+
+from .tklib import tklib, tkffi
+from . import TclError
+from .tclobj import TclObject, FromObj, AsObj, TypeCache
+
+import sys
+
+def varname_converter(input):
+    if isinstance(input, TclObject):
+        return input.string
+    return input
+
+
+def Tcl_AppInit(app):
+    if tklib.Tcl_Init(app.interp) == tklib.TCL_ERROR:
+        app.raiseTclError()
+    skip_tk_init = tklib.Tcl_GetVar(
+        app.interp, "_tkinter_skip_tk_init", tklib.TCL_GLOBAL_ONLY)
+    if skip_tk_init and tkffi.string(skip_tk_init) == "1":
+        return
+
+    if tklib.Tk_Init(app.interp) == tklib.TCL_ERROR:
+        app.raiseTclError()
+
+class _CommandData(object):
+    def __new__(cls, app, name, func):
+        self = object.__new__(cls)
+        self.app = app
+        self.name = name
+        self.func = func
+        handle = tkffi.new_handle(self)
+        app._commands[name] = handle  # To keep the command alive
+        return tkffi.cast("ClientData", handle)
+
+    @tkffi.callback("Tcl_CmdProc")
+    def PythonCmd(clientData, interp, argc, argv):
+        self = tkffi.from_handle(clientData)
+        assert self.app.interp == interp
+        try:
+            args = [tkffi.string(arg) for arg in argv[1:argc]]
+            result = self.func(*args)
+            obj = AsObj(result)
+            tklib.Tcl_SetObjResult(interp, obj)
+        except:
+            self.app.errorInCmd = True
+            self.app.exc_info = sys.exc_info()
+            return tklib.TCL_ERROR
+        else:
+            return tklib.TCL_OK
+
+    @tkffi.callback("Tcl_CmdDeleteProc")
+    def PythonCmdDelete(clientData):
+        self = tkffi.from_handle(clientData)
+        app = self.app
+        del app._commands[self.name]
+        return
+
+
+class TkApp(object):
+    def __new__(cls, screenName, baseName, className,
+                interactive, wantobjects, wantTk, sync, use):
+        if not wantobjects:
+            raise NotImplementedError("wantobjects=True only")
+        self = object.__new__(cls)
+        self.interp = tklib.Tcl_CreateInterp()
+        self._wantobjects = wantobjects
+        self.threaded = bool(tklib.Tcl_GetVar2Ex(
+            self.interp, "tcl_platform", "threaded",
+            tklib.TCL_GLOBAL_ONLY))
+        self.thread_id = tklib.Tcl_GetCurrentThread()
+        self.dispatching = False
+        self.quitMainLoop = False
+        self.errorInCmd = False
+
+        self._typeCache = TypeCache()
+        self._commands = {}
+
+        # Delete the 'exit' command, which can screw things up
+        tklib.Tcl_DeleteCommand(self.interp, "exit")
+
+        if screenName is not None:
+            tklib.Tcl_SetVar2(self.interp, "env", "DISPLAY", screenName,
+                              tklib.TCL_GLOBAL_ONLY)
+
+        if interactive:
+            tklib.Tcl_SetVar(self.interp, "tcl_interactive", "1",
+                             tklib.TCL_GLOBAL_ONLY)
+        else:
+            tklib.Tcl_SetVar(self.interp, "tcl_interactive", "0",
+                             tklib.TCL_GLOBAL_ONLY)
+
+        # This is used to get the application class for Tk 4.1 and up
+        argv0 = className.lower()
+        tklib.Tcl_SetVar(self.interp, "argv0", argv0,
+                         tklib.TCL_GLOBAL_ONLY)
+
+        if not wantTk:
+            tklib.Tcl_SetVar(self.interp, "_tkinter_skip_tk_init", "1",
+                             tklib.TCL_GLOBAL_ONLY)
+
+        # some initial arguments need to be in argv
+        if sync or use:
+            args = ""
+            if sync:
+                args += "-sync"
+            if use:
+                if sync:
+                    args += " "
+                args += "-use " + use
+
+            tklib.Tcl_SetVar(self.interp, "argv", args,
+                             tklib.TCL_GLOBAL_ONLY)
+
+        Tcl_AppInit(self)
+        # EnableEventHook()
+        return self
+
+    def __del__(self):
+        tklib.Tcl_DeleteInterp(self.interp)
+        # DisableEventHook()
+
+    def raiseTclError(self):
+        if self.errorInCmd:
+            self.errorInCmd = False
+            raise self.exc_info[0], self.exc_info[1], self.exc_info[2]
+        raise TclError(tkffi.string(tklib.Tcl_GetStringResult(self.interp)))
+
+    def wantobjects(self):
+        return self._wantobjects
+
+    def _check_tcl_appartment(self):
+        if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
+            raise RuntimeError("Calling Tcl from different appartment")
+
+    def loadtk(self):
+        # We want to guard against calling Tk_Init() multiple times
+        err = tklib.Tcl_Eval(self.interp, "info exists     tk_version")
+        if err == tklib.TCL_ERROR:
+            self.raiseTclError()
+        tk_exists = tklib.Tcl_GetStringResult(self.interp)
+        if not tk_exists or tkffi.string(tk_exists) != "1":
+            err = tklib.Tk_Init(self.interp)
+            if err == tklib.TCL_ERROR:
+                self.raiseTclError()
+
+    def _var_invoke(self, func, *args, **kwargs):
+        if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
+            # The current thread is not the interpreter thread.
+            # Marshal the call to the interpreter thread, then wait
+            # for completion.
+            raise NotImplementedError("Call from another thread")
+        return func(*args, **kwargs)
+
+    def _getvar(self, name1, name2=None, global_only=False):
+        name1 = varname_converter(name1)
+        if not name2:
+            name2 = tkffi.NULL
+        flags=tklib.TCL_LEAVE_ERR_MSG
+        if global_only:
+            flags |= tklib.TCL_GLOBAL_ONLY
+        res = tklib.Tcl_GetVar2Ex(self.interp, name1, name2, flags)
+        if not res:
+            self.raiseTclError()
+        assert self._wantobjects
+        return FromObj(self, res)
+
+    def _setvar(self, name1, value, global_only=False):
+        name1 = varname_converter(name1)
+        newval = AsObj(value)
+        flags=tklib.TCL_LEAVE_ERR_MSG
+        if global_only:
+            flags |= tklib.TCL_GLOBAL_ONLY
+        res = tklib.Tcl_SetVar2Ex(self.interp, name1, tkffi.NULL,
+                                  newval, flags)
+        if not res:
+            self.raiseTclError()
+
+    def _unsetvar(self, name1, name2=None, global_only=False):
+        name1 = varname_converter(name1)
+        if not name2:
+            name2 = tkffi.NULL
+        flags=tklib.TCL_LEAVE_ERR_MSG
+        if global_only:
+            flags |= tklib.TCL_GLOBAL_ONLY
+        res = tklib.Tcl_UnsetVar2(self.interp, name1, name2, flags)
+        if res == tklib.TCL_ERROR:
+            self.raiseTclError()
+
+    def getvar(self, name1, name2=None):
+        return self._var_invoke(self._getvar, name1, name2)
+
+    def globalgetvar(self, name1, name2=None):
+        return self._var_invoke(self._getvar, name1, name2, global_only=True)
+
+    def setvar(self, name1, value):
+        return self._var_invoke(self._setvar, name1, value)
+
+    def globalsetvar(self, name1, value):
+        return self._var_invoke(self._setvar, name1, value, global_only=True)
+
+    def unsetvar(self, name1, name2=None):
+        return self._var_invoke(self._unsetvar, name1, name2)
+
+    def globalunsetvar(self, name1, name2=None):
+        return self._var_invoke(self._unsetvar, name1, name2, global_only=True)
+
+    # COMMANDS
+
+    def createcommand(self, cmdName, func):
+        if not callable(func):
+            raise TypeError("command not callable")
+
+        if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
+            raise NotImplementedError("Call from another thread")
+
+        clientData = _CommandData(self, cmdName, func)
+
+        if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
+            raise NotImplementedError("Call from another thread")
+
+        res = tklib.Tcl_CreateCommand(
+            self.interp, cmdName, _CommandData.PythonCmd,
+            clientData, _CommandData.PythonCmdDelete)
+        if not res:
+            raise TclError("can't create Tcl command")
+
+    def deletecommand(self, cmdName):
+        if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
+            raise NotImplementedError("Call from another thread")
+
+        res = tklib.Tcl_DeleteCommand(self.interp, cmdName)
+        if res == -1:
+            raise TclError("can't delete Tcl command")
+
+    def call(self, *args):
+        flags = tklib.TCL_EVAL_DIRECT | tklib.TCL_EVAL_GLOBAL
+
+        # If args is a single tuple, replace with contents of tuple
+        if len(args) == 1 and isinstance(args[0], tuple):
+            args = args[0]
+
+        if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
+            # We cannot call the command directly. Instead, we must
+            # marshal the parameters to the interpreter thread.
+            raise NotImplementedError("Call from another thread")
+
+        objects = tkffi.new("Tcl_Obj*[]", len(args))
+        argc = len(args)
+        try:
+            for i, arg in enumerate(args):
+                if arg is None:
+                    argc = i
+                    break
+                obj = AsObj(arg)
+                tklib.Tcl_IncrRefCount(obj)
+                objects[i] = obj
+
+            res = tklib.Tcl_EvalObjv(self.interp, argc, objects, flags)
+            if res == tklib.TCL_ERROR:
+                self.raiseTclError()
+            else:
+                result = self._callResult()
+        finally:
+            for obj in objects:
+                if obj:
+                    tklib.Tcl_DecrRefCount(obj)
+        return result
+
+    def _callResult(self):
+        assert self._wantobjects
+        value = tklib.Tcl_GetObjResult(self.interp)
+        # Not sure whether the IncrRef is necessary, but something
+        # may overwrite the interpreter result while we are
+        # converting it.
+        tklib.Tcl_IncrRefCount(value)
+        res = FromObj(self, value)
+        tklib.Tcl_DecrRefCount(value)
+        return res
+
+    def eval(self, script):
+        self._check_tcl_appartment()
+        res = tklib.Tcl_Eval(self.interp, script)
+        if res == tklib.TCL_ERROR:
+            self.raiseTclError()
+        return tkffi.string(tklib.Tcl_GetStringResult(self.interp))
+
+    def evalfile(self, filename):
+        self._check_tcl_appartment()
+        res = tklib.Tcl_EvalFile(self.interp, filename)
+        if res == tklib.TCL_ERROR:
+            self.raiseTclError()
+        return tkffi.string(tklib.Tcl_GetStringResult(self.interp))
+
+    def split(self, arg):
+        if isinstance(arg, tuple):
+            return self._splitObj(arg)
+        else:
+            return self._split(arg)
+
+    def splitlist(self, arg):
+        if isinstance(arg, tuple):
+            return arg
+        if isinstance(arg, unicode):
+            arg = arg.encode('utf8')
+
+        argc = tkffi.new("int*")
+        argv = tkffi.new("char***")
+        res = tklib.Tcl_SplitList(self.interp, arg, argc, argv)
+        if res == tklib.TCL_ERROR:
+            self.raiseTclError()
+
+        result = tuple(tkffi.string(argv[0][i])
+                       for i in range(argc[0]))
+        tklib.Tcl_Free(argv[0])
+        return result
+
+    def _splitObj(self, arg):
+        if isinstance(arg, tuple):
+            size = len(arg)
+            # Recursively invoke SplitObj for all tuple items.
+            # If this does not return a new object, no action is
+            # needed.
+            result = None
+            newelems = (self._splitObj(elem) for elem in arg)
+            for elem, newelem in zip(arg, newelems):
+                if elem is not newelem:
+                    return newelems
+        elif isinstance(arg, str):
+            argc = tkffi.new("int*")
+            argv = tkffi.new("char***")
+            res = tklib.Tcl_SplitList(tkffi.NULL, arg, argc, argv)
+            if res == tklib.TCL_ERROR:
+                return arg
+            tklib.Tcl_Free(argv[0])
+            if argc[0] > 1:
+                return self._split(arg)
+        return arg
+
+    def _split(self, arg):
+        argc = tkffi.new("int*")
+        argv = tkffi.new("char***")
+        res = tklib.Tcl_SplitList(tkffi.NULL, arg, argc, argv)
+        if res == tklib.TCL_ERROR:
+            # Not a list.
+            # Could be a quoted string containing funnies, e.g. {"}.
+            # Return the string itself.
+            return arg
+
+        try:
+            if argc[0] == 0:
+                return ""
+            elif argc[0] == 1:
+                return argv[0][0]
+            else:
+                return (self._split(argv[0][i])
+                        for i in range(argc[0]))
+        finally:
+            tklib.Tcl_Free(argv[0])
+
+    def getboolean(self, s):
+        if isinstance(s, int):
+            return s
+        v = tkffi.new("int*")
+        res = tklib.Tcl_GetBoolean(self.interp, s, v)
+        if res == tklib.TCL_ERROR:
+            self.raiseTclError()
+
+    def mainloop(self, threshold):
+        self._check_tcl_appartment()
+        self.dispatching = True
+        while (tklib.Tk_GetNumMainWindows() > threshold and
+               not self.quitMainLoop and not self.errorInCmd):
+
+            if self.threaded:
+                result = tklib.Tcl_DoOneEvent(0)
+            else:
+                raise NotImplementedError("TCL configured without threads")
+
+            if result < 0:
+                break
+        self.dispatching = False
+        self.quitMainLoop = False
+        if self.errorInCmd:
+            self.errorInCmd = False
+            raise self.exc_info[0], self.exc_info[1], self.exc_info[2]
+
+    def quit(self):
+        self.quitMainLoop = True
diff --git a/lib_pypy/_tkinter/tclobj.py b/lib_pypy/_tkinter/tclobj.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_tkinter/tclobj.py
@@ -0,0 +1,114 @@
+# TclObject, conversions with Python objects
+
+from .tklib import tklib, tkffi
+
+class TypeCache(object):
+    def __init__(self):
+        self.BooleanType = tklib.Tcl_GetObjType("boolean")
+        self.ByteArrayType = tklib.Tcl_GetObjType("bytearray")
+        self.DoubleType = tklib.Tcl_GetObjType("double")
+        self.IntType = tklib.Tcl_GetObjType("int")
+        self.ListType = tklib.Tcl_GetObjType("list")
+        self.ProcBodyType = tklib.Tcl_GetObjType("procbody")
+        self.StringType = tklib.Tcl_GetObjType("string")
+        
+
+def FromObj(app, value):
+    """Convert a TclObj pointer into a Python object."""
+    typeCache = app._typeCache
+    if not value.typePtr:
+        buf = tkffi.buffer(value.bytes, value.length)
+        result = buf[:]
+        # If the result contains any bytes with the top bit set, it's
+        # UTF-8 and we should decode it to Unicode.
+        try:
+            result.decode('ascii')
+        except UnicodeDecodeError:
+            result = result.decode('utf8')
+        return result
+
+    elif value.typePtr == typeCache.BooleanType:
+        return result
+    elif value.typePtr == typeCache.ByteArrayType:
+        return result
+    elif value.typePtr == typeCache.DoubleType:
+        return value.internalRep.doubleValue
+    elif value.typePtr == typeCache.IntType:
+        return value.internalRep.longValue
+    elif value.typePtr == typeCache.ListType:
+        size = tkffi.new('int*')
+        status = tklib.Tcl_ListObjLength(app.interp, value, size)
+        if status == tklib.TCL_ERROR:
+            app.raiseTclError()
+        result = []
+        tcl_elem = tkffi.new("Tcl_Obj**")
+        for i in range(size[0]):
+            status = tklib.Tcl_ListObjIndex(app.interp,
+                                            value, i, tcl_elem)
+            if status == tklib.TCL_ERROR:
+                app.raiseTclError()
+            result.append(FromObj(app, tcl_elem[0]))
+        return tuple(result)
+    elif value.typePtr == typeCache.ProcBodyType:
+        return result
+    elif value.typePtr == typeCache.StringType:
+        buf = tklib.Tcl_GetUnicode(value)
+        length = tklib.Tcl_GetCharLength(value)
+        buf = tkffi.buffer(tkffi.cast("char*", buf), length*2)[:]
+        return buf.decode('utf-16')
+
+    return TclObject(value)
+
+def AsObj(value):
+    if isinstance(value, str):
+        return tklib.Tcl_NewStringObj(value, len(value))
+    elif isinstance(value, bool):
+        return tklib.Tcl_NewBooleanObj(value)
+    elif isinstance(value, int):
+        return tklib.Tcl_NewLongObj(value)
+    elif isinstance(value, float):
+        return tklib.Tcl_NewDoubleObj(value)
+    elif isinstance(value, tuple):
+        argv = tkffi.new("Tcl_Obj*[]", len(value))
+        for i in range(len(value)):
+            argv[i] = AsObj(value[i])
+        return tklib.Tcl_NewListObj(len(value), argv)
+    elif isinstance(value, unicode):
+        encoded = value.encode('utf-16')[2:]
+        buf = tkffi.new("char[]", encoded)
+        inbuf = tkffi.cast("Tcl_UniChar*", buf)
+        return tklib.Tcl_NewUnicodeObj(buf, len(encoded)/2)
+    elif isinstance(value, TclObject):
+        tklib.Tcl_IncrRefCount(value._value)
+        return value._value
+    else:
+        return AsObj(str(value))
+
+class TclObject(object):
+    def __new__(cls, value):
+        self = object.__new__(cls)
+        tklib.Tcl_IncrRefCount(value)
+        self._value = value
+        self._string = None
+        return self
+
+    def __del__(self):
+        tklib.Tcl_DecrRefCount(self._value)
+
+    def __str__(self):
+        if self._string and isinstance(self._string, str):
+            return self._string
+        return tkffi.string(tklib.Tcl_GetString(self._value))
+
+    @property
+    def string(self):
+        if self._string is None:
+            length = tkffi.new("int*")
+            s = tklib.Tcl_GetStringFromObj(self._value, length)
+            value = tkffi.buffer(s, length[0])[:]
+            try:
+                value.decode('ascii')
+            except UnicodeDecodeError:
+                value = value.decode('utf8')
+            self._string = value
+        return self._string
diff --git a/lib_pypy/_tkinter/tklib.py b/lib_pypy/_tkinter/tklib.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_tkinter/tklib.py
@@ -0,0 +1,114 @@
+# C bindings with libtcl and libtk.
+
+from cffi import FFI
+
+tkffi = FFI()
+
+tkffi.cdef("""
+char *get_tk_version();
+char *get_tcl_version();
+#define TCL_READABLE ...
+#define TCL_WRITABLE ...
+#define TCL_EXCEPTION ...
+#define TCL_ERROR ...
+#define TCL_OK ...
+
+#define TCL_LEAVE_ERR_MSG ...
+#define TCL_GLOBAL_ONLY ...
+#define TCL_EVAL_DIRECT ...
+#define TCL_EVAL_GLOBAL ...
+
+typedef unsigned short Tcl_UniChar;
+typedef ... Tcl_Interp;
+typedef ...* Tcl_ThreadId;
+typedef ...* Tcl_Command;
+
+typedef struct Tcl_ObjType {
+    char *name;
+    ...;
+} Tcl_ObjType;
+typedef struct Tcl_Obj {
+    char *bytes;
+    int length;
+    Tcl_ObjType *typePtr;
+    union {                     /* The internal representation: */
+        long longValue;         /*   - an long integer value. */
+        double doubleValue;     /*   - a double-precision floating value. */
+        struct {                /*   - internal rep as two pointers. */
+            void *ptr1;
+            void *ptr2;
+        } twoPtrValue;
+    } internalRep;
+    ...;
+} Tcl_Obj;
+
+Tcl_Interp *Tcl_CreateInterp();
+void Tcl_DeleteInterp(Tcl_Interp* interp);
+int Tcl_Init(Tcl_Interp* interp);
+int Tk_Init(Tcl_Interp* interp);
+
+void Tcl_Free(char* ptr);
+
+const char *Tcl_SetVar(Tcl_Interp* interp, const char* varName, const char* newValue, int flags);
+const char *Tcl_SetVar2(Tcl_Interp* interp, const char* name1, const char* name2, const char* newValue, int flags);
+const char *Tcl_GetVar(Tcl_Interp* interp, const char* varName, int flags);
+Tcl_Obj *Tcl_SetVar2Ex(Tcl_Interp* interp, const char* name1, const char* name2, Tcl_Obj* newValuePtr, int flags);
+Tcl_Obj *Tcl_GetVar2Ex(Tcl_Interp* interp, const char* name1, const char* name2, int flags);
+int Tcl_UnsetVar2(Tcl_Interp* interp, const char* name1, const char* name2, int flags);
+const Tcl_ObjType *Tcl_GetObjType(const char* typeName);
+
+Tcl_Obj *Tcl_NewStringObj(const char* bytes, int length);
+Tcl_Obj *Tcl_NewUnicodeObj(const Tcl_UniChar* unicode, int numChars);
+Tcl_Obj *Tcl_NewLongObj(long longValue);
+Tcl_Obj *Tcl_NewBooleanObj(int boolValue);
+Tcl_Obj *Tcl_NewDoubleObj(double doubleValue);
+
+void Tcl_IncrRefCount(Tcl_Obj* objPtr);
+void Tcl_DecrRefCount(Tcl_Obj* objPtr);
+
+int Tcl_GetBoolean(Tcl_Interp* interp, const char* src, int* boolPtr);
+char *Tcl_GetString(Tcl_Obj* objPtr);
+char *Tcl_GetStringFromObj(Tcl_Obj* objPtr, int* lengthPtr);
+
+Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj* objPtr);
+int Tcl_GetCharLength(Tcl_Obj* objPtr);
+
+Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj* const objv[]);
+int Tcl_ListObjLength(Tcl_Interp* interp, Tcl_Obj* listPtr, int* intPtr);
+int Tcl_ListObjIndex(Tcl_Interp* interp, Tcl_Obj* listPtr, int index, Tcl_Obj** objPtrPtr);
+int Tcl_SplitList(Tcl_Interp* interp, char* list, int* argcPtr, const char*** argvPtr);
+
+int Tcl_Eval(Tcl_Interp* interp, const char* script);
+int Tcl_EvalFile(Tcl_Interp* interp, const char* filename);
+int Tcl_EvalObjv(Tcl_Interp* interp, int objc, Tcl_Obj** objv, int flags);
+Tcl_Obj *Tcl_GetObjResult(Tcl_Interp* interp);
+const char *Tcl_GetStringResult(Tcl_Interp* interp);
+void Tcl_SetObjResult(Tcl_Interp* interp, Tcl_Obj* objPtr);
+
+typedef void* ClientData;
+typedef int Tcl_CmdProc(
+        ClientData clientData,
+        Tcl_Interp *interp,
+        int argc,
+        const char *argv[]);
+typedef void Tcl_CmdDeleteProc(
+        ClientData clientData);
+Tcl_Command Tcl_CreateCommand(Tcl_Interp* interp, const char* cmdName, Tcl_CmdProc proc, ClientData clientData, Tcl_CmdDeleteProc deleteProc);
+int Tcl_DeleteCommand(Tcl_Interp* interp, const char* cmdName);
+
+Tcl_ThreadId Tcl_GetCurrentThread();
+int Tcl_DoOneEvent(int flags);
+
+int Tk_GetNumMainWindows();
+""")
+
+tklib = tkffi.verify("""
+#include <tcl.h>
+#include <tk.h>
+
+char *get_tk_version() { return TK_VERSION; }
+char *get_tcl_version() { return TCL_VERSION; }
+""",
+include_dirs=['/usr/include/tcl'],
+libraries=['tcl', 'tk'],
+)
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
@@ -361,13 +361,13 @@
     backend = ffi._backend
     try:
         if '.' not in name and '/' not in name:
-            raise OSError
+            raise OSError("library not found: %r" % (name,))
         backendlib = backend.load_library(name, flags)
     except OSError:
         import ctypes.util
         path = ctypes.util.find_library(name)
         if path is None:
-            raise OSError("library not found: %r" % (name,))
+            raise     # propagate the original OSError
         backendlib = backend.load_library(path, flags)
     copied_enums = []
     #
diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py
--- a/lib_pypy/cffi/backend_ctypes.py
+++ b/lib_pypy/cffi/backend_ctypes.py
@@ -707,7 +707,7 @@
         class CTypesStructOrUnion(CTypesBaseStructOrUnion):
             __slots__ = ['_blob']
             _ctype = struct_or_union
-            _reftypename = '%s %s &' % (kind, name)
+            _reftypename = '%s &' % (name,)
             _kind = kind
         #
         CTypesStructOrUnion._fix_class()
@@ -934,7 +934,7 @@
         #
         class CTypesEnum(CTypesInt):
             __slots__ = []
-            _reftypename = 'enum %s &' % name
+            _reftypename = '%s &' % name
 
             def _get_own_repr(self):
                 value = self._value
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
@@ -244,6 +244,10 @@
         self.forcename = forcename
         self.build_c_name_with_marker()
 
+    def get_official_name(self):
+        assert self.c_name_with_marker.endswith('&')
+        return self.c_name_with_marker[:-1]
+
 
 class StructOrUnion(StructOrUnionOrEnum):
     fixedlayout = None
@@ -357,7 +361,9 @@
     def build_backend_type(self, ffi, finishlist):
         self.check_not_partial()
         finishlist.append(self)
-        return global_cache(self, ffi, 'new_struct_type', self.name, key=self)
+        
+        return global_cache(self, ffi, 'new_struct_type',
+                            self.get_official_name(), key=self)
 
 
 class UnionType(StructOrUnion):
@@ -365,7 +371,8 @@
 
     def build_backend_type(self, ffi, finishlist):
         finishlist.append(self)
-        return global_cache(self, ffi, 'new_union_type', self.name, key=self)
+        return global_cache(self, ffi, 'new_union_type',
+                            self.get_official_name(), key=self)
 
 
 class EnumType(StructOrUnionOrEnum):
@@ -388,7 +395,8 @@
     def build_backend_type(self, ffi, finishlist):
         self.check_not_partial()
         base_btype = self.build_baseinttype(ffi, finishlist)
-        return global_cache(self, ffi, 'new_enum_type', self.name,
+        return global_cache(self, ffi, 'new_enum_type',
+                            self.get_official_name(),
                             self.enumerators, self.enumvalues,
                             base_btype, key=self)
 
diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst
--- a/pypy/doc/how-to-contribute.rst
+++ b/pypy/doc/how-to-contribute.rst
@@ -76,4 +76,4 @@
 The rest of directories serve specific niche goal and are unlikely a good
 entry point.
 
-.. _`introduction to RPython`: getting-started-dev.rst
+.. _`introduction to RPython`: getting-started-dev.html
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
@@ -52,3 +52,12 @@
 
 .. branch: ctypes-byref
 Add the '_obj' attribute on ctypes pointer() and byref() objects
+
+.. branch: argsort-segfault
+Fix a segfault in argsort when sorting by chunks on multidim numpypy arrays (mikefc)
+
+.. branch: dtype-isnative
+.. branch: ndarray-round
+
+.. branch: faster-str-of-bigint
+Improve performance of str(long).
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -912,7 +912,10 @@
         return (None, None)
 
     def newlist_str(self, list_s):
-        return self.newlist([self.wrap(s) for s in list_s])
+        return self.newlist([self.wrapbytes(s) for s in list_s])
+
+    def newlist_unicode(self, list_u):
+        return self.newlist([self.wrap(u) for u in list_u])
 
     def newlist_hint(self, sizehint):
         from pypy.objspace.std.listobject import make_empty_list_with_size
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -379,7 +379,6 @@
     return tuple(parts), tuple(formats)
 
 def get_operrcls2(valuefmt):
-    from rpython.rlib.runicode import str_decode_utf_8
     valuefmt = valuefmt.decode('ascii')
     strings, formats = decompose_valuefmt(valuefmt)
     assert len(strings) == len(formats) + 1
@@ -407,8 +406,7 @@
                     if fmt == 'd':
                         result = str(value).decode('ascii')
                     elif fmt == '8':
-                        result, _ = str_decode_utf_8(value, len(value),
-                                                     'strict')
+                        result = value.decode('utf-8')
                     elif fmt == 'R':
                         result = space.unicode_w(space.repr(value))
                     elif fmt in 'NT':
@@ -440,7 +438,7 @@
 
     Supports the standard %s and %d formats, plus the following:
 
-    %8 - The result of arg.decode('utf-8', 'strict')
+    %8 - The result of arg.decode('utf-8')
     %N - The result of w_arg.getname(space)
     %R - The result of space.unicode_w(space.repr(w_arg))
     %T - The result of space.type(w_arg).getname(space)
diff --git a/pypy/module/__pypy__/interp_dict.py b/pypy/module/__pypy__/interp_dict.py
--- a/pypy/module/__pypy__/interp_dict.py
+++ b/pypy/module/__pypy__/interp_dict.py
@@ -5,6 +5,22 @@
 
 @unwrap_spec(type=str)
 def newdict(space, type):
+    """ newdict(type)
+
+    Create a normal dict with a special implementation strategy.
+
+    type is a string and can be:
+
+    * "module" - equivalent to some_module.__dict__
+
+    * "instance" - equivalent to an instance dict with a not-changing-much
+                   set of keys
+
+    * "kwargs" - keyword args dict equivalent of what you get from **kwargs
+                 in a function, optimized for passing around
+
+    * "strdict" - string-key only dict. This one should be chosen automatically
+    """
     if type == 'module':
         return space.newdict(module=True)
     elif type == 'instance':
@@ -18,6 +34,10 @@
                               type)
 
 def dictstrategy(space, w_obj):
+    """ dictstrategy(dict)
+
+    show the underlaying strategy used by a dict object
+    """
     if not isinstance(w_obj, W_DictMultiObject):
         raise OperationError(space.w_TypeError,
                              space.wrap("expecting dict object"))
diff --git a/pypy/module/_cffi_backend/ctypeenum.py b/pypy/module/_cffi_backend/ctypeenum.py
--- a/pypy/module/_cffi_backend/ctypeenum.py
+++ b/pypy/module/_cffi_backend/ctypeenum.py
@@ -13,7 +13,6 @@
     _mixin_ = True
 
     def __init__(self, space, name, size, align, enumerators, enumvalues):
-        name = "enum " + name
         self._super.__init__(self, space, size, name, len(name), align)
         self.enumerators2values = {}   # str -> int
         self.enumvalues2erators = {}   # int -> str
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -289,16 +289,6 @@
                "with verify() (see pypy/module/_cffi_backend/ctypefunc.py "
                "for details)"))
 
-        if USE_C_LIBFFI_MSVC and is_result_type:
-            # MSVC returns small structures in registers.  Pretend int32 or
-            # int64 return type.  This is needed as a workaround for what
-            # is really a bug of libffi_msvc seen as an independent library
-            # (ctypes has a similar workaround).
-            if ctype.size <= 4:
-                return clibffi.ffi_type_sint32
-            if ctype.size <= 8:
-                return clibffi.ffi_type_sint64
-
         # walk the fields, expanding arrays into repetitions; first,
         # only count how many flattened fields there are
         nflat = 0
@@ -318,6 +308,16 @@
                                "a struct with a zero-length array"))
             nflat += flat
 
+        if USE_C_LIBFFI_MSVC and is_result_type:
+            # MSVC returns small structures in registers.  Pretend int32 or
+            # int64 return type.  This is needed as a workaround for what
+            # is really a bug of libffi_msvc seen as an independent library
+            # (ctypes has a similar workaround).
+            if ctype.size <= 4:
+                return clibffi.ffi_type_sint32
+            if ctype.size <= 8:
+                return clibffi.ffi_type_sint64
+
         # allocate an array of (nflat + 1) ffi_types
         elements = self.fb_alloc(rffi.sizeof(FFI_TYPE_P) * (nflat + 1))
         elements = rffi.cast(FFI_TYPE_PP, elements)
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
@@ -187,7 +187,7 @@
         else:
             extra = " *"
         self.is_file = (ctitem.name == "struct _IO_FILE" or
-                        ctitem.name == "struct $FILE")
+                        ctitem.name == "FILE")
         self.is_void_ptr = isinstance(ctitem, ctypevoid.W_CTypeVoid)
         W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem)
 
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
@@ -25,7 +25,6 @@
     custom_field_pos = False
 
     def __init__(self, space, name):
-        name = '%s %s' % (self.kind, name)
         W_CType.__init__(self, space, -1, name, len(name))
 
     def check_complete(self, w_errorcls=None):
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
@@ -5,6 +5,7 @@
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rarithmetic import ovfcheck
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.tool import rffi_platform
 
 from pypy.module._cffi_backend import (ctypeobj, ctypeprim, ctypeptr,
     ctypearray, ctypestruct, ctypevoid, ctypeenum)
@@ -115,13 +116,15 @@
 # ____________________________________________________________
 
 SF_MSVC_BITFIELDS = 1
+SF_GCC_ARM_BITFIELDS = 2
 
 if sys.platform == 'win32':
     DEFAULT_SFLAGS = SF_MSVC_BITFIELDS
+elif rffi_platform.getdefined('__arm__', ''):
+    DEFAULT_SFLAGS = SF_GCC_ARM_BITFIELDS
 else:
     DEFAULT_SFLAGS = 0
 
-
 @unwrap_spec(name=str)
 def new_struct_type(space, name):
     return ctypestruct.W_CTypeStruct(space, name)
@@ -180,7 +183,7 @@
         # field is an anonymous bitfield
         falign = ftype.alignof()
         do_align = True
-        if fbitsize >= 0:
+        if (sflags & SF_GCC_ARM_BITFIELDS) == 0 and fbitsize >= 0:
             if (sflags & SF_MSVC_BITFIELDS) == 0:
                 # GCC: anonymous bitfields (of any size) don't cause alignment
                 do_align = (fname != '')
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
@@ -641,6 +641,8 @@
 
 def test_new_struct_type():
     BStruct = new_struct_type("foo")
+    assert repr(BStruct) == "<ctype 'foo'>"
+    BStruct = new_struct_type("struct foo")
     assert repr(BStruct) == "<ctype 'struct foo'>"
     BPtr = new_pointer_type(BStruct)
     assert repr(BPtr) == "<ctype 'struct foo *'>"
@@ -648,7 +650,7 @@
     py.test.raises(ValueError, alignof, BStruct)
 
 def test_new_union_type():
-    BUnion = new_union_type("foo")
+    BUnion = new_union_type("union foo")
     assert repr(BUnion) == "<ctype 'union foo'>"
     BPtr = new_pointer_type(BUnion)
     assert repr(BPtr) == "<ctype 'union foo *'>"
@@ -657,7 +659,7 @@
     BLong = new_primitive_type("long")
     BChar = new_primitive_type("char")
     BShort = new_primitive_type("short")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     assert BStruct.kind == "struct"
     assert BStruct.cname == "struct foo"
     assert BStruct.fields is None
@@ -689,7 +691,7 @@
 def test_complete_union():
     BLong = new_primitive_type("long")
     BChar = new_primitive_type("char")
-    BUnion = new_union_type("foo")
+    BUnion = new_union_type("union foo")
     assert BUnion.kind == "union"
     assert BUnion.cname == "union foo"
     assert BUnion.fields is None
@@ -708,7 +710,7 @@
 
 def test_struct_instance():
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     p = cast(BStructPtr, 0)
     py.test.raises(AttributeError, "p.a1")    # opaque
@@ -728,7 +730,7 @@
 def test_union_instance():
     BInt = new_primitive_type("int")
     BUInt = new_primitive_type("unsigned int")
-    BUnion = new_union_type("bar")
+    BUnion = new_union_type("union bar")
     complete_struct_or_union(BUnion, [('a1', BInt, -1), ('a2', BUInt, -1)])
     p = newp(new_pointer_type(BUnion), [-42])
     bigval = -42 + (1 << (8*size_of_int()))
@@ -744,7 +746,7 @@
 
 def test_struct_pointer():
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BInt, -1),
                                        ('a2', BInt, -1)])
@@ -758,7 +760,7 @@
     BVoidP = new_pointer_type(new_void_type())
     BInt = new_primitive_type("int")
     BIntPtr = new_pointer_type(BInt)
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BInt, -1),
                                        ('a2', BInt, -1),
@@ -792,7 +794,7 @@
 
 def test_array_in_struct():
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BArrayInt5 = new_array_type(new_pointer_type(BInt), 5)
     complete_struct_or_union(BStruct, [('a1', BArrayInt5, -1)])
     s = newp(new_pointer_type(BStruct), [[20, 24, 27, 29, 30]])
@@ -803,7 +805,7 @@
     def offsetof(BType, fieldname):
         return typeoffsetof(BType, fieldname)[1]
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     py.test.raises(TypeError, offsetof, BInt, "abc")
     py.test.raises(TypeError, offsetof, BStruct, "abc")
     complete_struct_or_union(BStruct, [('abc', BInt, -1), ('def', BInt, -1)])
@@ -832,7 +834,7 @@
 def test_function_type_taking_struct():
     BChar = new_primitive_type("char")
     BShort = new_primitive_type("short")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a1', BChar, -1),
                                        ('a2', BShort, -1)])
     BFunc = new_function_type((BStruct,), BShort, False)
@@ -937,7 +939,7 @@
 def test_call_function_7():
     BChar = new_primitive_type("char")
     BShort = new_primitive_type("short")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BChar, -1),
                                        ('a2', BShort, -1)])
@@ -953,7 +955,7 @@
 def test_call_function_20():
     BChar = new_primitive_type("char")
     BShort = new_primitive_type("short")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BChar, -1),
                                        ('a2', BShort, -1)])
@@ -965,7 +967,7 @@
 
 def test_call_function_21():
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a', BInt, -1),
                                        ('b', BInt, -1),
                                        ('c', BInt, -1),
@@ -985,7 +987,7 @@
 def test_call_function_22():
     BInt = new_primitive_type("int")
     BArray10 = new_array_type(new_pointer_type(BInt), 10)
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructP = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a', BArray10, -1)])
     BFunc22 = new_function_type((BStruct, BStruct), BStruct, False)
@@ -1023,7 +1025,7 @@
 def test_cannot_pass_struct_with_array_of_length_0():
     BInt = new_primitive_type("int")
     BArray0 = new_array_type(new_pointer_type(BInt), 0)
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a', BArray0)])
     py.test.raises(NotImplementedError, new_function_type,
                    (BStruct,), BInt, False)
@@ -1048,7 +1050,7 @@
 def test_cannot_call_with_a_autocompleted_struct():
     BSChar = new_primitive_type("signed char")
     BDouble = new_primitive_type("double")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('c', BDouble, -1, 8),
                                        ('a', BSChar, -1, 2),
@@ -1221,7 +1223,7 @@
     BSChar = new_primitive_type("signed char")
     BInt = new_primitive_type("int")
     BDouble = new_primitive_type("double")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a', BSChar, -1),
                                        ('b', BDouble, -1)])
@@ -1238,7 +1240,7 @@
 
 def test_callback_returning_big_struct():
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a', BInt, -1),
                                        ('b', BInt, -1),
@@ -1275,26 +1277,27 @@
 def test_enum_type():
     BUInt = new_primitive_type("unsigned int")
     BEnum = new_enum_type("foo", (), (), BUInt)
-    assert repr(BEnum) == "<ctype 'enum foo'>"
+    assert repr(BEnum) == "<ctype 'foo'>"
     assert BEnum.kind == "enum"
-    assert BEnum.cname == "enum foo"
+    assert BEnum.cname == "foo"
     assert BEnum.elements == {}
     #
     BInt = new_primitive_type("int")
-    BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
+    BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
     assert BEnum.kind == "enum"
+    assert BEnum.cname == "enum foo"
     assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
     # 'elements' is not the real dict, but merely a copy
     BEnum.elements[2] = '??'
     assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
     #
-    BEnum = new_enum_type("bar", ('ab', 'cd'), (5, 5), BUInt)
+    BEnum = new_enum_type("enum bar", ('ab', 'cd'), (5, 5), BUInt)
     assert BEnum.elements == {5: 'ab'}
     assert BEnum.relements == {'ab': 5, 'cd': 5}
 
 def test_cast_to_enum():
     BInt = new_primitive_type("int")
-    BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
+    BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
     assert sizeof(BEnum) == sizeof(BInt)
     e = cast(BEnum, 0)
     assert repr(e) == "<cdata 'enum foo' 0: def>"
@@ -1308,27 +1311,27 @@
     assert string(cast(BEnum, -242 + 2**128)) == '-242'
     #
     BUInt = new_primitive_type("unsigned int")
-    BEnum = new_enum_type("bar", ('def', 'c', 'ab'), (0, 1, 20), BUInt)
+    BEnum = new_enum_type("enum bar", ('def', 'c', 'ab'), (0, 1, 20), BUInt)
     e = cast(BEnum, -1)
     assert repr(e) == "<cdata 'enum bar' 4294967295>"     # unsigned int
     #
     BLong = new_primitive_type("long")
-    BEnum = new_enum_type("baz", (), (), BLong)
+    BEnum = new_enum_type("enum baz", (), (), BLong)
     assert sizeof(BEnum) == sizeof(BLong)
     e = cast(BEnum, -1)
     assert repr(e) == "<cdata 'enum baz' -1>"
 
 def test_enum_with_non_injective_mapping():
     BInt = new_primitive_type("int")
-    BEnum = new_enum_type("foo", ('ab', 'cd'), (7, 7), BInt)
+    BEnum = new_enum_type("enum foo", ('ab', 'cd'), (7, 7), BInt)
     e = cast(BEnum, 7)
     assert repr(e) == "<cdata 'enum foo' 7: ab>"
     assert string(e) == 'ab'
 
 def test_enum_in_struct():
     BInt = new_primitive_type("int")
-    BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
-    BStruct = new_struct_type("bar")
+    BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
+    BStruct = new_struct_type("struct bar")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BEnum, -1)])
     p = newp(BStructPtr, [-20])
@@ -1432,7 +1435,7 @@
 
 def test_struct_with_bitfields():
     BLong = new_primitive_type("long")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     LONGBITS = 8 * sizeof(BLong)
     complete_struct_or_union(BStruct, [('a1', BLong, 1),
                                        ('a2', BLong, 2),
@@ -1455,7 +1458,7 @@
 def test_bitfield_instance():
     BInt = new_primitive_type("int")
     BUnsignedInt = new_primitive_type("unsigned int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a1', BInt, 1),
                                        ('a2', BUnsignedInt, 2),
                                        ('a3', BInt, 3)])
@@ -1485,14 +1488,14 @@
 
 def test_bitfield_instance_init():
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a1', BInt, 1)])
     p = newp(new_pointer_type(BStruct), [-1])
     assert p.a1 == -1
     p = newp(new_pointer_type(BStruct), {'a1': -1})
     assert p.a1 == -1
     #
-    BUnion = new_union_type("bar")
+    BUnion = new_union_type("union bar")
     complete_struct_or_union(BUnion, [('a1', BInt, 1)])
     p = newp(new_pointer_type(BUnion), [-1])
     assert p.a1 == -1
@@ -1561,7 +1564,7 @@
     py.test.raises(IndexError, newp, BArray, tuple(b'123456'))
     py.test.raises(IndexError, newp, BArray, list(b'123456'))
     py.test.raises(IndexError, newp, BArray, b'123456')
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [])
     py.test.raises(TypeError, newp, new_pointer_type(BStruct), b'')
     py.test.raises(ValueError, newp, new_pointer_type(BStruct), [b'1'])
@@ -1601,7 +1604,7 @@
     p = newp(new_pointer_type(BFloat), cast(BFloat, 12.25))
     assert p[0] == 12.25
     #
-    BStruct = new_struct_type("foo_s")
+    BStruct = new_struct_type("struct foo_s")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BInt, -1)])
     s1 = newp(BStructPtr, [42])
@@ -1619,7 +1622,7 @@
     s2 = newp(BStructPtr, s1[0])
     assert s2.a1 == 42
     #
-    BUnion = new_union_type("foo_u")
+    BUnion = new_union_type("union foo_u")
     BUnionPtr = new_pointer_type(BUnion)
     complete_struct_or_union(BUnion, [('a1', BInt, -1)])
     u1 = newp(BUnionPtr, [42])
@@ -1697,7 +1700,7 @@
     BChar = new_primitive_type("char")
     BCharP = new_pointer_type(BChar)
     BCharArray10 = new_array_type(BCharP, 10)
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BCharArray10, -1)])
     p = newp(BStructPtr, None)
@@ -1714,7 +1717,7 @@
     new_function_type((), BFunc)    # works
     new_function_type((), new_primitive_type("int"))
     new_function_type((), new_pointer_type(BFunc))
-    BUnion = new_union_type("foo_u")
+    BUnion = new_union_type("union foo_u")
     complete_struct_or_union(BUnion, [])
     py.test.raises(NotImplementedError, new_function_type, (), BUnion)
     py.test.raises(TypeError, new_function_type, (), BArray)
@@ -1725,7 +1728,7 @@
     BFloat = new_primitive_type("float")
     BDouble = new_primitive_type("double")
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo_s")
+    BStruct = new_struct_type("struct foo_s")
     complete_struct_or_union(BStruct, [('a1', BChar, -1),
                                        ('a2', BShort, -1)])
     BFunc10 = new_function_type((BInt,), BStruct)
@@ -1735,7 +1738,7 @@
     assert s.a1 == bytechr(40)
     assert s.a2 == 40 * 40
     #
-    BStruct11 = new_struct_type("test11")
+    BStruct11 = new_struct_type("struct test11")
     complete_struct_or_union(BStruct11, [('a1', BInt, -1),
                                          ('a2', BInt, -1)])
     BFunc11 = new_function_type((BInt,), BStruct11)
@@ -1745,7 +1748,7 @@
     assert s.a1 == 40
     assert s.a2 == 40 * 40
     #
-    BStruct12 = new_struct_type("test12")
+    BStruct12 = new_struct_type("struct test12")
     complete_struct_or_union(BStruct12, [('a1', BDouble, -1),
                                          ])
     BFunc12 = new_function_type((BInt,), BStruct12)
@@ -1754,7 +1757,7 @@
     assert repr(s) == "<cdata 'struct test12' owning 8 bytes>"
     assert s.a1 == 40.0
     #
-    BStruct13 = new_struct_type("test13")
+    BStruct13 = new_struct_type("struct test13")
     complete_struct_or_union(BStruct13, [('a1', BInt, -1),
                                          ('a2', BInt, -1),
                                          ('a3', BInt, -1)])
@@ -1766,7 +1769,7 @@
     assert s.a2 == 40 * 40
     assert s.a3 == 40 * 40 * 40
     #
-    BStruct14 = new_struct_type("test14")
+    BStruct14 = new_struct_type("struct test14")
     complete_struct_or_union(BStruct14, [('a1', BFloat, -1),
                                          ])
     BFunc14 = new_function_type((BInt,), BStruct14)
@@ -1775,7 +1778,7 @@
     assert repr(s) == "<cdata 'struct test14' owning 4 bytes>"
     assert s.a1 == 40.0
     #
-    BStruct15 = new_struct_type("test15")
+    BStruct15 = new_struct_type("struct test15")
     complete_struct_or_union(BStruct15, [('a1', BFloat, -1),
                                          ('a2', BInt, -1)])
     BFunc15 = new_function_type((BInt,), BStruct15)
@@ -1785,7 +1788,7 @@
     assert s.a1 == 40.0
     assert s.a2 == 40 * 40
     #
-    BStruct16 = new_struct_type("test16")
+    BStruct16 = new_struct_type("struct test16")
     complete_struct_or_union(BStruct16, [('a1', BFloat, -1),
                                          ('a2', BFloat, -1)])
     BFunc16 = new_function_type((BInt,), BStruct16)
@@ -1795,7 +1798,7 @@
     assert s.a1 == 40.0
     assert s.a2 == -40.0
     #
-    BStruct17 = new_struct_type("test17")
+    BStruct17 = new_struct_type("struct test17")
     complete_struct_or_union(BStruct17, [('a1', BInt, -1),
                                          ('a2', BFloat, -1)])
     BFunc17 = new_function_type((BInt,), BStruct17)
@@ -1818,7 +1821,7 @@
     BFunc2 = new_function_type((), new_primitive_type("short"))
     BCharP = new_pointer_type(new_primitive_type("char"))
     BIntP = new_pointer_type(new_primitive_type("int"))
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BFunc, -1)])
     newp(BStructPtr, [cast(BFunc, 0)])
@@ -1845,7 +1848,7 @@
         assert not pyuni4
     #
     BWCharP = new_pointer_type(BWChar)
-    BStruct = new_struct_type("foo_s")
+    BStruct = new_struct_type("struct foo_s")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BWChar, -1),
                                        ('a2', BWCharP, -1)])
@@ -1957,7 +1960,7 @@
     # exception to the no-keepalive rule: p=newp(BStructPtr) returns a
     # pointer owning the memory, and p[0] returns a pointer to the
     # struct that *also* owns the memory
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1),
                                        ('a2', new_primitive_type("int"), -1),
@@ -1977,7 +1980,7 @@
     assert q.a1 == 123456
 
 def test_nokeepalive_struct():
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     BStructPtrPtr = new_pointer_type(BStructPtr)
     complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1)])
@@ -2164,7 +2167,7 @@
     assert repr(x) == "<cdata 'int[3]' NULL>"
 
 def test_cast_invalid():
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [])
     p = cast(new_pointer_type(BStruct), 123456)
     s = p[0]
@@ -2183,7 +2186,7 @@
 
 def test_bug_delattr():
     BLong = new_primitive_type("long")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a1', BLong, -1)])
     x = newp(new_pointer_type(BStruct))
     py.test.raises(AttributeError, "del x.a1")
@@ -2192,7 +2195,7 @@
     py.test.skip("later")
     BLong = new_primitive_type("long")
     BArray = new_array_type(new_pointer_type(BLong), None)
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructP = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BLong, -1),
                                        ('a2', BArray, -1)])
@@ -2308,7 +2311,7 @@
         BLong = new_primitive_type("long")
         BLongP = new_pointer_type(BLong)
         BArray0 = new_array_type(BLongP, length)
-        BStruct = new_struct_type("foo")
+        BStruct = new_struct_type("struct foo")
         BStructPtr = new_pointer_type(BStruct)
         complete_struct_or_union(BStruct, [('a1', BArray0, -1)])
         p = newp(BStructPtr, None)
@@ -2320,8 +2323,8 @@
 def test_nested_anonymous_struct():
     BInt = new_primitive_type("int")
     BChar = new_primitive_type("char")
-    BStruct = new_struct_type("foo")
-    BInnerStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
+    BInnerStruct = new_struct_type("struct foo")
     complete_struct_or_union(BInnerStruct, [('a1', BInt, -1),
                                             ('a2', BChar, -1)])
     complete_struct_or_union(BStruct, [('', BInnerStruct, -1),
@@ -2353,12 +2356,12 @@
     BChar = new_primitive_type("char")
     BShort = new_primitive_type("short")
     assert sizeof(BShort) == alignof(BShort) == 2
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a1', BChar),
                                        ('a2', BChar),
                                        ('a3', BChar)])
     assert sizeof(BStruct) == 3 and alignof(BStruct) == 1
-    BUnion = new_union_type("u")
+    BUnion = new_union_type("union u")
     complete_struct_or_union(BUnion, [('s', BStruct),
                                       ('i', BShort)])
     assert sizeof(BUnion) == 4
@@ -2366,7 +2369,7 @@
 
 def test_unaligned_struct():
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('b', BInt, -1, 1)],
                              None, 5, 1)
 
@@ -2424,7 +2427,7 @@
 
 def test_typeoffsetof():
     BChar = new_primitive_type("char")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BChar, -1),
                                        ('a2', BChar, -1),
@@ -2440,14 +2443,14 @@
 
 def test_typeoffsetof_no_bitfield():
     BInt = new_primitive_type("int")
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     complete_struct_or_union(BStruct, [('a1', BInt, 4)])
     py.test.raises(TypeError, typeoffsetof, BStruct, 'a1')
 
 def test_rawaddressof():
     BChar = new_primitive_type("char")
     BCharP = new_pointer_type(BChar)
-    BStruct = new_struct_type("foo")
+    BStruct = new_struct_type("struct foo")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BChar, -1),
                                        ('a2', BChar, -1),
@@ -2508,7 +2511,7 @@
     if sys.platform == "win32":
         py.test.skip("testing FILE not implemented")
     #
-    BFILE = new_struct_type("_IO_FILE")
+    BFILE = new_struct_type("struct _IO_FILE")
     BFILEP = new_pointer_type(BFILE)
     BChar = new_primitive_type("char")
     BCharP = new_pointer_type(BChar)
@@ -2540,7 +2543,7 @@
     if sys.platform == "win32":
         py.test.skip("testing FILE not implemented")
     #
-    B_NOT_FILE = new_struct_type("NOT_FILE")
+    B_NOT_FILE = new_struct_type("struct NOT_FILE")
     B_NOT_FILEP = new_pointer_type(B_NOT_FILE)
     BChar = new_primitive_type("char")
     BCharP = new_pointer_type(BChar)
@@ -2563,7 +2566,7 @@
     if sys.platform == "win32":
         py.test.skip("testing FILE not implemented")
     #
-    BFILE = new_struct_type("$FILE")
+    BFILE = new_struct_type("FILE")
     BFILEP = new_pointer_type(BFILE)
     BChar = new_primitive_type("char")
     BCharP = new_pointer_type(BChar)
@@ -2762,20 +2765,20 @@
     BShort = new_primitive_type("short")
     BInt = new_primitive_type("int")
     BUInt = new_primitive_type("unsigned int")
-    BStruct = new_struct_type("foo1")
+    BStruct = new_struct_type("struct foo1")
     complete_struct_or_union(BStruct, [('a', BChar, -1),
                                        ('b1', BInt, 9),
                                        ('b2', BUInt, 7),
                                        ('c', BChar, -1)], -1, -1, -1, flag)
-    if flag == 0:   # gcc
+    if flag % 2 == 0:   # gcc and gcc ARM
         assert typeoffsetof(BStruct, 'c') == (BChar, 3)
         assert sizeof(BStruct) == 4
-    else:           # msvc
+    else:               # msvc
         assert typeoffsetof(BStruct, 'c') == (BChar, 8)
         assert sizeof(BStruct) == 12
     assert alignof(BStruct) == 4
     #
-    BStruct = new_struct_type("foo2")
+    BStruct = new_struct_type("struct foo2")
     complete_struct_or_union(BStruct, [('a', BChar, -1),
                                        ('',  BShort, 9),
                                        ('c', BChar, -1)], -1, -1, -1, flag)
@@ -2783,11 +2786,14 @@
     if flag == 0:   # gcc
         assert sizeof(BStruct) == 5
         assert alignof(BStruct) == 1
-    else:           # msvc
+    elif flag == 1: # msvc
+        assert sizeof(BStruct) == 6
+        assert alignof(BStruct) == 2
+    else:           # gcc ARM
         assert sizeof(BStruct) == 6
         assert alignof(BStruct) == 2
     #
-    BStruct = new_struct_type("foo2")
+    BStruct = new_struct_type("struct foo2")
     complete_struct_or_union(BStruct, [('a', BChar, -1),
                                        ('',  BInt, 0),
                                        ('',  BInt, 0),
@@ -2795,10 +2801,15 @@
     if flag == 0:   # gcc
         assert typeoffsetof(BStruct, 'c') == (BChar, 4)
         assert sizeof(BStruct) == 5
-    else:           # msvc
+        assert alignof(BStruct) == 1
+    elif flag == 1:  # msvc
         assert typeoffsetof(BStruct, 'c') == (BChar, 1)
         assert sizeof(BStruct) == 2
-    assert alignof(BStruct) == 1
+        assert alignof(BStruct) == 1
+    else:            # gcc ARM
+        assert typeoffsetof(BStruct, 'c') == (BChar, 4)
+        assert sizeof(BStruct) == 8
+        assert alignof(BStruct) == 4
 
 
 def test_bitfield_as_gcc():
@@ -2807,6 +2818,9 @@
 def test_bitfield_as_msvc():
     _test_bitfield_details(flag=1)
 
+def test_bitfield_as_arm_gcc():
+    _test_bitfield_details(flag=2)
+
 
 def test_version():
     # this test is here mostly for PyPy
diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py
--- a/pypy/module/_collections/app_defaultdict.py
+++ b/pypy/module/_collections/app_defaultdict.py
@@ -63,4 +63,5 @@
 
            This API is used by pickle.py and copy.py.
         """
-        return (type(self), (self._default_factory,), None, None, self.items())
+        return (type(self), (self._default_factory,), None, None,
+                iter(self.items()))
diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py
--- a/pypy/module/_collections/test/test_defaultdict.py
+++ b/pypy/module/_collections/test/test_defaultdict.py
@@ -56,3 +56,9 @@
         assert len(d2) == 1
         assert d2[2] == 3
         assert d2[3] == 42
+
+    def test_reduce(self):
+        import _collections
+        d = _collections.defaultdict(None, {3: 4})
+        dict_iter = d.__reduce__()[4]
+        assert type(dict_iter) is type(iter(d.items()))
diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py
--- a/pypy/module/_rawffi/array.py
+++ b/pypy/module/_rawffi/array.py
@@ -13,19 +13,9 @@
 from pypy.module._rawffi.interp_rawffi import TYPEMAP
 from pypy.module._rawffi.interp_rawffi import size_alignment
 from pypy.module._rawffi.interp_rawffi import unpack_shape_with_length
+from pypy.module._rawffi.interp_rawffi import read_ptr, write_ptr
 from rpython.rlib.rarithmetic import r_uint
 
-def push_elem(ll_array, pos, value):
-    TP = lltype.typeOf(value)
-    ll_array = rffi.cast(rffi.CArrayPtr(TP), ll_array)
-    ll_array[pos] = value
-push_elem._annspecialcase_ = 'specialize:argtype(2)'
-
-def get_elem(ll_array, pos, ll_t):
-    ll_array = rffi.cast(rffi.CArrayPtr(ll_t), ll_array)
-    return ll_array[pos]
-get_elem._annspecialcase_ = 'specialize:arg(2)'
-
 
 class W_Array(W_DataShape):
     def __init__(self, basicffitype, size):
@@ -57,7 +47,7 @@
                                                 " array length"))
             for num in range(iterlength):
                 w_item = items_w[num]
-                unwrap_value(space, push_elem, result.ll_buffer, num,
+                unwrap_value(space, write_ptr, result.ll_buffer, num,
                              self.itemcode, w_item)
         return space.wrap(result)
 
@@ -118,7 +108,7 @@
             raise segfault_exception(space, "setting element of freed array")
         if num >= self.length or num < 0:
             raise OperationError(space.w_IndexError, space.w_None)
-        unwrap_value(space, push_elem, self.ll_buffer, num,
+        unwrap_value(space, write_ptr, self.ll_buffer, num,
                      self.shape.itemcode, w_value)
 
     def descr_setitem(self, space, w_index, w_value):
@@ -136,7 +126,7 @@
             raise segfault_exception(space, "accessing elements of freed array")
         if num >= self.length or num < 0:
             raise OperationError(space.w_IndexError, space.w_None)
-        return wrap_value(space, get_elem, self.ll_buffer, num,
+        return wrap_value(space, read_ptr, self.ll_buffer, num,
                           self.shape.itemcode)
 
     def descr_getitem(self, space, w_index):
diff --git a/pypy/module/_rawffi/callback.py b/pypy/module/_rawffi/callback.py
--- a/pypy/module/_rawffi/callback.py
+++ b/pypy/module/_rawffi/callback.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from rpython.rtyper.lltypesystem import lltype, rffi
-from pypy.module._rawffi.array import push_elem
+from pypy.module._rawffi.interp_rawffi import read_ptr, write_ptr
 from pypy.module._rawffi.structure import W_Structure
 from pypy.module._rawffi.interp_rawffi import (W_DataInstance, letter2tp,
      unwrap_value, unpack_argshapes, got_libffi_error)
@@ -40,7 +40,7 @@
                 args_w[i] = space.wrap(rffi.cast(rffi.ULONG, ll_args[i]))
         w_res = space.call(w_callable, space.newtuple(args_w))
         if callback_ptr.result is not None: # don't return void
-            unwrap_value(space, push_elem, ll_res, 0,
+            unwrap_value(space, write_ptr, ll_res, 0,
                          callback_ptr.result, w_res)
     except OperationError, e:
         tbprint(space, space.wrap(e.get_traceback()),
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -6,6 +6,7 @@
 
 from rpython.rlib.clibffi import *
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.tool import rffi_platform
 from rpython.rlib.unroll import unrolling_iterable
 import rpython.rlib.rposix as rposix
 
@@ -44,6 +45,8 @@
 }
 TYPEMAP_PTR_LETTERS = "POszZ"
 TYPEMAP_NUMBER_LETTERS = "bBhHiIlLqQ?"
+TYPEMAP_FLOAT_LETTERS = "fd" # XXX long doubles are not propperly supported in
+                             # rpython, so we ignore then here
 
 if _MS_WINDOWS:
     TYPEMAP['X'] = ffi_type_pointer
@@ -240,6 +243,52 @@
 )
 
 unroll_letters_for_numbers = unrolling_iterable(TYPEMAP_NUMBER_LETTERS)
+unroll_letters_for_floats = unrolling_iterable(TYPEMAP_FLOAT_LETTERS)
+
+_ARM = rffi_platform.getdefined('__arm__', '')
+
+def read_ptr(ptr, ofs, TP):
+    T = lltype.Ptr(rffi.CArray(TP))
+    for c in unroll_letters_for_floats:
+        # Note: if we are on ARM and have a float-ish value that is not word
+        # aligned accessing it directly causes a SIGBUS. Instead we use memcpy
+        # to avoid the problem
+        if (_ARM and LL_TYPEMAP[c] is TP
+                    and rffi.cast(lltype.Signed, ptr) & 3 != 0):
+            if ofs != 0:
+                ptr = rffi.ptradd(ptr, ofs*rffi.sizeof(TP))
+            with lltype.scoped_alloc(T.TO, 1) as t_array:
+                rffi.c_memcpy(
+                    rffi.cast(rffi.VOIDP, t_array),
+                    rffi.cast(rffi.VOIDP, ptr),
+                    rffi.sizeof(TP))
+                ptr_val = t_array[0]
+                return ptr_val
+    else:
+        return rffi.cast(T, ptr)[ofs]
+read_ptr._annspecialcase_ = 'specialize:arg(2)'
+
+def write_ptr(ptr, ofs, value):
+    TP = lltype.typeOf(value)
+    T = lltype.Ptr(rffi.CArray(TP))
+    for c in unroll_letters_for_floats:
+        # Note: if we are on ARM and have a float-ish value that is not word
+        # aligned accessing it directly causes a SIGBUS. Instead we use memcpy
+        # to avoid the problem
+        if (_ARM and LL_TYPEMAP[c] is TP
+                    and rffi.cast(lltype.Signed, ptr) & 3 != 0):
+            if ofs != 0:
+                ptr = rffi.ptradd(ptr, ofs*rffi.sizeof(TP))
+            with lltype.scoped_alloc(T.TO, 1) as s_array:
+                s_array[0] = value
+                rffi.c_memcpy(
+                    rffi.cast(rffi.VOIDP, ptr),
+                    rffi.cast(rffi.VOIDP, s_array),
+                    rffi.sizeof(TP))
+                return
+    else:
+        rffi.cast(T, ptr)[ofs] = value
+write_ptr._annspecialcase_ = 'specialize:argtype(2)'
 
 def segfault_exception(space, reason):


More information about the pypy-commit mailing list