[pypy-commit] pypy fix-longevity: (remi, plan_rich) merged default

plan_rich pypy.commits at gmail.com
Thu Feb 25 11:59:30 EST 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: fix-longevity
Changeset: r82521:3dce5a6242ac
Date: 2016-02-25 17:58 +0100
http://bitbucket.org/pypy/pypy/changeset/3dce5a6242ac/

Log:	(remi, plan_rich) merged default

diff too long, truncating to 2000 out of 2557 lines

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -41,29 +41,29 @@
   Amaury Forgeot d'Arc
   Antonio Cuni
   Samuele Pedroni
+  Matti Picus
   Alex Gaynor
   Brian Kearns
-  Matti Picus
   Philip Jenvey
   Michael Hudson
+  Ronan Lamy
   David Schneider
+  Manuel Jacob
   Holger Krekel
   Christian Tismer
   Hakan Ardo
-  Manuel Jacob
-  Ronan Lamy
   Benjamin Peterson
+  Richard Plangger
   Anders Chrigstrom
   Eric van Riet Paap
   Wim Lavrijsen
-  Richard Plangger
   Richard Emslie
   Alexander Schremmer
   Dan Villiom Podlaski Christiansen
+  Remi Meier
   Lukas Diekmann
   Sven Hager
   Anders Lehmann
-  Remi Meier
   Aurelien Campeas
   Niklaus Haldimann
   Camillo Bruni
@@ -72,8 +72,8 @@
   Romain Guillebert
   Leonardo Santagada
   Seo Sanghyeon
+  Ronny Pfannschmidt
   Justin Peel
-  Ronny Pfannschmidt
   David Edelsohn
   Anders Hammarquist
   Jakub Gustak
@@ -95,6 +95,7 @@
   Tyler Wade
   Michael Foord
   Stephan Diehl
+  Vincent Legoll
   Stefan Schwarzer
   Valentino Volonghi
   Tomek Meka
@@ -105,9 +106,9 @@
   Jean-Paul Calderone
   Timo Paulssen
   Squeaky
+  Marius Gedminas
   Alexandre Fayolle
   Simon Burton
-  Marius Gedminas
   Martin Matusiak
   Konstantin Lopuhin
   Wenzhu Man
@@ -116,16 +117,20 @@
   Ivan Sichmann Freitas
   Greg Price
   Dario Bertini
+  Stefano Rivera
   Mark Pearse
   Simon Cross
   Andreas Stührk
-  Stefano Rivera
+  Edd Barrett
   Jean-Philippe St. Pierre
   Guido van Rossum
   Pavel Vinogradov
+  Jeremy Thurgood
   Paweł Piotr Przeradowski
+  Spenser Bauman
   Paul deGrandis
   Ilya Osadchiy
+  marky1991
   Tobias Oberstein
   Adrian Kuhn
   Boris Feigin
@@ -134,14 +139,12 @@
   Georg Brandl
   Bert Freudenberg
   Stian Andreassen
-  Edd Barrett
+  Tobias Pape
   Wanja Saatkamp
   Gerald Klix
   Mike Blume
-  Tobias Pape
   Oscar Nierstrasz
   Stefan H. Muller
-  Jeremy Thurgood
   Rami Chowdhury
   Eugene Oden
   Henry Mason
@@ -153,6 +156,8 @@
   Lukas Renggli
   Guenter Jantzen
   Ned Batchelder
+  Tim Felgentreff
+  Anton Gulenko
   Amit Regmi
   Ben Young
   Nicolas Chauvat
@@ -162,12 +167,12 @@
   Nicholas Riley
   Jason Chu
   Igor Trindade Oliveira
-  Tim Felgentreff
+  Yichao Yu
   Rocco Moretti
   Gintautas Miliauskas
   Michael Twomey
   Lucian Branescu Mihaila
-  Yichao Yu
+  Devin Jeanpierre
   Gabriel Lavoie
   Olivier Dormond
   Jared Grubb
@@ -191,33 +196,33 @@
   Stanislaw Halik
   Mikael Schönenberg
   Berkin Ilbeyi
-  Elmo M?ntynen
+  Elmo Mäntynen
+  Faye Zhao
   Jonathan David Riehl
   Anders Qvist
   Corbin Simpson
   Chirag Jadwani
   Beatrice During
   Alex Perry
-  Vincent Legoll
+  Vaibhav Sood
   Alan McIntyre
-  Spenser Bauman
+  William Leslie
   Alexander Sedov
   Attila Gobi
+  Jasper.Schulz
   Christopher Pope
-  Devin Jeanpierre
-  Vaibhav Sood
   Christian Tismer 
   Marc Abramowitz
   Dan Stromberg
   Arjun Naik
   Valentina Mukhamedzhanova
   Stefano Parmesan
+  Mark Young
   Alexis Daboville
   Jens-Uwe Mager
   Carl Meyer
   Karl Ramm
   Pieter Zieschang
-  Anton Gulenko
   Gabriel
   Lukas Vacek
   Andrew Dalke
@@ -225,6 +230,7 @@
   Jakub Stasiak
   Nathan Taylor
   Vladimir Kryachko
+  Omer Katz
   Jacek Generowicz
   Alejandro J. Cura
   Jacob Oscarson
@@ -239,6 +245,7 @@
   Lars Wassermann
   Philipp Rustemeuer
   Henrik Vendelbo
+  Richard Lancaster
   Dan Buch
   Miguel de Val Borro
   Artur Lisiecki
@@ -250,18 +257,18 @@
   Tomo Cocoa
   Kim Jin Su
   Toni Mattis
+  Amber Brown
   Lucas Stadler
   Julian Berman
   Markus Holtermann
   roberto at goyle
   Yury V. Zaytsev
   Anna Katrina Dominguez
-  William Leslie
   Bobby Impollonia
-  Faye Zhao
   timo at eistee.fritz.box
   Andrew Thompson
   Yusei Tahara
+  Aaron Tubbs
   Ben Darnell
   Roberto De Ioris
   Juan Francisco Cantero Hurtado
@@ -273,6 +280,7 @@
   Christopher Armstrong
   Michael Hudson-Doyle
   Anders Sigfridsson
+  Nikolay Zinov
   Yasir Suhail
   Jason Michalski
   rafalgalczynski at gmail.com
@@ -282,6 +290,7 @@
   Gustavo Niemeyer
   Stephan Busemann
   Rafał Gałczyński
+  Matt Bogosian
   Christian Muirhead
   Berker Peksag
   James Lan
@@ -316,9 +325,9 @@
   Stefan Marr
   jiaaro
   Mads Kiilerich
-  Richard Lancaster
   opassembler.py
   Antony Lee
+  Jason Madden
   Yaroslav Fedevych
   Jim Hunziker
   Markus Unterwaditzer
@@ -327,6 +336,7 @@
   squeaky
   Zearin
   soareschen
+  Jonas Pfannschmidt
   Kurt Griffiths
   Mike Bayer
   Matthew Miller
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -170,12 +170,8 @@
                cmdline="--translationmodules",
                suggests=[("objspace.allworkingmodules", False)]),
 
-    BoolOption("usepycfiles", "Write and read pyc files when importing",
-               default=True),
-
     BoolOption("lonepycfiles", "Import pyc files with no matching py file",
-               default=False,
-               requires=[("objspace.usepycfiles", True)]),
+               default=False),
 
     StrOption("soabi",
               "Tag to differentiate extension modules built for different Python interpreters",
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -1,5 +1,20 @@
-Making a PyPy Release
-=====================
+The PyPy Release Process
+========================
+
+Release Policy
+++++++++++++++
+
+We try to create a stable release a few times a year. These are released on
+a branch named like release-2.x or release-4.x, and each release is tagged,
+for instance release-4.0.1. 
+
+After release, inevitably there are bug fixes. It is the responsibility of
+the commiter who fixes a bug to make sure this fix is on the release branch,
+so that we can then create a tagged bug-fix release, which will hopefully
+happen more often than stable releases.
+
+How to Create a PyPy Release
+++++++++++++++++++++++++++++
 
 Overview
 --------
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
@@ -72,6 +72,7 @@
     'Anton Gulenko':['anton gulenko', 'anton_gulenko'],
     'Richard Lancaster':['richardlancaster'],
     'William Leslie':['William ML Leslie'],
+    'Spenser Bauman':['Spenser Andrew Bauman'],
     }
 
 alias_map = {}
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -277,7 +277,6 @@
 
         if config.translation.sandbox:
             config.objspace.lonepycfiles = False
-            config.objspace.usepycfiles = False
 
         config.translating = True
 
diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -34,7 +34,7 @@
 import pypy.module.cpyext.pyerrors
 import pypy.module.cpyext.typeobject
 import pypy.module.cpyext.object
-import pypy.module.cpyext.stringobject
+import pypy.module.cpyext.bytesobject
 import pypy.module.cpyext.tupleobject
 import pypy.module.cpyext.setobject
 import pypy.module.cpyext.dictobject
diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/bytesobject.py
@@ -0,0 +1,319 @@
+from pypy.interpreter.error import OperationError
+from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import (
+    cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
+    PyObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
+from pypy.module.cpyext.pyerrors import PyErr_BadArgument
+from pypy.module.cpyext.pyobject import (
+    PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
+    make_typedescr, get_typedescr)
+
+##
+## Implementation of PyStringObject
+## ================================
+##
+## The problem
+## -----------
+##
+## PyString_AsString() must return a (non-movable) pointer to the underlying
+## buffer, whereas pypy strings are movable.  C code may temporarily store
+## this address and use it, as long as it owns a reference to the PyObject.
+## There is no "release" function to specify that the pointer is not needed
+## any more.
+##
+## Also, the pointer may be used to fill the initial value of string. This is
+## valid only when the string was just allocated, and is not used elsewhere.
+##
+## Solution
+## --------
+##
+## PyStringObject contains two additional members: the size and a pointer to a
+## char buffer; it may be NULL.
+##
+## - A string allocated by pypy will be converted into a PyStringObject with a
+##   NULL buffer.  The first time PyString_AsString() is called, memory is
+##   allocated (with flavor='raw') and content is copied.
+##
+## - A string allocated with PyString_FromStringAndSize(NULL, size) will
+##   allocate a PyStringObject structure, and a buffer with the specified
+##   size, but the reference won't be stored in the global map; there is no
+##   corresponding object in pypy.  When from_ref() or Py_INCREF() is called,
+##   the pypy string is created, and added to the global map of tracked
+##   objects.  The buffer is then supposed to be immutable.
+##
+## - _PyString_Resize() works only on not-yet-pypy'd strings, and returns a
+##   similar object.
+##
+## - PyString_Size() doesn't need to force the object.
+##
+## - There could be an (expensive!) check in from_ref() that the buffer still
+##   corresponds to the pypy gc-managed string.
+##
+
+PyStringObjectStruct = lltype.ForwardReference()
+PyStringObject = lltype.Ptr(PyStringObjectStruct)
+PyStringObjectFields = PyObjectFields + \
+    (("buffer", rffi.CCHARP), ("size", Py_ssize_t))
+cpython_struct("PyStringObject", PyStringObjectFields, PyStringObjectStruct)
+
+ at bootstrap_function
+def init_stringobject(space):
+    "Type description of PyStringObject"
+    make_typedescr(space.w_str.layout.typedef,
+                   basestruct=PyStringObject.TO,
+                   attach=string_attach,
+                   dealloc=string_dealloc,
+                   realize=string_realize)
+
+PyString_Check, PyString_CheckExact = build_type_checkers("String", "w_str")
+
+def new_empty_str(space, length):
+    """
+    Allocate a PyStringObject and its buffer, but without a corresponding
+    interpreter object.  The buffer may be mutated, until string_realize() is
+    called.  Refcount of the result is 1.
+    """
+    typedescr = get_typedescr(space.w_str.layout.typedef)
+    py_obj = typedescr.allocate(space, space.w_str)
+    py_str = rffi.cast(PyStringObject, py_obj)
+
+    buflen = length + 1
+    py_str.c_size = length
+    py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen,
+                                    flavor='raw', zero=True)
+    return py_str
+
+def string_attach(space, py_obj, w_obj):
+    """
+    Fills a newly allocated PyStringObject with the given string object. The
+    buffer must not be modified.
+    """
+    py_str = rffi.cast(PyStringObject, py_obj)
+    py_str.c_size = len(space.str_w(w_obj))
+    py_str.c_buffer = lltype.nullptr(rffi.CCHARP.TO)
+
+def string_realize(space, py_obj):
+    """
+    Creates the string in the interpreter. The PyStringObject buffer must not
+    be modified after this call.
+    """
+    py_str = rffi.cast(PyStringObject, py_obj)
+    s = rffi.charpsize2str(py_str.c_buffer, py_str.c_size)
+    w_obj = space.wrap(s)
+    track_reference(space, py_obj, w_obj)
+    return w_obj
+
+ at cpython_api([PyObject], lltype.Void, header=None)
+def string_dealloc(space, py_obj):
+    """Frees allocated PyStringObject resources.
+    """
+    py_str = rffi.cast(PyStringObject, py_obj)
+    if py_str.c_buffer:
+        lltype.free(py_str.c_buffer, flavor="raw")
+    from pypy.module.cpyext.object import PyObject_dealloc
+    PyObject_dealloc(space, py_obj)
+
+#_______________________________________________________________________
+
+ at cpython_api([CONST_STRING, Py_ssize_t], PyObject)
+def PyString_FromStringAndSize(space, char_p, length):
+    if char_p:
+        s = rffi.charpsize2str(char_p, length)
+        return make_ref(space, space.wrap(s))
+    else:
+        return rffi.cast(PyObject, new_empty_str(space, length))
+
+ at cpython_api([CONST_STRING], PyObject)
+def PyString_FromString(space, char_p):
+    s = rffi.charp2str(char_p)
+    return space.wrap(s)
+
+ at cpython_api([PyObject], rffi.CCHARP, error=0)
+def PyString_AsString(space, ref):
+    if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
+        pass    # typecheck returned "ok" without forcing 'ref' at all
+    elif not PyString_Check(space, ref):   # otherwise, use the alternate way
+        raise OperationError(space.w_TypeError, space.wrap(
+            "PyString_AsString only support strings"))
+    ref_str = rffi.cast(PyStringObject, ref)
+    if not ref_str.c_buffer:
+        # copy string buffer
+        w_str = from_ref(space, ref)
+        s = space.str_w(w_str)
+        ref_str.c_buffer = rffi.str2charp(s)
+    return ref_str.c_buffer
+
+ at cpython_api([PyObject, rffi.CCHARPP, rffi.CArrayPtr(Py_ssize_t)], rffi.INT_real, error=-1)
+def PyString_AsStringAndSize(space, ref, buffer, length):
+    if not PyString_Check(space, ref):
+        raise OperationError(space.w_TypeError, space.wrap(
+            "PyString_AsStringAndSize only support strings"))
+    ref_str = rffi.cast(PyStringObject, ref)
+    if not ref_str.c_buffer:
+        # copy string buffer
+        w_str = from_ref(space, ref)
+        s = space.str_w(w_str)
+        ref_str.c_buffer = rffi.str2charp(s)
+    buffer[0] = ref_str.c_buffer
+    if length:
+        length[0] = ref_str.c_size
+    else:
+        i = 0
+        while ref_str.c_buffer[i] != '\0':
+            i += 1
+        if i != ref_str.c_size:
+            raise OperationError(space.w_TypeError, space.wrap(
+                "expected string without null bytes"))
+    return 0
+
+ at cpython_api([PyObject], Py_ssize_t, error=-1)
+def PyString_Size(space, ref):
+    if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
+        ref = rffi.cast(PyStringObject, ref)
+        return ref.c_size
+    else:
+        w_obj = from_ref(space, ref)
+        return space.len_w(w_obj)
+
+ at cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
+def _PyString_Resize(space, ref, newsize):
+    """A way to resize a string object even though it is "immutable". Only use this to
+    build up a brand new string object; don't use this if the string may already be
+    known in other parts of the code.  It is an error to call this function if the
+    refcount on the input string object is not one. Pass the address of an existing
+    string object as an lvalue (it may be written into), and the new size desired.
+    On success, *string holds the resized string object and 0 is returned;
+    the address in *string may differ from its input value.  If the reallocation
+    fails, the original string object at *string is deallocated, *string is
+    set to NULL, a memory exception is set, and -1 is returned.
+    """
+    # XXX always create a new string so far
+    py_str = rffi.cast(PyStringObject, ref[0])
+    if not py_str.c_buffer:
+        raise OperationError(space.w_SystemError, space.wrap(
+            "_PyString_Resize called on already created string"))
+    try:
+        py_newstr = new_empty_str(space, newsize)
+    except MemoryError:
+        Py_DecRef(space, ref[0])
+        ref[0] = lltype.nullptr(PyObject.TO)
+        raise
+    to_cp = newsize
+    oldsize = py_str.c_size
+    if oldsize < newsize:
+        to_cp = oldsize
+    for i in range(to_cp):
+        py_newstr.c_buffer[i] = py_str.c_buffer[i]
+    Py_DecRef(space, ref[0])
+    ref[0] = rffi.cast(PyObject, py_newstr)
+    return 0
+
+ at cpython_api([PyObject, PyObject], rffi.INT, error=CANNOT_FAIL)
+def _PyString_Eq(space, w_str1, w_str2):
+    return space.eq_w(w_str1, w_str2)
+
+ at cpython_api([PyObjectP, PyObject], lltype.Void)
+def PyString_Concat(space, ref, w_newpart):
+    """Create a new string object in *string containing the contents of newpart
+    appended to string; the caller will own the new reference.  The reference to
+    the old value of string will be stolen.  If the new string cannot be created,
+    the old reference to string will still be discarded and the value of
+    *string will be set to NULL; the appropriate exception will be set."""
+
+    if not ref[0]:
+        return
+
+    if w_newpart is None or not PyString_Check(space, ref[0]) or \
+            not PyString_Check(space, w_newpart):
+        Py_DecRef(space, ref[0])
+        ref[0] = lltype.nullptr(PyObject.TO)
+        return
+    w_str = from_ref(space, ref[0])
+    w_newstr = space.add(w_str, w_newpart)
+    Py_DecRef(space, ref[0])
+    ref[0] = make_ref(space, w_newstr)
+
+ at cpython_api([PyObjectP, PyObject], lltype.Void)
+def PyString_ConcatAndDel(space, ref, newpart):
+    """Create a new string object in *string containing the contents of newpart
+    appended to string.  This version decrements the reference count of newpart."""
+    PyString_Concat(space, ref, newpart)
+    Py_DecRef(space, newpart)
+
+ at cpython_api([PyObject, PyObject], PyObject)
+def PyString_Format(space, w_format, w_args):
+    """Return a new string object from format and args. Analogous to format %
+    args.  The args argument must be a tuple."""
+    return space.mod(w_format, w_args)
+
+ at cpython_api([CONST_STRING], PyObject)
+def PyString_InternFromString(space, string):
+    """A combination of PyString_FromString() and
+    PyString_InternInPlace(), returning either a new string object that has
+    been interned, or a new ("owned") reference to an earlier interned string
+    object with the same value."""
+    s = rffi.charp2str(string)
+    return space.new_interned_str(s)
+
+ at cpython_api([PyObjectP], lltype.Void)
+def PyString_InternInPlace(space, string):
+    """Intern the argument *string in place.  The argument must be the
+    address of a pointer variable pointing to a Python string object.
+    If there is an existing interned string that is the same as
+    *string, it sets *string to it (decrementing the reference count
+    of the old string object and incrementing the reference count of
+    the interned string object), otherwise it leaves *string alone and
+    interns it (incrementing its reference count).  (Clarification:
+    even though there is a lot of talk about reference counts, think
+    of this function as reference-count-neutral; you own the object
+    after the call if and only if you owned it before the call.)
+
+    This function is not available in 3.x and does not have a PyBytes
+    alias."""
+    w_str = from_ref(space, string[0])
+    w_str = space.new_interned_w_str(w_str)
+    Py_DecRef(space, string[0])
+    string[0] = make_ref(space, w_str)
+
+ at cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject)
+def PyString_AsEncodedObject(space, w_str, encoding, errors):
+    """Encode a string object using the codec registered for encoding and return
+    the result as Python object. encoding and errors have the same meaning as
+    the parameters of the same name in the string encode() method. The codec to
+    be used is looked up using the Python codec registry. Return NULL if an
+    exception was raised by the codec.
+
+    This function is not available in 3.x and does not have a PyBytes alias."""
+    if not PyString_Check(space, w_str):
+        PyErr_BadArgument(space)
+
+    w_encoding = w_errors = None
+    if encoding:
+        w_encoding = space.wrap(rffi.charp2str(encoding))
+    if errors:
+        w_errors = space.wrap(rffi.charp2str(errors))
+    return space.call_method(w_str, 'encode', w_encoding, w_errors)
+
+ at cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject)
+def PyString_AsDecodedObject(space, w_str, encoding, errors):
+    """Decode a string object by passing it to the codec registered
+    for encoding and return the result as Python object. encoding and
+    errors have the same meaning as the parameters of the same name in
+    the string encode() method.  The codec to be used is looked up
+    using the Python codec registry. Return NULL if an exception was
+    raised by the codec.
+
+    This function is not available in 3.x and does not have a PyBytes alias."""
+    if not PyString_Check(space, w_str):
+        PyErr_BadArgument(space)
+
+    w_encoding = w_errors = None
+    if encoding:
+        w_encoding = space.wrap(rffi.charp2str(encoding))
+    if errors:
+        w_errors = space.wrap(rffi.charp2str(errors))
+    return space.call_method(w_str, "decode", w_encoding, w_errors)
+
+ at cpython_api([PyObject, PyObject], PyObject)
+def _PyString_Join(space, w_sep, w_seq):
+    return space.call_method(w_sep, 'join', w_seq)
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -191,7 +191,7 @@
 def from_ref(space, ref):
     """
     Finds the interpreter object corresponding to the given reference.  If the
-    object is not yet realized (see stringobject.py), creates it.
+    object is not yet realized (see bytesobject.py), creates it.
     """
     assert is_pyobj(ref)
     if not ref:
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
deleted file mode 100644
--- a/pypy/module/cpyext/stringobject.py
+++ /dev/null
@@ -1,319 +0,0 @@
-from pypy.interpreter.error import OperationError
-from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import (
-    cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
-    PyObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
-from pypy.module.cpyext.pyerrors import PyErr_BadArgument
-from pypy.module.cpyext.pyobject import (
-    PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
-    make_typedescr, get_typedescr)
-
-##
-## Implementation of PyStringObject
-## ================================
-##
-## The problem
-## -----------
-##
-## PyString_AsString() must return a (non-movable) pointer to the underlying
-## buffer, whereas pypy strings are movable.  C code may temporarily store
-## this address and use it, as long as it owns a reference to the PyObject.
-## There is no "release" function to specify that the pointer is not needed
-## any more.
-##
-## Also, the pointer may be used to fill the initial value of string. This is
-## valid only when the string was just allocated, and is not used elsewhere.
-##
-## Solution
-## --------
-##
-## PyStringObject contains two additional members: the size and a pointer to a
-## char buffer; it may be NULL.
-##
-## - A string allocated by pypy will be converted into a PyStringObject with a
-##   NULL buffer.  The first time PyString_AsString() is called, memory is
-##   allocated (with flavor='raw') and content is copied.
-##
-## - A string allocated with PyString_FromStringAndSize(NULL, size) will
-##   allocate a PyStringObject structure, and a buffer with the specified
-##   size, but the reference won't be stored in the global map; there is no
-##   corresponding object in pypy.  When from_ref() or Py_INCREF() is called,
-##   the pypy string is created, and added to the global map of tracked
-##   objects.  The buffer is then supposed to be immutable.
-##
-## - _PyString_Resize() works only on not-yet-pypy'd strings, and returns a
-##   similar object.
-##
-## - PyString_Size() doesn't need to force the object.
-##
-## - There could be an (expensive!) check in from_ref() that the buffer still
-##   corresponds to the pypy gc-managed string.
-##
-
-PyStringObjectStruct = lltype.ForwardReference()
-PyStringObject = lltype.Ptr(PyStringObjectStruct)
-PyStringObjectFields = PyObjectFields + \
-    (("buffer", rffi.CCHARP), ("size", Py_ssize_t))
-cpython_struct("PyStringObject", PyStringObjectFields, PyStringObjectStruct)
-
- at bootstrap_function
-def init_stringobject(space):
-    "Type description of PyStringObject"
-    make_typedescr(space.w_str.layout.typedef,
-                   basestruct=PyStringObject.TO,
-                   attach=string_attach,
-                   dealloc=string_dealloc,
-                   realize=string_realize)
-
-PyString_Check, PyString_CheckExact = build_type_checkers("String", "w_str")
-
-def new_empty_str(space, length):
-    """
-    Allocate a PyStringObject and its buffer, but without a corresponding
-    interpreter object.  The buffer may be mutated, until string_realize() is
-    called.  Refcount of the result is 1.
-    """
-    typedescr = get_typedescr(space.w_str.layout.typedef)
-    py_obj = typedescr.allocate(space, space.w_str)
-    py_str = rffi.cast(PyStringObject, py_obj)
-
-    buflen = length + 1
-    py_str.c_size = length
-    py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen,
-                                    flavor='raw', zero=True)
-    return py_str
-
-def string_attach(space, py_obj, w_obj):
-    """
-    Fills a newly allocated PyStringObject with the given string object. The
-    buffer must not be modified.
-    """
-    py_str = rffi.cast(PyStringObject, py_obj)
-    py_str.c_size = len(space.str_w(w_obj))
-    py_str.c_buffer = lltype.nullptr(rffi.CCHARP.TO)
-
-def string_realize(space, py_obj):
-    """
-    Creates the string in the interpreter. The PyStringObject buffer must not
-    be modified after this call.
-    """
-    py_str = rffi.cast(PyStringObject, py_obj)
-    s = rffi.charpsize2str(py_str.c_buffer, py_str.c_size)
-    w_obj = space.wrap(s)
-    track_reference(space, py_obj, w_obj)
-    return w_obj
-
- at cpython_api([PyObject], lltype.Void, header=None)
-def string_dealloc(space, py_obj):
-    """Frees allocated PyStringObject resources.
-    """
-    py_str = rffi.cast(PyStringObject, py_obj)
-    if py_str.c_buffer:
-        lltype.free(py_str.c_buffer, flavor="raw")
-    from pypy.module.cpyext.object import PyObject_dealloc
-    PyObject_dealloc(space, py_obj)
-
-#_______________________________________________________________________
-
- at cpython_api([CONST_STRING, Py_ssize_t], PyObject)
-def PyString_FromStringAndSize(space, char_p, length):
-    if char_p:
-        s = rffi.charpsize2str(char_p, length)
-        return make_ref(space, space.wrap(s))
-    else:
-        return rffi.cast(PyObject, new_empty_str(space, length))
-
- at cpython_api([CONST_STRING], PyObject)
-def PyString_FromString(space, char_p):
-    s = rffi.charp2str(char_p)
-    return space.wrap(s)
-
- at cpython_api([PyObject], rffi.CCHARP, error=0)
-def PyString_AsString(space, ref):
-    if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
-        pass    # typecheck returned "ok" without forcing 'ref' at all
-    elif not PyString_Check(space, ref):   # otherwise, use the alternate way
-        raise OperationError(space.w_TypeError, space.wrap(
-            "PyString_AsString only support strings"))
-    ref_str = rffi.cast(PyStringObject, ref)
-    if not ref_str.c_buffer:
-        # copy string buffer
-        w_str = from_ref(space, ref)
-        s = space.str_w(w_str)
-        ref_str.c_buffer = rffi.str2charp(s)
-    return ref_str.c_buffer
-
- at cpython_api([PyObject, rffi.CCHARPP, rffi.CArrayPtr(Py_ssize_t)], rffi.INT_real, error=-1)
-def PyString_AsStringAndSize(space, ref, buffer, length):
-    if not PyString_Check(space, ref):
-        raise OperationError(space.w_TypeError, space.wrap(
-            "PyString_AsStringAndSize only support strings"))
-    ref_str = rffi.cast(PyStringObject, ref)
-    if not ref_str.c_buffer:
-        # copy string buffer
-        w_str = from_ref(space, ref)
-        s = space.str_w(w_str)
-        ref_str.c_buffer = rffi.str2charp(s)
-    buffer[0] = ref_str.c_buffer
-    if length:
-        length[0] = ref_str.c_size
-    else:
-        i = 0
-        while ref_str.c_buffer[i] != '\0':
-            i += 1
-        if i != ref_str.c_size:
-            raise OperationError(space.w_TypeError, space.wrap(
-                "expected string without null bytes"))
-    return 0
-
- at cpython_api([PyObject], Py_ssize_t, error=-1)
-def PyString_Size(space, ref):
-    if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
-        ref = rffi.cast(PyStringObject, ref)
-        return ref.c_size
-    else:
-        w_obj = from_ref(space, ref)
-        return space.len_w(w_obj)
-
- at cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
-def _PyString_Resize(space, ref, newsize):
-    """A way to resize a string object even though it is "immutable". Only use this to
-    build up a brand new string object; don't use this if the string may already be
-    known in other parts of the code.  It is an error to call this function if the
-    refcount on the input string object is not one. Pass the address of an existing
-    string object as an lvalue (it may be written into), and the new size desired.
-    On success, *string holds the resized string object and 0 is returned;
-    the address in *string may differ from its input value.  If the reallocation
-    fails, the original string object at *string is deallocated, *string is
-    set to NULL, a memory exception is set, and -1 is returned.
-    """
-    # XXX always create a new string so far
-    py_str = rffi.cast(PyStringObject, ref[0])
-    if not py_str.c_buffer:
-        raise OperationError(space.w_SystemError, space.wrap(
-            "_PyString_Resize called on already created string"))
-    try:
-        py_newstr = new_empty_str(space, newsize)
-    except MemoryError:
-        Py_DecRef(space, ref[0])
-        ref[0] = lltype.nullptr(PyObject.TO)
-        raise
-    to_cp = newsize
-    oldsize = py_str.c_size
-    if oldsize < newsize:
-        to_cp = oldsize
-    for i in range(to_cp):
-        py_newstr.c_buffer[i] = py_str.c_buffer[i]
-    Py_DecRef(space, ref[0])
-    ref[0] = rffi.cast(PyObject, py_newstr)
-    return 0
-
- at cpython_api([PyObject, PyObject], rffi.INT, error=CANNOT_FAIL)
-def _PyString_Eq(space, w_str1, w_str2):
-    return space.eq_w(w_str1, w_str2)
-
- at cpython_api([PyObjectP, PyObject], lltype.Void)
-def PyString_Concat(space, ref, w_newpart):
-    """Create a new string object in *string containing the contents of newpart
-    appended to string; the caller will own the new reference.  The reference to
-    the old value of string will be stolen.  If the new string cannot be created,
-    the old reference to string will still be discarded and the value of
-    *string will be set to NULL; the appropriate exception will be set."""
-
-    if not ref[0]:
-        return
-
-    if w_newpart is None or not PyString_Check(space, ref[0]) or \
-            not PyString_Check(space, w_newpart):
-        Py_DecRef(space, ref[0])
-        ref[0] = lltype.nullptr(PyObject.TO)
-        return
-    w_str = from_ref(space, ref[0])
-    w_newstr = space.add(w_str, w_newpart)
-    Py_DecRef(space, ref[0])
-    ref[0] = make_ref(space, w_newstr)
-
- at cpython_api([PyObjectP, PyObject], lltype.Void)
-def PyString_ConcatAndDel(space, ref, newpart):
-    """Create a new string object in *string containing the contents of newpart
-    appended to string.  This version decrements the reference count of newpart."""
-    PyString_Concat(space, ref, newpart)
-    Py_DecRef(space, newpart)
-
- at cpython_api([PyObject, PyObject], PyObject)
-def PyString_Format(space, w_format, w_args):
-    """Return a new string object from format and args. Analogous to format %
-    args.  The args argument must be a tuple."""
-    return space.mod(w_format, w_args)
-
- at cpython_api([CONST_STRING], PyObject)
-def PyString_InternFromString(space, string):
-    """A combination of PyString_FromString() and
-    PyString_InternInPlace(), returning either a new string object that has
-    been interned, or a new ("owned") reference to an earlier interned string
-    object with the same value."""
-    s = rffi.charp2str(string)
-    return space.new_interned_str(s)
-
- at cpython_api([PyObjectP], lltype.Void)
-def PyString_InternInPlace(space, string):
-    """Intern the argument *string in place.  The argument must be the
-    address of a pointer variable pointing to a Python string object.
-    If there is an existing interned string that is the same as
-    *string, it sets *string to it (decrementing the reference count
-    of the old string object and incrementing the reference count of
-    the interned string object), otherwise it leaves *string alone and
-    interns it (incrementing its reference count).  (Clarification:
-    even though there is a lot of talk about reference counts, think
-    of this function as reference-count-neutral; you own the object
-    after the call if and only if you owned it before the call.)
-
-    This function is not available in 3.x and does not have a PyBytes
-    alias."""
-    w_str = from_ref(space, string[0])
-    w_str = space.new_interned_w_str(w_str)
-    Py_DecRef(space, string[0])
-    string[0] = make_ref(space, w_str)
-
- at cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject)
-def PyString_AsEncodedObject(space, w_str, encoding, errors):
-    """Encode a string object using the codec registered for encoding and return
-    the result as Python object. encoding and errors have the same meaning as
-    the parameters of the same name in the string encode() method. The codec to
-    be used is looked up using the Python codec registry. Return NULL if an
-    exception was raised by the codec.
-
-    This function is not available in 3.x and does not have a PyBytes alias."""
-    if not PyString_Check(space, w_str):
-        PyErr_BadArgument(space)
-
-    w_encoding = w_errors = None
-    if encoding:
-        w_encoding = space.wrap(rffi.charp2str(encoding))
-    if errors:
-        w_errors = space.wrap(rffi.charp2str(errors))
-    return space.call_method(w_str, 'encode', w_encoding, w_errors)
-
- at cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject)
-def PyString_AsDecodedObject(space, w_str, encoding, errors):
-    """Decode a string object by passing it to the codec registered
-    for encoding and return the result as Python object. encoding and
-    errors have the same meaning as the parameters of the same name in
-    the string encode() method.  The codec to be used is looked up
-    using the Python codec registry. Return NULL if an exception was
-    raised by the codec.
-
-    This function is not available in 3.x and does not have a PyBytes alias."""
-    if not PyString_Check(space, w_str):
-        PyErr_BadArgument(space)
-
-    w_encoding = w_errors = None
-    if encoding:
-        w_encoding = space.wrap(rffi.charp2str(encoding))
-    if errors:
-        w_errors = space.wrap(rffi.charp2str(errors))
-    return space.call_method(w_str, "decode", w_encoding, w_errors)
-
- at cpython_api([PyObject, PyObject], PyObject)
-def _PyString_Join(space, w_sep, w_seq):
-    return space.call_method(w_sep, 'join', w_seq)
diff --git a/pypy/module/cpyext/structmember.py b/pypy/module/cpyext/structmember.py
--- a/pypy/module/cpyext/structmember.py
+++ b/pypy/module/cpyext/structmember.py
@@ -6,7 +6,7 @@
 from pypy.module.cpyext.intobject import PyInt_AsLong, PyInt_AsUnsignedLong
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, from_ref, make_ref
-from pypy.module.cpyext.stringobject import (
+from pypy.module.cpyext.bytesobject import (
     PyString_FromString, PyString_FromStringAndSize)
 from pypy.module.cpyext.floatobject import PyFloat_AsDouble
 from pypy.module.cpyext.longobject import (
diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -0,0 +1,329 @@
+from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.bytesobject import new_empty_str, PyStringObject
+from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP
+from pypy.module.cpyext.pyobject import Py_DecRef, from_ref, make_ref
+
+import py
+import sys
+
+class AppTestStringObject(AppTestCpythonExtensionBase):
+    def test_stringobject(self):
+        module = self.import_extension('foo', [
+            ("get_hello1", "METH_NOARGS",
+             """
+                 return PyString_FromStringAndSize(
+                     "Hello world<should not be included>", 11);
+             """),
+            ("get_hello2", "METH_NOARGS",
+             """
+                 return PyString_FromString("Hello world");
+             """),
+            ("test_Size", "METH_NOARGS",
+             """
+                 PyObject* s = PyString_FromString("Hello world");
+                 int result = 0;
+
+                 if(PyString_Size(s) == 11) {
+                     result = 1;
+                 }
+                 if(s->ob_type->tp_basicsize != sizeof(void*)*5)
+                     result = 0;
+                 Py_DECREF(s);
+                 return PyBool_FromLong(result);
+             """),
+            ("test_Size_exception", "METH_NOARGS",
+             """
+                 PyObject* f = PyFloat_FromDouble(1.0);
+                 Py_ssize_t size = PyString_Size(f);
+
+                 Py_DECREF(f);
+                 return NULL;
+             """),
+             ("test_is_string", "METH_VARARGS",
+             """
+                return PyBool_FromLong(PyString_Check(PyTuple_GetItem(args, 0)));
+             """)])
+        assert module.get_hello1() == 'Hello world'
+        assert module.get_hello2() == 'Hello world'
+        assert module.test_Size()
+        raises(TypeError, module.test_Size_exception)
+
+        assert module.test_is_string("")
+        assert not module.test_is_string(())
+
+    def test_string_buffer_init(self):
+        module = self.import_extension('foo', [
+            ("getstring", "METH_NOARGS",
+             """
+                 PyObject *s, *t;
+                 char* c;
+                 Py_ssize_t len;
+
+                 s = PyString_FromStringAndSize(NULL, 4);
+                 if (s == NULL)
+                    return NULL;
+                 t = PyString_FromStringAndSize(NULL, 3);
+                 if (t == NULL)
+                    return NULL;
+                 Py_DECREF(t);
+                 c = PyString_AsString(s);
+                 c[0] = 'a';
+                 c[1] = 'b';
+                 c[3] = 'c';
+                 return s;
+             """),
+            ])
+        s = module.getstring()
+        assert len(s) == 4
+        assert s == 'ab\x00c'
+
+
+
+    def test_AsString(self):
+        module = self.import_extension('foo', [
+            ("getstring", "METH_NOARGS",
+             """
+                 PyObject* s1 = PyString_FromStringAndSize("test", 4);
+                 char* c = PyString_AsString(s1);
+                 PyObject* s2 = PyString_FromStringAndSize(c, 4);
+                 Py_DECREF(s1);
+                 return s2;
+             """),
+            ])
+        s = module.getstring()
+        assert s == 'test'
+
+    def test_py_string_as_string(self):
+        module = self.import_extension('foo', [
+            ("string_as_string", "METH_VARARGS",
+             '''
+             return PyString_FromStringAndSize(PyString_AsString(
+                       PyTuple_GetItem(args, 0)), 4);
+             '''
+            )])
+        assert module.string_as_string("huheduwe") == "huhe"
+
+    def test_py_string_as_string_None(self):
+        module = self.import_extension('foo', [
+            ("string_None", "METH_VARARGS",
+             '''
+             return PyString_AsString(Py_None);
+             '''
+            )])
+        raises(TypeError, module.string_None)
+
+    def test_AsStringAndSize(self):
+        module = self.import_extension('foo', [
+            ("getstring", "METH_NOARGS",
+             """
+                 PyObject* s1 = PyString_FromStringAndSize("te\\0st", 5);
+                 char *buf;
+                 Py_ssize_t len;
+                 if (PyString_AsStringAndSize(s1, &buf, &len) < 0)
+                     return NULL;
+                 if (len != 5) {
+                     PyErr_SetString(PyExc_AssertionError, "Bad Length");
+                     return NULL;
+                 }
+                 if (PyString_AsStringAndSize(s1, &buf, NULL) >= 0) {
+                     PyErr_SetString(PyExc_AssertionError, "Should Have failed");
+                     return NULL;
+                 }
+                 PyErr_Clear();
+                 Py_DECREF(s1);
+                 Py_INCREF(Py_None);
+                 return Py_None;
+             """),
+            ])
+        module.getstring()
+
+    def test_format_v(self):
+        module = self.import_extension('foo', [
+            ("test_string_format_v", "METH_VARARGS",
+             '''
+                 return helper("bla %d ble %s\\n",
+                        PyInt_AsLong(PyTuple_GetItem(args, 0)),
+                        PyString_AsString(PyTuple_GetItem(args, 1)));
+             '''
+             )
+            ], prologue='''
+            PyObject* helper(char* fmt, ...)
+            {
+              va_list va;
+              PyObject* res;
+              va_start(va, fmt);
+              res = PyString_FromFormatV(fmt, va);
+              va_end(va);
+              return res;
+            }
+            ''')
+        res = module.test_string_format_v(1, "xyz")
+        assert res == "bla 1 ble xyz\n"
+
+    def test_format(self):
+        module = self.import_extension('foo', [
+            ("test_string_format", "METH_VARARGS",
+             '''
+                 return PyString_FromFormat("bla %d ble %s\\n",
+                        PyInt_AsLong(PyTuple_GetItem(args, 0)),
+                        PyString_AsString(PyTuple_GetItem(args, 1)));
+             '''
+             )
+            ])
+        res = module.test_string_format(1, "xyz")
+        assert res == "bla 1 ble xyz\n"
+
+    def test_intern_inplace(self):
+        module = self.import_extension('foo', [
+            ("test_intern_inplace", "METH_O",
+             '''
+                 PyObject *s = args;
+                 Py_INCREF(s);
+                 PyString_InternInPlace(&s);
+                 return s;
+             '''
+             )
+            ])
+        # This does not test much, but at least the refcounts are checked.
+        assert module.test_intern_inplace('s') == 's'
+
+class TestString(BaseApiTest):
+    def test_string_resize(self, space, api):
+        py_str = new_empty_str(space, 10)
+        ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        py_str.c_buffer[0] = 'a'
+        py_str.c_buffer[1] = 'b'
+        py_str.c_buffer[2] = 'c'
+        ar[0] = rffi.cast(PyObject, py_str)
+        api._PyString_Resize(ar, 3)
+        py_str = rffi.cast(PyStringObject, ar[0])
+        assert py_str.c_size == 3
+        assert py_str.c_buffer[1] == 'b'
+        assert py_str.c_buffer[3] == '\x00'
+        # the same for growing
+        ar[0] = rffi.cast(PyObject, py_str)
+        api._PyString_Resize(ar, 10)
+        py_str = rffi.cast(PyStringObject, ar[0])
+        assert py_str.c_size == 10
+        assert py_str.c_buffer[1] == 'b'
+        assert py_str.c_buffer[10] == '\x00'
+        Py_DecRef(space, ar[0])
+        lltype.free(ar, flavor='raw')
+
+    def test_string_buffer(self, space, api):
+        py_str = new_empty_str(space, 10)
+        c_buf = py_str.c_ob_type.c_tp_as_buffer
+        assert c_buf
+        py_obj = rffi.cast(PyObject, py_str)
+        assert c_buf.c_bf_getsegcount(py_obj, lltype.nullptr(Py_ssize_tP.TO)) == 1
+        ref = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
+        assert c_buf.c_bf_getsegcount(py_obj, ref) == 1
+        assert ref[0] == 10
+        lltype.free(ref, flavor='raw')
+        ref = lltype.malloc(rffi.VOIDPP.TO, 1, flavor='raw')
+        assert c_buf.c_bf_getreadbuffer(py_obj, 0, ref) == 10
+        lltype.free(ref, flavor='raw')
+        Py_DecRef(space, py_obj)
+
+    def test_Concat(self, space, api):
+        ref = make_ref(space, space.wrap('abc'))
+        ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        ptr[0] = ref
+        prev_refcnt = ref.c_ob_refcnt
+        api.PyString_Concat(ptr, space.wrap('def'))
+        assert ref.c_ob_refcnt == prev_refcnt - 1
+        assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
+        api.PyString_Concat(ptr, space.w_None)
+        assert not ptr[0]
+        ptr[0] = lltype.nullptr(PyObject.TO)
+        api.PyString_Concat(ptr, space.wrap('def')) # should not crash
+        lltype.free(ptr, flavor='raw')
+
+    def test_ConcatAndDel(self, space, api):
+        ref1 = make_ref(space, space.wrap('abc'))
+        ref2 = make_ref(space, space.wrap('def'))
+        ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        ptr[0] = ref1
+        prev_refcnf = ref2.c_ob_refcnt
+        api.PyString_ConcatAndDel(ptr, ref2)
+        assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
+        assert ref2.c_ob_refcnt == prev_refcnf - 1
+        Py_DecRef(space, ptr[0])
+        ptr[0] = lltype.nullptr(PyObject.TO)
+        ref2 = make_ref(space, space.wrap('foo'))
+        prev_refcnf = ref2.c_ob_refcnt
+        api.PyString_ConcatAndDel(ptr, ref2) # should not crash
+        assert ref2.c_ob_refcnt == prev_refcnf - 1
+        lltype.free(ptr, flavor='raw')
+
+    def test_format(self, space, api):
+        assert "1 2" == space.unwrap(
+            api.PyString_Format(space.wrap('%s %d'), space.wrap((1, 2))))
+
+    def test_asbuffer(self, space, api):
+        bufp = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
+        lenp = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
+
+        w_text = space.wrap("text")
+        assert api.PyObject_AsCharBuffer(w_text, bufp, lenp) == 0
+        assert lenp[0] == 4
+        assert rffi.charp2str(bufp[0]) == 'text'
+
+        lltype.free(bufp, flavor='raw')
+        lltype.free(lenp, flavor='raw')
+
+    def test_intern(self, space, api):
+        buf = rffi.str2charp("test")
+        w_s1 = api.PyString_InternFromString(buf)
+        w_s2 = api.PyString_InternFromString(buf)
+        rffi.free_charp(buf)
+        assert w_s1 is w_s2
+
+    def test_AsEncodedObject(self, space, api):
+        ptr = space.wrap('abc')
+
+        errors = rffi.str2charp("strict")
+
+        encoding = rffi.str2charp("hex")
+        res = api.PyString_AsEncodedObject(
+            ptr, encoding, errors)
+        assert space.unwrap(res) == "616263"
+
+        res = api.PyString_AsEncodedObject(
+            ptr, encoding, lltype.nullptr(rffi.CCHARP.TO))
+        assert space.unwrap(res) == "616263"
+        rffi.free_charp(encoding)
+
+        encoding = rffi.str2charp("unknown_encoding")
+        self.raises(space, api, LookupError, api.PyString_AsEncodedObject,
+                    ptr, encoding, errors)
+        rffi.free_charp(encoding)
+
+        rffi.free_charp(errors)
+
+        res = api.PyString_AsEncodedObject(
+            ptr, lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO))
+        assert space.unwrap(res) == "abc"
+
+        self.raises(space, api, TypeError, api.PyString_AsEncodedObject,
+            space.wrap(2), lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO)
+        )
+
+    def test_AsDecodedObject(self, space, api):
+        w_str = space.wrap('caf\xe9')
+        encoding = rffi.str2charp("latin-1")
+        w_res = api.PyString_AsDecodedObject(w_str, encoding, None)
+        rffi.free_charp(encoding)
+        assert space.unwrap(w_res) == u"caf\xe9"
+
+    def test_eq(self, space, api):
+        assert 1 == api._PyString_Eq(space.wrap("hello"), space.wrap("hello"))
+        assert 0 == api._PyString_Eq(space.wrap("hello"), space.wrap("world"))
+
+    def test_join(self, space, api):
+        w_sep = space.wrap('<sep>')
+        w_seq = space.wrap(['a', 'b'])
+        w_joined = api._PyString_Join(w_sep, w_seq)
+        assert space.unwrap(w_joined) == 'a<sep>b'
diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
deleted file mode 100644
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ /dev/null
@@ -1,329 +0,0 @@
-from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
-from pypy.module.cpyext.stringobject import new_empty_str, PyStringObject
-from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP
-from pypy.module.cpyext.pyobject import Py_DecRef, from_ref, make_ref
-
-import py
-import sys
-
-class AppTestStringObject(AppTestCpythonExtensionBase):
-    def test_stringobject(self):
-        module = self.import_extension('foo', [
-            ("get_hello1", "METH_NOARGS",
-             """
-                 return PyString_FromStringAndSize(
-                     "Hello world<should not be included>", 11);
-             """),
-            ("get_hello2", "METH_NOARGS",
-             """
-                 return PyString_FromString("Hello world");
-             """),
-            ("test_Size", "METH_NOARGS",
-             """
-                 PyObject* s = PyString_FromString("Hello world");
-                 int result = 0;
-
-                 if(PyString_Size(s) == 11) {
-                     result = 1;
-                 }
-                 if(s->ob_type->tp_basicsize != sizeof(void*)*5)
-                     result = 0;
-                 Py_DECREF(s);
-                 return PyBool_FromLong(result);
-             """),
-            ("test_Size_exception", "METH_NOARGS",
-             """
-                 PyObject* f = PyFloat_FromDouble(1.0);
-                 Py_ssize_t size = PyString_Size(f);
-
-                 Py_DECREF(f);
-                 return NULL;
-             """),
-             ("test_is_string", "METH_VARARGS",
-             """
-                return PyBool_FromLong(PyString_Check(PyTuple_GetItem(args, 0)));
-             """)])
-        assert module.get_hello1() == 'Hello world'
-        assert module.get_hello2() == 'Hello world'
-        assert module.test_Size()
-        raises(TypeError, module.test_Size_exception)
-
-        assert module.test_is_string("")
-        assert not module.test_is_string(())
-
-    def test_string_buffer_init(self):
-        module = self.import_extension('foo', [
-            ("getstring", "METH_NOARGS",
-             """
-                 PyObject *s, *t;
-                 char* c;
-                 Py_ssize_t len;
-
-                 s = PyString_FromStringAndSize(NULL, 4);
-                 if (s == NULL)
-                    return NULL;
-                 t = PyString_FromStringAndSize(NULL, 3);
-                 if (t == NULL)
-                    return NULL;
-                 Py_DECREF(t);
-                 c = PyString_AsString(s);
-                 c[0] = 'a';
-                 c[1] = 'b';
-                 c[3] = 'c';
-                 return s;
-             """),
-            ])
-        s = module.getstring()
-        assert len(s) == 4
-        assert s == 'ab\x00c'
-
-
-
-    def test_AsString(self):
-        module = self.import_extension('foo', [
-            ("getstring", "METH_NOARGS",
-             """
-                 PyObject* s1 = PyString_FromStringAndSize("test", 4);
-                 char* c = PyString_AsString(s1);
-                 PyObject* s2 = PyString_FromStringAndSize(c, 4);
-                 Py_DECREF(s1);
-                 return s2;
-             """),
-            ])
-        s = module.getstring()
-        assert s == 'test'
-
-    def test_py_string_as_string(self):
-        module = self.import_extension('foo', [
-            ("string_as_string", "METH_VARARGS",
-             '''
-             return PyString_FromStringAndSize(PyString_AsString(
-                       PyTuple_GetItem(args, 0)), 4);
-             '''
-            )])
-        assert module.string_as_string("huheduwe") == "huhe"
-
-    def test_py_string_as_string_None(self):
-        module = self.import_extension('foo', [
-            ("string_None", "METH_VARARGS",
-             '''
-             return PyString_AsString(Py_None);
-             '''
-            )])
-        raises(TypeError, module.string_None)
-
-    def test_AsStringAndSize(self):
-        module = self.import_extension('foo', [
-            ("getstring", "METH_NOARGS",
-             """
-                 PyObject* s1 = PyString_FromStringAndSize("te\\0st", 5);
-                 char *buf;
-                 Py_ssize_t len;
-                 if (PyString_AsStringAndSize(s1, &buf, &len) < 0)
-                     return NULL;
-                 if (len != 5) {
-                     PyErr_SetString(PyExc_AssertionError, "Bad Length");
-                     return NULL;
-                 }
-                 if (PyString_AsStringAndSize(s1, &buf, NULL) >= 0) {
-                     PyErr_SetString(PyExc_AssertionError, "Should Have failed");
-                     return NULL;
-                 }
-                 PyErr_Clear();
-                 Py_DECREF(s1);
-                 Py_INCREF(Py_None);
-                 return Py_None;
-             """),
-            ])
-        module.getstring()
-
-    def test_format_v(self):
-        module = self.import_extension('foo', [
-            ("test_string_format_v", "METH_VARARGS",
-             '''
-                 return helper("bla %d ble %s\\n",
-                        PyInt_AsLong(PyTuple_GetItem(args, 0)),
-                        PyString_AsString(PyTuple_GetItem(args, 1)));
-             '''
-             )
-            ], prologue='''
-            PyObject* helper(char* fmt, ...)
-            {
-              va_list va;
-              PyObject* res;
-              va_start(va, fmt);
-              res = PyString_FromFormatV(fmt, va);
-              va_end(va);
-              return res;
-            }
-            ''')
-        res = module.test_string_format_v(1, "xyz")
-        assert res == "bla 1 ble xyz\n"
-
-    def test_format(self):
-        module = self.import_extension('foo', [
-            ("test_string_format", "METH_VARARGS",
-             '''
-                 return PyString_FromFormat("bla %d ble %s\\n",
-                        PyInt_AsLong(PyTuple_GetItem(args, 0)),
-                        PyString_AsString(PyTuple_GetItem(args, 1)));
-             '''
-             )
-            ])
-        res = module.test_string_format(1, "xyz")
-        assert res == "bla 1 ble xyz\n"
-
-    def test_intern_inplace(self):
-        module = self.import_extension('foo', [
-            ("test_intern_inplace", "METH_O",
-             '''
-                 PyObject *s = args;
-                 Py_INCREF(s);
-                 PyString_InternInPlace(&s);
-                 return s;
-             '''
-             )
-            ])
-        # This does not test much, but at least the refcounts are checked.
-        assert module.test_intern_inplace('s') == 's'
-
-class TestString(BaseApiTest):
-    def test_string_resize(self, space, api):
-        py_str = new_empty_str(space, 10)
-        ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
-        py_str.c_buffer[0] = 'a'
-        py_str.c_buffer[1] = 'b'
-        py_str.c_buffer[2] = 'c'
-        ar[0] = rffi.cast(PyObject, py_str)
-        api._PyString_Resize(ar, 3)
-        py_str = rffi.cast(PyStringObject, ar[0])
-        assert py_str.c_size == 3
-        assert py_str.c_buffer[1] == 'b'
-        assert py_str.c_buffer[3] == '\x00'
-        # the same for growing
-        ar[0] = rffi.cast(PyObject, py_str)
-        api._PyString_Resize(ar, 10)
-        py_str = rffi.cast(PyStringObject, ar[0])
-        assert py_str.c_size == 10
-        assert py_str.c_buffer[1] == 'b'
-        assert py_str.c_buffer[10] == '\x00'
-        Py_DecRef(space, ar[0])
-        lltype.free(ar, flavor='raw')
-
-    def test_string_buffer(self, space, api):
-        py_str = new_empty_str(space, 10)
-        c_buf = py_str.c_ob_type.c_tp_as_buffer
-        assert c_buf
-        py_obj = rffi.cast(PyObject, py_str)
-        assert c_buf.c_bf_getsegcount(py_obj, lltype.nullptr(Py_ssize_tP.TO)) == 1
-        ref = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
-        assert c_buf.c_bf_getsegcount(py_obj, ref) == 1
-        assert ref[0] == 10
-        lltype.free(ref, flavor='raw')
-        ref = lltype.malloc(rffi.VOIDPP.TO, 1, flavor='raw')
-        assert c_buf.c_bf_getreadbuffer(py_obj, 0, ref) == 10
-        lltype.free(ref, flavor='raw')
-        Py_DecRef(space, py_obj)
-
-    def test_Concat(self, space, api):
-        ref = make_ref(space, space.wrap('abc'))
-        ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
-        ptr[0] = ref
-        prev_refcnt = ref.c_ob_refcnt
-        api.PyString_Concat(ptr, space.wrap('def'))
-        assert ref.c_ob_refcnt == prev_refcnt - 1
-        assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
-        api.PyString_Concat(ptr, space.w_None)
-        assert not ptr[0]
-        ptr[0] = lltype.nullptr(PyObject.TO)
-        api.PyString_Concat(ptr, space.wrap('def')) # should not crash
-        lltype.free(ptr, flavor='raw')
-
-    def test_ConcatAndDel(self, space, api):
-        ref1 = make_ref(space, space.wrap('abc'))
-        ref2 = make_ref(space, space.wrap('def'))
-        ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
-        ptr[0] = ref1
-        prev_refcnf = ref2.c_ob_refcnt
-        api.PyString_ConcatAndDel(ptr, ref2)
-        assert space.str_w(from_ref(space, ptr[0])) == 'abcdef'
-        assert ref2.c_ob_refcnt == prev_refcnf - 1
-        Py_DecRef(space, ptr[0])
-        ptr[0] = lltype.nullptr(PyObject.TO)
-        ref2 = make_ref(space, space.wrap('foo'))
-        prev_refcnf = ref2.c_ob_refcnt
-        api.PyString_ConcatAndDel(ptr, ref2) # should not crash
-        assert ref2.c_ob_refcnt == prev_refcnf - 1
-        lltype.free(ptr, flavor='raw')
-
-    def test_format(self, space, api):
-        assert "1 2" == space.unwrap(
-            api.PyString_Format(space.wrap('%s %d'), space.wrap((1, 2))))
-
-    def test_asbuffer(self, space, api):
-        bufp = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
-        lenp = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
-
-        w_text = space.wrap("text")
-        assert api.PyObject_AsCharBuffer(w_text, bufp, lenp) == 0
-        assert lenp[0] == 4
-        assert rffi.charp2str(bufp[0]) == 'text'
-
-        lltype.free(bufp, flavor='raw')
-        lltype.free(lenp, flavor='raw')
-
-    def test_intern(self, space, api):
-        buf = rffi.str2charp("test")
-        w_s1 = api.PyString_InternFromString(buf)
-        w_s2 = api.PyString_InternFromString(buf)
-        rffi.free_charp(buf)
-        assert w_s1 is w_s2
-
-    def test_AsEncodedObject(self, space, api):
-        ptr = space.wrap('abc')
-
-        errors = rffi.str2charp("strict")
-
-        encoding = rffi.str2charp("hex")
-        res = api.PyString_AsEncodedObject(
-            ptr, encoding, errors)
-        assert space.unwrap(res) == "616263"
-
-        res = api.PyString_AsEncodedObject(
-            ptr, encoding, lltype.nullptr(rffi.CCHARP.TO))
-        assert space.unwrap(res) == "616263"
-        rffi.free_charp(encoding)
-
-        encoding = rffi.str2charp("unknown_encoding")
-        self.raises(space, api, LookupError, api.PyString_AsEncodedObject,
-                    ptr, encoding, errors)
-        rffi.free_charp(encoding)
-
-        rffi.free_charp(errors)
-
-        res = api.PyString_AsEncodedObject(
-            ptr, lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO))
-        assert space.unwrap(res) == "abc"
-
-        self.raises(space, api, TypeError, api.PyString_AsEncodedObject,
-            space.wrap(2), lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO)
-        )
-
-    def test_AsDecodedObject(self, space, api):
-        w_str = space.wrap('caf\xe9')
-        encoding = rffi.str2charp("latin-1")
-        w_res = api.PyString_AsDecodedObject(w_str, encoding, None)
-        rffi.free_charp(encoding)
-        assert space.unwrap(w_res) == u"caf\xe9"
-
-    def test_eq(self, space, api):
-        assert 1 == api._PyString_Eq(space.wrap("hello"), space.wrap("hello"))
-        assert 0 == api._PyString_Eq(space.wrap("hello"), space.wrap("world"))
-
-    def test_join(self, space, api):
-        w_sep = space.wrap('<sep>')
-        w_seq = space.wrap(['a', 'b'])
-        w_joined = api._PyString_Join(w_sep, w_seq)
-        assert space.unwrap(w_joined) == 'a<sep>b'
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -340,7 +340,7 @@
 @cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
              header=None, error=-1)
 def str_getreadbuffer(space, w_str, segment, ref):
