Author: Brian Kearns <bdkea...@gmail.com>
Branch: use-file-star-for-file
Changeset: r73371:224dfb42e83d
Date: 2014-09-07 18:42 -0400
http://bitbucket.org/pypy/pypy/changeset/224dfb42e83d/

Log:    merge default

diff too long, truncating to 2000 out of 5130 lines

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -35,280 +35,290 @@
 the beginning of each file) the files in the 'pypy' directory are each
 copyrighted by one or more of the following people and organizations:    
 
-    Armin Rigo
-    Maciej Fijalkowski
-    Carl Friedrich Bolz
-    Antonio Cuni
-    Amaury Forgeot d'Arc
-    Samuele Pedroni
-    Alex Gaynor
-    Michael Hudson
-    David Schneider
-    Matti Picus
-    Brian Kearns
-    Philip Jenvey
-    Holger Krekel
-    Christian Tismer
-    Hakan Ardo
-    Benjamin Peterson
-    Manuel Jacob
-    Anders Chrigstrom
-    Eric van Riet Paap
-    Wim Lavrijsen
-    Ronan Lamy
-    Richard Emslie
-    Alexander Schremmer
-    Dan Villiom Podlaski Christiansen
-    Lukas Diekmann
-    Sven Hager
-    Anders Lehmann
-    Aurelien Campeas
-    Niklaus Haldimann
-    Camillo Bruni
-    Laura Creighton
-    Toon Verwaest
-    Remi Meier
-    Leonardo Santagada
-    Seo Sanghyeon
-    Romain Guillebert
-    Justin Peel
-    Ronny Pfannschmidt
-    David Edelsohn
-    Anders Hammarquist
-    Jakub Gustak
-    Guido Wesdorp
-    Lawrence Oluyede
-    Bartosz Skowron
-    Daniel Roberts
-    Niko Matsakis
-    Adrien Di Mascio
-    Alexander Hesse
-    Ludovic Aubry
-    Jacob Hallen
-    Jason Creighton
-    Alex Martelli
-    Michal Bendowski
-    Jan de Mooij
-    stian
-    Michael Foord
-    Stephan Diehl
-    Stefan Schwarzer
-    Valentino Volonghi
-    Tomek Meka
-    Patrick Maupin
-    Bob Ippolito
-    Bruno Gola
-    Jean-Paul Calderone
-    Timo Paulssen
-    Squeaky
-    Alexandre Fayolle
-    Simon Burton
-    Marius Gedminas
-    John Witulski
-    Konstantin Lopuhin
-    Greg Price
-    Dario Bertini
-    Mark Pearse
-    Simon Cross
-    Andreas St&#252;hrk
-    Jean-Philippe St. Pierre
-    Guido van Rossum
-    Pavel Vinogradov
-    Pawe&#322; Piotr Przeradowski
-    Paul deGrandis
-    Ilya Osadchiy
-    Tobias Oberstein
-    Adrian Kuhn
-    Boris Feigin
-    Stefano Rivera
-    tav
-    Taavi Burns
-    Georg Brandl
-    Bert Freudenberg
-    Stian Andreassen
-    Laurence Tratt
-    Wanja Saatkamp
-    Ivan Sichmann Freitas
-    Gerald Klix
-    Mike Blume
-    Oscar Nierstrasz
-    Stefan H. Muller
-    Jeremy Thurgood
-    Gregor Wegberg
-    Rami Chowdhury
-    Tobias Pape
-    Edd Barrett
-    David Malcolm
-    Eugene Oden
-    Henry Mason
-    Preston Timmons
-    Jeff Terrace
-    David Ripton
-    Dusty Phillips
-    Lukas Renggli
-    Guenter Jantzen
-    Ned Batchelder
-    Amit Regmi
-    Ben Young
-    Nicolas Chauvat
-    Andrew Durdin
-    Andrew Chambers
-    Michael Schneider
-    Nicholas Riley
-    Jason Chu
-    Igor Trindade Oliveira
-    Rocco Moretti
-    Gintautas Miliauskas
-    Michael Twomey
-    Lucian Branescu Mihaila
-    Tim Felgentreff
-    Tyler Wade
-    Gabriel Lavoie
-    Olivier Dormond
-    Jared Grubb
-    Karl Bartel
-    Brian Dorsey
-    Victor Stinner
-    Andrews Medina
-    Stuart Williams
-    Jasper Schulz
-    Christian Hudon
-    Toby Watson
-    Antoine Pitrou
-    Aaron Iles
-    Michael Cheng
-    Justas Sadzevicius
-    Mikael Sch&#246;nenberg
-    Gasper Zejn
-    Neil Shepperd
-    Elmo M&#228;ntynen
-    Jonathan David Riehl
-    Stanislaw Halik
-    Anders Qvist
-    Chirag Jadwani
-    Beatrice During
-    Alex Perry
-    Vincent Legoll
-    Alan McIntyre
-    Alexander Sedov
-    Corbin Simpson
-    Christopher Pope
-    wenzhuman
-    Christian Tismer 
-    Marc Abramowitz
-    Dan Stromberg
-    Stefano Parmesan
-    Alexis Daboville
-    Jens-Uwe Mager
-    Carl Meyer
-    Karl Ramm
-    Pieter Zieschang
-    Gabriel
-    Lukas Vacek
-    Andrew Dalke
-    Sylvain Thenault
-    Nathan Taylor
-    Vladimir Kryachko
-    Jacek Generowicz
-    Alejandro J. Cura
-    Jacob Oscarson
-    Travis Francis Athougies
-    Ryan Gonzalez
-    Kristjan Valur Jonsson
-    Sebastian Pawlu&#347;
-    Neil Blakey-Milner
-    anatoly techtonik
-    Lutz Paelike
-    Lucio Torre
-    Lars Wassermann
-    Henrik Vendelbo
-    Dan Buch
-    Miguel de Val Borro
-    Artur Lisiecki
-    Sergey Kishchenko
-    Ignas Mikalajunas
-    Christoph Gerum
-    Martin Blais
-    Lene Wagner
-    Tomo Cocoa
-    roberto@goyle
-    Yury V. Zaytsev
-    Anna Katrina Dominguez
-    William Leslie
-    Bobby Impollonia
-    t...@eistee.fritz.box
-    Andrew Thompson
-    Ben Darnell
-    Roberto De Ioris
-    Juan Francisco Cantero Hurtado
-    Godefroid Chappelle
-    Joshua Gilbert
-    Dan Colish
-    Christopher Armstrong
-    Michael Hudson-Doyle
-    Anders Sigfridsson
-    Yasir Suhail
-    rafalgalczyn...@gmail.com
-    Floris Bruynooghe
-    Laurens Van Houtven
-    Akira Li
-    Gustavo Niemeyer
-    Stephan Busemann
-    Rafa&#322; Ga&#322;czy&#324;ski
-    Yusei Tahara
-    Christian Muirhead
-    James Lan
-    shoma hosaka
-    Daniel Neuh?user
-    Matthew Miller
-    Buck Golemon
-    Konrad Delong
-    Dinu Gherman
-    Chris Lambacher
-    coolbutusel...@gmail.com
-    Rodrigo Ara&#250;jo
-    w31rd0
-    Jim Baker
-    James Robert
-    Armin Ronacher
-    Brett Cannon
-    yrttyr
-    aliceinwire
-    OlivierBlanvillain
-    Zooko Wilcox-O Hearn
-    Tomer Chachamu
-    Christopher Groskopf
-    Asmo Soinio
-    Stefan Marr
-    jiaaro
-    opassembler.py
-    Antony Lee
-    Jim Hunziker
-    Markus Unterwaditzer
-    Even Wiik Thomassen
-    jbs
-    soareschen
-    Kurt Griffiths
-    Mike Bayer
-    Flavio Percoco
-    Kristoffer Kleine
-    yasirs
-    Michael Chermside
-    Anna Ravencroft
-    Julien Phalip
-    Dan Loewenherz
+  Armin Rigo
+  Maciej Fijalkowski
+  Carl Friedrich Bolz
+  Antonio Cuni
+  Amaury Forgeot d'Arc
+  Samuele Pedroni
+  Alex Gaynor
+  Michael Hudson
+  David Schneider
+  Matti Picus
+  Brian Kearns
+  Philip Jenvey
+  Holger Krekel
+  Christian Tismer
+  Hakan Ardo
+  Benjamin Peterson
+  Manuel Jacob
+  Anders Chrigstrom
+  Eric van Riet Paap
+  Ronan Lamy
+  Wim Lavrijsen
+  Richard Emslie
+  Alexander Schremmer
+  Dan Villiom Podlaski Christiansen
+  Lukas Diekmann
+  Sven Hager
+  Anders Lehmann
+  Aurelien Campeas
+  Niklaus Haldimann
+  Remi Meier
+  Camillo Bruni
+  Laura Creighton
+  Toon Verwaest
+  Leonardo Santagada
+  Seo Sanghyeon
+  Romain Guillebert
+  Justin Peel
+  Ronny Pfannschmidt
+  David Edelsohn
+  Anders Hammarquist
+  Jakub Gustak
+  Guido Wesdorp
+  Lawrence Oluyede
+  Bartosz Skowron
+  Gregor Wegberg
+  Daniel Roberts
+  Niko Matsakis
+  Adrien Di Mascio
+  Alexander Hesse
+  Ludovic Aubry
+  Jacob Hallen
+  Jason Creighton
+  Alex Martelli
+  Michal Bendowski
+  Jan de Mooij
+  stian
+  Michael Foord
+  Stephan Diehl
+  Tyler Wade
+  Stefan Schwarzer
+  Valentino Volonghi
+  Tomek Meka
+  Patrick Maupin
+  Bob Ippolito
+  Bruno Gola
+  Jean-Paul Calderone
+  Timo Paulssen
+  Squeaky
+  Alexandre Fayolle
+  Simon Burton
+  Marius Gedminas
+  Martin Matusiak
+  Konstantin Lopuhin
+  John Witulski
+  Wenzhu Man
+  Greg Price
+  Dario Bertini
+  Mark Pearse
+  Simon Cross
+  Ivan Sichmann Freitas
+  Andreas St&#252;hrk
+  Jean-Philippe St. Pierre
+  Guido van Rossum
+  Pavel Vinogradov
+  Stefano Rivera
+  Pawe&#322; Piotr Przeradowski
+  Paul deGrandis
+  Ilya Osadchiy
+  Tobias Oberstein
+  Adrian Kuhn
+  Boris Feigin
+  tav
+  Taavi Burns
+  Georg Brandl
+  Laurence Tratt
+  Bert Freudenberg
+  Stian Andreassen
+  Wanja Saatkamp
+  Gerald Klix
+  Mike Blume
+  Oscar Nierstrasz
+  Stefan H. Muller
+  Edd Barrett
+  Jeremy Thurgood
+  Rami Chowdhury
+  Tobias Pape
+  David Malcolm
+  Eugene Oden
+  Henry Mason
+  Vasily Kuznetsov
+  Preston Timmons
+  Jeff Terrace
+  David Ripton
+  Dusty Phillips
+  Lukas Renggli
+  Guenter Jantzen
+  Ned Batchelder
+  Amit Regmi
+  Ben Young
+  Nicolas Chauvat
+  Andrew Durdin
+  Andrew Chambers
+  Michael Schneider
+  Nicholas Riley
+  Jason Chu
+  Igor Trindade Oliveira
+  Tim Felgentreff
+  Rocco Moretti
+  Gintautas Miliauskas
+  Michael Twomey
+  Lucian Branescu Mihaila
+  Gabriel Lavoie
+  Olivier Dormond
+  Jared Grubb
+  Karl Bartel
+  Brian Dorsey
+  Victor Stinner
+  Andrews Medina
+  Stuart Williams
+  Jasper Schulz
+  Christian Hudon
+  Toby Watson
+  Antoine Pitrou
+  Aaron Iles
+  Michael Cheng
+  Justas Sadzevicius
+  Gasper Zejn
+  anatoly techtonik
+  Neil Shepperd
+  Mikael Sch&#246;nenberg
+  Elmo M?ntynen
+  Jonathan David Riehl
+  Stanislaw Halik
+  Anders Qvist
+  Corbin Simpson
+  Chirag Jadwani
+  Beatrice During
+  Alex Perry
+  Vincent Legoll
+  Alan McIntyre
+  Alexander Sedov
+  Christopher Pope
+  Christian Tismer 
+  Marc Abramowitz
+  Dan Stromberg
+  Stefano Parmesan
+  Alexis Daboville
+  Jens-Uwe Mager
+  Carl Meyer
+  Karl Ramm
+  Pieter Zieschang
+  Sebastian Pawlu&#347;
+  Gabriel
+  Lukas Vacek
+  Andrew Dalke
+  Sylvain Thenault
+  Nathan Taylor
+  Vladimir Kryachko
+  Arjun Naik
+  Attila Gobi
+  Jacek Generowicz
+  Alejandro J. Cura
+  Jacob Oscarson
+  Travis Francis Athougies
+  Ryan Gonzalez
+  Ian Foote
+  Kristjan Valur Jonsson
+  Neil Blakey-Milner
+  Lutz Paelike
+  Lucio Torre
+  Lars Wassermann
+  Valentina Mukhamedzhanova
+  Henrik Vendelbo
+  Dan Buch
+  Miguel de Val Borro
+  Artur Lisiecki
+  Sergey Kishchenko
+  Yichao Yu
+  Ignas Mikalajunas
+  Christoph Gerum
+  Martin Blais
+  Lene Wagner
+  Tomo Cocoa
+  roberto@goyle
+  Yury V. Zaytsev
+  Anna Katrina Dominguez
+  William Leslie
+  Bobby Impollonia
+  t...@eistee.fritz.box
+  Andrew Thompson
+  Yusei Tahara
+  Ben Darnell
+  Roberto De Ioris
+  Juan Francisco Cantero Hurtado
+  Godefroid Chappelle
+  Joshua Gilbert
+  Dan Colish
+  Christopher Armstrong
+  Michael Hudson-Doyle
+  Anders Sigfridsson
+  Yasir Suhail
+  Jason Michalski
+  rafalgalczyn...@gmail.com
+  Floris Bruynooghe
+  Laurens Van Houtven
+  Akira Li
+  Gustavo Niemeyer
+  Stephan Busemann
+  Rafa&#322; Ga&#322;czy&#324;ski
+  Christian Muirhead
+  James Lan
+  shoma hosaka
+  Daniel Neuh?user
+  Matthew Miller
+  Buck Golemon
+  Konrad Delong
+  Dinu Gherman
+  Chris Lambacher
+  coolbutusel...@gmail.com
+  Rodrigo Ara&#250;jo
+  Jim Baker
+  James Robert
+  Armin Ronacher
+  Brett Cannon
+  yrttyr
+  aliceinwire
+  OlivierBlanvillain
+  Zooko Wilcox-O Hearn
+  Tomer Chachamu
+  Christopher Groskopf
+  Asmo Soinio
+  Stefan Marr
+  jiaaro
+  Mads Kiilerich
+  opassembler.py
+  Antony Lee
+  Jim Hunziker
+  Markus Unterwaditzer
+  Even Wiik Thomassen
+  jbs
+  soareschen
+  Kurt Griffiths
+  Mike Bayer
+  Matthew Miller
+  Flavio Percoco
+  Kristoffer Kleine
+  yasirs
+  Michael Chermside
+  Anna Ravencroft
+  Dan Crosta
+  Julien Phalip
+  Dan Loewenherz
 
