[pypy-commit] pypy reflex-support: merge default into branch

wlav noreply at buildbot.pypy.org
Sat Aug 3 15:34:52 CEST 2013


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r65920:da64c461417c
Date: 2013-08-03 02:44 -0700
http://bitbucket.org/pypy/pypy/changeset/da64c461417c/

Log:	merge default into branch

diff too long, truncating to 2000 out of 100692 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
@@ -2,9 +2,9 @@
 =======
 
 Except when otherwise stated (look for LICENSE files in directories or
-information at the beginning of each file) all software and
-documentation in the 'pypy', 'ctype_configure', 'dotviewer', 'demo',
-and 'lib_pypy' directories is licensed as follows: 
+information at the beginning of each file) all software and documentation in
+the 'rpython', 'pypy', 'ctype_configure', 'dotviewer', 'demo', and 'lib_pypy'
+directories is licensed as follows: 
 
     The MIT License
 
@@ -38,176 +38,239 @@
     Armin Rigo
     Maciej Fijalkowski
     Carl Friedrich Bolz
+    Antonio Cuni
     Amaury Forgeot d'Arc
-    Antonio Cuni
     Samuele Pedroni
+    Alex Gaynor
     Michael Hudson
+    David Schneider
     Holger Krekel
-    Alex Gaynor
     Christian Tismer
     Hakan Ardo
     Benjamin Peterson
-    David Schneider
+    Matti Picus
+    Philip Jenvey
+    Anders Chrigstrom
+    Brian Kearns
     Eric van Riet Paap
-    Anders Chrigstrom
     Richard Emslie
+    Alexander Schremmer
+    Wim Lavrijsen
     Dan Villiom Podlaski Christiansen
-    Alexander Schremmer
+    Manuel Jacob
     Lukas Diekmann
+    Sven Hager
+    Anders Lehmann
     Aurelien Campeas
-    Anders Lehmann
+    Niklaus Haldimann
+    Ronan Lamy
     Camillo Bruni
-    Niklaus Haldimann
-    Sven Hager
+    Laura Creighton
+    Toon Verwaest
     Leonardo Santagada
-    Toon Verwaest
     Seo Sanghyeon
     Justin Peel
+    Ronny Pfannschmidt
+    David Edelsohn
+    Anders Hammarquist
+    Jakub Gustak
+    Guido Wesdorp
     Lawrence Oluyede
     Bartosz Skowron
-    Jakub Gustak
-    Guido Wesdorp
     Daniel Roberts
-    Laura Creighton
+    Niko Matsakis
     Adrien Di Mascio
     Ludovic Aubry
-    Niko Matsakis
-    Wim Lavrijsen
-    Matti Picus
+    Alexander Hesse
+    Jacob Hallen
+    Romain Guillebert
     Jason Creighton
-    Jacob Hallen
     Alex Martelli
-    Anders Hammarquist
+    Michal Bendowski
     Jan de Mooij
+    Michael Foord
     Stephan Diehl
-    Michael Foord
     Stefan Schwarzer
+    Valentino Volonghi
     Tomek Meka
     Patrick Maupin
+    stian
     Bob Ippolito
     Bruno Gola
+    Jean-Paul Calderone
+    Timo Paulssen
     Alexandre Fayolle
+    Simon Burton
     Marius Gedminas
-    Simon Burton
-    David Edelsohn
-    Jean-Paul Calderone
     John Witulski
-    Timo Paulssen
-    holger krekel
+    Greg Price
     Dario Bertini
     Mark Pearse
+    Simon Cross
+    Konstantin Lopuhin
     Andreas Stührk
     Jean-Philippe St. Pierre
     Guido van Rossum
     Pavel Vinogradov
-    Valentino Volonghi
     Paul deGrandis
     Ilya Osadchiy
-    Ronny Pfannschmidt
     Adrian Kuhn
+    Boris Feigin
     tav
     Georg Brandl
-    Philip Jenvey
+    Bert Freudenberg
+    Stian Andreassen
+    Stefano Rivera
+    Wanja Saatkamp
     Gerald Klix
-    Wanja Saatkamp
-    Boris Feigin
+    Mike Blume
+    Taavi Burns
     Oscar Nierstrasz
     David Malcolm
     Eugene Oden
     Henry Mason
+    Preston Timmons
     Jeff Terrace
+    David Ripton
+    Dusty Phillips
     Lukas Renggli
     Guenter Jantzen
+    Tobias Oberstein
+    Remi Meier
     Ned Batchelder
-    Bert Freudenberg
     Amit Regmi
     Ben Young
     Nicolas Chauvat
     Andrew Durdin
     Michael Schneider
     Nicholas Riley
+    Jason Chu
+    Igor Trindade Oliveira
+    Jeremy Thurgood
     Rocco Moretti
     Gintautas Miliauskas
     Michael Twomey
-    Igor Trindade Oliveira
     Lucian Branescu Mihaila
+    Tim Felgentreff
+    Tyler Wade
+    Gabriel Lavoie
     Olivier Dormond
     Jared Grubb
     Karl Bartel
-    Gabriel Lavoie
+    Brian Dorsey
     Victor Stinner
-    Brian Dorsey
     Stuart Williams
+    Jasper Schulz
     Toby Watson
     Antoine Pitrou
+    Aaron Iles
+    Michael Cheng
     Justas Sadzevicius
+    Gasper Zejn
     Neil Shepperd
     Mikael Schönenberg
-    Gasper Zejn
+    Elmo Mäntynen
+    Tobias Pape
     Jonathan David Riehl
-    Elmo Mäntynen
+    Stanislaw Halik
     Anders Qvist
+    Chirag Jadwani
     Beatrice During
+    Alex Perry
+    Vincent Legoll
+    Alan McIntyre
     Alexander Sedov
     Corbin Simpson
-    Vincent Legoll
-    Romain Guillebert
-    Alan McIntyre
-    Alex Perry
+    Christopher Pope
+    Laurence Tratt
+    Guillebert Romain
+    Christian Tismer 
+    Dan Stromberg
+    Stefano Parmesan
+    Christian Hudon
+    Alexis Daboville
     Jens-Uwe Mager
-    Simon Cross
-    Dan Stromberg
-    Guillebert Romain
     Carl Meyer
+    Karl Ramm
     Pieter Zieschang
+    Gabriel
+    Paweł Piotr Przeradowski
+    Andrew Dalke
+    Sylvain Thenault
+    Nathan Taylor
+    Vladimir Kryachko
+    Jacek Generowicz
     Alejandro J. Cura
-    Sylvain Thenault
-    Christoph Gerum
+    Jacob Oscarson
     Travis Francis Athougies
+    Kristjan Valur Jonsson
+    Neil Blakey-Milner
+    Lutz Paelike
+    Lucio Torre
+    Lars Wassermann
     Henrik Vendelbo
