[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