-    Heinrich-Heine University, Germany 
-    Open End AB (formerly AB Strakt), Sweden
-    merlinux GmbH, Germany 
-    tismerysoft GmbH, Germany 
-    Logilab Paris, France 
-    DFKI GmbH, Germany 
-    Impara, Germany
-    Change Maker, Sweden 
-    University of California Berkeley, USA
-    Google Inc.
-    King's College London
+  Heinrich-Heine University, Germany 
+  Open End AB (formerly AB Strakt), Sweden
+  merlinux GmbH, Germany 
+  tismerysoft GmbH, Germany 
+  Logilab Paris, France 
+  DFKI GmbH, Germany 
+  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
diff --git a/_pytest/README-BEFORE-UPDATING b/_pytest/README-BEFORE-UPDATING
new file mode 100644
--- /dev/null
+++ b/_pytest/README-BEFORE-UPDATING
@@ -0,0 +1,17 @@
+This is PyPy's code of the pytest lib.  We don't expect to upgrade it
+very often, but once we do:
+
+    WARNING!
+
+    WE HAVE MADE A FEW TWEAKS HERE!
+
+Please be sure that you don't just copy the newer version from
+upstream without checking the few changes that we did.  This
+can be done like this:
+
+    cd <this directory>
+    hg log . -v | less
+
+then search for all " _pytest/" in that list to know which are the
+relevant checkins.  (Look for the checkins that only edit one
+or two files in this directory.)
diff --git a/_pytest/resultlog.py b/_pytest/resultlog.py
--- a/_pytest/resultlog.py
+++ b/_pytest/resultlog.py
@@ -53,16 +53,24 @@
         self.config = config
         self.logfile = logfile # preferably line buffered
 
-    def write_log_entry(self, testpath, lettercode, longrepr):
-        py.builtin.print_("%s %s" % (lettercode, testpath), file=self.logfile)
+    def write_log_entry(self, testpath, lettercode, longrepr, sections=None):
+        _safeprint("%s %s" % (lettercode, testpath), file=self.logfile)
         for line in longrepr.splitlines():
-            py.builtin.print_(" %s" % line, file=self.logfile)
+            _safeprint(" %s" % line, file=self.logfile)
+        if sections is not None and (
+                lettercode in ('E', 'F')):    # to limit the size of logs
+            for title, content in sections:
+                _safeprint(" ---------- %s ----------" % (title,),
+                           file=self.logfile)
+                for line in content.splitlines():
+                    _safeprint(" %s" % line, file=self.logfile)
 
     def log_outcome(self, report, lettercode, longrepr):
         testpath = getattr(report, 'nodeid', None)
         if testpath is None:
             testpath = report.fspath
-        self.write_log_entry(testpath, lettercode, longrepr)
+        self.write_log_entry(testpath, lettercode, longrepr,
+                             getattr(report, 'sections', None))
 
     def pytest_runtest_logreport(self, report):
         if report.when != "call" and report.passed:
@@ -98,3 +106,8 @@
         if path is None:
             path = "cwd:%s" % py.path.local()
         self.write_log_entry(path, '!', str(excrepr))
