[pypy-commit] pypy py3.5-async: Merge with py3.5
raffael_t
pypy.commits at gmail.com
Tue Aug 16 05:15:52 EDT 2016
Author: Raffael Tfirst <raffael.tfirst at gmail.com>
Branch: py3.5-async
Changeset: r86213:a955efeebd40
Date: 2016-08-16 11:14 +0200
http://bitbucket.org/pypy/pypy/changeset/a955efeebd40/
Log: Merge with py3.5
diff too long, truncating to 2000 out of 4303 lines
diff --git a/include/PyPy.h b/include/PyPy.h
--- a/include/PyPy.h
+++ b/include/PyPy.h
@@ -2,7 +2,11 @@
#define _PYPY_H_
/* This header is meant to be included in programs that use PyPy as an
- embedded library. */
+ embedded library.
+
+ NOTE: this is deprecated. Instead, use cffi's embedding support:
+ http://cffi.readthedocs.org/en/latest/embedding.html
+*/
#ifdef __cplusplus
extern "C" {
diff --git a/lib-python/3/code.py b/lib-python/3/code.py
--- a/lib-python/3/code.py
+++ b/lib-python/3/code.py
@@ -140,32 +140,15 @@
sys.last_type, sys.last_value, last_tb = ei = sys.exc_info()
sys.last_traceback = last_tb
try:
- lines = []
- for value, tb in traceback._iter_chain(*ei[1:]):
- if isinstance(value, str):
- lines.append(value)
- lines.append('\n')
- continue
- if tb:
- tblist = traceback.extract_tb(tb)
- if tb is last_tb:
- # The last traceback includes the frame we
- # exec'd in
- del tblist[:1]
- tblines = traceback.format_list(tblist)
- if tblines:
- lines.append("Traceback (most recent call last):\n")
- lines.extend(tblines)
- lines.extend(traceback.format_exception_only(type(value),
- value))
+ lines = traceback.format_exception(ei[0], ei[1], last_tb.tb_next)
+ if sys.excepthook is sys.__excepthook__:
+ self.write(''.join(lines))
+ else:
+ # If someone has set sys.excepthook, we let that take precedence
+ # over self.write
+ sys.excepthook(ei[0], ei[1], last_tb)
finally:
- tblist = last_tb = ei = None
- if sys.excepthook is sys.__excepthook__:
- self.write(''.join(lines))
- else:
- # If someone has set sys.excepthook, we let that take precedence
- # over self.write
- sys.excepthook(sys.last_type, sys.last_value, last_tb)
+ last_tb = ei = None
def write(self, data):
"""Write a string.
diff --git a/lib-python/3/distutils/command/build_ext.py b/lib-python/3/distutils/command/build_ext.py
--- a/lib-python/3/distutils/command/build_ext.py
+++ b/lib-python/3/distutils/command/build_ext.py
@@ -11,7 +11,6 @@
from distutils.core import Command
from distutils.errors import *
from distutils.sysconfig import customize_compiler, get_python_version
-from distutils.sysconfig import get_config_h_filename
from distutils.dep_util import newer_group
from distutils.extension import Extension
from distutils.util import get_platform
@@ -30,6 +29,7 @@
show_compilers()
def _get_c_extension_suffix():
+ import importlib
suffixes = importlib.machinery.EXTENSION_SUFFIXES
return suffixes[0] if suffixes else None
@@ -204,6 +204,7 @@
# this allows distutils on windows to work in the source tree
if 0:
# pypy has no config_h_filename directory
+ from distutils.sysconfig import get_config_h_filename
self.include_dirs.append(os.path.dirname(get_config_h_filename()))
_sys_home = getattr(sys, '_home', None)
if _sys_home:
diff --git a/lib-python/3/site.py b/lib-python/3/site.py
--- a/lib-python/3/site.py
+++ b/lib-python/3/site.py
@@ -378,8 +378,8 @@
license = "See https://www.python.org/psf/license/"
licenseargs = (license, files, dirs)
- builtins.credits = _Printer("credits", credits)
- builtins.license = _Printer("license", *licenseargs)
+ builtins.credits = _sitebuiltins._Printer("credits", credits)
+ builtins.license = _sitebuiltins._Printer("license", *licenseargs)
def sethelper():
builtins.help = _sitebuiltins._Helper()
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: cffi
-Version: 1.7.0
+Version: 1.8.0
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "1.7.0"
-__version_info__ = (1, 7, 0)
+__version__ = "1.8.0"
+__version_info__ = (1, 8, 0)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -42,7 +42,9 @@
# include <stdint.h>
# endif
# if _MSC_VER < 1800 /* MSVC < 2013 */
- typedef unsigned char _Bool;
+# ifndef __cplusplus
+ typedef unsigned char _Bool;
+# endif
# endif
#else
# include <stdint.h>
@@ -59,7 +61,7 @@
#ifdef __cplusplus
# ifndef _Bool
-# define _Bool bool /* semi-hackish: C++ has no _Bool; bool is builtin */
+ typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */
# endif
#endif
@@ -196,20 +198,6 @@
return NULL;
}
-_CFFI_UNUSED_FN
-static PyObject **_cffi_unpack_args(PyObject *args_tuple, Py_ssize_t expected,
- const char *fnname)
-{
- if (PyTuple_GET_SIZE(args_tuple) != expected) {
- PyErr_Format(PyExc_TypeError,
- "%.150s() takes exactly %zd arguments (%zd given)",
- fnname, expected, PyTuple_GET_SIZE(args_tuple));
- return NULL;
- }
- return &PyTuple_GET_ITEM(args_tuple, 0); /* pointer to the first item,
- the others follow */
-}
-
/********** end CPython-specific section **********/
#else
_CFFI_UNUSED_FN
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@
f = PySys_GetObject((char *)"stderr");
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.7.0"
+ "\ncompiled with cffi version: 1.8.0"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py
--- a/lib_pypy/cffi/model.py
+++ b/lib_pypy/cffi/model.py
@@ -519,12 +519,10 @@
smallest_value = min(self.enumvalues)
largest_value = max(self.enumvalues)
else:
- import warnings
- warnings.warn("%r has no values explicitly defined; next version "
- "will refuse to guess which integer type it is "
- "meant to be (unsigned/signed, int/long)"
- % self._get_c_name())
- smallest_value = largest_value = 0
+ raise api.CDefError("%r has no values explicitly defined: "
+ "refusing to guess which integer type it is "
+ "meant to be (unsigned/signed, int/long)"
+ % self._get_c_name())
if smallest_value < 0: # needs a signed type
sign = 1
candidate1 = PrimitiveType("int")
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -275,6 +275,8 @@
def write_c_source_to_f(self, f, preamble):
self._f = f
prnt = self._prnt
+ if self.ffi._embedding is None:
+ prnt('#define Py_LIMITED_API')
#
# first the '#include' (actually done by inlining the file's content)
lines = self._rel_readlines('_cffi_include.h')
@@ -683,13 +685,11 @@
rng = range(len(tp.args))
for i in rng:
prnt(' PyObject *arg%d;' % i)
- prnt(' PyObject **aa;')
prnt()
- prnt(' aa = _cffi_unpack_args(args, %d, "%s");' % (len(rng), name))
- prnt(' if (aa == NULL)')
+ prnt(' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % (
+ name, len(rng), len(rng),
+ ', '.join(['&arg%d' % i for i in rng])))
prnt(' return NULL;')
- for i in rng:
- prnt(' arg%d = aa[%d];' % (i, i))
prnt()
#
for i, type in enumerate(tp.args):
@@ -862,6 +862,8 @@
enumfields = list(tp.enumfields())
for fldname, fldtype, fbitsize, fqual in enumfields:
fldtype = self._field_type(tp, fldname, fldtype)
+ self._check_not_opaque(fldtype,
+ "field '%s.%s'" % (tp.name, fldname))
# cname is None for _add_missing_struct_unions() only
op = OP_NOOP
if fbitsize >= 0:
@@ -911,6 +913,13 @@
first_field_index, c_fields))
self._seen_struct_unions.add(tp)
+ def _check_not_opaque(self, tp, location):
+ while isinstance(tp, model.ArrayType):
+ tp = tp.item
+ if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None:
+ raise TypeError(
+ "%s is of an opaque type (not declared in cdef())" % location)
+
def _add_missing_struct_unions(self):
# not very nice, but some struct declarations might be missing
# because they don't have any known C name. Check that they are
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -99,17 +99,24 @@
The garbage collectors used or implemented by PyPy are not based on
reference counting, so the objects are not freed instantly when they are no
-longer reachable. The most obvious effect of this is that files are not
+longer reachable. The most obvious effect of this is that files (and sockets, etc) are not
promptly closed when they go out of scope. For files that are opened for
writing, data can be left sitting in their output buffers for a while, making
the on-disk file appear empty or truncated. Moreover, you might reach your
OS's limit on the number of concurrently opened files.
-Fixing this is essentially impossible without forcing a
+If you are debugging a case where a file in your program is not closed
+properly, you can use the ``-X track-resources`` command line option. If it is
+given, a ``ResourceWarning`` is produced for every file and socket that the
+garbage collector closes. The warning will contain the stack trace of the
+position where the file or socket was created, to make it easier to see which
+parts of the program don't close files explicitly.
+
+Fixing this difference to CPython is essentially impossible without forcing a
reference-counting approach to garbage collection. The effect that you
get in CPython has clearly been described as a side-effect of the
implementation and not a language design decision: programs relying on
-this are basically bogus. It would anyway be insane to try to enforce
+this are basically bogus. It would be a too strong restriction to try to enforce
CPython's behavior in a language spec, given that it has no chance to be
adopted by Jython or IronPython (or any other port of Python to Java or
.NET).
@@ -134,7 +141,7 @@
Here are some more technical details. This issue affects the precise
time at which ``__del__`` methods are called, which
-is not reliable in PyPy (nor Jython nor IronPython). It also means that
+is not reliable or timely in PyPy (nor Jython nor IronPython). It also means that
**weak references** may stay alive for a bit longer than expected. This
makes "weak proxies" (as returned by ``weakref.proxy()``) somewhat less
useful: they will appear to stay alive for a bit longer in PyPy, and
diff --git a/pypy/doc/gc_info.rst b/pypy/doc/gc_info.rst
--- a/pypy/doc/gc_info.rst
+++ b/pypy/doc/gc_info.rst
@@ -14,10 +14,9 @@
Defaults to 1/2 of your cache or ``4M``.
Small values (like 1 or 1KB) are useful for debugging.
-``PYPY_GC_NURSERY_CLEANUP``
- The interval at which nursery is cleaned up. Must
- be smaller than the nursery size and bigger than the
- biggest object we can allotate in the nursery.
+``PYPY_GC_NURSERY_DEBUG``
+ If set to non-zero, will fill nursery with garbage, to help
+ debugging.
``PYPY_GC_INCREMENT_STEP``
The size of memory marked during the marking step. Default is size of
@@ -62,3 +61,8 @@
use.
Values are ``0`` (off), ``1`` (on major collections) or ``2`` (also
on minor collections).
+
+``PYPY_GC_MAX_PINNED``
+ The maximal number of pinned objects at any point in time. Defaults
+ to a conservative value depending on nursery size and maximum object
+ size inside the nursery. Useful for debugging by setting it to 0.
diff --git a/pypy/doc/man/pypy.1.rst b/pypy/doc/man/pypy.1.rst
--- a/pypy/doc/man/pypy.1.rst
+++ b/pypy/doc/man/pypy.1.rst
@@ -2,6 +2,9 @@
pypy
======
+.. note: this is turned into a regular man page "pypy.1" by
+ doing "make man" in pypy/doc/
+
SYNOPSIS
========
@@ -48,6 +51,10 @@
-B
Disable writing bytecode (``.pyc``) files.
+-X track-resources
+ Produce a ``ResourceWarning`` whenever a file or socket is closed by the
+ garbage collector.
+
--version
Print the PyPy version.
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -105,3 +105,26 @@
.. branch: ep2016sprint
Trying harder to make hash(-1) return -2, like it does on CPython
+
+.. branch: jitlog-exact-source-lines
+
+Log exact line positions in debug merge points.
+
+.. branch: null_byte_after_str
+
+Allocate all RPython strings with one extra byte, normally unused.
+It is used to hold a final zero in case we need some ``char *``
+representation of the string, together with checks like ``not
+can_move()`` or object pinning. Main new thing that this allows:
+``ffi.from_buffer(string)`` in CFFI. Additionally, and most
+importantly, CFFI calls that take directly a string as argument don't
+copy the string any more---this is like CFFI on CPython.
+
+.. branch: resource_warning
+
+Add a new command line option -X track-resources which will produce
+ResourceWarnings when the GC closes unclosed files and sockets.
+
+.. branch: cpyext-realloc
+
+Implement PyObject_Realloc
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -114,8 +114,15 @@
return getattr(space, name)(operand)
return do_fold
-def _fold_pow(space, left, right):
- return space.pow(left, right, space.w_None)
+def _fold_pow(space, w_left, w_right):
+ # don't constant-fold if "w_left" and "w_right" are integers and
+ # the estimated bit length of the power is unreasonably large
+ space.appexec([w_left, w_right], """(left, right):
+ if isinstance(left, (int, long)) and isinstance(right, (int, long)):
+ if left.bit_length() * right > 5000:
+ raise OverflowError
+ """)
+ return space.pow(w_left, w_right, space.w_None)
def _fold_not(space, operand):
return space.wrap(not space.is_true(operand))
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1322,6 +1322,25 @@
assert ops.BUILD_SET not in counts
assert ops.LOAD_CONST in counts
+ def test_dont_fold_huge_powers(self):
+ for source in (
+ "2 ** 3000", # not constant-folded: too big
+ "(-2) ** 3000",
+ ):
+ source = 'def f(): %s' % source
+ counts = self.count_instructions(source)
+ assert ops.BINARY_POWER in counts
+
+ for source in (
+ "2 ** 2000", # constant-folded
+ "2 ** -3000",
+ "1.001 ** 3000",
+ "1 ** 3000.0",
+ ):
+ source = 'def f(): %s' % source
+ counts = self.count_instructions(source)
+ assert ops.BINARY_POWER not in counts
+
def test_call_function_var(self):
source = """call(*me)"""
code, blocks = generate_function_code(source, self.space)
diff --git a/pypy/interpreter/astcompiler/test/test_validate.py b/pypy/interpreter/astcompiler/test/test_validate.py
--- a/pypy/interpreter/astcompiler/test/test_validate.py
+++ b/pypy/interpreter/astcompiler/test/test_validate.py
@@ -38,9 +38,8 @@
self.mod(m, "must have Load context", "eval")
def _check_arguments(self, fac, check):
- def arguments(args=None, vararg=None, varargannotation=None,
- kwonlyargs=None, kwarg=None, kwargannotation=None,
- defaults=None, kw_defaults=None):
+ def arguments(args=None, vararg=None, kwonlyargs=None,
+ kw_defaults=None, kwarg=None, defaults=None):
if args is None:
args = []
if kwonlyargs is None:
@@ -49,20 +48,12 @@
defaults = []
if kw_defaults is None:
kw_defaults = []
- args = ast.arguments(args, vararg, varargannotation, kwonlyargs,
- kwarg, kwargannotation, defaults, kw_defaults)
+ args = ast.arguments(args, vararg, kwonlyargs,
+ kw_defaults, kwarg, defaults)
return fac(args)
args = [ast.arg("x", ast.Name("x", ast.Store, 0, 0))]
check(arguments(args=args), "must have Load context")
- check(arguments(varargannotation=ast.Num(self.space.wrap(3), 0, 0)),
- "varargannotation but no vararg")
- check(arguments(varargannotation=ast.Name("x", ast.Store, 0, 0), vararg="x"),
- "must have Load context")
check(arguments(kwonlyargs=args), "must have Load context")
- check(arguments(kwargannotation=ast.Num(self.space.wrap(42), 0, 0)),
- "kwargannotation but no kwarg")
- check(arguments(kwargannotation=ast.Name("x", ast.Store, 0, 0),
- kwarg="x"), "must have Load context")
check(arguments(defaults=[ast.Num(self.space.wrap(3), 0, 0)]),
"more positional defaults than args")
check(arguments(kw_defaults=[ast.Num(self.space.wrap(4), 0, 0)]),
@@ -77,7 +68,7 @@
"must have Load context")
def test_funcdef(self):
- a = ast.arguments([], None, None, [], None, None, [], [])
+ a = ast.arguments([], None, [], [], None, [])
f = ast.FunctionDef("x", a, [], [], None, 0, 0)
self.stmt(f, "empty body on FunctionDef")
f = ast.FunctionDef("x", a, [ast.Pass(0, 0)], [ast.Name("x", ast.Store, 0, 0)],
@@ -91,8 +82,7 @@
self._check_arguments(fac, self.stmt)
def test_classdef(self):
- def cls(bases=None, keywords=None, starargs=None, kwargs=None,
- body=None, decorator_list=None):
+ def cls(bases=None, keywords=None, body=None, decorator_list=None):
if bases is None:
bases = []
if keywords is None:
@@ -101,16 +91,12 @@
body = [ast.Pass(0, 0)]
if decorator_list is None:
decorator_list = []
- return ast.ClassDef("myclass", bases, keywords, starargs,
- kwargs, body, decorator_list, 0, 0)
+ return ast.ClassDef("myclass", bases, keywords,
+ body, decorator_list, 0, 0)
self.stmt(cls(bases=[ast.Name("x", ast.Store, 0, 0)]),
"must have Load context")
self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store, 0, 0))]),
"must have Load context")
- self.stmt(cls(starargs=ast.Name("x", ast.Store, 0, 0)),
- "must have Load context")
- self.stmt(cls(kwargs=ast.Name("x", ast.Store, 0, 0)),
- "must have Load context")
self.stmt(cls(body=[]), "empty body on ClassDef")
self.stmt(cls(body=[None]), "None disallowed")
self.stmt(cls(decorator_list=[ast.Name("x", ast.Store, 0, 0)]),
@@ -250,7 +236,7 @@
self.expr(u, "must have Load context")
def test_lambda(self):
- a = ast.arguments([], None, None, [], None, None, [], [])
+ a = ast.arguments([], None, [], [], None, [])
self.expr(ast.Lambda(a, ast.Name("x", ast.Store, 0, 0), 0, 0),
"must have Load context")
def fac(args):
@@ -343,20 +329,12 @@
func = ast.Name("x", ast.Load, 0, 0)
args = [ast.Name("y", ast.Load, 0, 0)]
keywords = [ast.keyword("w", ast.Name("z", ast.Load, 0, 0))]
- stararg = ast.Name("p", ast.Load, 0, 0)
- kwarg = ast.Name("q", ast.Load, 0, 0)
- call = ast.Call(ast.Name("x", ast.Store, 0, 0), args, keywords, stararg,
- kwarg, 0, 0)
+ call = ast.Call(ast.Name("x", ast.Store, 0, 0), args, keywords, 0, 0)
self.expr(call, "must have Load context")
- call = ast.Call(func, [None], keywords, stararg, kwarg, 0, 0)
+ call = ast.Call(func, [None], keywords, 0, 0)
self.expr(call, "None disallowed")
bad_keywords = [ast.keyword("w", ast.Name("z", ast.Store, 0, 0))]
- call = ast.Call(func, args, bad_keywords, stararg, kwarg, 0, 0)
- self.expr(call, "must have Load context")
- call = ast.Call(func, args, keywords, ast.Name("z", ast.Store, 0, 0), kwarg, 0, 0)
- self.expr(call, "must have Load context")
- call = ast.Call(func, args, keywords, stararg,
- ast.Name("w", ast.Store, 0, 0), 0, 0)
+ call = ast.Call(func, args, bad_keywords, 0, 0)
self.expr(call, "must have Load context")
def test_num(self):
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1375,10 +1375,11 @@
for i in range(itemcount, 0, -1):
w_item = self.peekvalue(i-1)
# cannot use w_sum.update, w_item might not be a set
- iterator = w_item.itervalues()
+ iterator = space.iter(w_item)
while True:
- w_value = iterator.next_value()
- if w_value is None:
+ try:
+ w_value = space.next(iterator)
+ except OperationError:
break
w_sum.add(w_value)
while itemcount != 0:
diff --git a/pypy/interpreter/pyparser/test/test_pyparse.py b/pypy/interpreter/pyparser/test/test_pyparse.py
--- a/pypy/interpreter/pyparser/test/test_pyparse.py
+++ b/pypy/interpreter/pyparser/test/test_pyparse.py
@@ -167,6 +167,12 @@
py.test.raises(SyntaxError, self.parse, 'f()\n# blah\nblah()', "single")
py.test.raises(SyntaxError, self.parse, 'f()\nxy # blah\nblah()', "single")
py.test.raises(SyntaxError, self.parse, 'x = 5 # comment\nx = 6\n', "single")
+
+ def test_unpack(self):
+ self.parse('[*{2}, 3, *[4]]')
+ self.parse('{*{2}, 3, *[4]}')
+ self.parse('{**{}, 3:4, **{5:6, 7:8}}')
+ self.parse('f(2, *a, *b, **b, **c, **d)')
def test_async_await(self):
self.parse("async def coro(): await func")
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -209,7 +209,6 @@
self.check(['-c', 'pass'], {'PYTHONNOUSERSITE': '1'}, sys_argv=['-c'],
run_command='pass', **expected)
-
class TestInteraction:
"""
These tests require pexpect (UNIX-only).
@@ -1152,4 +1151,3 @@
# assert it did not crash
finally:
sys.path[:] = old_sys_path
-
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -134,7 +134,7 @@
assert self.space.lookup(w_instance, "gobbledygook") is None
w_instance = self.space.appexec([], """():
class Lookup(object):
- "bla"
+ "bla"
return Lookup()""")
assert self.space.str_w(self.space.lookup(w_instance, "__doc__")) == "bla"
@@ -148,7 +148,7 @@
assert is_callable(w_func)
w_lambda_func = self.space.appexec([], "(): return lambda: True")
assert is_callable(w_lambda_func)
-
+
w_instance = self.space.appexec([], """():
class Call(object):
def __call__(self): pass
@@ -308,7 +308,7 @@
def test_call_obj_args(self):
from pypy.interpreter.argument import Arguments
-
+
space = self.space
w_f = space.appexec([], """():
@@ -333,7 +333,7 @@
assert w_x is w_9
assert w_y is w_1
- w_res = space.call_obj_args(w_a, w_9, Arguments(space, []))
+ w_res = space.call_obj_args(w_a, w_9, Arguments(space, []))
assert w_res is w_9
def test_compare_by_iteration(self):
@@ -383,7 +383,7 @@
assert not space.isabstractmethod_w(space.getattr(w_B, space.wrap('g')))
assert not space.isabstractmethod_w(space.getattr(w_B, space.wrap('h')))
-class TestModuleMinimal:
+class TestModuleMinimal:
def test_sys_exists(self):
assert self.space.sys
diff --git a/pypy/module/_asyncio/test/test_asyncio.py b/pypy/module/_asyncio/test/test_asyncio.py
--- a/pypy/module/_asyncio/test/test_asyncio.py
+++ b/pypy/module/_asyncio/test/test_asyncio.py
@@ -18,3 +18,31 @@
loop.run_until_complete(f())
print("done with async loop")
"""
+
+ def test_asynchronous_context_managers(self):
+ """
+import encodings.idna
+import asyncio
+
+class Corotest(object):
+ def __init__(self):
+ self.res = "-"
+
+ async def coro(self, name, lock):
+ self.res += ' coro {}: waiting for lock -'.format(name)
+ async with lock:
+ self.res += ' coro {}: holding the lock -'.format(name)
+ await asyncio.sleep(1)
+ self.res += ' coro {}: releasing the lock -'.format(name)
+
+cor = Corotest()
+loop = asyncio.get_event_loop()
+lock = asyncio.Lock()
+coros = asyncio.gather(cor.coro(1, lock), cor.coro(2, lock))
+try:
+ loop.run_until_complete(coros)
+finally:
+ loop.close()
+
+assert cor.res == "- coro 1: waiting for lock - coro 1: holding the lock - coro 2: waiting for lock - coro 1: releasing the lock - coro 2: holding the lock - coro 2: releasing the lock -"
+ """
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
from rpython.rlib import rdynload, clibffi, entrypoint
from rpython.rtyper.lltypesystem import rffi
-VERSION = "1.7.0"
+VERSION = "1.8.0"
FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
try:
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -157,11 +157,13 @@
mustfree_max_plus_1 = 0
buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
try:
+ keepalives = [None] * len(args_w) # None or strings
for i in range(len(args_w)):
data = rffi.ptradd(buffer, cif_descr.exchange_args[i])
w_obj = args_w[i]
argtype = self.fargs[i]
- if argtype.convert_argument_from_object(data, w_obj):
+ if argtype.convert_argument_from_object(data, w_obj,
+ keepalives, i):
# argtype is a pointer type, and w_obj a list/tuple/str
mustfree_max_plus_1 = i + 1
@@ -177,9 +179,13 @@
if isinstance(argtype, W_CTypePointer):
data = rffi.ptradd(buffer, cif_descr.exchange_args[i])
flag = get_mustfree_flag(data)
+ raw_cdata = rffi.cast(rffi.CCHARPP, data)[0]
if flag == 1:
- raw_cdata = rffi.cast(rffi.CCHARPP, data)[0]
lltype.free(raw_cdata, flavor='raw')
+ elif flag >= 4:
+ value = keepalives[i]
+ assert value is not None
+ rffi.free_nonmovingbuffer(value, raw_cdata, chr(flag))
lltype.free(buffer, flavor='raw')
keepalive_until_here(args_w)
return w_res
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -83,7 +83,7 @@
raise oefmt(space.w_TypeError, "cannot initialize cdata '%s'",
self.name)
- def convert_argument_from_object(self, cdata, w_ob):
+ def convert_argument_from_object(self, cdata, w_ob, keepalives, i):
self.convert_from_object(cdata, w_ob)
return False
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -16,8 +16,8 @@
class W_CTypePtrOrArray(W_CType):
- _attrs_ = ['ctitem', 'can_cast_anything', 'length']
- _immutable_fields_ = ['ctitem', 'can_cast_anything', 'length']
+ _attrs_ = ['ctitem', 'can_cast_anything', 'accept_str', 'length']
+ _immutable_fields_ = ['ctitem', 'can_cast_anything', 'accept_str', 'length']
length = -1
def __init__(self, space, size, extra, extra_position, ctitem,
@@ -30,6 +30,9 @@
# - for functions, it is the return type
self.ctitem = ctitem
self.can_cast_anything = could_cast_anything and ctitem.cast_anything
+ self.accept_str = (self.can_cast_anything or
+ (ctitem.is_primitive_integer and
+ ctitem.size == rffi.sizeof(lltype.Char)))
def is_unichar_ptr_or_array(self):
return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveUniChar)
@@ -72,9 +75,7 @@
pass
else:
self._convert_array_from_listview(cdata, space.listview(w_ob))
- elif (self.can_cast_anything or
- (self.ctitem.is_primitive_integer and
- self.ctitem.size == rffi.sizeof(lltype.Char))):
+ elif self.accept_str:
if not space.isinstance_w(w_ob, space.w_str):
raise self._convert_error("bytes or list or tuple", w_ob)
s = space.str_w(w_ob)
@@ -262,8 +263,16 @@
else:
return lltype.nullptr(rffi.CCHARP.TO)
- def _prepare_pointer_call_argument(self, w_init, cdata):
+ def _prepare_pointer_call_argument(self, w_init, cdata, keepalives, i):
space = self.space
+ if self.accept_str and space.isinstance_w(w_init, space.w_str):
+ # special case to optimize strings passed to a "char *" argument
+ value = space.bytes_w(w_init)
+ keepalives[i] = value
+ buf, buf_flag = rffi.get_nonmovingbuffer_final_null(value)
+ rffi.cast(rffi.CCHARPP, cdata)[0] = buf
+ return ord(buf_flag) # 4, 5 or 6
+ #
if (space.isinstance_w(w_init, space.w_list) or
space.isinstance_w(w_init, space.w_tuple)):
length = space.int_w(space.len(w_init))
@@ -300,10 +309,11 @@
rffi.cast(rffi.CCHARPP, cdata)[0] = result
return 1
- def convert_argument_from_object(self, cdata, w_ob):
+ def convert_argument_from_object(self, cdata, w_ob, keepalives, i):
from pypy.module._cffi_backend.ctypefunc import set_mustfree_flag
result = (not isinstance(w_ob, cdataobj.W_CData) and
- self._prepare_pointer_call_argument(w_ob, cdata))
+ self._prepare_pointer_call_argument(w_ob, cdata,
+ keepalives, i))
if result == 0:
self.convert_from_object(cdata, w_ob)
set_mustfree_flag(cdata, result)
diff --git a/pypy/module/_cffi_backend/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -353,7 +353,7 @@
'array.array' or numpy arrays."""
#
w_ctchara = newtype._new_chara_type(self.space)
- return func.from_buffer(self.space, w_ctchara, w_python_buffer)
+ return func._from_buffer(self.space, w_ctchara, w_python_buffer)
@unwrap_spec(w_arg=W_CData)
diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -1,7 +1,8 @@
from rpython.rtyper.annlowlevel import llstr
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
-from rpython.rlib.objectmodel import keepalive_until_here
+from rpython.rlib.objectmodel import keepalive_until_here, we_are_translated
+from rpython.rlib import jit
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
@@ -132,17 +133,66 @@
raise oefmt(space.w_TypeError,
"needs 'char[]', got '%s'", w_ctype.name)
#
+ return _from_buffer(space, w_ctype, w_x)
+
+def _from_buffer(space, w_ctype, w_x):
buf = _fetch_as_read_buffer(space, w_x)
- try:
- _cdata = buf.get_raw_address()
- except ValueError:
- raise oefmt(space.w_TypeError,
- "from_buffer() got a '%T' object, which supports the "
- "buffer interface but cannot be rendered as a plain "
- "raw address on PyPy", w_x)
+ if space.isinstance_w(w_x, space.w_str):
+ _cdata = get_raw_address_of_string(space, w_x)
+ else:
+ try:
+ _cdata = buf.get_raw_address()
+ except ValueError:
+ raise oefmt(space.w_TypeError,
+ "from_buffer() got a '%T' object, which supports the "
+ "buffer interface but cannot be rendered as a plain "
+ "raw address on PyPy", w_x)
#
return cdataobj.W_CDataFromBuffer(space, _cdata, w_ctype, buf, w_x)
+# ____________________________________________________________
+
+class RawBytes(object):
+ def __init__(self, string):
+ self.ptr = rffi.str2charp(string, track_allocation=False)
+ def __del__(self):
+ rffi.free_charp(self.ptr, track_allocation=False)
+
+class RawBytesCache(object):
+ def __init__(self, space):
+ from pypy.interpreter.baseobjspace import W_Root
+ from rpython.rlib import rweakref
+ self.wdict = rweakref.RWeakKeyDictionary(W_Root, RawBytes)
+
+ at jit.dont_look_inside
+def get_raw_address_of_string(space, w_x):
+ """Special case for ffi.from_buffer(string). Returns a 'char *' that
+ is valid as long as the string object is alive. Two calls to
+ ffi.from_buffer(same_string) are guaranteed to return the same pointer.
+ """
+ from rpython.rtyper.annlowlevel import llstr
+ from rpython.rtyper.lltypesystem.rstr import STR
+ from rpython.rtyper.lltypesystem import llmemory
+ from rpython.rlib import rgc
+
+ cache = space.fromcache(RawBytesCache)
+ rawbytes = cache.wdict.get(w_x)
+ if rawbytes is None:
+ data = space.str_w(w_x)
+ if we_are_translated() and not rgc.can_move(data):
+ lldata = llstr(data)
+ data_start = (llmemory.cast_ptr_to_adr(lldata) +
+ rffi.offsetof(STR, 'chars') +
+ llmemory.itemoffsetof(STR.chars, 0))
+ data_start = rffi.cast(rffi.CCHARP, data_start)
+ data_start[len(data)] = '\x00' # write the final extra null
+ return data_start
+ rawbytes = RawBytes(data)
+ cache.wdict.set(w_x, rawbytes)
+ return rawbytes.ptr
+
+# ____________________________________________________________
+
def unsafe_escaping_ptr_for_ptr_or_array(w_cdata):
if not w_cdata.ctype.is_nonfunc_pointer_or_array:
diff --git a/pypy/module/_cffi_backend/parse_c_type.py b/pypy/module/_cffi_backend/parse_c_type.py
--- a/pypy/module/_cffi_backend/parse_c_type.py
+++ b/pypy/module/_cffi_backend/parse_c_type.py
@@ -97,11 +97,8 @@
[rffi.INT], rffi.CCHARP)
def parse_c_type(info, input):
- p_input = rffi.str2charp(input)
- try:
+ with rffi.scoped_view_charp(input) as p_input:
res = ll_parse_c_type(info, p_input)
- finally:
- rffi.free_charp(p_input)
return rffi.cast(lltype.Signed, res)
NULL_CTX = lltype.nullptr(PCTX.TO)
@@ -130,15 +127,13 @@
return rffi.getintfield(src_ctx, 'c_num_types')
def search_in_globals(ctx, name):
- c_name = rffi.str2charp(name)
- result = ll_search_in_globals(ctx, c_name,
- rffi.cast(rffi.SIZE_T, len(name)))
- rffi.free_charp(c_name)
+ with rffi.scoped_view_charp(name) as c_name:
+ result = ll_search_in_globals(ctx, c_name,
+ rffi.cast(rffi.SIZE_T, len(name)))
return rffi.cast(lltype.Signed, result)
def search_in_struct_unions(ctx, name):
- c_name = rffi.str2charp(name)
- result = ll_search_in_struct_unions(ctx, c_name,
- rffi.cast(rffi.SIZE_T, len(name)))
- rffi.free_charp(c_name)
+ with rffi.scoped_view_charp(name) as c_name:
+ result = ll_search_in_struct_unions(ctx, c_name,
+ rffi.cast(rffi.SIZE_T, len(name)))
return rffi.cast(lltype.Signed, result)
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
# ____________________________________________________________
import sys
-assert __version__ == "1.7.0", ("This test_c.py file is for testing a version"
+assert __version__ == "1.8.0", ("This test_c.py file is for testing a version"
" of cffi that differs from the one that we"
" get from 'import _cffi_backend'")
if sys.version_info < (3,):
@@ -3330,13 +3330,18 @@
BChar = new_primitive_type("char")
BCharP = new_pointer_type(BChar)
BCharA = new_array_type(BCharP, None)
- py.test.raises(TypeError, from_buffer, BCharA, b"foo")
+ p1 = from_buffer(BCharA, b"foo")
+ assert p1 == from_buffer(BCharA, b"foo")
+ import gc; gc.collect()
+ assert p1 == from_buffer(BCharA, b"foo")
py.test.raises(TypeError, from_buffer, BCharA, u+"foo")
try:
from __builtin__ import buffer
except ImportError:
pass
else:
+ # from_buffer(buffer(b"foo")) does not work, because it's not
+ # implemented on pypy; only from_buffer(b"foo") works.
py.test.raises(TypeError, from_buffer, BCharA, buffer(b"foo"))
py.test.raises(TypeError, from_buffer, BCharA, buffer(u+"foo"))
try:
diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ b/pypy/module/_multiprocessing/interp_connection.py
@@ -402,21 +402,20 @@
_WriteFile, ERROR_NO_SYSTEM_RESOURCES)
from rpython.rlib import rwin32
- charp = rffi.str2charp(buf)
- written_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
- flavor='raw')
- try:
- result = _WriteFile(
- self.handle, rffi.ptradd(charp, offset),
- size, written_ptr, rffi.NULL)
+ with rffi.scoped_view_charp(buf) as charp:
+ written_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
+ flavor='raw')
+ try:
+ result = _WriteFile(
+ self.handle, rffi.ptradd(charp, offset),
+ size, written_ptr, rffi.NULL)
- if (result == 0 and
- rwin32.GetLastError_saved() == ERROR_NO_SYSTEM_RESOURCES):
- raise oefmt(space.w_ValueError,
- "Cannot send %d bytes over connection", size)
- finally:
- rffi.free_charp(charp)
- lltype.free(written_ptr, flavor='raw')
+ if (result == 0 and
+ rwin32.GetLastError_saved() == ERROR_NO_SYSTEM_RESOURCES):
+ raise oefmt(space.w_ValueError,
+ "Cannot send %d bytes over connection", size)
+ finally:
+ lltype.free(written_ptr, flavor='raw')
def do_recv_string(self, space, buflength, maxlength):
from pypy.module._multiprocessing.interp_win32 import (
diff --git a/pypy/module/_posixsubprocess/interp_subprocess.py b/pypy/module/_posixsubprocess/interp_subprocess.py
--- a/pypy/module/_posixsubprocess/interp_subprocess.py
+++ b/pypy/module/_posixsubprocess/interp_subprocess.py
@@ -15,8 +15,9 @@
class CConfig:
_compilation_info_ = ExternalCompilationInfo(
- includes=['unistd.h', 'sys/syscall.h'])
+ includes=['unistd.h', 'sys/syscall.h', 'sys/stat.h'])
HAVE_SYS_SYSCALL_H = platform.Has("syscall")
+ HAVE_SYS_STAT_H = platform.Has("stat")
HAVE_SETSID = platform.Has("setsid")
config = platform.configure(CConfig)
@@ -29,6 +30,8 @@
compile_extra = []
if config['HAVE_SYS_SYSCALL_H']:
compile_extra.append("-DHAVE_SYS_SYSCALL_H")
+if config['HAVE_SYS_STAT_H']:
+ compile_extra.append("-DHAVE_SYS_STAT_H")
if config['HAVE_SETSID']:
compile_extra.append("-DHAVE_SETSID")
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -1,6 +1,7 @@
import sys, os
-import py
+import pytest
from pypy.tool.pytest.objspace import gettestobjspace
+from pypy.interpreter.gateway import interp2app
from rpython.tool.udir import udir
from rpython.rlib import rsocket
from rpython.rtyper.lltypesystem import lltype, rffi
@@ -13,8 +14,6 @@
mod.w_socket = space.appexec([], "(): import _socket as m; return m")
mod.path = udir.join('fd')
mod.path.write('fo')
- mod.raises = py.test.raises # make raises available from app-level tests
- mod.skip = py.test.skip
def test_gethostname():
host = space.appexec([w_socket], "(_socket): return _socket.gethostname()")
@@ -42,7 +41,7 @@
for host in ["localhost", "127.0.0.1", "::1"]:
if host == "::1" and not ipv6:
from pypy.interpreter.error import OperationError
- with py.test.raises(OperationError):
+ with pytest.raises(OperationError):
space.appexec([w_socket, space.wrap(host)],
"(_socket, host): return _socket.gethostbyaddr(host)")
continue
@@ -58,14 +57,14 @@
assert space.unwrap(port) == 25
# 1 arg version
if sys.version_info < (2, 4):
- py.test.skip("getservbyname second argument is not optional before python 2.4")
+ pytest.skip("getservbyname second argument is not optional before python 2.4")
port = space.appexec([w_socket, space.wrap(name)],
"(_socket, name): return _socket.getservbyname(name)")
assert space.unwrap(port) == 25
def test_getservbyport():
if sys.version_info < (2, 4):
- py.test.skip("getservbyport does not exist before python 2.4")
+ pytest.skip("getservbyport does not exist before python 2.4")
port = 25
# 2 args version
name = space.appexec([w_socket, space.wrap(port)],
@@ -139,7 +138,7 @@
def test_pton_ntop_ipv4():
if not hasattr(socket, 'inet_pton'):
- py.test.skip('No socket.inet_pton on this platform')
+ pytest.skip('No socket.inet_pton on this platform')
tests = [
("123.45.67.89", "\x7b\x2d\x43\x59"),
("0.0.0.0", "\x00" * 4),
@@ -155,9 +154,9 @@
def test_ntop_ipv6():
if not hasattr(socket, 'inet_pton'):
- py.test.skip('No socket.inet_pton on this platform')
+ pytest.skip('No socket.inet_pton on this platform')
if not socket.has_ipv6:
- py.test.skip("No IPv6 on this platform")
+ pytest.skip("No IPv6 on this platform")
tests = [
("\x00" * 16, "::"),
("\x01" * 16, ":".join(["101"] * 8)),
@@ -176,9 +175,9 @@
def test_pton_ipv6():
if not hasattr(socket, 'inet_pton'):
- py.test.skip('No socket.inet_pton on this platform')
+ pytest.skip('No socket.inet_pton on this platform')
if not socket.has_ipv6:
- py.test.skip("No IPv6 on this platform")
+ pytest.skip("No IPv6 on this platform")
tests = [
("\x00" * 16, "::"),
("\x01" * 16, ":".join(["101"] * 8)),
@@ -197,7 +196,7 @@
assert space.unwrap(w_packed) == packed
def test_has_ipv6():
- py.test.skip("has_ipv6 is always True on PyPy for now")
+ pytest.skip("has_ipv6 is always True on PyPy for now")
res = space.appexec([w_socket], "(_socket): return _socket.has_ipv6")
assert space.unwrap(res) == socket.has_ipv6
@@ -231,7 +230,7 @@
def test_addr_raw_packet():
from pypy.module._socket.interp_socket import addr_as_object
if not hasattr(rsocket._c, 'sockaddr_ll'):
- py.test.skip("posix specific test")
+ pytest.skip("posix specific test")
# HACK: To get the correct interface number of lo, which in most cases is 1,
# but can be anything (i.e. 39), we need to call the libc function
# if_nametoindex to get the correct index
@@ -653,11 +652,11 @@
class AppTestNetlink:
def setup_class(cls):
if not hasattr(os, 'getpid'):
- py.test.skip("AF_NETLINK needs os.getpid()")
+ pytest.skip("AF_NETLINK needs os.getpid()")
w_ok = space.appexec([], "(): import _socket; " +
"return hasattr(_socket, 'AF_NETLINK')")
if not space.is_true(w_ok):
- py.test.skip("no AF_NETLINK on this platform")
+ pytest.skip("no AF_NETLINK on this platform")
cls.space = space
def test_connect_to_kernel_netlink_routing_socket(self):
@@ -673,11 +672,11 @@
class AppTestPacket:
def setup_class(cls):
if not hasattr(os, 'getuid') or os.getuid() != 0:
- py.test.skip("AF_PACKET needs to be root for testing")
+ pytest.skip("AF_PACKET needs to be root for testing")
w_ok = space.appexec([], "(): import _socket; " +
"return hasattr(_socket, 'AF_PACKET')")
if not space.is_true(w_ok):
- py.test.skip("no AF_PACKET on this platform")
+ pytest.skip("no AF_PACKET on this platform")
cls.space = space
def test_convert_between_tuple_and_sockaddr_ll(self):
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -146,7 +146,7 @@
def __init__(self, ctx, protos):
self.protos = protos
- self.buf, self.pinned, self.is_raw = rffi.get_nonmovingbuffer(protos)
+ self.buf, self.bufflag = rffi.get_nonmovingbuffer(protos)
NPN_STORAGE.set(rffi.cast(lltype.Unsigned, self.buf), self)
# set both server and client callbacks, because the context
@@ -158,7 +158,7 @@
def __del__(self):
rffi.free_nonmovingbuffer(
- self.protos, self.buf, self.pinned, self.is_raw)
+ self.protos, self.buf, self.bufflag)
@staticmethod
def advertiseNPN_cb(s, data_ptr, len_ptr, args):
@@ -192,7 +192,7 @@
def __init__(self, ctx, protos):
self.protos = protos
- self.buf, self.pinned, self.is_raw = rffi.get_nonmovingbuffer(protos)
+ self.buf, self.bufflag = rffi.get_nonmovingbuffer(protos)
ALPN_STORAGE.set(rffi.cast(lltype.Unsigned, self.buf), self)
with rffi.scoped_str2charp(protos) as protos_buf:
@@ -204,7 +204,7 @@
def __del__(self):
rffi.free_nonmovingbuffer(
- self.protos, self.buf, self.pinned, self.is_raw)
+ self.protos, self.buf, self.bufflag)
@staticmethod
def selectALPN_cb(s, out_ptr, outlen_ptr, client, client_len, args):
@@ -239,7 +239,7 @@
Mix string into the OpenSSL PRNG state. entropy (a float) is a lower
bound on the entropy contained in string."""
- with rffi.scoped_str2charp(string) as buf:
+ with rffi.scoped_nonmovingbuffer(string) as buf:
libssl_RAND_add(buf, len(string), entropy)
def _RAND_bytes(space, n, pseudo):
diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py
--- a/pypy/module/cppyy/capi/builtin_capi.py
+++ b/pypy/module/cppyy/capi/builtin_capi.py
@@ -537,9 +537,8 @@
releasegil=ts_helper,
compilation_info=backend.eci)
def c_charp2stdstring(space, svalue):
- charp = rffi.str2charp(svalue)
- result = _c_charp2stdstring(charp)
- rffi.free_charp(charp)
+ with rffi.scoped_view_charp(svalue) as charp:
+ result = _c_charp2stdstring(charp)
return result
_c_stdstring2stdstring = rffi.llexternal(
"cppyy_stdstring2stdstring",
diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ b/pypy/module/cppyy/capi/cint_capi.py
@@ -82,9 +82,8 @@
releasegil=ts_helper,
compilation_info=eci)
def c_charp2TString(space, svalue):
- charp = rffi.str2charp(svalue)
- result = _c_charp2TString(charp)
- rffi.free_charp(charp)
+ with rffi.scoped_view_charp(svalue) as charp:
+ result = _c_charp2TString(charp)
return result
_c_TString2TString = rffi.llexternal(
"cppyy_TString2TString",
diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py
--- a/pypy/module/cppyy/capi/loadable_capi.py
+++ b/pypy/module/cppyy/capi/loadable_capi.py
@@ -65,6 +65,7 @@
else: # only other use is sring
n = len(obj._string)
assert raw_string == rffi.cast(rffi.CCHARP, 0)
+ # XXX could use rffi.get_nonmovingbuffer_final_null()
raw_string = rffi.str2charp(obj._string)
data = rffi.cast(rffi.CCHARPP, data)
data[0] = raw_string
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -11,6 +11,9 @@
from rpython.rtyper.annlowlevel import llhelper
from rpython.rlib.objectmodel import we_are_translated, keepalive_until_here
from rpython.rlib.objectmodel import dont_inline
+from rpython.rlib.rfile import (FILEP, c_fread, c_fclose, c_fwrite,
+ c_fdopen, c_fileno,
+ c_fopen)# for tests
from rpython.translator import cdir
from rpython.translator.tool.cbuild import ExternalCompilationInfo
from rpython.translator.gensupp import NameManager
@@ -84,44 +87,32 @@
assert CONST_WSTRING == rffi.CWCHARP
# FILE* interface
-FILEP = rffi.COpaquePtr('FILE')
if sys.platform == 'win32':
dash = '_'
else:
dash = ''
-fileno = rffi.llexternal(dash + 'fileno', [FILEP], rffi.INT)
-fopen = rffi.llexternal('fopen', [CONST_STRING, CONST_STRING], FILEP)
-fdopen = rffi.llexternal(dash + 'fdopen', [rffi.INT, CONST_STRING],
- FILEP, save_err=rffi.RFFI_SAVE_ERRNO)
-_fclose = rffi.llexternal('fclose', [FILEP], rffi.INT)
def fclose(fp):
- if not is_valid_fd(fileno(fp)):
+ if not is_valid_fd(c_fileno(fp)):
return -1
- return _fclose(fp)
+ return c_fclose(fp)
-_fwrite = rffi.llexternal('fwrite',
- [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
- rffi.SIZE_T)
def fwrite(buf, sz, n, fp):
- validate_fd(fileno(fp))
- return _fwrite(buf, sz, n, fp)
+ validate_fd(c_fileno(fp))
+ return c_fwrite(buf, sz, n, fp)
-_fread = rffi.llexternal('fread',
- [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
- rffi.SIZE_T)
def fread(buf, sz, n, fp):
- validate_fd(fileno(fp))
- return _fread(buf, sz, n, fp)
+ validate_fd(c_fileno(fp))
+ return c_fread(buf, sz, n, fp)
_feof = rffi.llexternal('feof', [FILEP], rffi.INT)
def feof(fp):
- validate_fd(fileno(fp))
+ validate_fd(c_fileno(fp))
return _feof(fp)
def is_valid_fp(fp):
- return is_valid_fd(fileno(fp))
+ return is_valid_fd(c_fileno(fp))
pypy_decl = 'pypy_decl.h'
diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -96,7 +96,8 @@
raise oefmt(space.w_ValueError,
"bytes_attach called on object with ob_size %d but trying to store %d",
py_str.c_ob_size, len(s))
- rffi.c_memcpy(py_str.c_ob_sval, rffi.str2charp(s), len(s))
+ with rffi.scoped_nonmovingbuffer(s) as s_ptr:
+ rffi.c_memcpy(py_str.c_ob_sval, s_ptr, len(s))
py_str.c_ob_sval[len(s)] = '\0'
py_str.c_ob_shash = space.hash_w(w_obj)
py_str.c_ob_sstate = rffi.cast(rffi.INT, 1) # SSTATE_INTERNED_MORTAL
diff --git a/pypy/module/cpyext/c-api.txt b/pypy/module/cpyext/c-api.txt
deleted file mode 100644
--- a/pypy/module/cpyext/c-api.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-Reference Count
-===============
-
-XXX
-
-Borrowed References
-===================
-
-XXX
-
-PyStringObject support
-======================
-
-The problem
------------
-
-PyString_AsString() returns 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.
-
-Note that 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.
-
-Proposed solution
------------------
-
-Our emulation of the PyStringObject contains an additional member: 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. When 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 buffer with the specified size, but the reference won't
- be stored in the global map py_objects_r2w; there won't be a
- corresponding object in pypy. When from_ref() or Py_INCREF() is
- called, the pypy string is created, and added in py_objects_r2w.
- 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 don't need to force the object. (in this case, another
- "size" member is needed)
-
-- There could be an (expensive!) check in from_ref() that the buffer
- still corresponds to the pypy gc-managed string.
-
-PySequence_Fast support
-======================
-There are five functions for fast sequence access offered by the CPython API:
-
-PyObject* PySequence_Fast(PyObject *o, const char *m)
-
-PyObject* PySequence_Fast_GET_ITEM( PyObject *o, int i)
-
-PyObject** PySequence_Fast_ITEMS( PyObject *o)
-
-PyObject* PySequence_ITEM( PyObject *o, int i)
-
-int PySequence_Fast_GET_SIZE( PyObject *o)
-
-PyPy supports four of these, but does not support PySequence_Fast_ITEMS.
-(Various ways to support PySequence_Fast_ITEMS were considered. They all had
-two things in common: they would have taken a lot of work, and they would have
-resulted in incomplete semantics or in poor performance. We decided that a slow
-implementation of PySequence_Fast_ITEMS was not very useful.)
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -25,6 +25,8 @@
flavor='raw',
add_memory_pressure=True)
+realloc = rffi.llexternal('realloc', [rffi.VOIDP, rffi.SIZE_T], rffi.VOIDP)
+
@cpython_api([rffi.VOIDP, size_t], rffi.VOIDP)
def PyObject_Realloc(space, ptr, size):
if not lltype.cast_ptr_to_int(ptr):
@@ -32,7 +34,7 @@
flavor='raw',
add_memory_pressure=True)
# XXX FIXME
- return lltype.nullptr(rffi.VOIDP.TO)
+ return realloc(ptr, size)
@cpython_api([rffi.VOIDP], lltype.Void)
def PyObject_Free(space, ptr):
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -10,7 +10,7 @@
from pypy.objspace.std import tupleobject
from pypy.module.cpyext.tupleobject import PyTuple_Check, PyTuple_SetItem
-from pypy.module.cpyext.object import Py_IncRef, Py_DecRef
+from pypy.module.cpyext.pyobject import decref
from pypy.module.cpyext.dictobject import PyDict_Check
@@ -252,7 +252,7 @@
def setitem(self, w_list, index, w_obj):
storage = self.unerase(w_list.lstorage)
index = self._check_index(index, storage._length)
- Py_DecRef(w_list.space, storage._elems[index])
+ decref(w_list.space, storage._elems[index])
storage._elems[index] = make_ref(w_list.space, w_obj)
def length(self, w_list):
@@ -264,9 +264,8 @@
return storage._elems
def getslice(self, w_list, start, stop, step, length):
- #storage = self.unerase(w_list.lstorage)
- raise oefmt(w_list.space.w_NotImplementedError,
- "settting a slice of a PySequence_Fast is not supported")
+ w_list.switch_to_object_strategy()
+ return w_list.strategy.getslice(w_list, start, stop, step, length)
def getitems(self, w_list):
# called when switching list strategy, so convert storage
@@ -389,5 +388,5 @@
def __del__(self):
for i in range(self._length):
- Py_DecRef(self.space, self._elems[i])
+ decref(self.space, self._elems[i])
lltype.free(self._elems, flavor='raw')
diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py
--- a/pypy/module/cpyext/test/test_eval.py
+++ b/pypy/module/cpyext/test/test_eval.py
@@ -3,7 +3,7 @@
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.eval import (
Py_single_input, Py_file_input, Py_eval_input, PyCompilerFlags)
-from pypy.module.cpyext.api import fopen, fclose, fileno, Py_ssize_tP
+from pypy.module.cpyext.api import c_fopen, c_fclose, c_fileno, Py_ssize_tP
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.astcompiler import consts
from rpython.tool.udir import udir
@@ -130,19 +130,19 @@
def test_run_file(self, space, api):
filepath = udir / "cpyext_test_runfile.py"
filepath.write("raise ZeroDivisionError")
- fp = fopen(str(filepath), "rb")
+ fp = c_fopen(str(filepath), "rb")
filename = rffi.str2charp(str(filepath))
w_globals = w_locals = space.newdict()
api.PyRun_File(fp, filename, Py_file_input, w_globals, w_locals)
- fclose(fp)
+ c_fclose(fp)
assert api.PyErr_Occurred() is space.w_ZeroDivisionError
api.PyErr_Clear()
# try again, but with a closed file
- fp = fopen(str(filepath), "rb")
- os.close(fileno(fp))
+ fp = c_fopen(str(filepath), "rb")
+ os.close(c_fileno(fp))
api.PyRun_File(fp, filename, Py_file_input, w_globals, w_locals)
- fclose(fp)
+ c_fclose(fp)
assert api.PyErr_Occurred() is space.w_IOError
api.PyErr_Clear()
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -212,8 +212,9 @@
assert type(x) is float
assert x == -12.34
- @pytest.mark.skipif(True, reason='realloc not fully implemented')
def test_object_realloc(self):
+ if not self.runappdirect:
+ skip('no untranslated support for realloc')
module = self.import_extension('foo', [
("realloctest", "METH_NOARGS",
"""
@@ -221,12 +222,11 @@
char *copy, *orig = PyObject_MALLOC(12);
memcpy(orig, "hello world", 12);
copy = PyObject_REALLOC(orig, 15);
+ /* realloc() takes care of freeing orig, if changed */
if (copy == NULL)
Py_RETURN_NONE;
ret = PyBytes_FromStringAndSize(copy, 12);
- if (copy != orig)
- PyObject_Free(copy);
- PyObject_Free(orig);
+ PyObject_Free(copy);
return ret;
""")])
x = module.realloctest()
diff --git a/pypy/module/cpyext/test/test_sequence.py b/pypy/module/cpyext/test/test_sequence.py
--- a/pypy/module/cpyext/test/test_sequence.py
+++ b/pypy/module/cpyext/test/test_sequence.py
@@ -78,6 +78,17 @@
assert api.PySequence_SetSlice(w_t, 1, 1, space.wrap((3,))) == 0
assert space.eq_w(w_t, space.wrap([1, 3, 5]))
+ def test_get_slice_fast(self, space, api):
+ w_t = space.wrap([1, 2, 3, 4, 5])
+ api.PySequence_Fast(w_t, "foo") # converts
+ assert space.unwrap(api.PySequence_GetSlice(w_t, 2, 4)) == [3, 4]
+ assert space.unwrap(api.PySequence_GetSlice(w_t, 1, -1)) == [2, 3, 4]
+
+ assert api.PySequence_DelSlice(w_t, 1, 4) == 0
+ assert space.eq_w(w_t, space.wrap([1, 5]))
+ assert api.PySequence_SetSlice(w_t, 1, 1, space.wrap((3,))) == 0
+ assert space.eq_w(w_t, space.wrap([1, 3, 5]))
+
def test_iter(self, space, api):
w_t = space.wrap((1, 2))
w_iter = api.PySeqIter_New(w_t)
@@ -226,18 +237,33 @@
assert space.int_w(space.len(w_l)) == 10
-class XAppTestSequenceObject(AppTestCpythonExtensionBase):
- def test_sequenceobject(self):
+class AppTestSequenceObject(AppTestCpythonExtensionBase):
+ def test_fast(self):
module = self.import_extension('foo', [
("test_fast_sequence", "METH_VARARGS",
"""
- PyObject * o = PyTuple_GetItem(args, 0);
+ int size, i;
+ PyTypeObject * common_type;
+ PyObject *foo, **objects;
+ PyObject * seq = PyTuple_GetItem(args, 0);
/* XXX assert it is a tuple */
- PyObject *foo = PySequence_Fast(o, "some string");
- PyObject ** res = PySequence_Fast_ITEMS(foo);
- /* XXX do some kind of test on res */
- /* XXX now what? who manages res's refcount? */
+ if (seq == NULL)
+ Py_RETURN_NONE;
+ foo = PySequence_Fast(seq, "some string");
+ objects = PySequence_Fast_ITEMS(foo);
+ size = PySequence_Fast_GET_SIZE(seq);
+ common_type = size > 0 ? Py_TYPE(objects[0]) : NULL;
+ for (i = 1; i < size; ++i) {
+ if (Py_TYPE(objects[i]) != common_type) {
+ common_type = NULL;
+ break;
+ }
+ }
+ Py_DECREF(foo);
+ Py_DECREF(common_type);
return PyBool_FromLong(1);
""")])
- assert module.test_fast_sequence([1, 2, 3, 4])
+ s = [1, 2, 3, 4]
+ assert module.test_fast_sequence(s[0:-1])
+ assert module.test_fast_sequence(s[::-1])
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -47,6 +47,7 @@
jl.MP_SCOPE, jl.MP_INDEX, jl.MP_OPCODE)
def get_location(next_instr, is_being_profiled, bytecode):
from pypy.tool.stdlib_opcode import opcode_method_names
+ from rpython.tool.error import offset2lineno
bcindex = ord(bytecode.co_code[next_instr])
opname = ""
if 0 <= bcindex < len(opcode_method_names):
@@ -54,7 +55,8 @@
name = bytecode.co_name
if not name:
name = ""
- return (bytecode.co_filename, bytecode.co_firstlineno,
+ line = offset2lineno(bytecode, intmask(next_instr))
+ return (bytecode.co_filename, line,
name, intmask(next_instr), opname)
def should_unroll_one_iteration(next_instr, is_being_profiled, bytecode):
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
@@ -19,6 +19,7 @@
self.defaultencoding = "utf-8"
self.filesystemencoding = None
self.debug = True
+ self.track_resources = False
self.dlopenflags = rdynload._dlopen_default_mode()
interpleveldefs = {
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ownlib.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ownlib.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ownlib.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ownlib.py
@@ -130,7 +130,7 @@
cls.module = str(udir.join('testownlib.dll'))
else:
subprocess.check_call(
- 'gcc testownlib.c -shared -fPIC -o testownlib.so',
+ 'cc testownlib.c -shared -fPIC -o testownlib.so',
cwd=str(udir), shell=True)
cls.module = str(udir.join('testownlib.so'))
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -852,9 +852,12 @@
assert str(e2.value) == "foo0() takes no arguments (2 given)"
assert str(e3.value) == "foo1() takes exactly one argument (0 given)"
assert str(e4.value) == "foo1() takes exactly one argument (2 given)"
- assert str(e5.value) == "foo2() takes exactly 2 arguments (0 given)"
- assert str(e6.value) == "foo2() takes exactly 2 arguments (1 given)"
- assert str(e7.value) == "foo2() takes exactly 2 arguments (3 given)"
+ assert str(e5.value) in ["foo2 expected 2 arguments, got 0",
+ "foo2() takes exactly 2 arguments (0 given)"]
+ assert str(e6.value) in ["foo2 expected 2 arguments, got 1",
+ "foo2() takes exactly 2 arguments (1 given)"]
+ assert str(e7.value) in ["foo2 expected 2 arguments, got 3",
+ "foo2() takes exactly 2 arguments (3 given)"]
def test_address_of_function():
ffi = FFI()
@@ -1916,3 +1919,47 @@
ffi.cdef("bool f(void);")
lib = verify(ffi, "test_bool_in_cpp", "char f(void) { return 2; }")
assert lib.f() == 1
+
+def test_bool_in_cpp_2():
+ ffi = FFI()
+ ffi.cdef('int add(int a, int b);')
+ lib = verify(ffi, "test_bool_bug_cpp", '''
+ typedef bool _Bool; /* there is a Windows header with this line */
+ int add(int a, int b)
+ {
+ return a + b;
+ }''', source_extension='.cpp')
+ c = lib.add(2, 3)
+ assert c == 5
+
+def test_struct_field_opaque():
+ ffi = FFI()
+ ffi.cdef("struct a { struct b b; };")
+ e = py.test.raises(TypeError, verify,
+ ffi, "test_struct_field_opaque", "?")
+ assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
+ " type (not declared in cdef())")
+ ffi = FFI()
+ ffi.cdef("struct a { struct b b[2]; };")
+ e = py.test.raises(TypeError, verify,
+ ffi, "test_struct_field_opaque", "?")
+ assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
+ " type (not declared in cdef())")
+ ffi = FFI()
+ ffi.cdef("struct a { struct b b[]; };")
+ e = py.test.raises(TypeError, verify,
+ ffi, "test_struct_field_opaque", "?")
+ assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
+ " type (not declared in cdef())")
+
+def test_function_arg_opaque():
+ py.test.skip("can currently declare a function with an opaque struct "
+ "as argument, but AFAICT it's impossible to call it later")
+
+def test_function_returns_opaque():
+ ffi = FFI()
+ ffi.cdef("struct a foo(int);")
+ e = py.test.raises(TypeError, verify,
+ ffi, "test_function_returns_opaque", "?")
+ assert str(e.value) == ("function foo: 'struct a' is used as result type,"
+ " but is opaque")
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_functions.py
@@ -133,6 +133,12 @@
# You cannot assing character format codes as restype any longer
raises(TypeError, setattr, f, "restype", "i")
+ def test_unicode_function_name(self):
+ f = dll[u'_testfunc_i_bhilfd']
+ f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
+ f.restype = c_int
+ result = f(1, 2, 3, 4, 5.0, 6.0)
+ assert result == 21
def test_truncate_python_longs(self):
f = dll._testfunc_i_bhilfd
diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py
--- a/pypy/module/time/interp_time.py
+++ b/pypy/module/time/interp_time.py
@@ -159,7 +159,6 @@
libraries=rtime.libraries
)
CLOCKS_PER_SEC = platform.ConstantInteger("CLOCKS_PER_SEC")
- clock_t = platform.SimpleType("clock_t", rffi.ULONG)
has_gettimeofday = platform.Has('gettimeofday')
has_clock_gettime = platform.Has('clock_gettime')
CLOCK_PROF = platform.DefinedConstantInteger('CLOCK_PROF')
@@ -233,7 +232,6 @@
HAS_CLOCK_MONOTONIC = cConfig.CLOCK_MONOTONIC is not None
HAS_MONOTONIC = (_WIN or _MACOSX or
(HAS_CLOCK_GETTIME and (HAS_CLOCK_HIGHRES or HAS_CLOCK_MONOTONIC)))
-clock_t = cConfig.clock_t
tm = cConfig.tm
glob_buf = lltype.malloc(tm, flavor='raw', zero=True, immortal=True)
@@ -1030,7 +1028,10 @@
with lltype.scoped_alloc(rposix.TMS) as tms:
ret = rposix.c_times(tms)
if rffi.cast(lltype.Signed, ret) != -1:
- cpu_time = float(tms.c_tms_utime + tms.c_tms_stime)
+ cpu_time = float(rffi.cast(lltype.Signed,
+ tms.c_tms_utime) +
+ rffi.cast(lltype.Signed,
+ tms.c_tms_stime))
if w_info is not None:
_setinfo(space, w_info, "times()",
1.0 / rposix.CLOCK_TICKS_PER_SECOND,
@@ -1038,7 +1039,7 @@
return space.wrap(cpu_time / rposix.CLOCK_TICKS_PER_SECOND)
return clock(space)
-_clock = external('clock', [], clock_t)
+_clock = external('clock', [], rposix.CLOCK_T)
def clock(space, w_info=None):
"""clock() -> floating point number
@@ -1052,7 +1053,7 @@
pass
value = _clock()
# Is this casting correct?
- if value == rffi.cast(clock_t, -1):
+ if intmask(value) == intmask(rffi.cast(rposix.CLOCK_T, -1)):
raise oefmt(space.w_RuntimeError,
"the processor time used is not available or its value"
"cannot be represented")
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -930,6 +930,7 @@
abstractinst.p_recursive_isinstance_type_w(space, w_inst, w_obj))
def type_get_dict(space, w_cls):
+ w_cls = _check(space, w_cls)
from pypy.objspace.std.dictproxyobject import W_DictProxyObject
w_dict = w_cls.getdict(space)
if w_dict is None:
@@ -1287,7 +1288,8 @@
cycle.append(candidate)
cycle.reverse()
names = [cls.getname(space) for cls in cycle]
- raise OperationError(space.w_TypeError, space.wrap(
+ # Can't use oefmt() here, since names is a list of unicodes
+ raise OperationError(space.w_TypeError, space.newunicode(
u"cycle among base classes: " + u' < '.join(names)))
diff --git a/pypy/tool/pytest/objspace.py b/pypy/tool/pytest/objspace.py
--- a/pypy/tool/pytest/objspace.py
+++ b/pypy/tool/pytest/objspace.py
@@ -143,3 +143,5 @@
def is_w(self, obj1, obj2):
return obj1 is obj2
+ def setitem(self, obj, key, value):
+ obj[key] = value
diff --git a/requirements.txt b/requirements.txt
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,3 @@
-# hypothesis is used for test generation on untranslated jit tests
+# hypothesis is used for test generation on untranslated tests
hypothesis
enum34>=1.1.2
diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -401,6 +401,9 @@
class __extend__(pairtype(SomeString, SomeTuple),
pairtype(SomeUnicodeString, SomeTuple)):
def mod((s_string, s_tuple)):
+ if not s_string.is_constant():
+ raise AnnotatorError("string formatting requires a constant "
+ "string/unicode on the left of '%'")
is_string = isinstance(s_string, SomeString)
is_unicode = isinstance(s_string, SomeUnicodeString)
assert is_string or is_unicode
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -4623,6 +4623,14 @@
a = self.RPythonAnnotator()
a.build_types(main, [int])
+ def test_string_mod_nonconstant(self):
+ def f(x):
+ return x % 5
+ a = self.RPythonAnnotator()
+ e = py.test.raises(AnnotatorError, a.build_types, f, [str])
+ assert ('string formatting requires a constant string/unicode'
+ in str(e.value))
+
def g(n):
return [0, 1, 2, n]
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -883,6 +883,7 @@
ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
self.cpu.translate_support_code)
assert itemsize == 1
+ ofs_items -= 1 # for the extra null character
scale = 0
self._gen_address(resloc, baseloc, ofsloc, scale, ofs_items)
diff --git a/rpython/jit/backend/llsupport/descr.py b/rpython/jit/backend/llsupport/descr.py
--- a/rpython/jit/backend/llsupport/descr.py
+++ b/rpython/jit/backend/llsupport/descr.py
@@ -280,7 +280,7 @@
concrete_type = '\x00'
def __init__(self, basesize, itemsize, lendescr, flag, is_pure=False, concrete_type='\x00'):
- self.basesize = basesize
+ self.basesize = basesize # this includes +1 for STR
self.itemsize = itemsize
self.lendescr = lendescr # or None, if no length
self.flag = flag
@@ -676,7 +676,7 @@
def unpack_arraydescr(arraydescr):
assert isinstance(arraydescr, ArrayDescr)
- ofs = arraydescr.basesize
+ ofs = arraydescr.basesize # this includes +1 for STR
size = arraydescr.itemsize
sign = arraydescr.is_item_signed()
return size, ofs, sign
diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -293,6 +293,7 @@
basesize, itemsize, ofs_length = get_array_token(rstr.STR,
self.cpu.translate_support_code)
assert itemsize == 1
+ basesize -= 1 # for the extra null character
self.emit_gc_load_or_indexed(op, op.getarg(0), op.getarg(1),
itemsize, itemsize, basesize, NOT_SIGNED)
elif opnum == rop.UNICODEGETITEM:
@@ -304,6 +305,7 @@
basesize, itemsize, ofs_length = get_array_token(rstr.STR,
self.cpu.translate_support_code)
assert itemsize == 1
+ basesize -= 1 # for the extra null character
self.emit_gc_store_or_indexed(op, op.getarg(0), op.getarg(1), op.getarg(2),
itemsize, itemsize, basesize)
elif opnum == rop.UNICODESETITEM:
diff --git a/rpython/jit/backend/llsupport/symbolic.py b/rpython/jit/backend/llsupport/symbolic.py
--- a/rpython/jit/backend/llsupport/symbolic.py
+++ b/rpython/jit/backend/llsupport/symbolic.py
@@ -29,7 +29,7 @@
def get_array_token(T, translate_support_code):
# T can be an array or a var-sized structure
if translate_support_code:
- basesize = llmemory.sizeof(T, 0)
+ basesize = llmemory.sizeof(T, 0) # this includes +1 for STR
if isinstance(T, lltype.Struct):
SUBARRAY = getattr(T, T._arrayfld)
itemsize = llmemory.sizeof(SUBARRAY.OF)
@@ -57,6 +57,7 @@
assert carray.length.size == WORD
ofs_length = before_array_part + carray.length.offset
basesize = before_array_part + carray.items.offset
+ basesize += T._hints.get('extra_item_after_alloc', 0) # +1 for STR
carrayitem = ll2ctypes.get_ctypes_type(T.OF)
itemsize = ctypes.sizeof(carrayitem)
return basesize, itemsize, ofs_length
diff --git a/rpython/jit/backend/llsupport/test/test_descr.py b/rpython/jit/backend/llsupport/test/test_descr.py
--- a/rpython/jit/backend/llsupport/test/test_descr.py
+++ b/rpython/jit/backend/llsupport/test/test_descr.py
@@ -435,8 +435,10 @@
def test_bytearray_descr():
c0 = GcCache(False)
descr = get_array_descr(c0, rstr.STR) # for bytearray
+ # note that we get a basesize that has 1 extra byte for the final null char
+ # (only for STR)
assert descr.flag == FLAG_UNSIGNED
- assert descr.basesize == struct.calcsize("PP") # hash, length
+ assert descr.basesize == struct.calcsize("PP") + 1 # hash, length, extra
assert descr.lendescr.offset == struct.calcsize("P") # hash
assert not descr.is_array_of_pointers()
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -647,6 +647,9 @@
""")
def test_rewrite_assembler_newstr_newunicode(self):
+ # note: strdescr.basesize already contains the extra final character,
+ # so that's why newstr(14) is rounded up to 'basesize+15' and not
+ # 'basesize+16'.
self.check_rewrite("""
[i2]
p0 = newstr(14)
@@ -657,12 +660,12 @@
""", """
[i2]
p0 = call_malloc_nursery( \
- %(strdescr.basesize + 16 * strdescr.itemsize + \
+ %(strdescr.basesize + 15 * strdescr.itemsize + \
unicodedescr.basesize + 10 * unicodedescr.itemsize)d)
gc_store(p0, 0, %(strdescr.tid)d, %(tiddescr.field_size)s)
gc_store(p0, %(strlendescr.offset)s, 14, %(strlendescr.field_size)s)
gc_store(p0, 0, 0, %(strhashdescr.field_size)s)
- p1 = nursery_ptr_increment(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d)
+ p1 = nursery_ptr_increment(p0, %(strdescr.basesize + 15 * strdescr.itemsize)d)
gc_store(p1, 0, %(unicodedescr.tid)d, %(tiddescr.field_size)s)
gc_store(p1, %(unicodelendescr.offset)s, 10, %(unicodelendescr.field_size)s)
gc_store(p1, 0, 0, %(unicodehashdescr.field_size)s)
@@ -1240,14 +1243,14 @@
# 'i3 = gc_load_i(p0,i5,%(unicodedescr.itemsize)d)'],
[True, (4,), 'i3 = strgetitem(p0,i1)' '->'
'i3 = gc_load_indexed_i(p0,i1,1,'
- '%(strdescr.basesize)d,1)'],
+ '%(strdescr.basesize-1)d,1)'],
#[False, (4,), 'i3 = strgetitem(p0,i1)' '->'
- # 'i5 = int_add(i1, %(strdescr.basesize)d);'
+ # 'i5 = int_add(i1, %(strdescr.basesize-1)d);'
# 'i3 = gc_load_i(p0,i5,1)'],
## setitem str/unicode
[True, (4,), 'i3 = strsetitem(p0,i1,0)' '->'
'i3 = gc_store_indexed(p0,i1,0,1,'
- '%(strdescr.basesize)d,1)'],
+ '%(strdescr.basesize-1)d,1)'],
[True, (2,4), 'i3 = unicodesetitem(p0,i1,0)' '->'
'i3 = gc_store_indexed(p0,i1,0,'
'%(unicodedescr.itemsize)d,'
diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py
--- a/rpython/jit/backend/llsupport/test/ztranslation_test.py
+++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py
@@ -3,7 +3,7 @@
from rpython.rlib.jit import JitDriver, unroll_parameters, set_param
from rpython.rlib.jit import PARAMETERS, dont_look_inside
from rpython.rlib.jit import promote, _get_virtualizable_token
-from rpython.rlib import jit_hooks, rposix
+from rpython.rlib import jit_hooks, rposix, rgc
from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rthread import ThreadLocalReference, ThreadLocalField
from rpython.jit.backend.detect_cpu import getcpuclass
@@ -11,7 +11,7 @@
from rpython.jit.codewriter.policy import StopAtXPolicy
from rpython.config.config import ConfigError
from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.lltypesystem import lltype, rffi, rstr
from rpython.rlib.rjitlog import rjitlog as jl
@@ -29,6 +29,7 @@
# - floats neg and abs
# - cast_int_to_float
# - llexternal with macro=True
+ # - extra place for the zero after STR instances
class BasicFrame(object):
_virtualizable_ = ['i']
@@ -56,7 +57,7 @@
return ("/home.py",0,0)
jitdriver = JitDriver(greens = [],
- reds = ['total', 'frame', 'j'],
+ reds = ['total', 'frame', 'prev_s', 'j'],
virtualizables = ['frame'],
get_location = get_location)
def f(i, j):
@@ -68,9 +69,12 @@
total = 0
frame = Frame(i)
j = float(j)
+ prev_s = rstr.mallocstr(16)
More information about the pypy-commit
mailing list