[pypy-commit] pypy py3.6: merge default (including a re-implementation of c46e92cbc2f9 for Python3)
cfbolz
pypy.commits at gmail.com
Wed Mar 27 16:07:23 EDT 2019
Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: py3.6
Changeset: r96366:5521ea7a9241
Date: 2019-03-27 21:00 +0100
http://bitbucket.org/pypy/pypy/changeset/5521ea7a9241/
Log: merge default (including a re-implementation of c46e92cbc2f9 for
Python3)
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -21,6 +21,7 @@
symbols = symtable.SymtableBuilder(space, module, info)
return TopLevelCodeGenerator(space, module, symbols, info).assemble()
+MAX_STACKDEPTH_CONTAINERS = 100
name_ops_default = misc.dict_to_switch({
ast.Load: ops.LOAD_NAME,
@@ -1222,10 +1223,31 @@
ifexp.orelse.walkabout(self)
self.use_next_block(end)
- def _visit_starunpack(self, node, elts, single_op, inner_op, outer_op):
+ def _visit_starunpack(self, node, elts, single_op, inner_op, outer_op, add_op):
elt_count = len(elts) if elts else 0
seen_star = 0
elt_subitems = 0
+ contains_starred = False
+ for i in range(elt_count):
+ elt = elts[i]
+ if isinstance(elt, ast.Starred):
+ contains_starred = True
+ break
+ if elt_count > MAX_STACKDEPTH_CONTAINERS and not contains_starred:
+ tuplecase = False
+ if add_op == -1: # tuples
+ self.emit_op_arg(ops.BUILD_LIST, 0)
+ add_op = ops.LIST_APPEND
+ tuplecase = True
+ else:
+ self.emit_op_arg(single_op, 0)
+ for elt in elts:
+ elt.walkabout(self)
+ self.emit_op_arg(add_op, 1)
+ if tuplecase:
+ self.emit_op_arg(ops.BUILD_TUPLE_UNPACK, 1)
+ return
+
for i in range(elt_count):
elt = elts[i]
is_starred = isinstance(elt, ast.Starred)
@@ -1279,7 +1301,7 @@
if tup.ctx == ast.Store:
self._visit_assignment(tup, tup.elts, tup.ctx)
elif tup.ctx == ast.Load:
- self._visit_starunpack(tup, tup.elts, ops.BUILD_TUPLE, ops.BUILD_TUPLE, ops.BUILD_TUPLE_UNPACK)
+ self._visit_starunpack(tup, tup.elts, ops.BUILD_TUPLE, ops.BUILD_TUPLE, ops.BUILD_TUPLE_UNPACK, -1)
else:
self.visit_sequence(tup.elts)
@@ -1288,7 +1310,8 @@
if l.ctx == ast.Store:
self._visit_assignment(l, l.elts, l.ctx)
elif l.ctx == ast.Load:
- self._visit_starunpack(l, l.elts, ops.BUILD_LIST, ops.BUILD_TUPLE, ops.BUILD_LIST_UNPACK)
+ self._visit_starunpack(
+ l, l.elts, ops.BUILD_LIST, ops.BUILD_TUPLE, ops.BUILD_LIST_UNPACK, ops.LIST_APPEND)
else:
self.visit_sequence(l.elts)
@@ -1343,7 +1366,7 @@
is_unpacking = False
def visit_Set(self, s):
- self._visit_starunpack(s, s.elts, ops.BUILD_SET, ops.BUILD_SET, ops.BUILD_SET_UNPACK)
+ self._visit_starunpack(s, s.elts, ops.BUILD_SET, ops.BUILD_SET, ops.BUILD_SET_UNPACK, ops.SET_ADD)
def visit_Name(self, name):
self.update_position(name.lineno)
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
@@ -1543,3 +1543,30 @@
assert ops.BUILD_TUPLE not in counts
+
+class TestHugeStackDepths:
+ def run_and_check_stacksize(self, source):
+ space = self.space
+ code = compile_with_astcompiler("a = " + source, 'exec', space)
+ assert code.co_stacksize < 100
+ w_dict = space.newdict()
+ code.exec_code(space, w_dict, w_dict)
+ return space.getitem(w_dict, space.newtext("a"))
+
+ def test_tuple(self):
+ source = "(" + ",".join([str(i) for i in range(200)]) + ")\n"
+ w_res = self.run_and_check_stacksize(source)
+ assert self.space.unwrap(w_res) == tuple(range(200))
+
+ def test_list(self):
+ source = "a = [" + ",".join([str(i) for i in range(200)]) + "]\n"
+ w_res = self.run_and_check_stacksize(source)
+ assert self.space.unwrap(w_res) == range(200)
+
+ def test_set(self):
+ source = "a = {" + ",".join([str(i) for i in range(200)]) + "}\n"
+ w_res = self.run_and_check_stacksize(source)
+ space = self.space
+ assert [space.int_w(w_x)
+ for w_x in space.unpackiterable(w_res)] == range(200)
+
diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -662,14 +662,17 @@
def wcharpsize2utf8(space, wcharp, size):
"""Safe version of rffi.wcharpsize2utf8.
- Raises app-level rutf8.OutOfRange if any wchar value is outside the valid
+ Raises app-level ValueError if any wchar value is outside the valid
codepoint range.
"""
try:
return rffi.wcharpsize2utf8(wcharp, size)
except rutf8.OutOfRange as e:
- raise oefmt(space.w_ValueError,
- "character %s is not in range [U+0000; U+10ffff]", 'U+%x' % e.code)
+ raise wrap_unicode_out_of_range_error(space, e)
+
+def wrap_unicode_out_of_range_error(space, e):
+ raise oefmt(space.w_ValueError,
+ "character %s is not in range [U+0000; U+10ffff]", 'U+%x' % e.code)
# ____________________________________________________________
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -5,6 +5,8 @@
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import interp_attrproperty
from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.interpreter.unicodehelper import wcharpsize2utf8
+from pypy.interpreter.unicodehelper import wrap_unicode_out_of_range_error
from rpython.rlib.clibffi import *
from rpython.rlib.objectmodel import we_are_translated
@@ -598,10 +600,13 @@
if address == 0:
return space.w_None
wcharp_addr = rffi.cast(rffi.CWCHARP, address)
- if maxlength == -1:
- s, lgt = rffi.wcharp2utf8(wcharp_addr)
- else:
- s, lgt = rffi.wcharp2utf8n(wcharp_addr, maxlength)
+ try:
+ if maxlength == -1:
+ s, lgt = rffi.wcharp2utf8(wcharp_addr)
+ else:
+ s, lgt = rffi.wcharp2utf8n(wcharp_addr, maxlength)
+ except rutf8.OutOfRange as e:
+ raise wrap_unicode_out_of_range_error(space, e)
return space.newutf8(s, lgt)
@unwrap_spec(address=r_uint, maxlength=int)
@@ -617,7 +622,7 @@
return wcharp2unicode(space, address)
elif maxlength < 0:
maxlength = 0
- s = rffi.wcharpsize2utf8(rffi.cast(rffi.CWCHARP, address), maxlength)
+ s = wcharpsize2utf8(space, rffi.cast(rffi.CWCHARP, address), maxlength)
return space.newutf8(s, maxlength)
@unwrap_spec(address=r_uint, newcontent='bufferstr', offset=int, size=int)
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -1225,6 +1225,23 @@
lib = _rawffi.CDLL(self.lib_name)
assert lib.name == self.lib_name
+ def test_wcharp2rawunicode(self):
+ import _rawffi
+ A = _rawffi.Array('i')
+ arg = A(1)
+ arg[0] = 0x1234
+ u = _rawffi.wcharp2rawunicode(arg.itemaddress(0))
+ assert u == u'\u1234'
+ u = _rawffi.wcharp2rawunicode(arg.itemaddress(0), 1)
+ assert u == u'\u1234'
+ arg[0] = -1
+ raises(ValueError, _rawffi.wcharp2rawunicode, arg.itemaddress(0))
+ raises(ValueError, _rawffi.wcharp2rawunicode, arg.itemaddress(0), 1)
+ arg[0] = 0x110000
+ raises(ValueError, _rawffi.wcharp2rawunicode, arg.itemaddress(0))
+ raises(ValueError, _rawffi.wcharp2rawunicode, arg.itemaddress(0), 1)
+ arg.free()
+
class AppTestAutoFree:
spaceconfig = dict(usemodules=['_rawffi', 'struct'])
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -14,6 +14,7 @@
interp2app, interpindirect2app, unwrap_spec)
from pypy.interpreter.typedef import (
GetSetProperty, TypeDef, make_weakref_descr)
+from pypy.interpreter.unicodehelper import wcharpsize2utf8
@unwrap_spec(typecode='text')
@@ -509,7 +510,8 @@
if s < 0:
s = 0
buf = rffi.cast(UNICODE_ARRAY, self._buffer_as_unsigned())
- return space.newutf8(rffi.wcharpsize2utf8(buf, s), s)
+ utf8 = wcharpsize2utf8(space, buf, s)
+ return space.newutf8(utf8, s)
else:
raise oefmt(space.w_ValueError,
"tounicode() may only be called on type 'u' arrays")
@@ -767,8 +769,16 @@
if self.len == 0:
return space.newtext("array('%s')" % self.typecode)
elif self.typecode == "u":
- r = space.repr(self.descr_tounicode(space))
- s = "array('%s', %s)" % (self.typecode, space.text_w(r))
+ try:
+ w_unicode = self.descr_tounicode(space)
+ except OperationError as e:
+ if not e.match(space, space.w_ValueError):
+ raise
+ w_exc_value = e.get_w_value(space)
+ r = "<%s>" % (space.text_w(w_exc_value),)
+ else:
+ r = space.text_w(space.repr(w_unicode))
+ s = "array('%s', %s)" % (self.typecode, r)
return space.newtext(s)
else:
r = space.repr(self.descr_tolist(space))
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -893,10 +893,16 @@
assert repr(mya('i', (1, 2, 3))) == "array('i', [1, 2, 3])"
def test_unicode_outofrange(self):
- a = self.array('u', u'\x01\u263a\x00\ufeff')
- b = self.array('u', u'\x01\u263a\x00\ufeff')
+ input_unicode = u'\x01\u263a\x00\ufeff'
+ a = self.array('u', input_unicode)
+ b = self.array('u', input_unicode)
b.byteswap()
raises(ValueError, "a != b")
+ assert str(a) == "array('u', %r)" % (input_unicode,)
+ assert str(b) == ("array('u', <character U+1000000 is not in"
+ " range [U+0000; U+10ffff]>)")
+ assert a.tounicode() == input_unicode
+ raises(ValueError, b.tounicode) # doesn't work
def test_weakref(self):
import weakref
diff --git a/pypy/module/gc/referents.py b/pypy/module/gc/referents.py
--- a/pypy/module/gc/referents.py
+++ b/pypy/module/gc/referents.py
@@ -20,7 +20,7 @@
# inherits from W_Root for internal reasons. Such instances don't
# have a typedef at all (or have a null typedef after translation).
if not we_are_translated():
- if not hasattr(w_obj, 'typedef'):
+ if getattr(w_obj, 'typedef', None) is None:
return None
else:
if w_obj is None or not w_obj.typedef:
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -1023,7 +1023,7 @@
def wcharpsize2utf8(w, size):
""" Helper to convert WCHARP pointer to utf8 in one go.
Equivalent to wcharpsize2unicode().encode("utf8")
- Raises ValueError if characters are outside range(0x110000)!
+ Raises rutf8.OutOfRange if characters are outside range(0x110000)!
"""
from rpython.rlib import rutf8
@@ -1033,6 +1033,9 @@
return s.build()
def wcharp2utf8(w):
+ """
+ Raises rutf8.OutOfRange if characters are outside range(0x110000)!
+ """
from rpython.rlib import rutf8
s = rutf8.Utf8StringBuilder()
@@ -1043,6 +1046,9 @@
return s.build(), i
def wcharp2utf8n(w, maxlen):
+ """
+ Raises rutf8.OutOfRange if characters are outside range(0x110000)!
+ """
from rpython.rlib import rutf8
s = rutf8.Utf8StringBuilder(maxlen)
More information about the pypy-commit
mailing list