-    Lutz Paelike
-    Jacob Oscarson
-    Martin Blais
-    Lucio Torre
-    Lene Wagner
+    Dan Buch
     Miguel de Val Borro
     Artur Lisiecki
-    Bruno Gola
+    Sergey Kishchenko
     Ignas Mikalajunas
-    Stefano Rivera
+    Christoph Gerum
+    Martin Blais
+    Lene Wagner
+    Tomo Cocoa
+    Andrews Medina
+    roberto at goyle
+    William Leslie
+    Bobby Impollonia
+    timo at eistee.fritz.box
+    Andrew Thompson
+    Yusei Tahara
+    Roberto De Ioris
+    Juan Francisco Cantero Hurtado
+    Godefroid Chappelle
     Joshua Gilbert
-    Godefroid Chappelle
-    Yusei Tahara
+    Dan Colish
     Christopher Armstrong
+    Michael Hudson-Doyle
+    Anders Sigfridsson
+    Yasir Suhail
+    Floris Bruynooghe
+    Akira Li
+    Gustavo Niemeyer
     Stephan Busemann
-    Gustavo Niemeyer
-    William Leslie
-    Akira Li
-    Kristjan Valur Jonsson
-    Bobby Impollonia
-    Michael Hudson-Doyle
-    Laurence Tratt
-    Yasir Suhail
-    Andrew Thompson
-    Anders Sigfridsson
-    Floris Bruynooghe
-    Jacek Generowicz
-    Dan Colish
-    Zooko Wilcox-O Hearn
-    Dan Loewenherz
+    Anna Katrina Dominguez
+    Christian Muirhead
+    James Lan
+    shoma hosaka
+    Daniel Neuhäuser
+    Buck Golemon
+    Konrad Delong
+    Dinu Gherman
     Chris Lambacher
-    Dinu Gherman
-    Brett Cannon
-    Daniel Neuhäuser
-    Michael Chermside
-    Konrad Delong
-    Anna Ravencroft
-    Greg Price
-    Armin Ronacher
-    Christian Muirhead
+    coolbutuseless at gmail.com
     Jim Baker
     Rodrigo Araújo
-    Romain Guillebert
+    Armin Ronacher
+    Brett Cannon
+    yrttyr
+    Zooko Wilcox-O Hearn
+    Tomer Chachamu
+    Christopher Groskopf
+    opassembler.py
+    Antony Lee
+    Jim Hunziker
+    Markus Unterwaditzer
+    Even Wiik Thomassen
+    jbs
+    soareschen
+    Flavio Percoco
+    Kristoffer Kleine
+    yasirs
+    Michael Chermside
+    Anna Ravencroft
+    Andrew Chambers
+    Julien Phalip
+    Dan Loewenherz
 
     Heinrich-Heine University, Germany 
     Open End AB (formerly AB Strakt), Sweden
@@ -218,45 +281,22 @@
     Impara, Germany
     Change Maker, Sweden 
     University of California Berkeley, USA
+    Google Inc.
+    King's College London
 
 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
 License.
  
-License for 'lib-python/2.7.0' and 'lib-python/2.7.0-modified'
-============================================================== 
+License for 'lib-python/2.7'
+============================
 
-Except when otherwise stated (look for LICENSE files or
-copyright/license information at the beginning of each file) the files
-in the 'lib-python/2.7.0' and 'lib-python/2.7.0-modified' directories
-are all copyrighted by the Python Software Foundation and licensed under
-the Python Software License of which you can find a copy here:
+Except when otherwise stated (look for LICENSE files or copyright/license
+information at the beginning of each file) the files in the 'lib-python/2.7'
+directory are all copyrighted by the Python Software Foundation and licensed
+under the Python Software License of which you can find a copy here:
 http://www.python.org/doc/Copyright.html 
 
-License for 'pypy/translator/jvm/src/jna.jar'
-=============================================
-
-The file 'pypy/translator/jvm/src/jna.jar' is licensed under the GNU
-Lesser General Public License of which you can find a copy here:
-http://www.gnu.org/licenses/lgpl.html
-
-License for 'pypy/translator/jvm/src/jasmin.jar'
-================================================
-
-The file 'pypy/translator/jvm/src/jasmin.jar' is copyright (c) 1996-2004 Jon Meyer
-and distributed with permission.  The use of Jasmin by PyPy does not imply
-that PyPy is endorsed by Jon Meyer nor any of Jasmin's contributors.  Furthermore,
-the following disclaimer applies to Jasmin:
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 License for 'pypy/module/unicodedata/'
 ======================================
 
diff --git a/lib-python/2.7/distutils/command/build_ext.py b/lib-python/2.7/distutils/command/build_ext.py
--- a/lib-python/2.7/distutils/command/build_ext.py
+++ b/lib-python/2.7/distutils/command/build_ext.py
@@ -8,7 +8,7 @@
 
 __revision__ = "$Id$"
 
-import sys, os, string, re
+import sys, os, string, re, imp
 from types import *
 from site import USER_BASE, USER_SITE
 from distutils.core import Command
@@ -33,6 +33,11 @@
     from distutils.ccompiler import show_compilers
     show_compilers()
 
+def _get_c_extension_suffix():
+    for ext, mod, typ in imp.get_suffixes():
+        if typ == imp.C_EXTENSION:
+            return ext
+
 
 class build_ext (Command):
 
@@ -677,10 +682,18 @@
         # OS/2 has an 8 character module (extension) limit :-(
         if os.name == "os2":
             ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8]
+        # PyPy tweak: first try to get the C extension suffix from
+        # 'imp'.  If it fails we fall back to the 'SO' config var, like
+        # the previous version of this code did.  This should work for
+        # CPython too.  The point is that on PyPy with cpyext, the
+        # config var 'SO' is just ".so" but we want to return
+        # ".pypy-VERSION.so" instead.
+        so_ext = _get_c_extension_suffix()
+        if so_ext is None:
+            so_ext = get_config_var('SO')     # fall-back
         # extensions in debug_mode are named 'module_d.pyd' under windows
-        so_ext = get_config_var('SO')
         if os.name == 'nt' and self.debug:
-            return os.path.join(*ext_path) + '_d' + so_ext
+            so_ext = '_d.pyd'
         return os.path.join(*ext_path) + so_ext
 
     def get_export_symbols (self, ext):
diff --git a/lib-python/2.7/distutils/command/install.py b/lib-python/2.7/distutils/command/install.py
--- a/lib-python/2.7/distutils/command/install.py
+++ b/lib-python/2.7/distutils/command/install.py
@@ -474,8 +474,8 @@
 
     def select_scheme (self, name):
         # it's the caller's problem if they supply a bad name!