-    from pypy.module.cpyext.stringobject import PyString_AsString
+    from pypy.module.cpyext.bytesobject import PyString_AsString
     if segment != 0:
         raise OperationError(space.w_SystemError, space.wrap
                              ("accessing non-existent string segment"))
@@ -353,7 +353,7 @@
 @cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
              header=None, error=-1)
 def str_getcharbuffer(space, w_str, segment, ref):
-    from pypy.module.cpyext.stringobject import PyString_AsString
+    from pypy.module.cpyext.bytesobject import PyString_AsString
     if segment != 0:
         raise OperationError(space.w_SystemError, space.wrap
                              ("accessing non-existent string segment"))
@@ -463,7 +463,7 @@
         w_typename = space.getattr(w_type, space.wrap('__name__'))
         heaptype = rffi.cast(PyHeapTypeObject, pto)
         heaptype.c_ht_name = make_ref(space, w_typename)
-        from pypy.module.cpyext.stringobject import PyString_AsString
+        from pypy.module.cpyext.bytesobject import PyString_AsString
         pto.c_tp_name = PyString_AsString(space, heaptype.c_ht_name)
     else:
         pto.c_tp_name = rffi.str2charp(w_type.name)
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -9,7 +9,7 @@
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
     make_typedescr, get_typedescr)