+
+def _safeprint(s, file):
+    if isinstance(s, unicode):
+        s = s.encode('utf-8')
+    py.builtin.print_(s, file=file)
diff --git a/lib-python/2.7/sysconfig.py b/lib-python/2.7/sysconfig.py
--- a/lib-python/2.7/sysconfig.py
+++ b/lib-python/2.7/sysconfig.py
@@ -7,30 +7,30 @@
 
 _INSTALL_SCHEMES = {
     'posix_prefix': {
-        'stdlib': '{base}/lib/python{py_version_short}',
-        'platstdlib': '{platbase}/lib/python{py_version_short}',
-        'purelib': '{base}/lib/python{py_version_short}/site-packages',
-        'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
-        'include': '{base}/include/python{py_version_short}',
-        'platinclude': '{platbase}/include/python{py_version_short}',
+        'stdlib': '{base}/lib/{implementation_lower}{py_version_short}',
+        'platstdlib': 
'{platbase}/lib/{implementation_lower}{py_version_short}',
+        'purelib': 
'{base}/lib/{implementation_lower}{py_version_short}/site-packages',
+        'platlib': 
'{platbase}/lib/{implementation_lower}{py_version_short}/site-packages',
+        'include': '{base}/include/{implementation_lower}{py_version_short}',
+        'platinclude': 
'{platbase}/include/{implementation_lower}{py_version_short}',
         'scripts': '{base}/bin',
         'data': '{base}',
         },
     'posix_home': {
-        'stdlib': '{base}/lib/python',
-        'platstdlib': '{base}/lib/python',
-        'purelib': '{base}/lib/python',
-        'platlib': '{base}/lib/python',
-        'include': '{base}/include/python',
-        'platinclude': '{base}/include/python',
+        'stdlib': '{base}/lib/{implementation_lower}',
+        'platstdlib': '{base}/lib/{implementation_lower}',
+        'purelib': '{base}/lib/{implementation_lower}',
+        'platlib': '{base}/lib/{implementation_lower}',
+        'include': '{base}/include/{implementation_lower}',
+        'platinclude': '{base}/include/{implementation_lower}',
         'scripts': '{base}/bin',
         'data'   : '{base}',
         },
     'pypy': {
-        'stdlib': '{base}/lib-python/{py_version_short}',
-        'platstdlib': '{base}/lib-python/{py_version_short}',
-        'purelib': '{base}/lib-python/{py_version_short}',
-        'platlib': '{base}/lib-python/{py_version_short}',
+        'stdlib': '{base}/lib-{implementation_lower}/{py_version_short}',
+        'platstdlib': '{base}/lib-{implementation_lower}/{py_version_short}',
+        'purelib': '{base}/lib-{implementation_lower}/{py_version_short}',
+        'platlib': '{base}/lib-{implementation_lower}/{py_version_short}',
         'include': '{base}/include',
         'platinclude': '{base}/include',
         'scripts': '{base}/bin',
@@ -57,37 +57,37 @@
         'data'   : '{base}',
         },
     'os2_home': {
-        'stdlib': '{userbase}/lib/python{py_version_short}',
-        'platstdlib': '{userbase}/lib/python{py_version_short}',
-        'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
-        'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
-        'include': '{userbase}/include/python{py_version_short}',
+        'stdlib': '{userbase}/lib/{implementation_lower}{py_version_short}',
+        'platstdlib': 
'{userbase}/lib/{implementation_lower}{py_version_short}',
+        'purelib': 
'{userbase}/lib/{implementation_lower}{py_version_short}/site-packages',
+        'platlib': 
'{userbase}/lib/{implementation_lower}{py_version_short}/site-packages',
+        'include': 
'{userbase}/include/{implementation_lower}{py_version_short}',
         'scripts': '{userbase}/bin',
         'data'   : '{userbase}',
         },
     'nt_user': {
-        'stdlib': '{userbase}/Python{py_version_nodot}',
-        'platstdlib': '{userbase}/Python{py_version_nodot}',
-        'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
-        'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
-        'include': '{userbase}/Python{py_version_nodot}/Include',
+        'stdlib': '{userbase}/{implementation}{py_version_nodot}',
+        'platstdlib': '{userbase}/{implementation}{py_version_nodot}',
+        'purelib': 
'{userbase}/{implementation}{py_version_nodot}/site-packages',
+        'platlib': 
'{userbase}/{implementation}{py_version_nodot}/site-packages',
+        'include': '{userbase}/{implementation}{py_version_nodot}/Include',
         'scripts': '{userbase}/Scripts',
         'data'   : '{userbase}',
         },
     'posix_user': {
-        'stdlib': '{userbase}/lib/python{py_version_short}',
-        'platstdlib': '{userbase}/lib/python{py_version_short}',
-        'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
-        'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
-        'include': '{userbase}/include/python{py_version_short}',
+        'stdlib': '{userbase}/lib/{implementation_lower}{py_version_short}',
+        'platstdlib': 
'{userbase}/lib/{implementation_lower}{py_version_short}',
+        'purelib': 
'{userbase}/lib/{implementation_lower}{py_version_short}/site-packages',
+        'platlib': 
'{userbase}/lib/{implementation_lower}{py_version_short}/site-packages',
+        'include': 
'{userbase}/include/{implementation_lower}{py_version_short}',
         'scripts': '{userbase}/bin',
         'data'   : '{userbase}',
         },
     'osx_framework_user': {
-        'stdlib': '{userbase}/lib/python',
-        'platstdlib': '{userbase}/lib/python',
-        'purelib': '{userbase}/lib/python/site-packages',
-        'platlib': '{userbase}/lib/python/site-packages',
+        'stdlib': '{userbase}/lib/{implementation_lower}',
+        'platstdlib': '{userbase}/lib/{implementation_lower}',
+        'purelib': '{userbase}/lib/{implementation_lower}/site-packages',
+        'platlib': '{userbase}/lib/{implementation_lower}/site-packages',
         'include': '{userbase}/include',
         'scripts': '{userbase}/bin',
         'data'   : '{userbase}',
@@ -104,6 +104,11 @@
 _CONFIG_VARS = None
 _USER_BASE = None
 
+def _get_implementation():
+    if '__pypy__' in sys.builtin_module_names:
+        return 'PyPy'
+    return 'Python'
+
 def _safe_realpath(path):
     try:
         return realpath(path)
@@ -475,6 +480,8 @@
         _CONFIG_VARS['base'] = _PREFIX
         _CONFIG_VARS['platbase'] = _EXEC_PREFIX
         _CONFIG_VARS['projectbase'] = _PROJECT_BASE
+        _CONFIG_VARS['implementation'] = _get_implementation()
+        _CONFIG_VARS['implementation_lower'] = _get_implementation().lower()
 
         if os.name in ('nt', 'os2'):
             _init_non_posix(_CONFIG_VARS)
@@ -644,6 +651,8 @@
     _print_dict('Paths', get_paths())
     print
     _print_dict('Variables', get_config_vars())
+    print
+    _print_dict('User', get_paths('%s_user' % os.name))
 
 
 if __name__ == '__main__':
diff --git a/lib-python/2.7/test/pickletester.py 
b/lib-python/2.7/test/pickletester.py
--- a/lib-python/2.7/test/pickletester.py
+++ b/lib-python/2.7/test/pickletester.py
@@ -6,14 +6,16 @@
 import pickletools
 import copy_reg
 
-from test.test_support import TestFailed, verbose, have_unicode, TESTFN, 
impl_detail
+from test.test_support import TestFailed, verbose, have_unicode, TESTFN
 try:
-    from test.test_support import _2G, _1M, precisionbigmemtest
+    from test.test_support import _2G, _1M, precisionbigmemtest, impl_detail
 except ImportError:
     # this import might fail when run on older Python versions by test_xpickle
     _2G = _1M = 0
     def precisionbigmemtest(*args, **kwargs):
         return lambda self: None
+    def impl_detail(*args, **kwargs):
+        return lambda self: None
 
 # Tests that try a number of pickle protocols should have a
 #     for proto in protocols:
diff --git a/lib-python/2.7/test/test_mmap.py b/lib-python/2.7/test/test_mmap.py
--- a/lib-python/2.7/test/test_mmap.py
+++ b/lib-python/2.7/test/test_mmap.py
@@ -179,25 +179,27 @@
         import sys
         f = open(TESTFN, "r+b")
         try:
-            m = mmap.mmap(f.fileno(), mapsize+1)
-        except ValueError:
-            # we do not expect a ValueError on Windows
-            # CAUTION:  This also changes the size of the file on disk, and
-            # later tests assume that the length hasn't changed.  We need to
-            # repair that.
+            try:
+                m = mmap.mmap(f.fileno(), mapsize+1)
+            except ValueError:
+                # we do not expect a ValueError on Windows
+                # CAUTION:  This also changes the size of the file on disk, and
+                # later tests assume that the length hasn't changed.  We need 
to
+                # repair that.
+                if sys.platform.startswith('win'):
+                    self.fail("Opening mmap with size+1 should work on 
Windows.")
+            else:
+                # we expect a ValueError on Unix, but not on Windows
+                if not sys.platform.startswith('win'):
+                    self.fail("Opening mmap with size+1 should raise 
ValueError.")
+                m.close()
+        finally:
+            f.close()
             if sys.platform.startswith('win'):
-                self.fail("Opening mmap with size+1 should work on Windows.")
-        else:
-            # we expect a ValueError on Unix, but not on Windows
-            if not sys.platform.startswith('win'):
-                self.fail("Opening mmap with size+1 should raise ValueError.")
-            m.close()
-        f.close()
-        if sys.platform.startswith('win'):
-            # Repair damage from the resizing test.
-            f = open(TESTFN, 'r+b')
-            f.truncate(mapsize)
-            f.close()
+                # Repair damage from the resizing test.
+                f = open(TESTFN, 'r+b')
+                f.truncate(mapsize)
+                f.close()
 
         # Opening mmap with access=ACCESS_WRITE
         f = open(TESTFN, "r+b")
diff --git a/py/README-BEFORE-UPDATING b/py/README-BEFORE-UPDATING
new file mode 100644
--- /dev/null
+++ b/py/README-BEFORE-UPDATING
@@ -0,0 +1,17 @@
+This is PyPy's code of the py lib.  We don't expect to upgrade it
+very often, but once we do:
+
+    WARNING!
+
+    WE HAVE MADE A FEW TWEAKS HERE!
+
+Please be sure that you don't just copy the newer version from
+upstream without checking the few changes that we did.  This
+can be done like this:
+
+    cd <this directory>
+    hg log . -v | less
+
+then search for all " py/" in that list to know which are the
+relevant checkins.  (Look for the checkins that only edit one
+or two files in this directory.)
diff --git a/py/_code/code.py b/py/_code/code.py
--- a/py/_code/code.py
+++ b/py/_code/code.py
@@ -588,7 +588,7 @@
 class TerminalRepr:
     def __str__(self):
         s = self.__unicode__()
-        if sys.version_info[0] < 3:
+        if sys.version_info[0] < 3 and isinstance(s, unicode):
             s = s.encode('utf-8')
         return s
 
diff --git a/py/_path/local.py b/py/_path/local.py
--- a/py/_path/local.py
+++ b/py/_path/local.py
@@ -750,7 +750,8 @@
     mkdtemp = classmethod(mkdtemp)
 
     def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3,
-                          lock_timeout = 172800):   # two days
+                          lock_timeout = 172800,   # two days
+                          min_timeout = 300):      # five minutes
         """ return unique directory with a number greater than the current
             maximum one.  The number is assumed to start directly after prefix.
             if keep is true directories with a number less than (maxnum-keep)
@@ -818,6 +819,20 @@
             for path in rootdir.listdir():
                 num = parse_num(path)
                 if num is not None and num <= (maxnum - keep):
+                    if min_timeout:
+                        # NB: doing this is needed to prevent (or reduce
+                        # a lot the chance of) the following situation:
+                        # 'keep+1' processes call make_numbered_dir() at
+                        # the same time, they create dirs, but then the
+                        # last process notices the first dir doesn't have
+                        # (yet) a .lock in it and kills it.
+                        try:
+                            t1 = path.lstat().mtime
+                            t2 = lockfile.lstat().mtime
+                            if abs(t2-t1) < min_timeout:
+                                continue   # skip directories too recent
+                        except py.error.Error:
+                            continue   # failure to get a time, better skip
                     lf = path.join('.lock')
                     try:
                         t1 = lf.lstat().mtime
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -52,11 +52,10 @@
 if sys.platform == "win32":
     working_modules.add("_winreg")
     # unix only modules
-    working_modules.remove("crypt")
-    working_modules.remove("fcntl")
-    working_modules.remove("pwd")
-    working_modules.remove("termios")
-    working_modules.remove("_minimal_curses")
+    for name in ["crypt", "fcntl", "pwd", "termios", "_minimal_curses"]:
+        working_modules.remove(name)
+        if name in translation_modules:
+            translation_modules.remove(name)
 
     if "cppyy" in working_modules:
         working_modules.remove("cppyy")  # not tested on win32
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -65,9 +65,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '2.3'
+version = '2.4'
 # The full version, including alpha/beta/rc tags.
-release = '2.3.0'
+release = '2.4.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -80,7 +80,7 @@
   Martin Matusiak
   Konstantin Lopuhin
   John Witulski
-  wenzhu man
+  Wenzhu Man
   Greg Price
   Dario Bertini
   Mark Pearse
diff --git a/pypy/doc/index-of-release-notes.rst 
b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
 
 .. toctree::
 
+   release-2.4.0.rst
    release-2.3.1.rst
    release-2.3.0.rst
    release-2.2.1.rst
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -40,7 +40,7 @@
 
 * `FAQ`_: some frequently asked questions.
 
-* `Release 2.3.1`_: the latest official release
+* `Release 2.4.0`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
 
@@ -110,7 +110,7 @@
 .. _`Getting Started`: getting-started.html
 .. _`Papers`: extradoc.html
 .. _`Videos`: video-index.html
-.. _`Release 2.3.1`: http://pypy.org/download.html
+.. _`Release 2.4.0`: http://pypy.org/download.html
 .. _`speed.pypy.org`: http://speed.pypy.org
 .. _`RPython toolchain`: translation.html
 .. _`potential project ideas`: project-ideas.html
diff --git a/pypy/doc/release-2.4.rst b/pypy/doc/release-2.4.0.rst
rename from pypy/doc/release-2.4.rst
rename to pypy/doc/release-2.4.0.rst
--- a/pypy/doc/release-2.4.rst
+++ b/pypy/doc/release-2.4.0.rst
@@ -1,67 +1,75 @@
 =================================================
-PyPy 2.4 - ????????
+PyPy 2.4 - Snow White
 =================================================
 
-We're pleased to announce PyPy 2.4, a significant milestone on it's own right
-and the proud parent of our recent PyPy3 and STM releases.
+We're pleased to announce PyPy 2.4, which contains significant performance
+enhancements and bug fixes. 
 
-This release contains several improvements and bugfixes.
+You can already download the PyPy 2.4-beta1 pre-release here:
 
-You can download the PyPy 2.4 release here:
+    https://bitbucket.org/pypy/pypy/downloads
+
+It should also soon be available on:
 
     http://pypy.org/download.html
 
 We would like to thank our donors for the continued support of the PyPy
 project, and for those who donate to our three sub-projects.
-We've shown quite a bit of progress 
-but we're slowly running out of funds.
+We've shown quite a bit of progress, but we're slowly running out of funds.
 Please consider donating more, or even better convince your employer to donate,
-so we can finish those projects!  The three sub-projects are:
+so we can finish those projects! We would like to also point out that in
+September, `the Python Software Foundation`_ will `match funds`_ for
+any donations up to $10k!  The three sub-projects are:
 
-* `Py3k`_ (supporting Python 3.x): We have released a Python 3.2.5 compatable 
version
-   we call PyPy3 2.3.1, and are working toward a Python 3.3 compatable version
+* `Py3k`_ (supporting Python 3.x): We have released a Python 3.2.5 compatible 
version
+   we call PyPy3 2.3.1, and are working toward a Python 3.3 compatible version
 
-* `STM`_ (software transactional memory): We have release a first working 
version, and
-continue to try out new promising paths of acheiving a fast multithreaded 
python
+* `STM`_ (software transactional memory): We have released a first working 
version,
+  and continue to try out new promising paths of achieving a fast 
multithreaded Python
 
-* `NumPy`_ which requires installation of our fork of upstream numpy, 
available `on bitbucket`_
+* `NumPy`_ which requires installation of our fork of upstream numpy, 
+  available `on bitbucket`_
 
 .. _`Py3k`: http://pypy.org/py3donate.html
 .. _`STM`: http://pypy.org/tmdonate2.html
 .. _`NumPy`: http://pypy.org/numpydonate.html
 .. _`on bitbucket`: https://www.bitbucket.org/pypy/numpy   
+.. _`the Python Software Foundation`: https://www.python.org/psf/
+.. _`match funds`: 
http://morepypy.blogspot.com/2014/09/python-software-foundation-matching.html
 
 What is PyPy?
 =============
 
 PyPy is a very compliant Python interpreter, almost a drop-in replacement for
-CPython 2.7. It's fast (`pypy 2.3 and cpython 2.7.x`_ performance comparison;
-note that cpython's speed has not changed since 2.7.2)
+CPython 2.7. It's fast (`pypy 2.4 and cpython 2.7.x`_ performance comparison)
 due to its integrated tracing JIT compiler.
 
-This release supports x86 machines running Linux 32/64, Mac OS X 64, Windows,
-and OpenBSD,
-as well as newer ARM hardware (ARMv6 or ARMv7, with VFPv3) running Linux. 
+This release supports **x86** machines on most common operating systems 
+(Linux 32/64, Mac OS X 64, Windows, and OpenBSD),
+as well as newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux. 
 
 While we support 32 bit python on Windows, work on the native Windows 64
 bit python is still stalling, we would welcome a volunteer
 to `handle that`_.
 
-.. _`pypy 2.3 and cpython 2.7.x`: http://speed.pypy.org
+.. _`pypy 2.4 and cpython 2.7.x`: http://speed.pypy.org
 .. _`handle that`: 
http://doc.pypy.org/en/latest/windows.html#what-is-missing-for-a-full-64-bit-translation
 
 Highlights
 ==========
 
-Benchmarks improved after internal improvements in string and bytearray 
handling,
-and a major rewrite of the GIL handling. Many of these improvements are 
offshoots
-of the STM work.
+Benchmarks improved after internal enhancements in string and
+bytearray handling, and a major rewrite of the GIL handling. This means
+that external calls are now a lot faster, especially the CFFI ones. It also
+means better performance in a lot of corner cases with handling strings or
+bytearrays.
 
-We merged in Python's 2.7.8 stdlib in a record time of one week, proving the
-maturity of our underlying RPython code base and PyPy interpreter.
+PyPy now uses Python 2.7.8 standard library.
 
-We welcomed more than 12 new contributors, and conducted two Google Summer of 
Code
-projects XXX details?
+We welcomed more than 12 new contributors, and conducted two Google
+Summer of Code projects, as well as other student projects not
+directly related to Summer of Code.
+
 
 Issues reported with our previous release were fixed after reports from users 
on
 our new issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at
@@ -71,33 +79,39 @@
 * Reduced internal copying of bytearray operations
 
 * Tweak the internal structure of StringBuilder to speed up large string
-handling, which becomes advantageous on large programs at the cost of slightly
-slower small *benchmark* type programs.
+  handling, which becomes advantageous on large programs at the cost of 
slightly
+  slower small *benchmark* type programs.
 
-* Boost performance of thread-local variables in both unjitted and jitted code
+* Boost performance of thread-local variables in both unjitted and jitted code,
+  this mostly affects errno handling on linux, which makes external calls
+  faster.
 
 * Move to a mixed polling and mutex GIL model that make mutli-threaded jitted
   code run *much* faster
 
-* Optimize errno handling in linux
+* Optimize errno handling in linux (x86 and x86-64 only)
 
 * Remove ctypes pythonapi and ctypes.PyDLL, which never worked on PyPy
 
 * Fix performance regression on ufunc(<scalar>, <scalar>) in numpy
 
-* Classes in the ast module are now distinct from structures used by the 
compiler,
-  which simplifies and speeds up translation of our source code to the PyPy 
binary
-  interpreter
+* Classes in the ast module are now distinct from structures used by
+  the compiler, which simplifies and speeds up translation of our
+  source code to the PyPy binary interpreter
 
 * Upgrade stdlib from 2.7.5 to 2.7.8
 
-* 
-
+* Win32 now links statically to zlib, expat, bzip, and openssl-1.0.1i.
+  No more missing DLLs
+  
 * Many issues were resolved_ since the 2.3.1 release on June 8
 
 .. _`whats-new`: http://doc.pypy.org/en/latest/whatsnew-2.3.1.html
 .. _resolved: https://bitbucket.org/pypy/pypy/issues?status=resolved
 
+We have further improvements on the way: rpython file handling and
+usable numpy linalg compatabiity should be merged soon.
+
 Please try it out and let us know what you think. We especially welcome
 success stories, we know you are using PyPy, please tell us about it!
 
diff --git a/pypy/doc/tool/makecontributor.py b/pypy/doc/tool/makecontributor.py
--- a/pypy/doc/tool/makecontributor.py
+++ b/pypy/doc/tool/makecontributor.py
@@ -68,7 +68,7 @@
     'Manuel Jacob': ['mjacob'],
     'Rami Chowdhury': ['necaris'],
     'Stanislaw Halik':['w31rd0'],
-    'wenzhu man':['wenzhuman'],
+    'Wenzhu Man':['wenzhu man', 'wenzhuman'],
     }
 
 alias_map = {}
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-2.4.0.rst
copy from pypy/doc/whatsnew-head.rst
copy to pypy/doc/whatsnew-2.4.0.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-2.4.0.rst
@@ -60,3 +60,7 @@
 
 .. branch: stdlib-2.7.8
 Upgrades from 2.7.6 to 2.7.8
+
+.. branch: cpybug-seq-radd-rmul
+Fix issue #1861 - cpython compatability madness
+
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
@@ -1,62 +1,8 @@
+
 =======================
-What's new in PyPy 2.4+
+What's new in PyPy 2.5+
 =======================
 
-.. this is a revision shortly after release-2.3.x
-.. startrev: ca9b7cf02cf4
+.. this is a revision shortly after release-2.4.x
+.. startrev: 7026746cbb1b
 
-.. branch: fix-bytearray-complexity
-Bytearray operations no longer copy the bytearray unnecessarily
-
-Added support for ``__getitem__``, ``__setitem__``, ``__getslice__``,
-``__setslice__``,  and ``__len__`` to RPython
-
-.. branch: stringbuilder2-perf
-Give the StringBuilder a more flexible internal structure, with a
-chained list of strings instead of just one string. This make it
-more efficient when building large strings, e.g. with cStringIO().
-
-Also, use systematically jit.conditional_call() instead of regular
-branches. This lets the JIT make more linear code, at the cost of
-forcing a bit more data (to be passed as arguments to
-conditional_calls). I would expect the net result to be a slight
-slow-down on some simple benchmarks and a speed-up on bigger
-programs.
-
-.. branch: ec-threadlocal
-Change the executioncontext's lookup to be done by reading a thread-
-local variable (which is implemented in C using '__thread' if
-possible, and pthread_getspecific() otherwise). On Linux x86 and
-x86-64, the JIT backend has a special optimization that lets it emit
-directly a single MOV from a %gs- or %fs-based address. It seems
-actually to give a good boost in performance.
-
-.. branch: fast-gil
-A faster way to handle the GIL, particularly in JIT code. The GIL is
-now a composite of two concepts: a global number (it's just set from
-1 to 0 and back around CALL_RELEASE_GIL), and a real mutex. If there
-are threads waiting to acquire the GIL, one of them is actively
-checking the global number every 0.1 ms to 1 ms.  Overall, JIT loops
-full of external function calls now run a bit faster (if no thread was
-started yet), or a *lot* faster (if threads were started already).
-
-.. branch: jit-get-errno
-Optimize the errno handling in the JIT, notably around external
-function calls. Linux-only.
-
-.. branch: disable_pythonapi
-Remove non-functioning ctypes.pyhonapi and ctypes.PyDLL, document this
-incompatibility with cpython. Recast sys.dllhandle to an int.
-
-.. branch: scalar-operations
-Fix performance regression on ufunc(<scalar>, <scalar>) in numpy.
-
-.. branch: pytest-25
-Update our copies of py.test and pylib to versions 2.5.2 and 1.4.20, 
-respectively.
-
-.. branch: split-ast-classes
-Classes in the ast module are now distinct from structures used by the 
compiler.
-
-.. branch: stdlib-2.7.8
-Upgrades from 2.7.6 to 2.7.8
diff --git a/pypy/interpreter/mixedmodule.py b/pypy/interpreter/mixedmodule.py
--- a/pypy/interpreter/mixedmodule.py
+++ b/pypy/interpreter/mixedmodule.py
@@ -7,7 +7,6 @@
 
 class MixedModule(Module):
     applevel_name = None
-    expose__file__attribute = True
 
     # The following attribute is None as long as the module has not been
     # imported yet, and when it has been, it is mod.__dict__.items() just
@@ -144,8 +143,6 @@
             for name, spec in cls.appleveldefs.items():
                 loaders[name] = getappfileloader(pkgroot, appname, spec)
             assert '__file__' not in loaders
-            if cls.expose__file__attribute:
-                loaders['__file__'] = cls.get__file__
             if '__doc__' not in loaders:
                 loaders['__doc__'] = cls.get__doc__
 
@@ -159,28 +156,6 @@
         w_obj = loader(space)
         space.setattr(space.wrap(self), space.wrap(name), w_obj)
 
-    def get__file__(cls, space):
-        """ NOT_RPYTHON.
-        return the __file__ attribute of a MixedModule
-        which is the root-directory for the various
-        applevel and interplevel snippets that make
-        up the module.
-        """
-        try:
-            fname = cls._fname
-        except AttributeError:
-            pkgroot = cls.__module__
-            mod = __import__(pkgroot, None, None, ['__doc__'])
-            fname = mod.__file__
-            assert os.path.basename(fname).startswith('__init__.py')
-            # make it clear that it's not really the interp-level module
-            # at this path that we are seeing, but an app-level version of it
-            fname = os.path.dirname(fname)
-            cls._fname = fname
-        return space.wrap(fname)
-
-    get__file__ = classmethod(get__file__)
-
     def get__doc__(cls, space):
         return space.wrap(cls.__doc__)
     get__doc__ = classmethod(get__doc__)
diff --git a/pypy/interpreter/module.py b/pypy/interpreter/module.py
--- a/pypy/interpreter/module.py
+++ b/pypy/interpreter/module.py
@@ -29,6 +29,17 @@
                           space.w_None)
         self.startup_called = False
 
+    def _cleanup_(self):
+        """Called by the annotator on prebuilt Module instances.
+        We don't have many such modules, but for the ones that
+        show up, remove their __file__ rather than translate it
+        statically inside the executable."""
+        try:
+            space = self.space
+            space.delitem(self.w_dict, space.wrap('__file__'))
+        except OperationError:
+            pass
+
     def install(self):
         """NOT_RPYTHON: installs this module into space.builtin_modules"""
         w_mod = self.space.wrap(self)
diff --git a/pypy/interpreter/test/test_app_main.py 
b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -985,6 +985,11 @@
             assert sys.path == old_sys_path + [self.goal_dir]
 
             app_main.setup_bootstrap_path(self.fake_exe)
+            assert sys.executable == ''      # not executable!
+            assert sys.path == old_sys_path + [self.goal_dir]
+
+            os.chmod(self.fake_exe, 0755)
+            app_main.setup_bootstrap_path(self.fake_exe)
             assert sys.executable == self.fake_exe
             assert self.goal_dir not in sys.path
 
diff --git a/pypy/interpreter/test/test_extmodules.py 
b/pypy/interpreter/test/test_extmodules.py
--- a/pypy/interpreter/test/test_extmodules.py
+++ b/pypy/interpreter/test/test_extmodules.py
@@ -64,5 +64,5 @@
     @pytest.mark.skipif("config.option.runappdirect")
     def test_import(self):
         import extmod
-        assert extmod.__file__.endswith('extmod')
+        assert not hasattr(extmod, '__file__')
         assert type(extmod.time()) is float
diff --git a/pypy/interpreter/test/test_module.py 
b/pypy/interpreter/test/test_module.py
--- a/pypy/interpreter/test/test_module.py
+++ b/pypy/interpreter/test/test_module.py
@@ -1,4 +1,5 @@
-
+import py
+from pypy.interpreter.error import OperationError
 from pypy.interpreter.module import Module
 
 class TestModule: 
@@ -17,6 +18,18 @@
         space.raises_w(space.w_AttributeError,
                        space.delattr, w_m, w('x'))
 
+    def test___file__(self, space):
+        w = space.wrap
+        m = Module(space, space.wrap('m'))
+        py.test.raises(OperationError, space.getattr, w(m), w('__file__'))
+        m._cleanup_()
+        py.test.raises(OperationError, space.getattr, w(m), w('__file__'))
+        space.setattr(w(m), w('__file__'), w('m.py'))
+        space.getattr(w(m), w('__file__'))   # does not raise
+        m._cleanup_()
+        py.test.raises(OperationError, space.getattr, w(m), w('__file__'))
+
+
 class AppTest_ModuleObject: 
     def test_attr(self):
         m = __import__('__builtin__')
@@ -42,12 +55,9 @@
         bar = type(sys)('bar','docstring')
         assert bar.__doc__ == 'docstring'
 
-    def test___file__(self): 
-        import sys, os
-        if not hasattr(sys, "pypy_objspaceclass"):
-            skip("need PyPy for sys.__file__ checking")
-        assert sys.__file__ 
-        assert os.path.basename(sys.__file__) == 'sys'
+    def test___file__(self):
+        import sys
+        assert not hasattr(sys, '__file__')
 
     def test_repr(self):
         import sys
diff --git a/pypy/module/__builtin__/__init__.py 
b/pypy/module/__builtin__/__init__.py
--- a/pypy/module/__builtin__/__init__.py
+++ b/pypy/module/__builtin__/__init__.py
@@ -7,7 +7,6 @@
 
 class Module(MixedModule):
     """Built-in functions, exceptions, and other objects."""
-    expose__file__attribute = False
 
     appleveldefs = {
         'execfile'      : 'app_io.execfile',
diff --git a/pypy/module/_cffi_backend/ctypeprim.py 
b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -182,8 +182,12 @@
             value = misc.read_raw_long_data(cdata, self.size)
             return self.space.wrap(value)
         else:
-            value = misc.read_raw_signed_data(cdata, self.size)
-            return self.space.wrap(value)    # r_longlong => on 32-bit, 'long'
+            return self._convert_to_object_longlong(cdata)
+
+    def _convert_to_object_longlong(self, cdata):
+        # in its own function: LONGLONG may make the whole function jit-opaque
+        value = misc.read_raw_signed_data(cdata, self.size)
+        return self.space.wrap(value)    # r_longlong => on 32-bit, 'long'
 
     def convert_from_object(self, cdata, w_ob):
         if self.value_fits_long:
@@ -193,8 +197,12 @@
                     self._overflow(w_ob)
             misc.write_raw_signed_data(cdata, value, self.size)
         else:
-            value = misc.as_long_long(self.space, w_ob)
-            misc.write_raw_signed_data(cdata, value, self.size)
+            self._convert_from_object_longlong(cdata, w_ob)
+
+    def _convert_from_object_longlong(self, cdata, w_ob):
+        # in its own function: LONGLONG may make the whole function jit-opaque
+        value = misc.as_long_long(self.space, w_ob)
+        misc.write_raw_signed_data(cdata, value, self.size)
 
     def get_vararg_type(self):
         if self.size < rffi.sizeof(rffi.INT):
@@ -264,8 +272,12 @@
                     self._overflow(w_ob)
             misc.write_raw_unsigned_data(cdata, value, self.size)
         else:
-            value = misc.as_unsigned_long_long(self.space, w_ob, strict=True)
-            misc.write_raw_unsigned_data(cdata, value, self.size)
+            self._convert_from_object_longlong(cdata, w_ob)
+
+    def _convert_from_object_longlong(self, cdata, w_ob):
+        # in its own function: LONGLONG may make the whole function jit-opaque
+        value = misc.as_unsigned_long_long(self.space, w_ob, strict=True)
+        misc.write_raw_unsigned_data(cdata, value, self.size)
 
     def convert_to_object(self, cdata):
         if self.value_fits_ulong:
@@ -275,8 +287,12 @@
             else:
                 return self.space.wrap(value)    # r_uint => 'long' object
         else:
-            value = misc.read_raw_unsigned_data(cdata, self.size)
-            return self.space.wrap(value)    # r_ulonglong => 'long' object
+            return self._convert_to_object_longlong(cdata)
+
+    def _convert_to_object_longlong(self, cdata):
+        # in its own function: LONGLONG may make the whole function jit-opaque
+        value = misc.read_raw_unsigned_data(cdata, self.size)
+        return self.space.wrap(value)    # r_ulonglong => 'long' object
 
     def get_vararg_type(self):
         if self.size < rffi.sizeof(rffi.INT):
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
@@ -17,7 +17,7 @@
 
 
 class W_CTypeStructOrUnion(W_CType):
-    _immutable_fields_ = ['alignment?', 'fields_list?', 'fields_dict?',
+    _immutable_fields_ = ['alignment?', 'fields_list?[*]', 'fields_dict?',
                           'custom_field_pos?', 'with_var_array?']
     # fields added by complete_struct_or_union():
     alignment = -1
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
@@ -389,7 +389,7 @@
 
     w_ctype.size = totalsize
     w_ctype.alignment = totalalignment
-    w_ctype.fields_list = fields_list
+    w_ctype.fields_list = fields_list[:]
     w_ctype.fields_dict = fields_dict
     w_ctype.custom_field_pos = custom_field_pos
     w_ctype.with_var_array = with_var_array
diff --git a/pypy/module/_io/interp_stringio.py 
b/pypy/module/_io/interp_stringio.py
--- a/pypy/module/_io/interp_stringio.py
+++ b/pypy/module/_io/interp_stringio.py
@@ -86,7 +86,7 @@
         initval = space.unicode_w(w_initval)
         size = len(initval)
         self.resize_buffer(size)
-        self.buf = [c for c in initval]
+        self.buf = list(initval)
         pos = space.getindex_w(w_pos, space.w_TypeError)
         if pos < 0:
             raise OperationError(space.w_ValueError,
diff --git a/pypy/module/_pypyjson/interp_encoder.py 
b/pypy/module/_pypyjson/interp_encoder.py
--- a/pypy/module/_pypyjson/interp_encoder.py
+++ b/pypy/module/_pypyjson/interp_encoder.py
@@ -1,4 +1,6 @@
 from rpython.rlib.rstring import StringBuilder
+from rpython.rlib.runicode import str_decode_utf_8
+from pypy.interpreter import unicodehelper
 
 
 HEX = '0123456789abcdef'
@@ -17,20 +19,37 @@
 def raw_encode_basestring_ascii(space, w_string):
     if space.isinstance_w(w_string, space.w_str):
         s = space.str_w(w_string)
-        for c in s:
+        for i in range(len(s)):
+            c = s[i]
             if c >= ' ' and c <= '~' and c != '"' and c != '\\':
                 pass
             else:
+                first = i
                 break
         else:
             # the input is a string with only non-special ascii chars
             return w_string
 
-        w_string = space.call_method(w_string, 'decode', space.wrap('utf-8'))
+        eh = unicodehelper.decode_error_handler(space)
+        u = str_decode_utf_8(
+                s, len(s), None, final=True, errorhandler=eh,
+                allow_surrogates=True)[0]
+        sb = StringBuilder(len(u))
+        sb.append_slice(s, 0, first)
+    else:
+        # We used to check if 'u' contains only safe characters, and return
+        # 'w_string' directly.  But this requires an extra pass over all
+        # characters, and the expected use case of this function, from
+        # json.encoder, will anyway re-encode a unicode result back to
+        # a string (with the ascii encoding).  This requires two passes
+        # over the characters.  So we may as well directly turn it into a
+        # string here --- only one pass.
+        u = space.unicode_w(w_string)
+        sb = StringBuilder(len(u))
+        first = 0
 
-    u = space.unicode_w(w_string)
-    sb = StringBuilder(len(u))
-    for c in u:
+    for i in range(first, len(u)):
+        c = u[i]
         if c <= u'~':
             if c == u'"' or c == u'\\':
                 sb.append('\\')
diff --git a/pypy/module/cpyext/include/patchlevel.h 
b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
 #define PY_VERSION             "2.7.8"
 
 /* PyPy version as a string */
-#define PYPY_VERSION "2.4.0-alpha0"
+#define PYPY_VERSION "2.5.0-alpha0"
 
 /* Subversion Revision number of this file (not of the repository).
  * Empty since Mercurial migration. */
diff --git a/pypy/module/errno/test/test_errno.py 
b/pypy/module/errno/test/test_errno.py
--- a/pypy/module/errno/test/test_errno.py
+++ b/pypy/module/errno/test/test_errno.py
@@ -8,7 +8,7 @@
         cls.w_errorcode = cls.space.wrap(errno.errorcode)
 
     def test_posix(self):
-        assert self.errno.__file__
+        assert not hasattr(self.errno, '__file__')
 
     def test_constants(self):
         for code, name in self.errorcode.iteritems():
diff --git a/pypy/module/posix/test/test_posix2.py 
b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -96,7 +96,7 @@
             need_sparse_files()
 
     def test_posix_is_pypy_s(self):
-        assert self.posix.__file__
+        assert hasattr(self.posix, '_statfields')
 
     def test_some_posix_basic_operation(self):
         path = self.path
@@ -282,13 +282,8 @@
         f = posix.fdopen(fd, "r")
         f.close()
 
-        # Ensure that fcntl is not faked
-        try:
-            import fcntl
-        except ImportError:
-            pass
-        else:
-            assert fcntl.__file__.endswith('pypy/module/fcntl')
+        # There used to be code here to ensure that fcntl is not faked
+        # but we can't do that cleanly any more
         exc = raises(OSError, posix.fdopen, fd)
         assert exc.value.errno == errno.EBADF
 
diff --git a/pypy/module/posix/test/test_posix_libfile.py 
b/pypy/module/posix/test/test_posix_libfile.py
--- a/pypy/module/posix/test/test_posix_libfile.py
+++ b/pypy/module/posix/test/test_posix_libfile.py
@@ -19,7 +19,7 @@
         cls.w_path = cls.space.wrap(str(path))
 
     def test_posix_is_pypy_s(self):
-        assert self.posix.__file__
+        assert hasattr(self.posix, '_statfields')
 
     def test_fdopen(self):
         path = self.path
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py 
b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -17,13 +17,18 @@
             # now we can inline it as call assembler
             i = 0
             j = 0
-            while i < 20:
+            while i < 25:
                 i += 1
                 j += rec(100) # ID: call_rec
             return j
         #
-        log = self.run(fn, [], threshold=18)
-        loop, = log.loops_by_filename(self.filepath)
+        # NB. the parameters below are a bit ad-hoc.  After 16 iterations,
+        # the we trace from the "while" and reach a "trace too long".  Then
+        # in the next execution, we trace the "rec" function from start;
+        # that's "functrace" below.  Then after one or two extra iterations
+        # we try again from "while", and this time we succeed.
+        log = self.run(fn, [], threshold=20)
+        functrace, loop = log.loops_by_filename(self.filepath)
         assert loop.match_by_id('call_rec', """
             ...
             p53 = call_assembler(..., descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_cprofile.py 
b/pypy/module/pypyjit/test_pypy_c/test_cprofile.py
--- a/pypy/module/pypyjit/test_pypy_c/test_cprofile.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_cprofile.py
@@ -1,4 +1,4 @@
-import py, sys
+import py, sys, re
 from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
 
 class TestCProfile(BaseTestPyPyC):
@@ -26,10 +26,20 @@
         for method in ['append', 'pop']:
             loop, = log.loops_by_id(method)
             print loop.ops_by_id(method)
-            # on 32-bit, there is f1=read_timestamp(); ...;
-            # f2=read_timestamp(); f3=call(llong_sub,f1,f2)
-            # which should turn into a single PADDQ/PSUBQ
-            if sys.maxint != 2147483647:
-                assert ' call(' not in repr(loop.ops_by_id(method))
+            # on 32-bit, there is f1=call(read_timestamp); ...;
+            # f2=call(read_timestamp); f3=call(llong_sub,f1,f2)
+            # but all calls can be special-cased by the backend if
+            # supported.  On 64-bit there is only the two calls to
+            # read_timestamp.
+            r = re.compile(r" call[(]ConstClass[(](.+?)[)]")
+            calls = r.findall(repr(loop.ops_by_id(method)))
+            if sys.maxint == 2147483647:
+                assert len(calls) == 6
+            else:
+                assert len(calls) == 2
+            for x in calls:
+                assert ('ll_read_timestamp' in x or 'llong_sub' in x
+                        or 'llong_add' in x)
+            #
             assert ' call_may_force(' not in repr(loop.ops_by_id(method))
             assert ' cond_call(' in repr(loop.ops_by_id(method))
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py 
b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -340,30 +340,19 @@
         guard_value(p166, ConstPtr(ptr72), descr=...)
         p167 = call(ConstClass(_ll_0_alloc_with_del___), descr=<Callr . EF=4>)
         guard_no_exception(descr=...)
-        i168 = call(ConstClass(_ll_1_raw_malloc_varsize__Signed), 6, 
descr=<Calli . i EF=4 OS=110>)
-        i169 = int_add(i168, i97)
-        i170 = int_sub(i160, i106)
-        setfield_gc(p167, i168, descr=<FieldU 
pypy.module._cffi_backend.cdataobj.W_CData.inst__cdata .>)
+        i112 = int_sub(i160, -32768)
         setfield_gc(p167, ConstPtr(null), descr=<FieldP 
pypy.module._cffi_backend.cdataobj.W_CData.inst__lifeline_ .+>)
-        setfield_gc(p167, ConstPtr(ptr89), descr=<FieldP 
pypy.module._cffi_backend.cdataobj.W_CData.inst_ctype .+>)
-        i171 = uint_gt(i170, i108)
-        guard_false(i171, descr=...)
-        i172 = int_sub(i160, -32768)
-        i173 = int_and(i172, 65535)
-        i174 = int_add(i173, -32768)
-        setarrayitem_raw(i169, 0, i174, descr=<ArrayS 2>)
-        i175 = int_add(i168, i121)
-        i176 = int_sub(i160, i130)
-        i177 = uint_gt(i176, i132)
-        guard_false(i177, descr=...)
-        setarrayitem_raw(i175, 0, i174, descr=<ArrayS 2>)
-        i178 = int_add(i168, i140)
-        i179 = int_sub(i160, i149)
-        i180 = uint_gt(i179, i151)
-        guard_false(i180, descr=...)
-        setarrayitem_raw(i178, 0, i174, descr=<ArrayS 2>)
+        setfield_gc(p167, ConstPtr(ptr85), descr=<FieldP 
pypy.module._cffi_backend.cdataobj.W_CData.inst_ctype .+>)
+        i114 = uint_gt(i112, 65535)
+        guard_false(i114, descr=...)
+        i115 = int_and(i112, 65535)
+        i116 = int_add(i115, -32768)
         --TICK--
-        i183 = arraylen_gc(p67, descr=<ArrayP .>)
-        i184 = arraylen_gc(p92, descr=<ArrayP .>)
+        i119 = call(ConstClass(_ll_1_raw_malloc_varsize__Signed), 6, 
descr=<Calli . i EF=4 OS=110>)
+        raw_store(i119, 0, i116, descr=<ArrayS 2>)
+        raw_store(i119, 2, i116, descr=<ArrayS 2>)
+        raw_store(i119, 4, i116, descr=<ArrayS 2>)
+        setfield_gc(p167, i119, descr=<FieldU 
pypy.module._cffi_backend.cdataobj.W_CData.inst__cdata .+>)
+        i123 = arraylen_gc(p67, descr=<ArrayP .>)
         jump(..., descr=...)
         """)
diff --git a/pypy/module/select/interp_select.py 
b/pypy/module/select/interp_select.py
--- a/pypy/module/select/interp_select.py
+++ b/pypy/module/select/interp_select.py
@@ -98,6 +98,9 @@
     for w_f in list_w:
         fd = space.c_filedescriptor_w(w_f)
         if fd > nfds:
+            if _c.MAX_FD_SIZE is not None and fd >= _c.MAX_FD_SIZE:
+                raise oefmt(space.w_ValueError,
+                            "file descriptor out of range in select()")
             nfds = fd
         _c.FD_SET(fd, ll_list)
         fdlist.append(fd)
diff --git a/pypy/module/select/test/test_select.py 
b/pypy/module/select/test/test_select.py
--- a/pypy/module/select/test/test_select.py
+++ b/pypy/module/select/test/test_select.py
@@ -198,6 +198,16 @@
         finally:
             writeend.close()
 
+    def test_select_descr_out_of_bounds(self):
+        import sys, select
+        raises(ValueError, select.select, [-1], [], [])
+        raises(ValueError, select.select, [], [-2], [])
+        raises(ValueError, select.select, [], [], [-3])
+        if sys.platform != 'win32':
+            raises(ValueError, select.select, [2000000000], [], [])
+            raises(ValueError, select.select, [], [2000000000], [])
+            raises(ValueError, select.select, [], [], [2000000000])
+
     def test_poll(self):
         import select
         if not hasattr(select, 'poll'):
diff --git a/pypy/module/sys/initpath.py b/pypy/module/sys/initpath.py
--- a/pypy/module/sys/initpath.py
+++ b/pypy/module/sys/initpath.py
@@ -18,6 +18,13 @@
 _WIN32 = sys.platform == 'win32'
 
 
+def _exists_and_is_executable(fn):
+    # os.access checks using the user's real uid and gid.
+    # Since pypy should not be run setuid/setgid, this
+    # should be sufficient.
+    return os.path.isfile(fn) and os.access(fn, os.X_OK)
+
+
 def find_executable(executable):
     """
     Return the absolute path of the executable, by looking into PATH and
@@ -34,14 +41,14 @@
         if path:
             for dir in path.split(os.pathsep):
                 fn = os.path.join(dir, executable)
-                if os.path.isfile(fn):
+                if _exists_and_is_executable(fn):
                     executable = fn
                     break
     executable = rpath.rabspath(executable)
 
     # 'sys.executable' should not end up being an non-existing file;
     # just use '' in this case. (CPython issue #7774)
-    return executable if os.path.isfile(executable) else ''
+    return executable if _exists_and_is_executable(executable) else ''
 
 
 def _readlink_maybe(filename):
diff --git a/pypy/module/sys/test/test_initpath.py 
b/pypy/module/sys/test/test_initpath.py
--- a/pypy/module/sys/test/test_initpath.py
+++ b/pypy/module/sys/test/test_initpath.py
@@ -57,6 +57,7 @@
     a.join('pypy').ensure(file=True)
     b.join('pypy').ensure(file=True)
     #
+    monkeypatch.setattr(os, 'access', lambda x, y: True)
     # if there is already a slash, don't do anything
     monkeypatch.chdir(tmpdir)
     assert find_executable('a/pypy') == a.join('pypy')
@@ -82,7 +83,11 @@
     # if pypy is found but it's not a file, ignore it
     c.join('pypy').ensure(dir=True)
     assert find_executable('pypy') == a.join('pypy')
+    # if pypy is found but it's not executable, ignore it
+    monkeypatch.setattr(os, 'access', lambda x, y: False)
+    assert find_executable('pypy') == ''
     #
+    monkeypatch.setattr(os, 'access', lambda x, y: True)
     monkeypatch.setattr(initpath, 'we_are_translated', lambda: True)
     monkeypatch.setattr(initpath, '_WIN32', True)
     monkeypatch.setenv('PATH', str(a))
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -10,7 +10,7 @@
 #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
 CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
 
-PYPY_VERSION               = (2, 4, 0, "alpha", 0)    #XXX # sync patchlevel.h
+PYPY_VERSION               = (2, 5, 0, "alpha", 0)    #XXX # sync patchlevel.h
 
 if platform.name == 'msvc':
     COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
diff --git a/pypy/module/thread/test/test_thread.py 
b/pypy/module/thread/test/test_thread.py
--- a/pypy/module/thread/test/test_thread.py
+++ b/pypy/module/thread/test/test_thread.py
@@ -13,18 +13,26 @@
         def f():
             lock.acquire()
             lock.release()
+        start = thread._count()
         try:
             try:
                 for i in range(1000):
                     thread.start_new_thread(f, ())
             finally:
                 lock.release()
-                # wait a bit to allow most threads to finish now
-                time.sleep(0.5)
         except (thread.error, MemoryError):
             cls.w_can_start_many_threads = space.wrap(False)
         else:
             cls.w_can_start_many_threads = space.wrap(True)
+        # wait a bit to allow all threads to finish now
+        remaining = thread._count()
+        retries = 0
+        while remaining > start:
+            retries += 1
+            if retries == 200:
+                raise Exception("the test's threads don't stop!")
+            time.sleep(0.2)
+            remaining = thread._count()
 
     def test_start_new_thread(self):
         import thread
@@ -227,7 +235,7 @@
         import signal
 
         def f():
-            for x in range(5):
+            for x in range(40):
                 if waiting:
                     thread.interrupt_main()
                     return
@@ -236,7 +244,7 @@
 
         def busy_wait():
             waiting.append(None)
-            for x in range(10):
+            for x in range(50):
                 print 'tick...', x  # <-force the GIL to be released, as
                 time.sleep(0.1)    #   time.sleep doesn't do non-translated
             waiting.pop()
@@ -245,6 +253,8 @@
         signal.signal(signal.SIGINT, signal.default_int_handler)
 
         for i in range(100):
+            print
+            print "loop", i
             waiting = []
             thread.start_new_thread(f, ())
             raises(KeyboardInterrupt, busy_wait)
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -671,6 +671,7 @@
     left, right = specialnames
     errormsg = "unsupported operand type(s) for %s: '%%N' and '%%N'" % (
         symbol.replace('%', '%%'),)
+    seq_bug_compat = (symbol == '+' or symbol == '*')
 
     def binop_impl(space, w_obj1, w_obj2):
         w_typ1 = space.type(w_obj1)
@@ -686,20 +687,16 @@
             # __xxx__ and __rxxx__ methods where found by identity.
             # Note that space.is_w() is potentially not happy if one of them
             # is None...
-            if w_left_src is not w_right_src:    # XXX
-                # -- cpython bug compatibility: see objspace/std/test/
-                # -- test_unicodeobject.test_str_unicode_concat_overrides.
-                # -- The following handles "unicode + string subclass" by
-                # -- pretending that the unicode is a superclass of the
-                # -- string, thus giving priority to the string subclass'
-                # -- __radd__() method.  The case "string + unicode subclass"
-                # -- is handled directly by add__String_Unicode().
-                if symbol == '+' and space.is_w(w_typ1, space.w_unicode):
-                    w_typ1 = space.w_basestring
-                # -- end of bug compatibility
-                if space.is_true(space.issubtype(w_typ2, w_typ1)):
-                    if (w_left_src and w_right_src and
-                        not space.abstract_issubclass_w(w_left_src, 
w_right_src) and
+            if w_right_src and (w_left_src is not w_right_src) and w_left_src:
+                # 'seq_bug_compat' is for cpython bug-to-bug compatibility:
+                # see objspace/std/test/test_unicodeobject.*concat_overrides
+                # and objspace/test/test_descrobject.*rmul_overrides.
+                # For cases like "unicode + string subclass".
+                if ((seq_bug_compat and w_typ1.flag_sequence_bug_compat
+                                    and not w_typ2.flag_sequence_bug_compat)
+                        # the non-bug-compat part is the following check:
+                        or space.is_true(space.issubtype(w_typ2, w_typ1))):
+                    if (not space.abstract_issubclass_w(w_left_src, 
w_right_src) and
                         not space.abstract_issubclass_w(w_typ1, w_right_src)):
                         w_obj1, w_obj2 = w_obj2, w_obj1
                         w_left_impl, w_right_impl = w_right_impl, w_left_impl
diff --git a/pypy/objspace/std/bytearrayobject.py 
b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -534,7 +534,7 @@
         if not e.match(space, space.w_TypeError):
             raise
     else:
-        return [c for c in buf.as_str()]
+        return list(buf.as_str())
 
     # sequence of bytes
     w_iter = space.iter(w_source)
@@ -1131,6 +1131,7 @@
     reverse = interp2app(W_BytearrayObject.descr_reverse,
                          doc=BytearrayDocstrings.reverse.__doc__),
 )
+W_BytearrayObject.typedef.flag_sequence_bug_compat = True
 
 init_signature = Signature(['source', 'encoding', 'errors'], None, None)
 init_defaults = [None, None, None]
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -951,6 +951,7 @@
     _formatter_field_name_split =
         interp2app(W_BytesObject.descr_formatter_field_name_split),
 )
+W_BytesObject.typedef.flag_sequence_bug_compat = True
 
 
 def string_escape_encode(s, quote):
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -1874,3 +1874,4 @@
     insert = interp2app(W_ListObject.descr_insert),
     remove = interp2app(W_ListObject.descr_remove),
 )
+W_ListObject.typedef.flag_sequence_bug_compat = True
diff --git a/pypy/objspace/std/stdtypedef.py b/pypy/objspace/std/stdtypedef.py
--- a/pypy/objspace/std/stdtypedef.py
+++ b/pypy/objspace/std/stdtypedef.py
@@ -93,6 +93,8 @@
                               overridetypedef=overridetypedef)
         if typedef is not overridetypedef:
             w_type.w_doc = space.wrap(typedef.doc)