-        if hasattr(sys, 'pypy_version_info') and not (
-                name.endswith('_user') or name.endswith('_home')):
+        if (hasattr(sys, 'pypy_version_info') and
+            not name.endswith(('_user', '_home'))):
             name = 'pypy'
         scheme = INSTALL_SCHEMES[name]
         for key in SCHEME_KEYS:
diff --git a/lib-python/2.7/distutils/sysconfig.py b/lib-python/2.7/distutils/sysconfig.py
--- a/lib-python/2.7/distutils/sysconfig.py
+++ b/lib-python/2.7/distutils/sysconfig.py
@@ -1,30 +1,16 @@
-"""Provide access to Python's configuration information.  The specific
-configuration variables available depend heavily on the platform and
-configuration.  The values may be retrieved using
-get_config_var(name), and the list of variables is available via
-get_config_vars().keys().  Additional convenience functions are also
-available.
-
-Written by:   Fred L. Drake, Jr.
-Email:        <fdrake at acm.org>
-"""
-
-__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $"
-
-import sys
-
 
 # The content of this file is redirected from
 # sysconfig_cpython or sysconfig_pypy.
+# All underscore names are imported too, because
+# people like to use undocumented sysconfig._xxx
+# directly.
 
+import sys
 if '__pypy__' in sys.builtin_module_names:
-    from distutils.sysconfig_pypy import *
-    from distutils.sysconfig_pypy import _config_vars # needed by setuptools
-    from distutils.sysconfig_pypy import _variable_rx # read_setup_file()
+    from distutils import sysconfig_pypy as _sysconfig_module
 else:
-    from distutils.sysconfig_cpython import *
-    from distutils.sysconfig_cpython import _config_vars # needed by setuptools
-    from distutils.sysconfig_cpython import _variable_rx # read_setup_file()
+    from distutils import sysconfig_cpython as _sysconfig_module
+globals().update(_sysconfig_module.__dict__)
 
 _USE_CLANG = None
 
diff --git a/lib-python/2.7/distutils/sysconfig_cpython.py b/lib-python/2.7/distutils/sysconfig_cpython.py
--- a/lib-python/2.7/distutils/sysconfig_cpython.py
+++ b/lib-python/2.7/distutils/sysconfig_cpython.py
@@ -9,7 +9,7 @@
 Email:        <fdrake at acm.org>
 """
 
-__revision__ = "$Id$"
+__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $"
 
 import os
 import re
diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py
--- a/lib-python/2.7/distutils/sysconfig_pypy.py
+++ b/lib-python/2.7/distutils/sysconfig_pypy.py
@@ -1,9 +1,18 @@
-"""PyPy's minimal configuration information.
+"""Provide access to Python's configuration information.
+This is actually PyPy's minimal configuration information.
+
+The specific configuration variables available depend heavily on the
+platform and configuration.  The values may be retrieved using
+get_config_var(name), and the list of variables is available via
+get_config_vars().keys().  Additional convenience functions are also
+available.
 """
 
+__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $"
+
 import sys
 import os
-import imp
+import shlex
 
 from distutils.errors import DistutilsPlatformError
 
@@ -49,16 +58,11 @@
 
 _config_vars = None
 
-def _get_so_extension():
-    for ext, mod, typ in imp.get_suffixes():
-        if typ == imp.C_EXTENSION:
-            return ext
-
 def _init_posix():
     """Initialize the module as appropriate for POSIX systems."""
     g = {}
     g['EXE'] = ""
-    g['SO'] = _get_so_extension() or ".so"
+    g['SO'] = ".so"
     g['SOABI'] = g['SO'].rsplit('.')[0]
     g['LIBDIR'] = os.path.join(sys.prefix, 'lib')
     g['CC'] = "gcc -pthread" # -pthread might not be valid on OS/X, check
@@ -71,7 +75,7 @@
     """Initialize the module as appropriate for NT"""
     g = {}
     g['EXE'] = ".exe"
-    g['SO'] = _get_so_extension() or ".pyd"
+    g['SO'] = ".pyd"
     g['SOABI'] = g['SO'].rsplit('.')[0]
 
     global _config_vars
@@ -119,13 +123,21 @@
     optional C speedup components.
     """
     if compiler.compiler_type == "unix":
-        compiler.compiler_so.extend(['-fPIC', '-Wimplicit'])
+        compiler.compiler_so.extend(['-O2', '-fPIC', '-Wimplicit'])
         compiler.shared_lib_extension = get_config_var('SO')
+        if "CPPFLAGS" in os.environ:
+            cppflags = shlex.split(os.environ["CPPFLAGS"])
+            compiler.compiler.extend(cppflags)
+            compiler.compiler_so.extend(cppflags)
+            compiler.linker_so.extend(cppflags)
         if "CFLAGS" in os.environ:
-            cflags = os.environ["CFLAGS"]
-            compiler.compiler.append(cflags)
-            compiler.compiler_so.append(cflags)
-            compiler.linker_so.append(cflags)
+            cflags = shlex.split(os.environ["CFLAGS"])
+            compiler.compiler.extend(cflags)
+            compiler.compiler_so.extend(cflags)
+            compiler.linker_so.extend(cflags)
+        if "LDFLAGS" in os.environ:
+            ldflags = shlex.split(os.environ["LDFLAGS"])
+            compiler.linker_so.extend(ldflags)
 
 
 from sysconfig_cpython import (
diff --git a/lib-python/2.7/json/__init__.py b/lib-python/2.7/json/__init__.py
--- a/lib-python/2.7/json/__init__.py
+++ b/lib-python/2.7/json/__init__.py
@@ -105,6 +105,12 @@
 
 __author__ = 'Bob Ippolito <bob at redivi.com>'
 
+try:
+    # PyPy speedup, the interface is different than CPython's _json
+    import _pypyjson
+except ImportError:
+    _pypyjson = None
+
 from .decoder import JSONDecoder
 from .encoder import JSONEncoder
 
@@ -241,7 +247,6 @@
 _default_decoder = JSONDecoder(encoding=None, object_hook=None,
                                object_pairs_hook=None)
 
-
 def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
         parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
     """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
@@ -323,7 +328,10 @@
     if (cls is None and encoding is None and object_hook is None and
             parse_int is None and parse_float is None and
             parse_constant is None and object_pairs_hook is None and not kw):
-        return _default_decoder.decode(s)
+        if _pypyjson and not isinstance(s, unicode):
+            return _pypyjson.loads(s)
+        else:
+            return _default_decoder.decode(s)
     if cls is None:
         cls = JSONDecoder
     if object_hook is not None:
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,21 +134,30 @@
 DEBUG = 10
 NOTSET = 0
 