-from pypy.module.cpyext.stringobject import PyString_Check
+from pypy.module.cpyext.bytesobject import PyString_Check
 from pypy.module.sys.interp_encoding import setdefaultencoding
 from pypy.module._codecs.interp_codecs import CodecState
 from pypy.objspace.std import unicodeobject
@@ -17,7 +17,7 @@
 from rpython.tool.sourcetools import func_renamer
 import sys
 
-## See comment in stringobject.py.
+## See comment in bytesobject.py.
 
 PyUnicodeObjectStruct = lltype.ForwardReference()
 PyUnicodeObject = lltype.Ptr(PyUnicodeObjectStruct)
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -85,7 +85,7 @@
     # The "imp" module does not respect this, and is allowed to find
     # lone .pyc files.
     # check the .pyc file
-    if space.config.objspace.usepycfiles and space.config.objspace.lonepycfiles:
+    if space.config.objspace.lonepycfiles:
         pycfile = filepart + ".pyc"
         if file_exists(pycfile):
             # existing .pyc file
@@ -888,17 +888,11 @@
     """
     w = space.wrap
 
-    if space.config.objspace.usepycfiles:
-        src_stat = os.fstat(fd)
-        cpathname = pathname + 'c'
-        mtime = int(src_stat[stat.ST_MTIME])
-        mode = src_stat[stat.ST_MODE]
-        stream = check_compiled_module(space, cpathname, mtime)
-    else:
-        cpathname = None
-        mtime = 0
-        mode = 0
-        stream = None
+    src_stat = os.fstat(fd)
+    cpathname = pathname + 'c'
+    mtime = int(src_stat[stat.ST_MTIME])
+    mode = src_stat[stat.ST_MODE]
+    stream = check_compiled_module(space, cpathname, mtime)
 
     if stream:
         # existing and up-to-date .pyc file
@@ -913,7 +907,7 @@
     else:
         code_w = parse_source_module(space, pathname, source)
 
-        if space.config.objspace.usepycfiles and write_pyc:
+        if write_pyc:
             if not space.is_true(space.sys.get('dont_write_bytecode')):
                 write_compiled_module(space, code_w, cpathname, mode, mtime)
 
diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -98,6 +98,10 @@
         'a=5\nb=6\rc="""hello\r\nworld"""\r', mode='wb')
     p.join('mod.py').write(
         'a=15\nb=16\rc="""foo\r\nbar"""\r', mode='wb')
+    setuppkg("test_bytecode",
+             a = '',
+             b = '',
+             c = '')
 
     # create compiled/x.py and a corresponding pyc file
     p = setuppkg("compiled", x = "x = 84")
@@ -119,7 +123,7 @@
                 stream.try_to_find_file_descriptor())
         finally:
             stream.close()
-        if space.config.objspace.usepycfiles:
+        if not space.config.translation.sandbox:
             # also create a lone .pyc file
             p.join('lone.pyc').write(p.join('x.pyc').read(mode='rb'),
                                      mode='wb')
@@ -146,6 +150,8 @@
     """)
 
 def _teardown(space, w_saved_modules):