+        if hasattr(typedef, 'flag_sequence_bug_compat'):
+            w_type.flag_sequence_bug_compat = typedef.flag_sequence_bug_compat
         w_type.lazyloaders = lazyloaders
         return w_type
 
diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py
--- a/pypy/objspace/std/tupleobject.py
+++ b/pypy/objspace/std/tupleobject.py
@@ -244,6 +244,7 @@
     count = interp2app(W_AbstractTupleObject.descr_count),
     index = interp2app(W_AbstractTupleObject.descr_index)
 )
+W_AbstractTupleObject.typedef.flag_sequence_bug_compat = True
 
 
 class W_TupleObject(W_AbstractTupleObject):
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -67,6 +67,7 @@
     _immutable_fields_ = ["flag_heaptype",
                           "flag_cpytype",
                           "flag_abstract?",
+                          "flag_sequence_bug_compat",
                           'needsdel',
                           'weakrefable',
                           'hasdict',
@@ -104,6 +105,7 @@
         w_self.flag_heaptype = False
         w_self.flag_cpytype = False
         w_self.flag_abstract = False
+        w_self.flag_sequence_bug_compat = False
         w_self.instancetypedef = overridetypedef
 
         if overridetypedef is not None:
diff --git a/pypy/objspace/std/unicodeobject.py 
b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -1068,6 +1068,7 @@
     _formatter_field_name_split =
         interp2app(W_UnicodeObject.descr_formatter_field_name_split),
 )
+W_UnicodeObject.typedef.flag_sequence_bug_compat = True
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to