-_levelNames = {
-    CRITICAL : 'CRITICAL',
-    ERROR : 'ERROR',
-    WARNING : 'WARNING',
-    INFO : 'INFO',
-    DEBUG : 'DEBUG',
-    NOTSET : 'NOTSET',
-    'CRITICAL' : CRITICAL,
-    'ERROR' : ERROR,
-    'WARN' : WARNING,
-    'WARNING' : WARNING,
-    'INFO' : INFO,
-    'DEBUG' : DEBUG,
-    'NOTSET' : NOTSET,
+# 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',
+    WARNING: 'WARNING',
+    INFO: 'INFO',
+    DEBUG: 'DEBUG',
+    NOTSET: 'NOTSET',
 }
+_nameToLevel = {
+    'CRITICAL': CRITICAL,
+    'ERROR': ERROR,
+    'WARN': WARNING,
+    'WARNING': WARNING,
+    'INFO': INFO,
+    'DEBUG': DEBUG,
+    'NOTSET': NOTSET,
+}
+_levelNames = dict(_levelToName)
+_levelNames.update(_nameToLevel)   # backward compatibility
 
 def getLevelName(level):
     """
@@ -164,7 +173,11 @@
 
     Otherwise, the string "Level %s" % level is returned.
     """
-    return _levelNames.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):
     """
@@ -174,8 +187,8 @@
     """
     _acquireLock()
     try:    #unlikely to cause an exception, but you never know...
-        _levelNames[level] = levelName
-        _levelNames[levelName] = level
+        _levelToName[level] = levelName
+        _nameToLevel[levelName] = level
     finally:
         _releaseLock()
 
@@ -183,9 +196,9 @@
     if isinstance(level, int):
         rv = level
     elif str(level) == level:
-        if level not in _levelNames:
+        if level not in _nameToLevel:
             raise ValueError("Unknown level: %r" % level)
-        rv = _levelNames[level]
+        rv = _nameToLevel[level]
     else:
         raise TypeError("Level not an integer or a valid string: %r" % level)
     return rv
@@ -277,7 +290,7 @@
         self.lineno = lineno
         self.funcName = func
         self.created = ct
-        self.msecs = (ct - long(ct)) * 1000
+        self.msecs = (ct - int(ct)) * 1000
         self.relativeCreated = (self.created - _startTime) * 1000
         if logThreads and thread:
             self.thread = thread.get_ident()
diff --git a/lib-python/2.7/logging/config.py b/lib-python/2.7/logging/config.py
--- a/lib-python/2.7/logging/config.py
+++ b/lib-python/2.7/logging/config.py
@@ -156,7 +156,7 @@
         h = klass(*args)
         if "level" in opts:
             level = cp.get(sectname, "level")
-            h.setLevel(logging._levelNames[level])
+            h.setLevel(level)
         if len(fmt):
             h.setFormatter(formatters[fmt])
         if issubclass(klass, logging.handlers.MemoryHandler):
@@ -187,7 +187,7 @@
     opts = cp.options(sectname)
     if "level" in opts:
         level = cp.get(sectname, "level")
-        log.setLevel(logging._levelNames[level])
+        log.setLevel(level)
     for h in root.handlers[:]:
         root.removeHandler(h)
     hlist = cp.get(sectname, "handlers")
@@ -237,7 +237,7 @@
             existing.remove(qn)
         if "level" in opts:
             level = cp.get(sectname, "level")
-            logger.setLevel(logging._levelNames[level])
+            logger.setLevel(level)
         for h in logger.handlers[:]:
             logger.removeHandler(h)
         logger.propagate = propagate
diff --git a/lib-python/2.7/opcode.py b/lib-python/2.7/opcode.py
--- a/lib-python/2.7/opcode.py
+++ b/lib-python/2.7/opcode.py
@@ -193,5 +193,6 @@
 hasname.append(201)
 def_op('CALL_METHOD', 202)            # #args not including 'self'
 def_op('BUILD_LIST_FROM_ARG', 203)
+jrel_op('JUMP_IF_NOT_DEBUG', 204)     # jump over assert statements
 
 del def_op, name_op, jrel_op, jabs_op
diff --git a/lib-python/2.7/pydoc.py b/lib-python/2.7/pydoc.py
--- a/lib-python/2.7/pydoc.py
+++ b/lib-python/2.7/pydoc.py
@@ -1953,7 +1953,11 @@
                 if key is None:
                     callback(None, modname, '')
                 else:
-                    desc = split(__import__(modname).__doc__ or '', '\n')[0]
+                    try:
+                        module_doc = __import__(modname).__doc__
+                    except ImportError:
+                        module_doc = None
+                    desc = split(module_doc or '', '\n')[0]
                     if find(lower(modname + ' - ' + desc), key) >= 0:
                         callback(None, modname, desc)
 
diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py
--- a/lib-python/2.7/socket.py
+++ b/lib-python/2.7/socket.py
@@ -96,6 +96,7 @@
 
 
 _realsocket = socket
+_type = type
 
 # WSA error codes
 if sys.platform.lower().startswith("win"):
@@ -173,31 +174,37 @@
 
     __doc__ = _realsocket.__doc__
 
+    __slots__ = ["_sock", "__weakref__"]
+
     def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
         if _sock is None:
             _sock = _realsocket(family, type, proto)
+        elif _type(_sock) is _realsocket:
+            _sock._reuse()
+        # PyPy note about refcounting: implemented with _reuse()/_drop()
+        # on the class '_socket.socket'.  Python 3 did it differently
+        # with a reference counter on this class 'socket._socketobject'
+        # instead, but it is a less compatible change (breaks eventlet).
         self._sock = _sock
-        self._io_refs = 0
-        self._closed = False
 
     def send(self, data, flags=0):
-        return self._sock.send(data, flags=flags)
+        return self._sock.send(data, flags)
     send.__doc__ = _realsocket.send.__doc__
 
     def recv(self, buffersize, flags=0):
-        return self._sock.recv(buffersize, flags=flags)
+        return self._sock.recv(buffersize, flags)
     recv.__doc__ = _realsocket.recv.__doc__
 
     def recv_into(self, buffer, nbytes=0, flags=0):
-        return self._sock.recv_into(buffer, nbytes=nbytes, flags=flags)
+        return self._sock.recv_into(buffer, nbytes, flags)
     recv_into.__doc__ = _realsocket.recv_into.__doc__
 
     def recvfrom(self, buffersize, flags=0):
-        return self._sock.recvfrom(buffersize, flags=flags)
+        return self._sock.recvfrom(buffersize, flags)
     recvfrom.__doc__ = _realsocket.recvfrom.__doc__
 
     def recvfrom_into(self, buffer, nbytes=0, flags=0):
-        return self._sock.recvfrom_into(buffer, nbytes=nbytes, flags=flags)
+        return self._sock.recvfrom_into(buffer, nbytes, flags)
     recvfrom_into.__doc__ = _realsocket.recvfrom_into.__doc__
 
     def sendto(self, data, param2, param3=None):
@@ -208,13 +215,17 @@
     sendto.__doc__ = _realsocket.sendto.__doc__
 
     def close(self):
