[pypy-commit] pypy pytest: merge from default
RonnyPfannschmidt
noreply at buildbot.pypy.org
Mon Apr 23 10:31:13 CEST 2012
Author: Ronny Pfannschmidt <Ronny.Pfannschmidt at gmx.de>
Branch: pytest
Changeset: r54651:f61b3f64c7ab
Date: 2012-04-23 10:14 +0200
http://bitbucket.org/pypy/pypy/changeset/f61b3f64c7ab/
Log: merge from default
diff --git a/lib_pypy/numpypy/core/fromnumeric.py b/lib_pypy/numpypy/core/fromnumeric.py
--- a/lib_pypy/numpypy/core/fromnumeric.py
+++ b/lib_pypy/numpypy/core/fromnumeric.py
@@ -411,7 +411,8 @@
[3, 7]]])
"""
- raise NotImplementedError('Waiting on interp level method')
+ swapaxes = a.swapaxes
+ return swapaxes(axis1, axis2)
def transpose(a, axes=None):
diff --git a/py/bin/_findpy.py b/py/bin/_findpy.py
new file mode 100644
--- /dev/null
+++ b/py/bin/_findpy.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+#
+# find and import a version of 'py'
+#
+import sys
+import os
+from os.path import dirname as opd, exists, join, basename, abspath
+
+def searchpy(current):
+ while 1:
+ last = current
+ initpy = join(current, '__init__.py')
+ if not exists(initpy):
+ pydir = join(current, 'py')
+ # recognize py-package and ensure it is importable
+ if exists(pydir) and exists(join(pydir, '__init__.py')):
+ #for p in sys.path:
+ # if p == current:
+ # return True
+ if current != sys.path[0]: # if we are already first, then ok
+ sys.stderr.write("inserting into sys.path: %s\n" % current)
+ sys.path.insert(0, current)
+ return True
+ current = opd(current)
+ if last == current:
+ return False
+
+if not searchpy(abspath(os.curdir)):
+ if not searchpy(opd(abspath(sys.argv[0]))):
+ if not searchpy(opd(__file__)):
+ pass # let's hope it is just on sys.path
+
+import py
+import pytest
+
+if __name__ == '__main__':
+ print ("py lib is at %s" % py.__file__)
diff --git a/py/bin/py.test b/py/bin/py.test
new file mode 100755
--- /dev/null
+++ b/py/bin/py.test
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+from _findpy import pytest
+raise SystemExit(pytest.main())
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
@@ -483,7 +483,7 @@
return a_str.strip(' ')
elif n == 1:
return a_str.rstrip(' ')
- else:
+ else:
return a_str.lstrip(' ')
s = a.build_types(f, [int, annmodel.SomeString(no_nul=True)])
assert s.no_nul
@@ -3737,6 +3737,25 @@
s = a.build_types(f, [int])
assert s.listdef.listitem.range_step == 0
+ def test_specialize_arg_memo(self):
+ @objectmodel.specialize.memo()
+ def g(n):
+ return n
+ @objectmodel.specialize.arg(0)
+ def f(i):
+ return g(i)
+ def main(i):
+ if i == 2:
+ return f(2)
+ elif i == 3:
+ return f(3)
+ else:
+ raise NotImplementedError
+
+ a = self.RPythonAnnotator()
+ s = a.build_types(main, [int])
+ assert isinstance(s, annmodel.SomeInteger)
+
def g(n):
return [0,1,2,n]
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -320,10 +320,14 @@
default=False),
BoolOption("getattributeshortcut",
"track types that override __getattribute__",
- default=False),
+ default=False,
+ # weakrefs needed, because of get_subclasses()
+ requires=[("translation.rweakref", True)]),
BoolOption("newshortcut",
"cache and shortcut calling __new__ from builtin types",
- default=False),
+ default=False,
+ # weakrefs needed, because of get_subclasses()
+ requires=[("translation.rweakref", True)]),
BoolOption("logspaceoptypes",
"a instrumentation option: before exit, print the types seen by "
@@ -337,7 +341,9 @@
requires=[("objspace.std.builtinshortcut", True)]),
BoolOption("withidentitydict",
"track types that override __hash__, __eq__ or __cmp__ and use a special dict strategy for those which do not",
- default=False),
+ default=False,
+ # weakrefs needed, because of get_subclasses()
+ requires=[("translation.rweakref", True)]),
]),
])
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
@@ -158,6 +158,12 @@
.. __: http://morepypy.blogspot.com/2008/02/python-finalizers-semantics-part-1.html
.. __: http://morepypy.blogspot.com/2008/02/python-finalizers-semantics-part-2.html
+Note that this difference might show up indirectly in some cases. For
+example, a generator left pending in the middle is --- again ---
+garbage-collected later in PyPy than in CPython. You can see the
+difference if the ``yield`` keyword it is suspended at is itself
+enclosed in a ``try:`` or a ``with:`` block.
+
Using the default GC called ``minimark``, the built-in function ``id()``
works like it does in CPython. With other GCs it returns numbers that
are not real addresses (because an object can move around several times)
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -85,6 +85,10 @@
Collects the arguments of a function call.
Instances should be considered immutable.
+
+ Some parts of this class are written in a slightly convoluted style to help
+ the JIT. It is really crucial to get this right, because Python's argument
+ semantics are complex, but calls occur everywhere.
"""
### Construction ###
@@ -169,9 +173,17 @@
def _combine_starstarargs_wrapped(self, w_starstararg):
# unpack the ** arguments
space = self.space
+ keywords, values_w = space.view_as_kwargs(w_starstararg)
+ if keywords is not None: # this path also taken for empty dicts
+ if self.keywords is None:
+ self.keywords = keywords[:] # copy to make non-resizable
+ self.keywords_w = values_w[:]
+ else:
+ self._check_not_duplicate_kwargs(keywords, values_w)
+ self.keywords = self.keywords + keywords
+ self.keywords_w = self.keywords_w + values_w
+ return not jit.isconstant(len(self.keywords))
if space.isinstance_w(w_starstararg, space.w_dict):
- if not space.is_true(w_starstararg):
- return False # don't call unpackiterable - it's jit-opaque
keys_w = space.unpackiterable(w_starstararg)
else:
try:
@@ -186,11 +198,8 @@
"a mapping, not %s" % (typename,)))
raise
keys_w = space.unpackiterable(w_keys)
- if keys_w:
- self._do_combine_starstarargs_wrapped(keys_w, w_starstararg)
- return True
- else:
- return False # empty dict; don't disable the JIT
+ self._do_combine_starstarargs_wrapped(keys_w, w_starstararg)
+ return True
def _do_combine_starstarargs_wrapped(self, keys_w, w_starstararg):
space = self.space
@@ -227,6 +236,20 @@
self.keywords_w = self.keywords_w + keywords_w
self.keyword_names_w = keys_w
+ @jit.look_inside_iff(lambda self, keywords, keywords_w:
+ jit.isconstant(len(keywords) and
+ jit.isconstant(self.keywords)))
+ def _check_not_duplicate_kwargs(self, keywords, keywords_w):
+ # looks quadratic, but the JIT should remove all of it nicely.
+ # Also, all the lists should be small
+ for key in keywords:
+ for otherkey in self.keywords:
+ if otherkey == key:
+ raise operationerrfmt(self.space.w_TypeError,
+ "got multiple values "
+ "for keyword argument "
+ "'%s'", key)
+
def fixedunpack(self, argcount):
"""The simplest argument parsing: get the 'argcount' arguments,
or raise a real ValueError if the length is wrong."""
@@ -385,7 +408,7 @@
# collect extra keyword arguments into the **kwarg
if has_kwarg:
- w_kwds = self.space.newdict()
+ w_kwds = self.space.newdict(kwargs=True)
if num_remainingkwds:
#
limit = len(keywords)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -914,6 +914,12 @@
"""
return None
+ def view_as_kwargs(self, w_dict):
+ """ if w_dict is a kwargs-dict, return two lists, one of unwrapped
+ strings and one of wrapped values. otherwise return (None, None)
+ """
+ return (None, None)
+
def newlist_str(self, list_s):
return self.newlist([self.wrap(s) for s in list_s])
diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -75,7 +75,10 @@
def unpackiterable(self, it):
return list(it)
- def newdict(self):
+ def view_as_kwargs(self, x):
+ return None, None
+
+ def newdict(self, kwargs=False):
return {}
def newlist(self, l=[]):
@@ -488,6 +491,57 @@
assert len(l) == 1
assert l[0] == space.wrap(5)
+ def test_starstarargs_special(self):
+ class kwargs(object):
+ def __init__(self, k, v):
+ self.k = k
+ self.v = v
+ class MyDummySpace(DummySpace):
+ def view_as_kwargs(self, kw):
+ if isinstance(kw, kwargs):
+ return kw.k, kw.v
+ return None, None
+ space = MyDummySpace()
+ for i in range(3):
+ kwds = [("c", 3)]
+ kwds_w = dict(kwds[:i])
+ keywords = kwds_w.keys()
+ keywords_w = kwds_w.values()
+ rest = dict(kwds[i:])
+ w_kwds = kwargs(rest.keys(), rest.values())
+ if i == 2:
+ w_kwds = None
+ assert len(keywords) == len(keywords_w)
+ args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
+ l = [None, None, None]
+ args._match_signature(None, l, Signature(["a", "b", "c"]), defaults_w=[4])
+ assert l == [1, 2, 3]
+ args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
+ l = [None, None, None, None]
+ args._match_signature(None, l, Signature(["a", "b", "b1", "c"]), defaults_w=[4, 5])
+ assert l == [1, 2, 4, 3]
+ args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
+ l = [None, None, None, None]
+ args._match_signature(None, l, Signature(["a", "b", "c", "d"]), defaults_w=[4, 5])
+ assert l == [1, 2, 3, 5]
+ args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
+ l = [None, None, None, None]
+ py.test.raises(ArgErr, args._match_signature, None, l,
+ Signature(["c", "b", "a", "d"]), defaults_w=[4, 5])
+ args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
+ l = [None, None, None, None]
+ py.test.raises(ArgErr, args._match_signature, None, l,
+ Signature(["a", "b", "c1", "d"]), defaults_w=[4, 5])
+ args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
+ l = [None, None, None]
+ args._match_signature(None, l, Signature(["a", "b"], None, "**"))
+ assert l == [1, 2, {'c': 3}]
+ excinfo = py.test.raises(OperationError, Arguments, space, [], ["a"],
+ [1], w_starstararg=kwargs(["a"], [2]))
+ assert excinfo.value.w_type is TypeError
+
+
+
class TestErrorHandling(object):
def test_missing_args(self):
# got_nargs, nkwds, expected_nargs, has_vararg, has_kwarg,
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1223,7 +1223,7 @@
def run_one_step(self):
# Execute the frame forward. This method contains a loop that leaves
# whenever the 'opcode_implementations' (which is one of the 'opimpl_'
- # methods) returns True. This is the case when the current frame
+ # methods) raises ChangeFrame. This is the case when the current frame
# changes, due to a call or a return.
try:
staticdata = self.metainterp.staticdata
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -341,9 +341,13 @@
def add(self, w_iobase):
assert w_iobase.streamholder is None
- holder = StreamHolder(w_iobase)
- w_iobase.streamholder = holder
- self.streams[holder] = None
+ if rweakref.has_weakref_support():
+ holder = StreamHolder(w_iobase)
+ w_iobase.streamholder = holder
+ self.streams[holder] = None
+ #else:
+ # no support for weakrefs, so ignore and we
+ # will not get autoflushing
def remove(self, w_iobase):
holder = w_iobase.streamholder
diff --git a/pypy/module/_lsprof/interp_lsprof.py b/pypy/module/_lsprof/interp_lsprof.py
--- a/pypy/module/_lsprof/interp_lsprof.py
+++ b/pypy/module/_lsprof/interp_lsprof.py
@@ -185,6 +185,7 @@
if subentry is not None:
subentry._stop(tt, it)
+ at jit.elidable_promote()
def create_spec(space, w_arg):
if isinstance(w_arg, Method):
w_function = w_arg.w_function
diff --git a/pypy/module/cpyext/iterator.py b/pypy/module/cpyext/iterator.py
--- a/pypy/module/cpyext/iterator.py
+++ b/pypy/module/cpyext/iterator.py
@@ -22,7 +22,7 @@
cannot be iterated."""
return space.iter(w_obj)
- at cpython_api([PyObject], PyObject, error=CANNOT_FAIL)
+ at cpython_api([PyObject], PyObject)
def PyIter_Next(space, w_obj):
"""Return the next value from the iteration o. If the object is an
iterator, this retrieves the next value from the iteration, and returns
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -2253,24 +2253,6 @@
"""Concat two strings giving a new Unicode string."""
raise NotImplementedError
- at cpython_api([PyObject, PyObject, Py_ssize_t], PyObject)
-def PyUnicode_Split(space, s, sep, maxsplit):
- """Split a string giving a list of Unicode strings. If sep is NULL, splitting
- will be done at all whitespace substrings. Otherwise, splits occur at the given
- separator. At most maxsplit splits will be done. If negative, no limit is
- set. Separators are not included in the resulting list.
-
- This function used an int type for maxsplit. This might require
- changes in your code for properly supporting 64-bit systems."""
- raise NotImplementedError
-
- at cpython_api([PyObject, rffi.INT_real], PyObject)
-def PyUnicode_Splitlines(space, s, keepend):
- """Split a Unicode string at line breaks, returning a list of Unicode strings.
- CRLF is considered to be one line break. If keepend is 0, the Line break
- characters are not included in the resulting strings."""
- raise NotImplementedError
-
@cpython_api([PyObject, PyObject, rffi.CCHARP], PyObject)
def PyUnicode_Translate(space, str, table, errors):
"""Translate a string by applying a character mapping table to it and return the
@@ -2287,29 +2269,6 @@
use the default error handling."""
raise NotImplementedError
- at cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t, rffi.INT_real], Py_ssize_t, error=-2)
-def PyUnicode_Find(space, str, substr, start, end, direction):
- """Return the first position of substr in str*[*start:end] using the given
- direction (direction == 1 means to do a forward search, direction == -1 a
- backward search). The return value is the index of the first match; a value of
- -1 indicates that no match was found, and -2 indicates that an error
- occurred and an exception has been set.
-
- This function used an int type for start and end. This
- might require changes in your code for properly supporting 64-bit
- systems."""
- raise NotImplementedError
-
- at cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t], Py_ssize_t, error=-1)
-def PyUnicode_Count(space, str, substr, start, end):
- """Return the number of non-overlapping occurrences of substr in
- str[start:end]. Return -1 if an error occurred.
-
- This function returned an int type and used an int
- type for start and end. This might require changes in your code for
- properly supporting 64-bit systems."""
- raise NotImplementedError
-
@cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
def PyUnicode_RichCompare(space, left, right, op):
"""Rich compare two unicode strings and return one of the following:
diff --git a/pypy/module/cpyext/test/test_iterator.py b/pypy/module/cpyext/test/test_iterator.py
--- a/pypy/module/cpyext/test/test_iterator.py
+++ b/pypy/module/cpyext/test/test_iterator.py
@@ -15,3 +15,8 @@
assert space.unwrap(api.PyIter_Next(w_iter)) == 3
assert api.PyIter_Next(w_iter) is None
assert not api.PyErr_Occurred()
+
+ def test_iternext_error(self,space, api):
+ assert api.PyIter_Next(space.w_None) is None
+ assert api.PyErr_Occurred() is space.w_TypeError
+ api.PyErr_Clear()
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -453,7 +453,35 @@
def test_tailmatch(self, space, api):
w_str = space.wrap(u"abcdef")
- assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 2, 10, 1) == 1
- assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 1, 5, -1) == 1
+ assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 2, 10, -1) == 1
+ assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 1, 5, 1) == 1
self.raises(space, api, TypeError,
api.PyUnicode_Tailmatch, w_str, space.wrap(3), 2, 10, 1)
+
+ def test_count(self, space, api):
+ w_str = space.wrap(u"abcabdab")
+ assert api.PyUnicode_Count(w_str, space.wrap(u"ab"), 0, -1) == 2
+ assert api.PyUnicode_Count(w_str, space.wrap(u"ab"), 0, 2) == 1
+ assert api.PyUnicode_Count(w_str, space.wrap(u"ab"), -5, 30) == 2
+
+ def test_find(self, space, api):
+ w_str = space.wrap(u"abcabcd")
+ assert api.PyUnicode_Find(w_str, space.wrap(u"c"), 0, 7, 1) == 2
+ assert api.PyUnicode_Find(w_str, space.wrap(u"c"), 3, 7, 1) == 5
+ assert api.PyUnicode_Find(w_str, space.wrap(u"c"), 0, 7, -1) == 5
+ assert api.PyUnicode_Find(w_str, space.wrap(u"c"), 3, 7, -1) == 5
+ assert api.PyUnicode_Find(w_str, space.wrap(u"c"), 0, 4, -1) == 2
+ assert api.PyUnicode_Find(w_str, space.wrap(u"z"), 0, 4, -1) == -1
+
+ def test_split(self, space, api):
+ w_str = space.wrap(u"a\nb\nc\nd")
+ assert "[u'a', u'b', u'c', u'd']" == space.unwrap(space.repr(
+ api.PyUnicode_Split(w_str, space.wrap('\n'), -1)))
+ assert r"[u'a', u'b', u'c\nd']" == space.unwrap(space.repr(
+ api.PyUnicode_Split(w_str, space.wrap('\n'), 2)))
+ assert r"[u'a', u'b', u'c d']" == space.unwrap(space.repr(
+ api.PyUnicode_Split(space.wrap(u'a\nb c d'), None, 2)))
+ assert "[u'a', u'b', u'c', u'd']" == space.unwrap(space.repr(
+ api.PyUnicode_Splitlines(w_str, 0)))
+ assert r"[u'a\n', u'b\n', u'c\n', u'd']" == space.unwrap(space.repr(
+ api.PyUnicode_Splitlines(w_str, 1)))
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -593,8 +593,51 @@
suffix match), 0 otherwise. Return -1 if an error occurred."""
str = space.unicode_w(w_str)
substr = space.unicode_w(w_substr)
- if rffi.cast(lltype.Signed, direction) >= 0:
+ if rffi.cast(lltype.Signed, direction) <= 0:
return stringtype.stringstartswith(str, substr, start, end)
else:
return stringtype.stringendswith(str, substr, start, end)
+ at cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t], Py_ssize_t, error=-1)
+def PyUnicode_Count(space, w_str, w_substr, start, end):
+ """Return the number of non-overlapping occurrences of substr in
+ str[start:end]. Return -1 if an error occurred."""
+ w_count = space.call_method(w_str, "count", w_substr,
+ space.wrap(start), space.wrap(end))
+ return space.int_w(w_count)
+
+ at cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t, rffi.INT_real],
+ Py_ssize_t, error=-2)
+def PyUnicode_Find(space, w_str, w_substr, start, end, direction):
+ """Return the first position of substr in str*[*start:end] using
+ the given direction (direction == 1 means to do a forward search,
+ direction == -1 a backward search). The return value is the index
+ of the first match; a value of -1 indicates that no match was
+ found, and -2 indicates that an error occurred and an exception
+ has been set."""
+ if rffi.cast(lltype.Signed, direction) > 0:
+ w_pos = space.call_method(w_str, "find", w_substr,
+ space.wrap(start), space.wrap(end))
+ else:
+ w_pos = space.call_method(w_str, "rfind", w_substr,
+ space.wrap(start), space.wrap(end))
+ return space.int_w(w_pos)
+
+ at cpython_api([PyObject, PyObject, Py_ssize_t], PyObject)
+def PyUnicode_Split(space, w_str, w_sep, maxsplit):
+ """Split a string giving a list of Unicode strings. If sep is
+ NULL, splitting will be done at all whitespace substrings.
+ Otherwise, splits occur at the given separator. At most maxsplit
+ splits will be done. If negative, no limit is set. Separators
+ are not included in the resulting list."""
+ if w_sep is None:
+ w_sep = space.w_None
+ return space.call_method(w_str, "split", w_sep, space.wrap(maxsplit))
+
+ at cpython_api([PyObject, rffi.INT_real], PyObject)
+def PyUnicode_Splitlines(space, w_str, keepend):
+ """Split a Unicode string at line breaks, returning a list of
+ Unicode strings. CRLF is considered to be one line break. If
+ keepend is 0, the Line break characters are not included in the
+ resulting strings."""
+ return space.call_method(w_str, "splitlines", space.wrap(keepend))
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -513,7 +513,30 @@
arr = concrete.copy(space)
arr.setshape(space, new_shape)
return arr
-
+
+ @unwrap_spec(axis1=int, axis2=int)
+ def descr_swapaxes(self, space, axis1, axis2):
+ """a.swapaxes(axis1, axis2)
+
+ Return a view of the array with `axis1` and `axis2` interchanged.
+
+ Refer to `numpy.swapaxes` for full documentation.
+
+ See Also
+ --------
+ numpy.swapaxes : equivalent function
+ """
+ concrete = self.get_concrete()
+ shape = concrete.shape[:]
+ strides = concrete.strides[:]
+ backstrides = concrete.backstrides[:]
+ shape[axis1], shape[axis2] = shape[axis2], shape[axis1]
+ strides[axis1], strides[axis2] = strides[axis2], strides[axis1]
+ backstrides[axis1], backstrides[axis2] = backstrides[axis2], backstrides[axis1]
+ arr = W_NDimSlice(concrete.start, strides,
+ backstrides, shape, concrete)
+ return space.wrap(arr)
+
def descr_tolist(self, space):
if len(self.shape) == 0:
assert isinstance(self, Scalar)
@@ -1412,6 +1435,7 @@
copy = interp2app(BaseArray.descr_copy),
flatten = interp2app(BaseArray.descr_flatten),
reshape = interp2app(BaseArray.descr_reshape),
+ swapaxes = interp2app(BaseArray.descr_swapaxes),
tolist = interp2app(BaseArray.descr_tolist),
take = interp2app(BaseArray.descr_take),
compress = interp2app(BaseArray.descr_compress),
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
@@ -1410,6 +1410,35 @@
assert (array([1, 2]).repeat(2) == array([1, 1, 2, 2])).all()
+ def test_swapaxes(self):
+ from _numpypy import array
+ # testcases from numpy docstring
+ x = array([[1, 2, 3]])
+ assert (x.swapaxes(0, 1) == array([[1], [2], [3]])).all()
+ x = array([[[0,1],[2,3]],[[4,5],[6,7]]]) # shape = (2, 2, 2)
+ assert (x.swapaxes(0, 2) == array([[[0, 4], [2, 6]],
+ [[1, 5], [3, 7]]])).all()
+ assert (x.swapaxes(0, 1) == array([[[0, 1], [4, 5]],
+ [[2, 3], [6, 7]]])).all()
+ assert (x.swapaxes(1, 2) == array([[[0, 2], [1, 3]],
+ [[4, 6],[5, 7]]])).all()
+
+ # more complex shape i.e. (2, 2, 3)
+ x = array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
+ assert (x.swapaxes(0, 1) == array([[[1, 2, 3], [7, 8, 9]],
+ [[4, 5, 6], [10, 11, 12]]])).all()
+ assert (x.swapaxes(0, 2) == array([[[1, 7], [4, 10]], [[2, 8], [5, 11]],
+ [[3, 9], [6, 12]]])).all()
+ assert (x.swapaxes(1, 2) == array([[[1, 4], [2, 5], [3, 6]],
+ [[7, 10], [8, 11],[9, 12]]])).all()
+
+ # test slice
+ assert (x[0:1,0:2].swapaxes(0,2) == array([[[1], [4]], [[2], [5]],
+ [[3], [6]]])).all()
+ # test virtual
+ assert ((x + x).swapaxes(0,1) == array([[[ 2, 4, 6], [14, 16, 18]],
+ [[ 8, 10, 12], [20, 22, 24]]])).all()
+
class AppTestMultiDim(BaseNumpyAppTest):
def test_init(self):
import _numpypy
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -762,6 +762,8 @@
def test_logaddexp(self):
import math
+ import sys
+ float_max, float_min = sys.float_info.max, sys.float_info.min
from _numpypy import logaddexp
# From the numpy documentation
@@ -772,7 +774,8 @@
assert logaddexp(0, 0) == math.log(2)
assert logaddexp(float('-inf'), 0) == 0
- assert logaddexp(12345678, 12345678) == float('inf')
+ assert logaddexp(float_max, float_max) == float_max
+ assert logaddexp(float_min, float_min) == math.log(2)
assert math.isnan(logaddexp(float('nan'), 1))
assert math.isnan(logaddexp(1, float('nan')))
@@ -785,6 +788,8 @@
def test_logaddexp2(self):
import math
+ import sys
+ float_max, float_min = sys.float_info.max, sys.float_info.min
from _numpypy import logaddexp2
log2 = math.log(2)
@@ -796,7 +801,8 @@
assert logaddexp2(0, 0) == 1
assert logaddexp2(float('-inf'), 0) == 0
- assert logaddexp2(12345678, 12345678) == float('inf')
+ assert logaddexp2(float_max, float_max) == float_max
+ assert logaddexp2(float_min, float_min) == 1.0
assert math.isnan(logaddexp2(float('nan'), 1))
assert math.isnan(logaddexp2(1, float('nan')))
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -17,6 +17,7 @@
'render_as_void': True})
degToRad = math.pi / 180.0
log2 = math.log(2)
+log2e = 1./log2
def simple_unary_op(func):
specialize.argtype(1)(func)
@@ -841,45 +842,26 @@
@simple_binary_op
def logaddexp(self, v1, v2):
- try:
- v1e = math.exp(v1)
- except OverflowError:
- v1e = rfloat.INFINITY
- try:
- v2e = math.exp(v2)
- except OverflowError:
- v2e = rfloat.INFINITY
+ tmp = v1 - v2
+ if tmp > 0:
+ return v1 + rfloat.log1p(math.exp(-tmp))
+ elif tmp <= 0:
+ return v2 + rfloat.log1p(math.exp(tmp))
+ else:
+ return v1 + v2
- v12e = v1e + v2e
- try:
- return math.log(v12e)
- except ValueError:
- if v12e == 0.0:
- # CPython raises ValueError here, so we have to check
- # the value to find the correct numpy return value
- return -rfloat.INFINITY
- return rfloat.NAN
+ def npy_log2_1p(self, v):
+ return log2e * rfloat.log1p(v)
@simple_binary_op
def logaddexp2(self, v1, v2):
- try:
- v1e = math.pow(2, v1)
- except OverflowError:
- v1e = rfloat.INFINITY
- try:
- v2e = math.pow(2, v2)
- except OverflowError:
- v2e = rfloat.INFINITY
-
- v12e = v1e + v2e
- try:
- return math.log(v12e) / log2
- except ValueError:
- if v12e == 0.0:
- # CPython raises ValueError here, so we have to check
- # the value to find the correct numpy return value
- return -rfloat.INFINITY
- return rfloat.NAN
+ tmp = v1 - v2
+ if tmp > 0:
+ return v1 + self.npy_log2_1p(math.pow(2, -tmp))
+ if tmp <= 0:
+ return v2 + self.npy_log2_1p(math.pow(2, tmp))
+ else:
+ return v1 + v2
class NonNativeFloat(NonNativePrimitive, Float):
_mixin_ = True
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -244,6 +244,7 @@
print guards
assert len(guards) <= 20
+
def test_stararg_virtual(self):
def main(x):
def g(*args):
@@ -486,3 +487,38 @@
--TICK--
jump(..., descr=...)
""")
+
+ def test_kwargs_virtual2(self):
+ log = self.run("""
+ def f(*args, **kwargs):
+ kwargs['a'] = kwargs['z'] * 0
+ return g(1, *args, **kwargs)
+
+ def g(x, y, z=2, a=1):
+ return x - y + z + a
+
+ def main(stop):
+ res = 0
+ i = 0
+ while i < stop:
+ res = f(res, z=i) # ID: call
+ i += 1
+ return res""", [1000])
+ assert log.result == 500
+ loop, = log.loops_by_id('call')
+ print loop.ops_by_id('call')
+ assert loop.match("""
+ i65 = int_lt(i58, i29)
+ guard_true(i65, descr=...)
+ guard_not_invalidated(..., descr=...)
+ i66 = force_token()
+ i67 = force_token()
+ i69 = int_sub_ovf(1, i56)
+ guard_no_overflow(..., descr=...)
+ i70 = int_add_ovf(i69, i58)
+ guard_no_overflow(..., descr=...)
+ i71 = int_add(i58, 1)
+ --TICK--
+ jump(..., descr=...)
+ """)
+
diff --git a/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py b/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
--- a/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
+++ b/pypy/module/test_lib_pypy/numpypy/core/test_fromnumeric.py
@@ -136,4 +136,11 @@
raises(NotImplementedError, "transpose(x, axes=(1, 0, 2))")
# x = ones((1, 2, 3))
# assert transpose(x, (1, 0, 2)).shape == (2, 1, 3)
-
+
+ def test_fromnumeric(self):
+ from numpypy import array, swapaxes
+ x = array([[1,2,3]])
+ assert (swapaxes(x,0,1) == array([[1], [2], [3]])).all()
+ x = array([[[0,1],[2,3]],[[4,5],[6,7]]])
+ assert (swapaxes(x,0,2) == array([[[0, 4], [2, 6]],
+ [[1, 5], [3, 7]]])).all()
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -414,7 +414,8 @@
def contains(space, w_container, w_item):
w_descr = space.lookup(w_container, '__contains__')
if w_descr is not None:
- return space.get_and_call_function(w_descr, w_container, w_item)
+ w_result = space.get_and_call_function(w_descr, w_container, w_item)
+ return space.nonzero(w_result)
return space._contains(w_container, w_item)
def _contains(space, w_container, w_item):
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -110,7 +110,7 @@
"NOT_RPYTHON"
raise NotImplementedError
- def newdict(self, module=False, instance=False,
+ def newdict(self, module=False, instance=False, kwargs=False,
strdict=False):
return w_some_obj()
diff --git a/pypy/objspace/flow/flowcontext.py b/pypy/objspace/flow/flowcontext.py
--- a/pypy/objspace/flow/flowcontext.py
+++ b/pypy/objspace/flow/flowcontext.py
@@ -434,6 +434,13 @@
self.lastblock = block
self.pushvalue(w_result)
+ def BUILD_LIST_FROM_ARG(self, _, next_instr):
+ # This opcode was added with pypy-1.8. Here is a simpler
+ # version, enough for annotation.
+ last_val = self.popvalue()
+ self.pushvalue(self.space.newlist([]))
+ self.pushvalue(last_val)
+
# XXX Unimplemented 2.7 opcodes ----------------
# Set literals, set comprehensions
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -33,7 +33,7 @@
@staticmethod
def allocate_and_init_instance(space, w_type=None, module=False,
- instance=False, strdict=False):
+ instance=False, strdict=False, kwargs=False):
if space.config.objspace.std.withcelldict and module:
from pypy.objspace.std.celldict import ModuleDictStrategy
@@ -46,11 +46,15 @@
assert w_type is None
strategy = space.fromcache(StringDictStrategy)
+ elif kwargs:
+ assert w_type is None
+ from pypy.objspace.std.kwargsdict import KwargsDictStrategy
+ strategy = space.fromcache(KwargsDictStrategy)
else:
strategy = space.fromcache(EmptyDictStrategy)
-
if w_type is None:
w_type = space.w_dict
+
storage = strategy.get_empty_storage()
w_self = space.allocate_instance(W_DictMultiObject, w_type)
W_DictMultiObject.__init__(w_self, space, strategy, storage)
@@ -91,7 +95,8 @@
getitem_str delitem length \
clear w_keys values \
items iter setdefault \
- popitem listview_str listview_int".split()
+ popitem listview_str listview_int \
+ view_as_kwargs".split()
def make_method(method):
def f(self, *args):
@@ -165,6 +170,9 @@
def listview_int(self, w_dict):
return None
+ def view_as_kwargs(self, w_dict):
+ return (None, None)
+
class EmptyDictStrategy(DictStrategy):
erase, unerase = rerased.new_erasing_pair("empty")
@@ -254,6 +262,9 @@
def popitem(self, w_dict):
raise KeyError
+ def view_as_kwargs(self, w_dict):
+ return ([], [])
+
registerimplementation(W_DictMultiObject)
# DictImplementation lattice
diff --git a/pypy/objspace/std/kwargsdict.py b/pypy/objspace/std/kwargsdict.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/kwargsdict.py
@@ -0,0 +1,165 @@
+## ----------------------------------------------------------------------------
+## dict strategy (see dictmultiobject.py)
+
+from pypy.rlib import rerased, jit
+from pypy.objspace.std.dictmultiobject import (DictStrategy,
+ IteratorImplementation,
+ ObjectDictStrategy,
+ StringDictStrategy)
+
+
+class KwargsDictStrategy(DictStrategy):
+ erase, unerase = rerased.new_erasing_pair("kwargsdict")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def wrap(self, key):
+ return self.space.wrap(key)
+
+ def unwrap(self, wrapped):
+ return self.space.str_w(wrapped)
+
+ def get_empty_storage(self):
+ d = ([], [])
+ return self.erase(d)
+
+ def is_correct_type(self, w_obj):
+ space = self.space
+ return space.is_w(space.type(w_obj), space.w_str)
+
+ def _never_equal_to(self, w_lookup_type):
+ return False
+
+ def iter(self, w_dict):
+ return KwargsDictIterator(self.space, self, w_dict)
+
+ def w_keys(self, w_dict):
+ return self.space.newlist([self.space.wrap(key) for key in self.unerase(w_dict.dstorage)[0]])
+
+ def setitem(self, w_dict, w_key, w_value):
+ space = self.space
+ if self.is_correct_type(w_key):
+ self.setitem_str(w_dict, self.unwrap(w_key), w_value)
+ return
+ else:
+ self.switch_to_object_strategy(w_dict)
+ w_dict.setitem(w_key, w_value)
+
+ def setitem_str(self, w_dict, key, w_value):
+ self._setitem_str_indirection(w_dict, key, w_value)
+
+ @jit.look_inside_iff(lambda self, w_dict, key, w_value:
+ jit.isconstant(self.length(w_dict)) and jit.isconstant(key))
+ def _setitem_str_indirection(self, w_dict, key, w_value):
+ keys, values_w = self.unerase(w_dict.dstorage)
+ result = []
+ for i in range(len(keys)):
+ if keys[i] == key:
+ values_w[i] = w_value
+ break
+ else:
+ # limit the size so that the linear searches don't become too long
+ if len(keys) >= 16:
+ self.switch_to_string_strategy(w_dict)
+ w_dict.setitem_str(key, w_value)
+ else:
+ keys.append(key)
+ values_w.append(w_value)
+
+ def setdefault(self, w_dict, w_key, w_default):
+ # XXX could do better, but is it worth it?
+ self.switch_to_object_strategy(w_dict)
+ return w_dict.setdefault(w_key, w_default)
+
+ def delitem(self, w_dict, w_key):
+ # XXX could do better, but is it worth it?
+ self.switch_to_object_strategy(w_dict)
+ return w_dict.delitem(w_key)
+
+ def length(self, w_dict):
+ return len(self.unerase(w_dict.dstorage)[0])
+
+ def getitem_str(self, w_dict, key):
+ return self._getitem_str_indirection(w_dict, key)
+
+ @jit.look_inside_iff(lambda self, w_dict, key: jit.isconstant(self.length(w_dict)) and jit.isconstant(key))
+ def _getitem_str_indirection(self, w_dict, key):
+ keys, values_w = self.unerase(w_dict.dstorage)
+ result = []
+ for i in range(len(keys)):
+ if keys[i] == key:
+ return values_w[i]
+ return None
+
+ def getitem(self, w_dict, w_key):
+ space = self.space
+ if self.is_correct_type(w_key):
+ return self.getitem_str(w_dict, self.unwrap(w_key))
+ elif self._never_equal_to(space.type(w_key)):
+ return None
+ else:
+ self.switch_to_object_strategy(w_dict)
+ return w_dict.getitem(w_key)
+
+ def w_keys(self, w_dict):
+ l = self.unerase(w_dict.dstorage)[0]
+ return self.space.newlist_str(l[:])
+
+ def values(self, w_dict):
+ return self.unerase(w_dict.dstorage)[1][:] # to make non-resizable
+
+ def items(self, w_dict):
+ space = self.space
+ keys, values_w = self.unerase(w_dict.dstorage)
+ result = []
+ for i in range(len(keys)):
+ result.append(space.newtuple([self.wrap(keys[i]), values_w[i]]))
+ return result
+
+ def popitem(self, w_dict):
+ keys, values_w = self.unerase(w_dict.dstorage)
+ key = keys.pop()
+ w_value = values_w.pop()
+ return (self.wrap(key), w_value)
+
+ def clear(self, w_dict):
+ w_dict.dstorage = self.get_empty_storage()
+
+ def switch_to_object_strategy(self, w_dict):
+ strategy = self.space.fromcache(ObjectDictStrategy)
+ keys, values_w = self.unerase(w_dict.dstorage)
+ d_new = strategy.unerase(strategy.get_empty_storage())
+ for i in range(len(keys)):
+ d_new[self.wrap(keys[i])] = values_w[i]
+ w_dict.strategy = strategy
+ w_dict.dstorage = strategy.erase(d_new)
+
+ def switch_to_string_strategy(self, w_dict):
+ strategy = self.space.fromcache(StringDictStrategy)
+ keys, values_w = self.unerase(w_dict.dstorage)
+ storage = strategy.get_empty_storage()
+ d_new = strategy.unerase(storage)
+ for i in range(len(keys)):
+ d_new[keys[i]] = values_w[i]
+ w_dict.strategy = strategy
+ w_dict.dstorage = storage
+
+ def view_as_kwargs(self, w_dict):
+ return self.unerase(w_dict.dstorage)
+
+
+class KwargsDictIterator(IteratorImplementation):
+ def __init__(self, space, strategy, dictimplementation):
+ IteratorImplementation.__init__(self, space, strategy, dictimplementation)
+ keys, values_w = strategy.unerase(self.dictimplementation.dstorage)
+ self.iterator = iter(range(len(keys)))
+ # XXX this potentially leaks
+ self.keys = keys
+ self.values_w = values_w
+
+ def next_entry(self):
+ # note that this 'for' loop only runs once, at most
+ for i in self.iterator:
+ return self.space.wrap(self.keys[i]), self.values_w[i]
+ else:
+ return None, None
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -313,11 +313,11 @@
def newlist_str(self, list_s):
return W_ListObject.newlist_str(self, list_s)
- def newdict(self, module=False, instance=False,
+ def newdict(self, module=False, instance=False, kwargs=False,
strdict=False):
return W_DictMultiObject.allocate_and_init_instance(
self, module=module, instance=instance,
- strdict=strdict)
+ strdict=strdict, kwargs=kwargs)
def newset(self):
from pypy.objspace.std.setobject import newset
@@ -472,6 +472,11 @@
return w_obj.getitems_int()
return None
+ def view_as_kwargs(self, w_dict):
+ if type(w_dict) is W_DictMultiObject:
+ return w_dict.view_as_kwargs()
+ return (None, None)
+
def _uses_list_iter(self, w_obj):
from pypy.objspace.descroperation import list_iter
return self.lookup(w_obj, '__iter__') is list_iter(self)
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -14,6 +14,7 @@
from pypy.objspace.std.tupleobject import W_TupleObject
from pypy.rlib.rstring import StringBuilder, split
from pypy.interpreter.buffer import StringBuffer
+from pypy.rlib import jit
from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
stringendswith, stringstartswith, joined2
@@ -398,6 +399,8 @@
return _str_join_many_items(space, w_self, list_w, size)
+ at jit.look_inside_iff(lambda space, w_self, list_w, size:
+ jit.loop_unrolling_heuristic(list_w, size))
def _str_join_many_items(space, w_self, list_w, size):
self = w_self._value
reslen = len(self) * (size - 1)
diff --git a/pypy/objspace/std/test/test_kwargsdict.py b/pypy/objspace/std/test/test_kwargsdict.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_kwargsdict.py
@@ -0,0 +1,120 @@
+import py
+from pypy.conftest import gettestobjspace, option
+from pypy.objspace.std.test.test_dictmultiobject import FakeSpace, W_DictMultiObject
+from pypy.objspace.std.kwargsdict import *
+
+space = FakeSpace()
+strategy = KwargsDictStrategy(space)
+
+def test_create():
+ keys = ["a", "b", "c"]
+ values = [1, 2, 3]
+ storage = strategy.erase((keys, values))
+ d = W_DictMultiObject(space, strategy, storage)
+ assert d.getitem_str("a") == 1
+ assert d.getitem_str("b") == 2
+ assert d.getitem_str("c") == 3
+ assert d.getitem(space.wrap("a")) == 1
+ assert d.getitem(space.wrap("b")) == 2
+ assert d.getitem(space.wrap("c")) == 3
+ assert d.w_keys() == keys
+ assert d.values() == values
+
+def test_set_existing():
+ keys = ["a", "b", "c"]
+ values = [1, 2, 3]
+ storage = strategy.erase((keys, values))
+ d = W_DictMultiObject(space, strategy, storage)
+ assert d.getitem_str("a") == 1
+ assert d.getitem_str("b") == 2
+ assert d.getitem_str("c") == 3
+ assert d.setitem_str("a", 4) is None
+ assert d.getitem_str("a") == 4
+ assert d.getitem_str("b") == 2
+ assert d.getitem_str("c") == 3
+ assert d.setitem_str("b", 5) is None
+ assert d.getitem_str("a") == 4
+ assert d.getitem_str("b") == 5
+ assert d.getitem_str("c") == 3
+ assert d.setitem_str("c", 6) is None
+ assert d.getitem_str("a") == 4
+ assert d.getitem_str("b") == 5
+ assert d.getitem_str("c") == 6
+ assert d.getitem(space.wrap("a")) == 4
+ assert d.getitem(space.wrap("b")) == 5
+ assert d.getitem(space.wrap("c")) == 6
+ assert d.w_keys() == keys
+ assert d.values() == values
+ assert keys == ["a", "b", "c"]
+ assert values == [4, 5, 6]
+
+
+def test_set_new():
+ keys = ["a", "b", "c"]
+ values = [1, 2, 3]
+ storage = strategy.erase((keys, values))
+ d = W_DictMultiObject(space, strategy, storage)
+ assert d.getitem_str("a") == 1
+ assert d.getitem_str("b") == 2
+ assert d.getitem_str("c") == 3
+ assert d.getitem_str("d") is None
+ assert d.setitem_str("d", 4) is None
+ assert d.getitem_str("a") == 1
+ assert d.getitem_str("b") == 2
+ assert d.getitem_str("c") == 3
+ assert d.getitem_str("d") == 4
+ assert d.w_keys() == keys
+ assert d.values() == values
+ assert keys == ["a", "b", "c", "d"]
+ assert values == [1, 2, 3, 4]
+
+def test_limit_size():
+ storage = strategy.get_empty_storage()
+ d = W_DictMultiObject(space, strategy, storage)
+ for i in range(100):
+ assert d.setitem_str("d%s" % i, 4) is None
+ assert d.strategy is not strategy
+ assert "StringDictStrategy" == d.strategy.__class__.__name__
+
+def test_keys_doesnt_wrap():
+ space = FakeSpace()
+ space.newlist = None
+ strategy = KwargsDictStrategy(space)
+ keys = ["a", "b", "c"]
+ values = [1, 2, 3]
+ storage = strategy.erase((keys, values))
+ d = W_DictMultiObject(space, strategy, storage)
+ w_l = d.w_keys() # does not crash
+
+
+from pypy.objspace.std.test.test_dictmultiobject import BaseTestRDictImplementation, BaseTestDevolvedDictImplementation
+def get_impl(self):
+ storage = strategy.erase(([], []))
+ return W_DictMultiObject(space, strategy, storage)
+class TestKwargsDictImplementation(BaseTestRDictImplementation):
+ StrategyClass = KwargsDictStrategy
+ get_impl = get_impl
+ def test_delitem(self):
+ pass # delitem devolves for now
+
+class TestDevolvedKwargsDictImplementation(BaseTestDevolvedDictImplementation):
+ get_impl = get_impl
+ StrategyClass = KwargsDictStrategy
+
+
+class AppTestKwargsDictStrategy(object):
+ def setup_class(cls):
+ if option.runappdirect:
+ py.test.skip("__repr__ doesn't work on appdirect")
+
+ def w_get_strategy(self, obj):
+ import __pypy__
+ r = __pypy__.internal_repr(obj)
+ return r[r.find("(") + 1: r.find(")")]
+
+ def test_create(self):
+ def f(**args):
+ return args
+ d = f(a=1)
+ assert "KwargsDictStrategy" in self.get_strategy(d)
+
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -16,6 +16,7 @@
from pypy.rlib.runicode import unicode_encode_unicode_escape
from pypy.module.unicodedata import unicodedb
from pypy.tool.sourcetools import func_with_new_name
+from pypy.rlib import jit
from pypy.objspace.std.formatting import mod_format
from pypy.objspace.std.stringtype import stringstartswith, stringendswith
@@ -214,6 +215,8 @@
return _unicode_join_many_items(space, w_self, list_w, size)
+ at jit.look_inside_iff(lambda space, w_self, list_w, size:
+ jit.loop_unrolling_heuristic(list_w, size))
def _unicode_join_many_items(space, w_self, list_w, size):
self = w_self._value
prealloc_size = len(self) * (size - 1)
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -694,5 +694,31 @@
l = len(X(X(2)))
assert l == 2 and type(l) is int
+ def test_bool___contains__(self):
+ class X(object):
+ def __contains__(self, item):
+ if item == 'foo':
+ return 42
+ else:
+ return 'hello world'
+ x = X()
+ res = 'foo' in x
+ assert res is True
+ res = 'bar' in x
+ assert res is True
+ #
+ class MyError(Exception):
+ pass
+ class CannotConvertToBool(object):
+ def __nonzero__(self):
+ raise MyError
+ class X(object):
+ def __contains__(self, item):
+ return CannotConvertToBool()
+ x = X()
+ raises(MyError, "'foo' in x")
+
+
+
class AppTestWithBuiltinShortcut(AppTest_Descroperation):
OPTIONS = {'objspace.std.builtinshortcut': True}
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -204,6 +204,14 @@
return NonConstant(False)
isvirtual._annspecialcase_ = "specialize:call_location"
+LIST_CUTOFF = 2
+
+ at specialize.call_location()
+def loop_unrolling_heuristic(lst, size):
+ """ In which cases iterating over items of lst can be unrolled
+ """
+ return isvirtual(lst) or (isconstant(size) and size <= LIST_CUTOFF)
+
class Entry(ExtRegistryEntry):
_about_ = hint
diff --git a/pypy/rlib/parsing/test/test_ebnfparse.py b/pypy/rlib/parsing/test/test_ebnfparse.py
--- a/pypy/rlib/parsing/test/test_ebnfparse.py
+++ b/pypy/rlib/parsing/test/test_ebnfparse.py
@@ -103,6 +103,7 @@
""")
parse = make_parse_function(regexs, rules)
tree = parse("prefix(\n\tlonger(and_nested(term(X))), Xya, _, X0, _).")
+ assert tree.children[0].children[0].children[2].children[0].getsourcepos().lineno == 1
assert tree is not None
tree = parse("""
foo(X, Y) :- bar(Y, X), bar(Y, X) ; foobar(X, Y, 1234, atom).""")
diff --git a/pypy/rlib/parsing/tree.py b/pypy/rlib/parsing/tree.py
--- a/pypy/rlib/parsing/tree.py
+++ b/pypy/rlib/parsing/tree.py
@@ -23,6 +23,9 @@
self.symbol = symbol
self.additional_info = additional_info
self.token = token
+
+ def getsourcepos(self):
+ return self.token.source_pos
def __repr__(self):
return "Symbol(%r, %r)" % (self.symbol, self.additional_info)
@@ -49,6 +52,9 @@
self.children = children
self.symbol = symbol
+ def getsourcepos(self):
+ return self.children[0].getsourcepos()
+
def __str__(self):
return "%s(%s)" % (self.symbol, ", ".join([str(c) for c in self.children]))
diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py
--- a/pypy/rlib/ropenssl.py
+++ b/pypy/rlib/ropenssl.py
@@ -3,8 +3,9 @@
from pypy.translator.platform import platform
from pypy.translator.tool.cbuild import ExternalCompilationInfo
-import sys
+import sys, os
+link_files = []
if sys.platform == 'win32' and platform.name != 'mingw32':
libraries = ['libeay32', 'ssleay32',
'user32', 'advapi32', 'gdi32', 'msvcrt', 'ws2_32']
@@ -17,8 +18,17 @@
# so that openssl/ssl.h can repair this nonsense.
'wincrypt.h']
else:
- libraries = ['ssl', 'crypto']
+ libraries = ['z']
includes = []
+ if (sys.platform.startswith('linux') and
+ os.path.exists('/usr/lib/libssl.a') and
+ os.path.exists('/usr/lib/libcrypto.a')):
+ # use static linking to avoid the infinite
+ # amount of troubles due to symbol versions
+ # and 0.9.8/1.0.0
+ link_files += ['/usr/lib/libssl.a', '/usr/lib/libcrypto.a']
+ else:
+ libraries += ['ssl', 'crypto']
includes += [
'openssl/ssl.h',
@@ -30,6 +40,7 @@
eci = ExternalCompilationInfo(
libraries = libraries,
+ link_files = link_files,
includes = includes,
export_symbols = [],
post_include_bits = [
diff --git a/pypy/rlib/rweakref.py b/pypy/rlib/rweakref.py
--- a/pypy/rlib/rweakref.py
+++ b/pypy/rlib/rweakref.py
@@ -9,6 +9,9 @@
ref = weakref.ref # basic regular weakrefs are supported in RPython
+def has_weakref_support():
+ return True # returns False if --no-translation-rweakref
+
class RWeakValueDictionary(object):
"""A dictionary containing weak values."""
@@ -68,6 +71,20 @@
from pypy.annotation.bookkeeper import getbookkeeper
from pypy.tool.pairtype import pairtype
+class Entry(extregistry.ExtRegistryEntry):
+ _about_ = has_weakref_support
+
+ def compute_result_annotation(self):
+ translator = self.bookkeeper.annotator.translator
+ res = translator.config.translation.rweakref
+ return self.bookkeeper.immutablevalue(res)
+
+ def specialize_call(self, hop):
+ from pypy.rpython.lltypesystem import lltype
+ hop.exception_cannot_occur()
+ return hop.inputconst(lltype.Bool, hop.s_result.const)
+
+
class SomeWeakValueDict(annmodel.SomeObject):
knowntype = RWeakValueDictionary
diff --git a/pypy/rlib/test/test_rweakref.py b/pypy/rlib/test/test_rweakref.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/test/test_rweakref.py
@@ -0,0 +1,14 @@
+from pypy.rlib.rweakref import has_weakref_support
+from pypy.rpython.test.test_llinterp import interpret
+
+
+def test_has_weakref_support():
+ assert has_weakref_support()
+
+ res = interpret(lambda: has_weakref_support(), [],
+ **{'translation.rweakref': True})
+ assert res == True
+
+ res = interpret(lambda: has_weakref_support(), [],
+ **{'translation.rweakref': False})
+ assert res == False
diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -709,7 +709,8 @@
return count
@enforceargs(int, None)
- @jit.look_inside_iff(lambda length, items: jit.isconstant(length) and length <= 2)
+ @jit.look_inside_iff(lambda length, items: jit.loop_unrolling_heuristic(
+ items, length))
def ll_join_strs(length, items):
# Special case for length 1 items, helps both the JIT and other code
if length == 1:
diff --git a/pypy/tool/clean_old_branches.py b/pypy/tool/clean_old_branches.py
--- a/pypy/tool/clean_old_branches.py
+++ b/pypy/tool/clean_old_branches.py
@@ -4,30 +4,28 @@
called 'closed-branch'. It reduces the number of heads.
"""
-import os, sys
+import os
+import sys
+import commands
-if not os.listdir('.hg'):
+if not os.path.isdir('.hg'):
print 'Must run this script from the top-level directory.'
sys.exit(1)
-def heads(args):
- g = os.popen(r"hg heads --topo %s --template '{node|short}:{branches}\n'"
- % args, 'r')
- result = g.read()
- g.close()
+def heads():
+ result = commands.getoutput(
+ "hg heads --topo --closed --template '{node|short}:{branches}:{extras}\n'")
result = result.splitlines(False)
+ result = [s.split(':', 2) for s in result]
for line in result:
- if len(line.split(':', 1)) != 2:
+ if len(line) != 3:
raise ValueError("'result' contains: %r" % line)
- result = [s.split(':', 1) for s in result]
- result = [(head, branch) for (head, branch) in result
- if branch not in ['', 'closed-branches']]
+ result = [(head, branch) for (head, branch, extra) in result
+ if branch not in ['', 'closed-branches'] and 'close' in extra]
return result
-all_heads = heads("--closed")
-opened_heads = heads("")
-closed_heads = [s for s in all_heads if s not in opened_heads]
+closed_heads = heads()
if not closed_heads:
print >> sys.stderr, 'no dangling closed heads.'
@@ -56,16 +54,14 @@
print '*** error %r' % (err,)
sys.exit(1)
+print '*** switching to closed branches *** '
+do("hg up --clean closed-branches")
+do("hg --config extensions.purge= purge --all")
+
for head, branch in closed_heads:
print
print '***** %s ***** %s *****' % (branch, head)
- do("hg up --clean closed-branches")
- do("hg --config extensions.purge= purge --all")
- do("hg merge -y %s" % head)
- for fn in os.listdir('.'):
- if fn.lower() != '.hg':
- do("rm -fr -- '%s'" % fn)
- do("hg rm --after -- '%s' || true" % fn)
+ do("hg debugsetparents closed-branches %s" % head)
do("hg ci -m'Merge closed head %s on branch %s'" % (head, branch))
print
diff --git a/pypy/tool/test/test_udir.py b/pypy/tool/test/test_udir.py
--- a/pypy/tool/test/test_udir.py
+++ b/pypy/tool/test/test_udir.py
@@ -13,6 +13,8 @@
def test_make_udir_with_basename():
root = str(udir.udir.ensure('make_udir2', dir=1))
p1 = udir.make_udir(dir=root, basename='foobar')
+ def assert_relto(path, root, expected):
+ assert path.relto(root) == expected, path.relto(root)
assert p1.relto(root) == 'usession-foobar-0'
p1 = udir.make_udir(dir=root, basename='-foobar')
assert p1.relto(root) == 'usession-foobar-1'
@@ -24,3 +26,5 @@
assert p1.relto(root) == 'usession-0'
p1 = udir.make_udir(dir=root, basename='-')
assert p1.relto(root) == 'usession-1'
+ p1 = udir.make_udir(dir=root, basename='fun/bar')
+ assert p1.relto(root) == 'usession-fun--bar-0'
diff --git a/pypy/tool/udir.py b/pypy/tool/udir.py
--- a/pypy/tool/udir.py
+++ b/pypy/tool/udir.py
@@ -41,6 +41,7 @@
basename = basename.encode(sys.getdefaultencoding())
else:
basename = ''
+ basename = basename.replace('/', '--')
if not basename.startswith('-'):
basename = '-' + basename
if not basename.endswith('-'):
diff --git a/pypy/translator/driver.py b/pypy/translator/driver.py
--- a/pypy/translator/driver.py
+++ b/pypy/translator/driver.py
@@ -115,12 +115,10 @@
backend, ts = self.get_backend_and_type_system()
for task in self.tasks:
explicit_task = task
- parts = task.split('_')
- if len(parts) == 1:
- if task in ('annotate',):
- expose_task(task)
+ if task == 'annotate':
+ expose_task(task)
else:
- task, postfix = parts
+ task, postfix = task.split('_')
if task in ('rtype', 'backendopt', 'llinterpret',
'pyjitpl'):
if ts:
More information about the pypy-commit
mailing list