[pypy-commit] pypy numpypy-argminmax: merge default into branch
mattip
noreply at buildbot.pypy.org
Wed Jul 4 23:05:20 CEST 2012
Author: mattip <matti.picus at gmail.com>
Branch: numpypy-argminmax
Changeset: r55923:5e348c42ac82
Date: 2012-07-05 00:01 +0300
http://bitbucket.org/pypy/pypy/changeset/5e348c42ac82/
Log: merge default into branch
diff --git a/lib_pypy/disassembler.py b/lib_pypy/disassembler.py
--- a/lib_pypy/disassembler.py
+++ b/lib_pypy/disassembler.py
@@ -24,6 +24,11 @@
self.lineno = lineno
self.line_starts_here = False
+ def __str__(self):
+ if self.arg is None:
+ return "%s" % (self.__class__.__name__,)
+ return "%s (%s)" % (self.__class__.__name__, self.arg)
+
def __repr__(self):
if self.arg is None:
return "<%s at %d>" % (self.__class__.__name__, self.pos)
diff --git a/pypy/annotation/annrpython.py b/pypy/annotation/annrpython.py
--- a/pypy/annotation/annrpython.py
+++ b/pypy/annotation/annrpython.py
@@ -133,44 +133,6 @@
self.build_graph_types(graph, inputcells, complete_now=False)
self.complete_helpers(policy)
return graph
-
- def annotate_helper_method(self, _class, attr, args_s, policy=None):
- """ Warning! this method is meant to be used between
- annotation and rtyping
- """
- if policy is None:
- from pypy.annotation.policy import AnnotatorPolicy
- policy = AnnotatorPolicy()
-
- assert attr != '__class__'
- classdef = self.bookkeeper.getuniqueclassdef(_class)
- attrdef = classdef.find_attribute(attr)
- s_result = attrdef.getvalue()
- classdef.add_source_for_attribute(attr, classdef.classdesc)
- self.bookkeeper
- assert isinstance(s_result, annmodel.SomePBC)
- olddesc = s_result.any_description()
- desc = olddesc.bind_self(classdef)
- args = self.bookkeeper.build_args("simple_call", args_s[:])
- desc.consider_call_site(self.bookkeeper, desc.getcallfamily(), [desc],
- args, annmodel.s_ImpossibleValue, None)
- result = []
- def schedule(graph, inputcells):
- result.append((graph, inputcells))
- return annmodel.s_ImpossibleValue
-
- prevpolicy = self.policy
- self.policy = policy
- self.bookkeeper.enter(None)
- try:
- desc.pycall(schedule, args, annmodel.s_ImpossibleValue)
- finally:
- self.bookkeeper.leave()
- self.policy = prevpolicy
- [(graph, inputcells)] = result
- self.build_graph_types(graph, inputcells, complete_now=False)
- self.complete_helpers(policy)
- return graph
def complete_helpers(self, policy):
saved = self.policy, self.added_blocks
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -514,9 +514,9 @@
continue
self.add_source_attribute(name, value, mixin=True)
- def add_sources_for_class(self, cls, mixin=False):
+ def add_sources_for_class(self, cls):
for name, value in cls.__dict__.items():
- self.add_source_attribute(name, value, mixin)
+ self.add_source_attribute(name, value)
def getallclassdefs(self):
return self._classdefs.values()
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -2747,20 +2747,6 @@
s = a.build_types(f, [])
assert s.knowntype == int
- def test_helper_method_annotator(self):
- def fun():
- return 21
-
- class A(object):
- def helper(self):
- return 42
-
- a = self.RPythonAnnotator()
- a.build_types(fun, [])
- a.annotate_helper_method(A, "helper", [])
- assert a.bookkeeper.getdesc(A.helper).getuniquegraph()
- assert a.bookkeeper.getdesc(A().helper).getuniquegraph()
-
def test_chr_out_of_bounds(self):
def g(n, max):
if n < max:
diff --git a/pypy/config/test/test_pypyoption.py b/pypy/config/test/test_pypyoption.py
--- a/pypy/config/test/test_pypyoption.py
+++ b/pypy/config/test/test_pypyoption.py
@@ -71,7 +71,7 @@
c = Config(descr)
for path in c.getpaths(include_groups=True):
fn = prefix + "." + path + ".txt"
- yield check_file_exists, fn
+ yield fn, check_file_exists, fn
def test__ffi_opt():
config = get_pypy_config(translating=True)
diff --git a/pypy/doc/config/objspace.usemodules.cppyy.txt b/pypy/doc/config/objspace.usemodules.cppyy.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.usemodules.cppyy.txt
@@ -0,0 +1,1 @@
+Use the 'cppyy' module
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -87,14 +87,19 @@
$ cd pypy
$ hg up reflex-support # optional
$ cd pypy/translator/goal
+
+ # This example shows python, but using pypy-c is faster and uses less memory
$ python translate.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy
This will build a ``pypy-c`` that includes the cppyy module, and through that,
Reflex support.
Of course, if you already have a pre-built version of the ``pypy`` interpreter,
you can use that for the translation rather than ``python``.
+If not, you may want `to obtain a binary distribution`_ to speed up the
+translation step.
.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview
+.. _`to obtain a binary distribution`: http://doc.pypy.org/en/latest/getting-started.html#download-a-pre-built-pypy
Basic example
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
@@ -11,7 +11,8 @@
.. branch: reflex-support
Provides cppyy module (disabled by default) for access to C++ through Reflex.
See doc/cppyy.rst for full details and functionality.
-
+.. branch: nupypy-axis-arg-check
+Check that axis arg is valid in _numpypy
.. "uninteresting" branches that we should just ignore for the whatsnew:
.. branch: slightly-shorter-c
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -496,7 +496,12 @@
# apply kw_spec
for name, spec in kw_spec.items():
- unwrap_spec[argnames.index(name)] = spec
+ try:
+ unwrap_spec[argnames.index(name)] = spec
+ except ValueError:
+ raise ValueError("unwrap_spec() got a keyword %r but it is not "
+ "the name of an argument of the following "
+ "function" % (name,))
return unwrap_spec
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
@@ -227,20 +227,29 @@
# length
self.setlen(0)
- def setlen(self, size):
+ def setlen(self, size, zero=False, overallocate=True):
if size > 0:
if size > self.allocated or size < self.allocated / 2:
- if size < 9:
- some = 3
+ if overallocate:
+ if size < 9:
+ some = 3
+ else:
+ some = 6
+ some += size >> 3
else:
- some = 6
- some += size >> 3
+ some = 0
self.allocated = size + some
- new_buffer = lltype.malloc(mytype.arraytype,
- self.allocated, flavor='raw',
- add_memory_pressure=True)
- for i in range(min(size, self.len)):
- new_buffer[i] = self.buffer[i]
+ if zero:
+ new_buffer = lltype.malloc(mytype.arraytype,
+ self.allocated, flavor='raw',
+ add_memory_pressure=True,
+ zero=True)
+ else:
+ new_buffer = lltype.malloc(mytype.arraytype,
+ self.allocated, flavor='raw',
+ add_memory_pressure=True)
+ for i in range(min(size, self.len)):
+ new_buffer[i] = self.buffer[i]
else:
self.len = size
return
@@ -346,7 +355,7 @@
def getitem__Array_Slice(space, self, w_slice):
start, stop, step, size = space.decode_index4(w_slice, self.len)
w_a = mytype.w_class(self.space)
- w_a.setlen(size)
+ w_a.setlen(size, overallocate=False)
assert step != 0
j = 0
for i in range(start, stop, step):
@@ -368,26 +377,18 @@
def setitem__Array_Slice_Array(space, self, w_idx, w_item):
start, stop, step, size = self.space.decode_index4(w_idx, self.len)
assert step != 0
- if w_item.len != size:
+ if w_item.len != size or self is w_item:
+ # XXX this is a giant slow hack
w_lst = array_tolist__Array(space, self)
w_item = space.call_method(w_item, 'tolist')
space.setitem(w_lst, w_idx, w_item)
self.setlen(0)
self.fromsequence(w_lst)
else:
- if self is w_item:
- with lltype.scoped_alloc(mytype.arraytype, self.allocated) as new_buffer:
- for i in range(self.len):
- new_buffer[i] = w_item.buffer[i]
- j = 0
- for i in range(start, stop, step):
- self.buffer[i] = new_buffer[j]
- j += 1
- else:
- j = 0
- for i in range(start, stop, step):
- self.buffer[i] = w_item.buffer[j]
- j += 1
+ j = 0
+ for i in range(start, stop, step):
+ self.buffer[i] = w_item.buffer[j]
+ j += 1
def setslice__Array_ANY_ANY_ANY(space, self, w_i, w_j, w_x):
space.setitem(self, space.newslice(w_i, w_j, space.w_None), w_x)
@@ -459,6 +460,7 @@
self.buffer[i] = val
def delitem__Array_ANY(space, self, w_idx):
+ # XXX this is a giant slow hack
w_lst = array_tolist__Array(space, self)
space.delitem(w_lst, w_idx)
self.setlen(0)
@@ -471,7 +473,7 @@
def add__Array_Array(space, self, other):
a = mytype.w_class(space)
- a.setlen(self.len + other.len)
+ a.setlen(self.len + other.len, overallocate=False)
for i in range(self.len):
a.buffer[i] = self.buffer[i]
for i in range(other.len):
@@ -487,46 +489,50 @@
return self
def mul__Array_ANY(space, self, w_repeat):
+ return _mul_helper(space, self, w_repeat, False)
+
+ def mul__ANY_Array(space, w_repeat, self):
+ return _mul_helper(space, self, w_repeat, False)
+
+ def inplace_mul__Array_ANY(space, self, w_repeat):
+ return _mul_helper(space, self, w_repeat, True)
+
+ def _mul_helper(space, self, w_repeat, is_inplace):
try:
repeat = space.getindex_w(w_repeat, space.w_OverflowError)
except OperationError, e:
if e.match(space, space.w_TypeError):
raise FailedToImplement
raise
- a = mytype.w_class(space)
repeat = max(repeat, 0)
try:
newlen = ovfcheck(self.len * repeat)
except OverflowError:
raise MemoryError
- a.setlen(newlen)
- for r in range(repeat):
- for i in range(self.len):
- a.buffer[r * self.len + i] = self.buffer[i]
+ oldlen = self.len
+ if is_inplace:
+ a = self
+ start = 1
+ else:
+ a = mytype.w_class(space)
+ start = 0
+ # <a performance hack>
+ if oldlen == 1:
+ if self.buffer[0] == rffi.cast(mytype.itemtype, 0):
+ a.setlen(newlen, zero=True, overallocate=False)
+ return a
+ a.setlen(newlen, overallocate=False)
+ item = self.buffer[0]
+ for r in range(start, repeat):
+ a.buffer[r] = item
+ return a
+ # </a performance hack>
+ a.setlen(newlen, overallocate=False)
+ for r in range(start, repeat):
+ for i in range(oldlen):
+ a.buffer[r * oldlen + i] = self.buffer[i]
return a
- def mul__ANY_Array(space, w_repeat, self):
- return mul__Array_ANY(space, self, w_repeat)
-
- def inplace_mul__Array_ANY(space, self, w_repeat):
- try:
- repeat = space.getindex_w(w_repeat, space.w_OverflowError)
- except OperationError, e:
- if e.match(space, space.w_TypeError):
- raise FailedToImplement
- raise
- oldlen = self.len
- repeat = max(repeat, 0)
- try:
- newlen = ovfcheck(self.len * repeat)
- except OverflowError:
- raise MemoryError
- self.setlen(newlen)
- for r in range(1, repeat):
- for i in range(oldlen):
- self.buffer[r * oldlen + i] = self.buffer[i]
- return self
-
# Convertions
def array_tolist__Array(space, self):
@@ -602,6 +608,7 @@
# Compare methods
@specialize.arg(3)
def _cmp_impl(space, self, other, space_fn):
+ # XXX this is a giant slow hack
w_lst1 = array_tolist__Array(space, self)
w_lst2 = space.call_method(other, 'tolist')
return space_fn(w_lst1, w_lst2)
@@ -648,7 +655,7 @@
def array_copy__Array(space, self):
w_a = mytype.w_class(self.space)
- w_a.setlen(self.len)
+ w_a.setlen(self.len, overallocate=False)
rffi.c_memcpy(
rffi.cast(rffi.VOIDP, w_a.buffer),
rffi.cast(rffi.VOIDP, self.buffer),
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
@@ -890,6 +890,46 @@
a[::-1] = a
assert a == self.array('b', [3, 2, 1, 0])
+ def test_array_multiply(self):
+ a = self.array('b', [0])
+ b = a * 13
+ assert b[12] == 0
+ b = 13 * a
+ assert b[12] == 0
+ a *= 13
+ assert a[12] == 0
+ a = self.array('b', [1])
+ b = a * 13
+ assert b[12] == 1
+ b = 13 * a
+ assert b[12] == 1
+ a *= 13
+ assert a[12] == 1
+ a = self.array('i', [0])
+ b = a * 13
+ assert b[12] == 0
+ b = 13 * a
+ assert b[12] == 0
+ a *= 13
+ assert a[12] == 0
+ a = self.array('i', [1])
+ b = a * 13
+ assert b[12] == 1
+ b = 13 * a
+ assert b[12] == 1
+ a *= 13
+ assert a[12] == 1
+ a = self.array('i', [0, 0])
+ b = a * 13
+ assert len(b) == 26
+ assert b[22] == 0
+ b = 13 * a
+ assert len(b) == 26
+ assert b[22] == 0
+ a *= 13
+ assert a[22] == 0
+ assert len(a) == 26
+
class AppTestArrayBuiltinShortcut(AppTestArray):
OPTIONS = {'objspace.std.builtinshortcut': True}
diff --git a/pypy/module/cppyy/test/conftest.py b/pypy/module/cppyy/test/conftest.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/conftest.py
@@ -0,0 +1,5 @@
+import py
+
+def pytest_runtest_setup(item):
+ if py.path.local.sysfind('genreflex') is None:
+ py.test.skip("genreflex is not installed")
diff --git a/pypy/module/cppyy/test/test_cppyy.py b/pypy/module/cppyy/test/test_cppyy.py
--- a/pypy/module/cppyy/test/test_cppyy.py
+++ b/pypy/module/cppyy/test/test_cppyy.py
@@ -145,7 +145,7 @@
e1 = None
gc.collect()
assert t.get_overload("getCount").call(None) == 1
- e2.destruct()
+ e2.destruct()
assert t.get_overload("getCount").call(None) == 0
e2 = None
gc.collect()
diff --git a/pypy/module/cppyy/test/test_operators.py b/pypy/module/cppyy/test/test_operators.py
--- a/pypy/module/cppyy/test/test_operators.py
+++ b/pypy/module/cppyy/test/test_operators.py
@@ -133,7 +133,7 @@
o = gbl.operator_unsigned_long();
o.m_ulong = sys.maxint + 128
- assert o.m_ulong == sys.maxint + 128
+ assert o.m_ulong == sys.maxint + 128
assert long(o) == sys.maxint + 128
o = gbl.operator_float(); o.m_float = 3.14
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -163,6 +163,7 @@
'sum': 'app_numpy.sum',
'min': 'app_numpy.min',
'identity': 'app_numpy.identity',
+ 'eye': 'app_numpy.eye',
'max': 'app_numpy.max',
'arange': 'app_numpy.arange',
}
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -16,6 +16,26 @@
a[i][i] = 1
return a
+def eye(n, m=None, k=0, dtype=None):
+ if m is None:
+ m = n
+ a = _numpypy.zeros((n, m), dtype=dtype)
+ ni = 0
+ mi = 0
+
+ if k < 0:
+ p = n + k
+ ni = -k
+ else:
+ p = n - k
+ mi = k
+
+ while ni < n and mi < m:
+ a[ni][mi] = 1
+ ni += 1
+ mi += 1
+ return a
+
def sum(a,axis=None, out=None):
'''sum(a, axis=None)
Sum of array elements over a given axis.
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1155,6 +1155,38 @@
assert d.shape == (3, 3)
assert d.dtype == dtype('int32')
assert (d == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]).all()
+
+ def test_eye(self):
+ from _numpypy import eye, array
+ from _numpypy import int32, float64, dtype
+ a = eye(0)
+ assert len(a) == 0
+ assert a.dtype == dtype('float64')
+ assert a.shape == (0, 0)
+ b = eye(1, dtype=int32)
+ assert len(b) == 1
+ assert b[0][0] == 1
+ assert b.shape == (1, 1)
+ assert b.dtype == dtype('int32')
+ c = eye(2)
+ assert c.shape == (2, 2)
+ assert (c == [[1, 0], [0, 1]]).all()
+ d = eye(3, dtype='int32')
+ assert d.shape == (3, 3)
+ assert d.dtype == dtype('int32')
+ assert (d == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]).all()
+ e = eye(3, 4)
+ assert e.shape == (3, 4)
+ assert (e == [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]]).all()
+ f = eye(2, 4, k=3)
+ assert f.shape == (2, 4)
+ assert (f == [[0, 0, 0, 1], [0, 0, 0, 0]]).all()
+ g = eye(3, 4, k=-1)
+ assert g.shape == (3, 4)
+ assert (g == [[0, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0]]).all()
+
+
+
def test_prod(self):
from _numpypy import array
diff --git a/pypy/module/select/interp_kqueue.py b/pypy/module/select/interp_kqueue.py
--- a/pypy/module/select/interp_kqueue.py
+++ b/pypy/module/select/interp_kqueue.py
@@ -7,6 +7,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.tool import rffi_platform
from pypy.translator.tool.cbuild import ExternalCompilationInfo
+import sys
eci = ExternalCompilationInfo(
@@ -20,14 +21,26 @@
_compilation_info_ = eci
-CConfig.kevent = rffi_platform.Struct("struct kevent", [
- ("ident", rffi.UINTPTR_T),
- ("filter", rffi.SHORT),
- ("flags", rffi.USHORT),
- ("fflags", rffi.UINT),
- ("data", rffi.INTPTR_T),
- ("udata", rffi.VOIDP),
-])
+if "openbsd" in sys.platform:
+ IDENT_UINT = True
+ CConfig.kevent = rffi_platform.Struct("struct kevent", [
+ ("ident", rffi.UINT),
+ ("filter", rffi.SHORT),
+ ("flags", rffi.USHORT),
+ ("fflags", rffi.UINT),
+ ("data", rffi.INT),
+ ("udata", rffi.VOIDP),
+ ])
+else:
+ IDENT_UINT = False
+ CConfig.kevent = rffi_platform.Struct("struct kevent", [
+ ("ident", rffi.UINTPTR_T),
+ ("filter", rffi.SHORT),
+ ("flags", rffi.USHORT),
+ ("fflags", rffi.UINT),
+ ("data", rffi.INTPTR_T),
+ ("udata", rffi.VOIDP),
+ ])
CConfig.timespec = rffi_platform.Struct("struct timespec", [
@@ -243,16 +256,24 @@
self.event.c_udata = rffi.cast(rffi.VOIDP, udata)
def _compare_all_fields(self, other, op):
- l_ident = self.event.c_ident
- r_ident = other.event.c_ident
+ if IDENT_UINT:
+ l_ident = rffi.cast(lltype.Unsigned, self.event.c_ident)
+ r_ident = rffi.cast(lltype.Unsigned, other.event.c_ident)
+ else:
+ l_ident = self.event.c_ident
+ r_ident = other.event.c_ident
l_filter = rffi.cast(lltype.Signed, self.event.c_filter)
r_filter = rffi.cast(lltype.Signed, other.event.c_filter)
l_flags = rffi.cast(lltype.Unsigned, self.event.c_flags)
r_flags = rffi.cast(lltype.Unsigned, other.event.c_flags)
l_fflags = rffi.cast(lltype.Unsigned, self.event.c_fflags)
r_fflags = rffi.cast(lltype.Unsigned, other.event.c_fflags)
- l_data = self.event.c_data
- r_data = other.event.c_data
+ if IDENT_UINT:
+ l_data = rffi.cast(lltype.Signed, self.event.c_data)
+ r_data = rffi.cast(lltype.Signed, other.event.c_data)
+ else:
+ l_data = self.event.c_data
+ r_data = other.event.c_data
l_udata = rffi.cast(lltype.Unsigned, self.event.c_udata)
r_udata = rffi.cast(lltype.Unsigned, other.event.c_udata)
diff --git a/pypy/rlib/parsing/parsing.py b/pypy/rlib/parsing/parsing.py
--- a/pypy/rlib/parsing/parsing.py
+++ b/pypy/rlib/parsing/parsing.py
@@ -107,14 +107,12 @@
error = None # for the annotator
if self.parser.is_nonterminal(symbol):
rule = self.parser.get_rule(symbol)
- lastexpansion = len(rule.expansions) - 1
subsymbol = None
error = None
for expansion in rule.expansions:
curr = i
children = []
- for j in range(len(expansion)):
- subsymbol = expansion[j]
+ for subsymbol in expansion:
node, next, error2 = self.match_symbol(curr, subsymbol)
if node is None:
error = combine_errors(error, error2)
diff --git a/pypy/rlib/rerased.py b/pypy/rlib/rerased.py
--- a/pypy/rlib/rerased.py
+++ b/pypy/rlib/rerased.py
@@ -48,6 +48,9 @@
def __repr__(self):
return 'ErasingPairIdentity(%r)' % self.name
+ def __deepcopy__(self, memo):
+ return self
+
def _getdict(self, bk):
try:
dict = bk._erasing_pairs_tunnel
diff --git a/pypy/rlib/test/test_rerased.py b/pypy/rlib/test/test_rerased.py
--- a/pypy/rlib/test/test_rerased.py
+++ b/pypy/rlib/test/test_rerased.py
@@ -1,5 +1,7 @@
import py
import sys
+import copy
+
from pypy.rlib.rerased import *
from pypy.annotation import model as annmodel
from pypy.annotation.annrpython import RPythonAnnotator
@@ -59,6 +61,13 @@
#assert is_integer(e) is False
assert unerase_list_X(e) is l
+def test_deepcopy():
+ x = "hello"
+ e = eraseX(x)
+ e2 = copy.deepcopy(e)
+ assert uneraseX(e) is x
+ assert uneraseX(e2) is x
+
def test_annotate_1():
def f():
return eraseX(X())
diff --git a/pypy/rpython/lltypesystem/rlist.py b/pypy/rpython/lltypesystem/rlist.py
--- a/pypy/rpython/lltypesystem/rlist.py
+++ b/pypy/rpython/lltypesystem/rlist.py
@@ -170,8 +170,8 @@
# adapted C code
- at enforceargs(None, int)
-def _ll_list_resize_really(l, newsize):
+ at enforceargs(None, int, None)
+def _ll_list_resize_really(l, newsize, overallocate):
"""
Ensure l.items has room for at least newsize elements, and set
l.length to newsize. Note that l.items may change, and even if
@@ -188,13 +188,15 @@
l.length = 0
l.items = _ll_new_empty_item_array(typeOf(l).TO)
return
- else:
+ elif overallocate:
if newsize < 9:
some = 3
else:
some = 6
some += newsize >> 3
new_allocated = newsize + some
+ else:
+ new_allocated = newsize
# new_allocated is a bit more than newsize, enough to ensure an amortized
# linear complexity for e.g. repeated usage of l.append(). In case
# it overflows sys.maxint, it is guaranteed negative, and the following
@@ -214,31 +216,36 @@
# this common case was factored out of _ll_list_resize
# to see if inlining it gives some speed-up.
+ at jit.dont_look_inside
def _ll_list_resize(l, newsize):
- # Bypass realloc() when a previous overallocation is large enough
- # to accommodate the newsize. If the newsize falls lower than half
- # the allocated size, then proceed with the realloc() to shrink the list.
- allocated = len(l.items)
- if allocated >= newsize and newsize >= ((allocated >> 1) - 5):
- l.length = newsize
- else:
- _ll_list_resize_really(l, newsize)
+ """Called only in special cases. Forces the allocated and actual size
+ of the list to be 'newsize'."""
+ _ll_list_resize_really(l, newsize, False)
@jit.look_inside_iff(lambda l, newsize: jit.isconstant(len(l.items)) and jit.isconstant(newsize))
@jit.oopspec("list._resize_ge(l, newsize)")
def _ll_list_resize_ge(l, newsize):
+ """This is called with 'newsize' larger than the current length of the
+ list. If the list storage doesn't have enough space, then really perform
+ a realloc(). In the common case where we already overallocated enough,
+ then this is a very fast operation.
+ """
if len(l.items) >= newsize:
l.length = newsize
else:
- _ll_list_resize_really(l, newsize)
+ _ll_list_resize_really(l, newsize, True)
@jit.look_inside_iff(lambda l, newsize: jit.isconstant(len(l.items)) and jit.isconstant(newsize))
@jit.oopspec("list._resize_le(l, newsize)")
def _ll_list_resize_le(l, newsize):
+ """This is called with 'newsize' smaller than the current length of the
+ list. If 'newsize' falls lower than half the allocated size, proceed
+ with the realloc() to shrink the list.
+ """
if newsize >= (len(l.items) >> 1) - 5:
l.length = newsize
else:
- _ll_list_resize_really(l, newsize)
+ _ll_list_resize_really(l, newsize, False)
def ll_append_noresize(l, newitem):
length = l.length
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -144,7 +144,7 @@
# XXX many of these includes are not portable at all
includes += ['dirent.h', 'sys/stat.h',
'sys/times.h', 'utime.h', 'sys/types.h', 'unistd.h',
- 'signal.h', 'sys/wait.h', 'fcntl.h', 'pty.h']
+ 'signal.h', 'sys/wait.h', 'fcntl.h']
else:
includes += ['sys/utime.h']
diff --git a/pypy/rpython/normalizecalls.py b/pypy/rpython/normalizecalls.py
--- a/pypy/rpython/normalizecalls.py
+++ b/pypy/rpython/normalizecalls.py
@@ -39,7 +39,8 @@
row)
if did_something:
assert not callfamily.normalized, "change in call family normalisation"
- assert nshapes == 1, "XXX call table too complex"
+ if nshapes != 1:
+ raise_call_table_too_complex_error(callfamily, annotator)
while True:
progress = False
for shape, table in callfamily.calltables.items():
@@ -50,6 +51,38 @@
return # done
assert not callfamily.normalized, "change in call family normalisation"
+def raise_call_table_too_complex_error(callfamily, annotator):
+ msg = []
+ items = callfamily.calltables.items()
+ for i, (shape1, table1) in enumerate(items):
+ for shape2, table2 in items[i + 1:]:
+ if shape1 == shape2:
+ continue
+ row1 = table1[0]
+ row2 = table2[0]
+ problematic_function_graphs = set(row1.values()).union(set(row2.values()))
+ pfg = [str(graph) for graph in problematic_function_graphs]
+ pfg.sort()
+ msg.append("the following functions:")
+ msg.append(" %s" % ("\n ".join(pfg), ))
+ msg.append("are called with inconsistent numbers of arguments")
+ if shape1[0] != shape2[0]:
+ msg.append("sometimes with %s arguments, sometimes with %s" % (shape1[0], shape2[0]))
+ else:
+ pass # XXX better message in this case
+ callers = []
+ msg.append("the callers of these functions are:")
+ for tag, (caller, callee) in annotator.translator.callgraph.iteritems():
+ if callee not in problematic_function_graphs:
+ continue
+ if str(caller) in callers:
+ continue
+ callers.append(str(caller))
+ callers.sort()
+ for caller in callers:
+ msg.append(" %s" % (caller, ))
+ raise TyperError("\n".join(msg))
+
def normalize_calltable_row_signature(annotator, shape, row):
graphs = row.values()
assert graphs, "no graph??"
diff --git a/pypy/rpython/rlist.py b/pypy/rpython/rlist.py
--- a/pypy/rpython/rlist.py
+++ b/pypy/rpython/rlist.py
@@ -20,8 +20,11 @@
'll_setitem_fast': (['self', Signed, 'item'], Void),
})
ADTIList = ADTInterface(ADTIFixedList, {
+ # grow the length if needed, overallocating a bit
'_ll_resize_ge': (['self', Signed ], Void),
+ # shrink the length, keeping it overallocated if useful
'_ll_resize_le': (['self', Signed ], Void),
+ # resize to exactly the given size
'_ll_resize': (['self', Signed ], Void),
})
@@ -1018,6 +1021,8 @@
ll_delitem_nonneg(dum_nocheck, lst, index)
def ll_inplace_mul(l, factor):
+ if factor == 1:
+ return l
length = l.ll_length()
if factor < 0:
factor = 0
@@ -1027,7 +1032,6 @@
raise MemoryError
res = l
res._ll_resize(resultlen)
- #res._ll_resize_ge(resultlen)
j = length
while j < resultlen:
i = 0
diff --git a/pypy/rpython/test/test_normalizecalls.py b/pypy/rpython/test/test_normalizecalls.py
--- a/pypy/rpython/test/test_normalizecalls.py
+++ b/pypy/rpython/test/test_normalizecalls.py
@@ -2,6 +2,7 @@
from pypy.annotation import model as annmodel
from pypy.translator.translator import TranslationContext, graphof
from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.error import TyperError
from pypy.rpython.test.test_llinterp import interpret
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.normalizecalls import TotalOrderSymbolic, MAX
@@ -158,6 +159,39 @@
res = llinterp.eval_graph(graphof(translator, dummyfn), [2])
assert res == -2
+ def test_methods_with_defaults(self):
+ class Base:
+ def fn(self):
+ raise NotImplementedError
+ class Sub1(Base):
+ def fn(self, x=1):
+ return 1 + x
+ class Sub2(Base):
+ def fn(self):
+ return -2
+ def otherfunc(x):
+ return x.fn()
+ def dummyfn(n):
+ if n == 1:
+ x = Sub1()
+ n = x.fn(2)
+ else:
+ x = Sub2()
+ return otherfunc(x) + x.fn()
+
+ excinfo = py.test.raises(TyperError, "self.rtype(dummyfn, [int], int)")
+ msg = """the following functions:
+ .+Base.fn
+ .+Sub1.fn
+ .+Sub2.fn
+are called with inconsistent numbers of arguments
+sometimes with 2 arguments, sometimes with 1
+the callers of these functions are:
+ .+otherfunc
+ .+dummyfn"""
+ import re
+ assert re.match(msg, excinfo.value.args[0])
+
class PBase:
def fn(self):
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -5,6 +5,22 @@
from pypy.tool.logparser import parse_log_file, extract_category
from copy import copy
+def parse_code_data(arg):
+ name = None
+ lineno = 0
+ filename = None
+ bytecode_no = 0
+ bytecode_name = None
+ m = re.search('<code object ([<>\w]+)[\.,] file \'(.+?)\'[\.,] line (\d+)> #(\d+) (\w+)',
+ arg)
+ if m is None:
+ # a non-code loop, like StrLiteralSearch or something
+ if arg:
+ bytecode_name = arg
+ else:
+ name, filename, lineno, bytecode_no, bytecode_name = m.groups()
+ return name, bytecode_name, filename, int(lineno), int(bytecode_no)
+
class Op(object):
bridge = None
offset = None
@@ -132,38 +148,24 @@
pass
class TraceForOpcode(object):
- filename = None
- startlineno = 0
- name = None
code = None
- bytecode_no = 0
- bytecode_name = None
is_bytecode = True
inline_level = None
has_dmp = False
- def parse_code_data(self, arg):
- m = re.search('<code object ([<>\w]+)[\.,] file \'(.+?)\'[\.,] line (\d+)> #(\d+) (\w+)',
- arg)
- if m is None:
- # a non-code loop, like StrLiteralSearch or something
- if arg:
- self.bytecode_name = arg
- else:
- self.name, self.filename, lineno, bytecode_no, self.bytecode_name = m.groups()
- self.startlineno = int(lineno)
- self.bytecode_no = int(bytecode_no)
-
-
def __init__(self, operations, storage, loopname):
for op in operations:
if op.name == 'debug_merge_point':
self.inline_level = int(op.args[0])
- self.parse_code_data(op.args[2][1:-1])
+ parsed = parse_code_data(op.args[2][1:-1])
+ (self.name, self.bytecode_name, self.filename,
+ self.startlineno, self.bytecode_no) = parsed
break
else:
self.inline_level = 0
- self.parse_code_data(loopname)
+ parsed = parse_code_data(loopname)
+ (self.name, self.bytecode_name, self.filename,
+ self.startlineno, self.bytecode_no) = parsed
self.operations = operations
self.storage = storage
self.code = storage.disassemble_code(self.filename, self.startlineno,
diff --git a/pypy/tool/sourcetools.py b/pypy/tool/sourcetools.py
--- a/pypy/tool/sourcetools.py
+++ b/pypy/tool/sourcetools.py
@@ -224,6 +224,7 @@
if func.func_dict:
f.func_dict = {}
f.func_dict.update(func.func_dict)
+ f.func_doc = func.func_doc
return f
def func_renamer(newname):
diff --git a/pypy/tool/test/test_sourcetools.py b/pypy/tool/test/test_sourcetools.py
--- a/pypy/tool/test/test_sourcetools.py
+++ b/pypy/tool/test/test_sourcetools.py
@@ -22,3 +22,15 @@
assert f.func_name == "g"
assert f.func_defaults == (5,)
assert f.prop is int
+
+def test_func_rename_decorator():
+ def bar():
+ 'doc'
+
+ bar2 = func_with_new_name(bar, 'bar2')
+ assert bar.func_doc == bar2.func_doc == 'doc'
+
+ bar.func_doc = 'new doc'
+ bar3 = func_with_new_name(bar, 'bar3')
+ assert bar3.func_doc == 'new doc'
+ assert bar2.func_doc != bar3.func_doc
More information about the pypy-commit
mailing list