-        # This function should not reference any globals. See issue #808164.
+        s = self._sock
+        if type(s) is _realsocket:
+            s._drop()
         self._sock = _closedsocket()
     close.__doc__ = _realsocket.close.__doc__
 
     def accept(self):
         sock, addr = self._sock.accept()
-        return _socketobject(_sock=sock), addr
+        sockobj = _socketobject(_sock=sock)
+        sock._drop()    # already a copy in the _socketobject()
+        return sockobj, addr
     accept.__doc__ = _realsocket.accept.__doc__
 
     def dup(self):
@@ -228,24 +239,7 @@
 
         Return a regular file object corresponding to the socket.  The mode
         and bufsize arguments are as for the built-in open() function."""
-        self._io_refs += 1
-        return _fileobject(self, mode, bufsize)
-
-    def _decref_socketios(self):
-        if self._io_refs > 0:
-            self._io_refs -= 1
-        if self._closed:
-            self.close()
-
-    def _real_close(self):
-        # This function should not reference any globals. See issue #808164.
-        self._sock.close()
-
-    def close(self):
-        # This function should not reference any globals. See issue #808164.
-        self._closed = True
-        if self._io_refs <= 0:
-            self._real_close()
+        return _fileobject(self._sock, mode, bufsize)
 
     family = property(lambda self: self._sock.family, doc="the socket family")
     type = property(lambda self: self._sock.type, doc="the socket type")
@@ -286,6 +280,8 @@
                  "_close"]
 
     def __init__(self, sock, mode='rb', bufsize=-1, close=False):
+        if type(sock) is _realsocket:
+            sock._reuse()
         self._sock = sock
         self.mode = mode # Not actually used in this version
         if bufsize < 0:
@@ -320,11 +316,11 @@
             if self._sock:
                 self.flush()
         finally:
-            if self._sock:
-                if self._close:
-                    self._sock.close()
-                else:
-                    self._sock._decref_socketios()
+            s = self._sock
+            if type(s) is _realsocket:
+                s._drop()
+            if self._close:
+                self._sock.close()
             self._sock = None
 
     def __del__(self):
diff --git a/lib-python/2.7/test/test_code.py b/lib-python/2.7/test/test_code.py
--- a/lib-python/2.7/test/test_code.py
+++ b/lib-python/2.7/test/test_code.py
@@ -75,7 +75,7 @@
 cellvars: ()
 freevars: ()
 nlocals: 0
-flags: 67
+flags: 1048643
 consts: ("'doc string'", 'None')
 
 """
diff --git a/lib-python/2.7/test/test_codecs.py b/lib-python/2.7/test/test_codecs.py
--- a/lib-python/2.7/test/test_codecs.py
+++ b/lib-python/2.7/test/test_codecs.py
@@ -2,7 +2,11 @@
 import unittest
 import codecs
 import locale
-import sys, StringIO, _testcapi
+import sys, StringIO
+try:
+    import _testcapi
+except ImportError:
+    _testcapi = None
 
 class Queue(object):
     """
@@ -1387,7 +1391,7 @@
                     decodedresult += reader.read()
                 self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding))
 
-            if encoding not in broken_incremental_coders:
+            if encoding not in broken_incremental_coders and _testcapi:
                 # check incremental decoder/encoder (fetched via the Python
                 # and C API) and iterencode()/iterdecode()
                 try:
diff --git a/lib-python/2.7/test/test_dis.py b/lib-python/2.7/test/test_dis.py
--- a/lib-python/2.7/test/test_dis.py
+++ b/lib-python/2.7/test/test_dis.py
@@ -53,25 +53,26 @@
     pass
 
 dis_bug1333982 = """\
- %-4d         0 LOAD_CONST               1 (0)
-              3 POP_JUMP_IF_TRUE        41
-              6 LOAD_GLOBAL              0 (AssertionError)
-              9 LOAD_FAST                0 (x)
-             12 BUILD_LIST_FROM_ARG      0
-             15 GET_ITER
-        >>   16 FOR_ITER                12 (to 31)
-             19 STORE_FAST               1 (s)
-             22 LOAD_FAST                1 (s)
-             25 LIST_APPEND              2
-             28 JUMP_ABSOLUTE           16
+ %-4d         0 JUMP_IF_NOT_DEBUG       41 (to 44)
+              3 LOAD_CONST               1 (0)
+              6 POP_JUMP_IF_TRUE        44
+              9 LOAD_GLOBAL              0 (AssertionError)
+             12 LOAD_FAST                0 (x)
+             15 BUILD_LIST_FROM_ARG      0
+             18 GET_ITER
+        >>   19 FOR_ITER                12 (to 34)
+             22 STORE_FAST               1 (s)
+             25 LOAD_FAST                1 (s)
+             28 LIST_APPEND              2
+             31 JUMP_ABSOLUTE           19
 
- %-4d   >>   31 LOAD_CONST               2 (1)
-             34 BINARY_ADD
-             35 CALL_FUNCTION            1
-             38 RAISE_VARARGS            1
+ %-4d   >>   34 LOAD_CONST               2 (1)
+             37 BINARY_ADD
+             38 CALL_FUNCTION            1
+             41 RAISE_VARARGS            1
 