+    p = udir.join('impsubdir')
+    p.remove()
     space.appexec([w_saved_modules], """
         ((saved_path, saved_modules)):
             import sys
@@ -1342,15 +1348,56 @@
         assert isinstance(importer, zipimport.zipimporter)
 
 
-class AppTestNoPycFile(object):
+class AppTestWriteBytecode(object):
     spaceconfig = {
-        "objspace.usepycfiles": False,
-        "objspace.lonepycfiles": False
+        "translation.sandbox": False
     }
+
     def setup_class(cls):
-        usepycfiles = cls.spaceconfig['objspace.usepycfiles']
+        cls.saved_modules = _setup(cls.space)
+        sandbox = cls.spaceconfig['translation.sandbox']
+        cls.w_sandbox = cls.space.wrap(sandbox)
+
+    def teardown_class(cls):
+        _teardown(cls.space, cls.saved_modules)
+        cls.space.appexec([], """
+            ():
+                import sys
+                sys.dont_write_bytecode = False
+        """)
+
+    def test_default(self):
+        import os.path
+        from test_bytecode import a
+        assert a.__file__.endswith('a.py')
+        assert os.path.exists(a.__file__ + 'c') == (not self.sandbox)
+
+    def test_write_bytecode(self):
+        import os.path
+        import sys
+        sys.dont_write_bytecode = False
+        from test_bytecode import b
+        assert b.__file__.endswith('b.py')
+        assert os.path.exists(b.__file__ + 'c')
+
+    def test_dont_write_bytecode(self):
+        import os.path
+        import sys
+        sys.dont_write_bytecode = True
+        from test_bytecode import c
+        assert c.__file__.endswith('c.py')
+        assert not os.path.exists(c.__file__ + 'c')
+
+
+class AppTestWriteBytecodeSandbox(AppTestWriteBytecode):
+    spaceconfig = {
+        "translation.sandbox": True
+    }
+
+
+class _AppTestLonePycFileBase(object):
+    def setup_class(cls):
         lonepycfiles = cls.spaceconfig['objspace.lonepycfiles']
-        cls.w_usepycfiles = cls.space.wrap(usepycfiles)
         cls.w_lonepycfiles = cls.space.wrap(lonepycfiles)
         cls.saved_modules = _setup(cls.space)
 
@@ -1359,10 +1406,7 @@
 
     def test_import_possibly_from_pyc(self):
         from compiled import x
-        if self.usepycfiles:
-            assert x.__file__.endswith('x.pyc')
-        else:
-            assert x.__file__.endswith('x.py')
+        assert x.__file__.endswith('x.pyc')
         try:
             from compiled import lone
         except ImportError:
@@ -1371,15 +1415,13 @@
             assert self.lonepycfiles, "should not have found 'lone.pyc'"
             assert lone.__file__.endswith('lone.pyc')
 
-class AppTestNoLonePycFile(AppTestNoPycFile):
+class AppTestNoLonePycFile(_AppTestLonePycFileBase):
     spaceconfig = {
-        "objspace.usepycfiles": True,
         "objspace.lonepycfiles": False
     }
 
-class AppTestLonePycFile(AppTestNoPycFile):
+class AppTestLonePycFile(_AppTestLonePycFileBase):
     spaceconfig = {
-        "objspace.usepycfiles": True,
         "objspace.lonepycfiles": True
     }
 
diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -77,7 +77,7 @@
         'meta_path'             : 'space.wrap([])',
         'path_hooks'            : 'space.wrap([])',
         'path_importer_cache'   : 'space.wrap({})',
-        'dont_write_bytecode'   : 'space.w_False',
+        'dont_write_bytecode'   : 'space.wrap(space.config.translation.sandbox)',
 
         'getdefaultencoding'    : 'interp_encoding.getdefaultencoding',
         'setdefaultencoding'    : 'interp_encoding.setdefaultencoding',
diff --git a/pypy/module/sys/app.py b/pypy/module/sys/app.py
--- a/pypy/module/sys/app.py
+++ b/pypy/module/sys/app.py
@@ -70,11 +70,11 @@
     return None
 
 copyright_str = """
-Copyright 2003-2014 PyPy development team.
+Copyright 2003-2016 PyPy development team.
 All Rights Reserved.
 For further information, see <http://pypy.org>
 
-Portions Copyright (c) 2001-2014 Python Software Foundation.
+Portions Copyright (c) 2001-2016 Python Software Foundation.
 All Rights Reserved.
 
 Portions Copyright (c) 2000 BeOpen.com.
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
@@ -30,6 +30,11 @@
 contains_jmp = jit.JitDriver(greens = ['tp'], reds = 'auto',
                              name = 'tuple.contains')
 
+hash_driver = jit.JitDriver(
+    name='tuple.hash',
+    greens=['w_type'],
+    reds='auto')
+
 class W_AbstractTupleObject(W_Root):
     __slots__ = ()
 
@@ -262,8 +267,14 @@
     def length(self):
         return len(self.wrappeditems)
 
-    @jit.look_inside_iff(lambda self, _1: _unroll_condition(self))
     def descr_hash(self, space):
+        if _unroll_condition(self):
+            return self._descr_hash_unroll(space)
+        else:
+            return self._descr_hash_jitdriver(space)
+
+    @jit.unroll_safe
+    def _descr_hash_unroll(self, space):
         mult = 1000003
         x = 0x345678
         z = len(self.wrappeditems)
@@ -275,6 +286,20 @@
         x += 97531
         return space.wrap(intmask(x))
 
+    def _descr_hash_jitdriver(self, space):
+        mult = 1000003
+        x = 0x345678
+        z = len(self.wrappeditems)
+        w_type = space.type(self.wrappeditems[0])
+        for w_item in self.wrappeditems:
+            hash_driver.jit_merge_point(w_type=w_type)
+            y = space.hash_w(w_item)
+            x = (x ^ y) * mult
+            z -= 1
+            mult += 82520 + z + z
+        x += 97531
+        return space.wrap(intmask(x))
+
     def descr_eq(self, space, w_other):
         if not isinstance(w_other, W_AbstractTupleObject):
             return space.w_NotImplemented
diff --git a/pypy/tool/test/test_tab.py b/pypy/tool/test/test_tab.py
--- a/pypy/tool/test/test_tab.py
+++ b/pypy/tool/test/test_tab.py
@@ -6,7 +6,7 @@
 from pypy.conftest import pypydir
 
 ROOT = os.path.abspath(os.path.join(pypydir, '..'))
-EXCLUDE = {}
+EXCLUDE = {'/virt_test/lib/python2.7/site-packages/setuptools'}
 
 
 def test_no_tabs():
diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -2042,6 +2042,11 @@
         self.vable_flags[op.args[0]] = op.args[2].value
         return []
 
+    def rewrite_op_jit_enter_portal_frame(self, op):
+        return [op]
+    def rewrite_op_jit_leave_portal_frame(self, op):
+        return [op]
+
     # ---------
     # ll_math.sqrt_nonneg()
 
diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -944,6 +944,14 @@
         pass
 
     @arguments("i")
+    def bhimpl_jit_enter_portal_frame(x):
+        pass
+
+    @arguments()
+    def bhimpl_jit_leave_portal_frame():
+        pass
+
+    @arguments("i")


More information about the pypy-commit mailing list