- %-4d   >>   41 LOAD_CONST               0 (None)
-             44 RETURN_VALUE
+ %-4d   >>   44 LOAD_CONST               0 (None)
+             47 RETURN_VALUE
 """%(bug1333982.func_code.co_firstlineno + 1,
      bug1333982.func_code.co_firstlineno + 2,
      bug1333982.func_code.co_firstlineno + 3)
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
@@ -65,7 +65,8 @@
             self.saved_handlers = logging._handlers.copy()
             self.saved_handler_list = logging._handlerList[:]
             self.saved_loggers = logger_dict.copy()
-            self.saved_level_names = logging._levelNames.copy()
+            self.saved_name_to_level = logging._nameToLevel.copy()
+            self.saved_level_to_name = logging._levelToName.copy()
         finally:
             logging._releaseLock()
 
@@ -97,8 +98,10 @@
         self.root_logger.setLevel(self.original_logging_level)
         logging._acquireLock()
         try:
-            logging._levelNames.clear()
-            logging._levelNames.update(self.saved_level_names)
+            logging._levelToName.clear()
+            logging._levelToName.update(self.saved_level_to_name)
+            logging._nameToLevel.clear()
+            logging._nameToLevel.update(self.saved_name_to_level)
             logging._handlers.clear()
             logging._handlers.update(self.saved_handlers)
             logging._handlerList[:] = self.saved_handler_list
@@ -275,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/2.7/test/test_os.py b/lib-python/2.7/test/test_os.py
--- a/lib-python/2.7/test/test_os.py
+++ b/lib-python/2.7/test/test_os.py
@@ -275,7 +275,7 @@
         try:
             result.f_bfree = 1
             self.fail("No exception thrown")
-        except TypeError:
+        except (TypeError, AttributeError):
             pass
 
         try:
diff --git a/lib-python/2.7/test/test_sysconfig.py b/lib-python/2.7/test/test_sysconfig.py
--- a/lib-python/2.7/test/test_sysconfig.py
+++ b/lib-python/2.7/test/test_sysconfig.py
@@ -7,7 +7,8 @@
 import subprocess
 from copy import copy, deepcopy
 
-from test.test_support import run_unittest, TESTFN, unlink, get_attribute
+from test.test_support import (run_unittest, TESTFN, unlink, get_attribute,
+                               import_module)
 
 import sysconfig
 from sysconfig import (get_paths, get_platform, get_config_vars,
@@ -236,7 +237,10 @@
 
     def test_get_config_h_filename(self):
         config_h = sysconfig.get_config_h_filename()
-        self.assertTrue(os.path.isfile(config_h), config_h)
+        # import_module skips the test when the CPython C Extension API
+        # appears to not be supported
+        self.assertTrue(os.path.isfile(config_h) or
+                        not import_module('_testcapi'), config_h)
 
     def test_get_scheme_names(self):
         wanted = ('nt', 'nt_user', 'os2', 'os2_home', 'osx_framework_user',
diff --git a/lib-python/2.7/test/test_traceback.py b/lib-python/2.7/test/test_traceback.py
--- a/lib-python/2.7/test/test_traceback.py
+++ b/lib-python/2.7/test/test_traceback.py
@@ -1,6 +1,9 @@
 """Test cases for traceback module"""
 
-from _testcapi import traceback_print
+try:
+    from _testcapi import traceback_print
+except ImportError:
+    traceback_print = None
 from StringIO import StringIO
 import sys
 import unittest
@@ -176,6 +179,8 @@
 class TracebackFormatTests(unittest.TestCase):
 
     def test_traceback_format(self):
+        if traceback_print is None:
+            raise unittest.SkipTest('Requires _testcapi')
         try:
             raise KeyError('blah')
         except KeyError:
diff --git a/lib-python/2.7/test/test_unicode.py b/lib-python/2.7/test/test_unicode.py
--- a/lib-python/2.7/test/test_unicode.py
+++ b/lib-python/2.7/test/test_unicode.py
@@ -1609,7 +1609,10 @@
         self.assertEqual("{}".format(u), '__unicode__ overridden')
 
     def test_encode_decimal(self):
-        from _testcapi import unicode_encodedecimal
+        try:
+            from _testcapi import unicode_encodedecimal
+        except ImportError:
+            raise unittest.SkipTest('Requires _testcapi')
         self.assertEqual(unicode_encodedecimal(u'123'),
                          b'123')
         self.assertEqual(unicode_encodedecimal(u'\u0663.\u0661\u0664'),
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -130,7 +130,7 @@
     RegrTest('test_bz2.py', usemodules='bz2'),
     RegrTest('test_calendar.py'),
     RegrTest('test_call.py', core=True),
-    RegrTest('test_capi.py'),
+    RegrTest('test_capi.py', usemodules='cpyext'),
     RegrTest('test_cd.py'),
     RegrTest('test_cfgparser.py'),
     RegrTest('test_cgi.py'),
@@ -177,7 +177,7 @@
     RegrTest('test_cprofile.py'),
     RegrTest('test_crypt.py', usemodules='crypt'),
     RegrTest('test_csv.py', usemodules='_csv'),
-    RegrTest('test_ctypes.py', usemodules="_rawffi thread"),
+    RegrTest('test_ctypes.py', usemodules="_rawffi thread cpyext"),
     RegrTest('test_curses.py'),
     RegrTest('test_datetime.py', usemodules='binascii struct'),
     RegrTest('test_dbm.py'),
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -120,6 +120,7 @@
         return self._buffer[0] != 0
 
     contents = property(getcontents, setcontents)
+    _obj = property(getcontents) # byref interface
 
     def _as_ffi_pointer_(self, ffitype):
         return as_ffi_pointer(self, ffitype)
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__)
 
@@ -166,9 +166,7 @@
         if self is StructOrUnion:
             return
         if '_fields_' not in self.__dict__:
-            self._fields_ = []
-            self._names = []
-            _set_shape(self, [], self._is_union)
+            self._fields_ = []  # As a side-effet, this also sets the ffishape.
 
     __setattr__ = struct_setattr
 
diff --git a/lib_pypy/_ctypes_test.py b/lib_pypy/_ctypes_test.py
--- a/lib_pypy/_ctypes_test.py
+++ b/lib_pypy/_ctypes_test.py
@@ -1,60 +1,7 @@
-import os, sys
-import tempfile
-
-def compile_shared():
-    """Compile '_ctypes_test.c' into an extension module, and import it
-    """
-    thisdir = os.path.dirname(__file__)
-    output_dir = tempfile.mkdtemp()
-
-    from distutils.ccompiler import new_compiler
-    from distutils import sysconfig
-
-    compiler = new_compiler()
-    compiler.output_dir = output_dir
-
-    # Compile .c file
-    include_dir = os.path.join(thisdir, '..', 'include')
-    if sys.platform == 'win32':
-        ccflags = ['-D_CRT_SECURE_NO_WARNINGS']
-    else:
-        ccflags = ['-fPIC', '-Wimplicit-function-declaration']
-    res = compiler.compile([os.path.join(thisdir, '_ctypes_test.c')],
-                           include_dirs=[include_dir],
-                           extra_preargs=ccflags)
-    object_filename = res[0]
-
-    # set link options
-    output_filename = '_ctypes_test' + sysconfig.get_config_var('SO')
-    if sys.platform == 'win32':
-        # XXX libpypy-c.lib is currently not installed automatically
-        library = os.path.join(thisdir, '..', 'include', 'libpypy-c')
-        if not os.path.exists(library + '.lib'):
-            #For a nightly build
-            library = os.path.join(thisdir, '..', 'include', 'python27')
-        if not os.path.exists(library + '.lib'):
-            # For a local translation
-            library = os.path.join(thisdir, '..', 'pypy', 'goal', 'libpypy-c')
-        libraries = [library, 'oleaut32']
-        extra_ldargs = ['/MANIFEST',  # needed for VC10
-                        '/EXPORT:init_ctypes_test']
-    else:
-        libraries = []
-        extra_ldargs = []
-
-    # link the dynamic library
-    compiler.link_shared_object(
-        [object_filename],
-        output_filename,
-        libraries=libraries,
-        extra_preargs=extra_ldargs)
-
-    # Now import the newly created library, it will replace our module in sys.modules
-    import imp
-    fp, filename, description = imp.find_module('_ctypes_test', path=[output_dir])
-    imp.load_module('_ctypes_test', fp, filename, description)
-
-
+try:
+    import cpyext
+except ImportError:
+    raise ImportError("No module named '_ctypes_test'")
 try:
     import _ctypes
     _ctypes.PyObj_FromPtr = None
@@ -62,4 +9,5 @@
 except ImportError:
     pass    # obscure condition of _ctypes_test.py being imported by py.test
 else:
-    compile_shared()
+    import _pypy_testcapi
+    _pypy_testcapi.compile_shared('_ctypes_test.c', '_ctypes_test')
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)
@@ -953,7 +966,7 @@
     r, g, b = ffi.new("short *"), ffi.new("short *"), ffi.new("short *")
     if lib.color_content(color, r, g, b) == lib.ERR:
         raise error("Argument 1 was out of range. Check value of COLORS.")
-    return (r, g, b)
+    return (r[0], g[0], b[0])
 
 
 def color_pair(n):
@@ -1108,6 +1121,7 @@
         term = ffi.NULL
     err = ffi.new("int *")
     if lib.setupterm(term, fd, err) == lib.ERR:
+        err = err[0]
         if err == 0:
             raise error("setupterm: could not find terminal")
         elif err == -1:
@@ -1197,6 +1211,7 @@
 
 
 def putp(text):
+    text = _texttype(text)
     return _check_ERR(lib.putp(text), "putp")
 
 
diff --git a/lib_pypy/_pypy_irc_topic.py b/lib_pypy/_pypy_irc_topic.py
--- a/lib_pypy/_pypy_irc_topic.py
+++ b/lib_pypy/_pypy_irc_topic.py
@@ -1,4 +1,4 @@
-"""eclguba: flagnk naq frznagvpf bs clguba, fcrrq bs p, erfgevpgvbaf bs wnin naq pbzcvyre reebe zrffntrf nf crargenoyr nf ZHZCF
+__doc__ = """eclguba: flagnk naq frznagvpf bs clguba, fcrrq bs p, erfgevpgvbaf bs wnin naq pbzcvyre reebe zrffntrf nf crargenoyr nf ZHZCF
 pglcrf unf n fcva bs 1/3
 ' ' vf n fcnpr gbb
 Clguba 2.k rfg cerfdhr zbeg, ivir Clguba!
@@ -165,6 +165,63 @@
 Nyy rkprcgoybpxf frrz fnar.
 N cvax tyvggrel ebgngvat ynzoqn
 "vg'f yvxryl grzcbenel hagvy sberire" nevtb
+"Lbh xabj jung'f avpr nobhg EClguba?  Ybatre fjbeq svtugf."
+nccneragyl pbashfvba vf n srngher
+nccneragyl pbashfvba vf n srngher... be vf vg?
+ClCl 1.7 eryrnfrq
+vs lbh jnag gb or penml, lbh qba'g unir gb sbepr vg
+vs lbh jnag vg gb or iveghny, lbh fubhyq abg sbepr vg
+<Nyrk_Tnlabe> svwny: V whfg... fgnegrq pbqvat naq fhqqragyl... nobzvangvba
+fabj, fabj! :-)
+fabj, fabj, fabj, fabj
+clcl 1.8 eryrnfrq
+vg jnf srj lnxf gbb yngr
+ClCl vf n enpr orgjrra hf funivat lnxf, naq gur havirefr gelvat gb cebqhpr zber naq zber lnxf
+Jevgvat na SC7 nabalzbhf cebcbfny sbe ClCl vf yvxr znxvat n gi nq sbe n uvtu cresbeznapr fcbegf pne jvgubhg orvat noyr gb zragvba vgf zbqry be znahsnpghere
+Fabj, fabj (ntnva)
+Fgvyy fabjvat
+thrff jung, fabj
+"lbh haqrerfgvzngr gur vzcbegnapr bs zvpebnepuvgrpgher" "ab, vg'f zber gung jr ner fgvyy unccvyl va gur ynaq bs ernpunoyr sehvg"
+Jub nz V?  Naq vs lrf, ubj znal?
+ClCl vf nyjnlf n cynfzn
+"genafyngvba gbbypunva" = "EClgure"?  gb jevgr vagrEClguref va
+"sberire" va clcl grezf zrnaf yvxr srj zbaguf :)
+"Onu.  PClguba bofphevgl. - Nezva Evtb"
+svwny: pna V vavgvngr lbh ba gur (rnfl ohg) aba-gevivny gbcvp bs jevgvat P shapgvba glcrf? :-)
+nyy fbsgjner vzcebirzragf unccra ol n ovg
+gur genprf qba'g yvr
+:-) be engure ":-/" bss-ol-bar-xrl reebe
+Be Nezva Evtb. V guvax ur'f noyr gb haqrefgnaq k86 gur jnl Plcure pna frr jbzra va gur zngevk.
+V zvtug, ohg abobql erfcrpgf zr
+cerohvyg vafgnapr Ryyvcfvf unf ab nggevohgr 'reeab'
+guvf frnfba'f svefg "fabj! fabj!" vf urer
+ClCl 2.0 orgn1 eryrnfrq - orggre yngr guna arire
+Fjvgreynaq 2012: zber fabj va Qrprzore guna rire fvapr clcl fgnegrq
+Fjvgmreynaq 2012: zber fabj va Qrprzore guna rire fvapr clcl fgnegrq
+<nevtngb> n sngny reebe, ol qrsvavgvba, vf sngny
+<nagbphav> V'z tynq gung jr cebtenz va Clguba naq jr qba'g qrny jvgu gubfr vffhrf rirel qnl. Ncneg gur snpg gung jr unir gb qrny jvgu gurz naljnl, vg frrzf
+unccl arj lrne!
+"zrffl" vf abg n whqtrzrag, ohg whfg n snpg bs pbzcyvpngrqarff
+n ybg bs fabj
+qb lbh xabj nobhg n gbnfgre jvgu 8XO bs ENZ naq 64XO bs EBZ?
+vg'f orra fabjvat rirelqnl sbe n juvyr, V pna'g whfg chg "fabj, fabj" hc urer rirel qnl
+fabjonyy svtugf!
+sbejneq pbzcngvovyvgl jvgu bcgvzvmngvbaf gung unira'g orra vairagrq lrg
+jr fgvyy unir gb jevgr fbsgjner jvgu n zrgnfcnpr ohooyr va vg
+cebonoyl gur ynfg gvzr va gur frnfba, ohg: fabj, fabj!
+ClCl 2.0-orgn2 eryrnfrq
+Gur ceboyrz vf gung sbe nyzbfg nal aba-gevivny cebtenz, vg'f abg pyrne jung 'pbeerpg' zrnaf.
+ClCl 2.0 nyzbfg eryrnfrq
+ClCl 2.0 eryrnfrq
+WVG pbzcvyref fubhyq or jevggra ol crbcyr jub npghnyyl unir snvgu va WVG pbzcvyref' novyvgl gb znxrf guvatf tb fpernzvat snfg
+ClCl 2.0.1 eryrnfrq
+arire haqrerfgvzngr gur vzcebonoyr jura lbh qb fbzrguvat ng 2TUm
+ClCl 2.0.2 eryrnfrq
+nyy jr arrq vf n angvir Cebybt znpuvar
+V haqrefgnaq ubj qravnyvfz vf n onq qrohttvat grpuavdhr
+rirel IZ fubhyq pbzr jvgu arheny argjbex genvarq gb erpbtavmr zvpeborapuznexf naq enaqbzyl syhpghngr gurz +/-9000%
+lbh qvq abg nccebnpu clcl sebz gur rnfl raq: fgz, gura wvg. vg'f n ovg gur Abegu snpr
+va ClCl orvat bayl zbqrengryl zntvp vf n tbbq guvat <psobym>
 """
 
 from string import ascii_uppercase, ascii_lowercase
diff --git a/lib_pypy/_testcapi.py b/lib_pypy/_pypy_testcapi.py
copy from lib_pypy/_testcapi.py
copy to lib_pypy/_pypy_testcapi.py
--- a/lib_pypy/_testcapi.py
+++ b/lib_pypy/_pypy_testcapi.py
@@ -1,14 +1,20 @@
-import os, sys
+import os, sys, imp
 import tempfile
 
-def compile_shared():
-    """Compile '_testcapi.c' into an extension module, and import it
+def _get_c_extension_suffix():
+    for ext, mod, typ in imp.get_suffixes():
+        if typ == imp.C_EXTENSION:
+            return ext
+
+
+def compile_shared(csource, modulename):
+    """Compile '_testcapi.c' or '_ctypes_test.c' into an extension module,
+    and import it.
     """
     thisdir = os.path.dirname(__file__)
     output_dir = tempfile.mkdtemp()
 
     from distutils.ccompiler import new_compiler
-    from distutils import sysconfig
 
     compiler = new_compiler()
     compiler.output_dir = output_dir
@@ -19,13 +25,13 @@
         ccflags = ['-D_CRT_SECURE_NO_WARNINGS']
     else:
         ccflags = ['-fPIC', '-Wimplicit-function-declaration']
-    res = compiler.compile([os.path.join(thisdir, '_testcapimodule.c')],
+    res = compiler.compile([os.path.join(thisdir, csource)],
                            include_dirs=[include_dir],
                            extra_preargs=ccflags)
     object_filename = res[0]
 
     # set link options
-    output_filename = '_testcapi' + sysconfig.get_config_var('SO')
+    output_filename = modulename + _get_c_extension_suffix()
     if sys.platform == 'win32':
         # XXX libpypy-c.lib is currently not installed automatically
         library = os.path.join(thisdir, '..', 'include', 'libpypy-c')
@@ -37,7 +43,7 @@
             library = os.path.join(thisdir, '..', 'pypy', 'goal', 'libpypy-c')
         libraries = [library, 'oleaut32']
         extra_ldargs = ['/MANIFEST',  # needed for VC10
-                        '/EXPORT:init_testcapi']
+                        '/EXPORT:init' + modulename]
     else:
         libraries = []
         extra_ldargs = []
@@ -49,9 +55,7 @@
         libraries=libraries,
         extra_preargs=extra_ldargs)
 
-    # Now import the newly created library, it will replace our module in sys.modules
-    import imp
-    fp, filename, description = imp.find_module('_testcapi', path=[output_dir])
-    imp.load_module('_testcapi', fp, filename, description)
-
-compile_shared()
+    # Now import the newly created library, it will replace the original
+    # module in sys.modules
+    fp, filename, description = imp.find_module(modulename, path=[output_dir])
+    imp.load_module(modulename, fp, filename, description)
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -1305,7 +1305,7 @@
         for i in xrange(_lib.sqlite3_column_count(self._statement)):
             name = _lib.sqlite3_column_name(self._statement, i)
             if name:
-                name = _ffi.string(name).decode('utf-8').split("[")[0].strip()
+                name = _ffi.string(name).split("[")[0].strip()
             desc.append((name, None, None, None, None, None, None))
         return desc
 
diff --git a/lib_pypy/_testcapi.py b/lib_pypy/_testcapi.py
--- a/lib_pypy/_testcapi.py
+++ b/lib_pypy/_testcapi.py
@@ -1,57 +1,7 @@
-import os, sys
-import tempfile
-
-def compile_shared():
-    """Compile '_testcapi.c' into an extension module, and import it
-    """
-    thisdir = os.path.dirname(__file__)
-    output_dir = tempfile.mkdtemp()
-
-    from distutils.ccompiler import new_compiler
-    from distutils import sysconfig
-
-    compiler = new_compiler()
-    compiler.output_dir = output_dir
-
-    # Compile .c file
-    include_dir = os.path.join(thisdir, '..', 'include')
-    if sys.platform == 'win32':
-        ccflags = ['-D_CRT_SECURE_NO_WARNINGS']
-    else:
-        ccflags = ['-fPIC', '-Wimplicit-function-declaration']
-    res = compiler.compile([os.path.join(thisdir, '_testcapimodule.c')],
-                           include_dirs=[include_dir],
-                           extra_preargs=ccflags)
-    object_filename = res[0]
-
-    # set link options
-    output_filename = '_testcapi' + sysconfig.get_config_var('SO')
-    if sys.platform == 'win32':
-        # XXX libpypy-c.lib is currently not installed automatically
-        library = os.path.join(thisdir, '..', 'include', 'libpypy-c')
-        if not os.path.exists(library + '.lib'):
-            #For a nightly build
-            library = os.path.join(thisdir, '..', 'include', 'python27')
-        if not os.path.exists(library + '.lib'):
-            # For a local translation
-            library = os.path.join(thisdir, '..', 'pypy', 'goal', 'libpypy-c')
-        libraries = [library, 'oleaut32']
-        extra_ldargs = ['/MANIFEST',  # needed for VC10
-                        '/EXPORT:init_testcapi']
-    else:
-        libraries = []
-        extra_ldargs = []
-
-    # link the dynamic library
-    compiler.link_shared_object(
-        [object_filename],
-        output_filename,
-        libraries=libraries,
-        extra_preargs=extra_ldargs)
-
-    # Now import the newly created library, it will replace our module in sys.modules
-    import imp
-    fp, filename, description = imp.find_module('_testcapi', path=[output_dir])
-    imp.load_module('_testcapi', fp, filename, description)
-
-compile_shared()
+try:
+    import cpyext
+except ImportError:
+    raise ImportError("No module named '_testcapi'")
+else:
+    import _pypy_testcapi
+    _pypy_testcapi.compile_shared('_testcapimodule.c', '_testcapi')
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


More information about the pypy-commit mailing list