[pypy-commit] pypy more-rposix: hg merge default
amauryfa
noreply at buildbot.pypy.org
Sun May 3 18:37:49 CEST 2015
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: more-rposix
Changeset: r77004:bbd40bb55e9d
Date: 2015-04-23 23:28 +0200
http://bitbucket.org/pypy/pypy/changeset/bbd40bb55e9d/
Log: hg merge default
diff too long, truncating to 2000 out of 6881 lines
diff --git a/.tddium.requirements.txt b/.tddium.requirements.txt
deleted file mode 100644
--- a/.tddium.requirements.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-pytest
diff --git a/lib-python/2.7/test/test_urllib2net.py b/lib-python/2.7/test/test_urllib2net.py
--- a/lib-python/2.7/test/test_urllib2net.py
+++ b/lib-python/2.7/test/test_urllib2net.py
@@ -102,11 +102,8 @@
def test_ftp(self):
urls = [
- 'ftp://ftp.kernel.org/pub/linux/kernel/README',
- 'ftp://ftp.kernel.org/pub/linux/kernel/non-existent-file',
- #'ftp://ftp.kernel.org/pub/leenox/kernel/test',
- 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC'
- '/research-reports/00README-Legal-Rules-Regs',
+ 'ftp://ftp.debian.org/debian/README',
+ 'ftp://ftp.debian.org/debian/non-existent-file',
]
self._test_urls(urls, self._extra_handlers())
@@ -255,6 +252,7 @@
with test_support.transient_internet(url, timeout=None):
u = _urlopen_with_retry(url)
self.assertIsNone(u.fp._sock.fp._sock.gettimeout())
+ u.close()
def test_http_default_timeout(self):
self.assertIsNone(socket.getdefaulttimeout())
@@ -266,6 +264,7 @@
finally:
socket.setdefaulttimeout(None)
self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 60)
+ u.close()
def test_http_no_timeout(self):
self.assertIsNone(socket.getdefaulttimeout())
@@ -277,20 +276,23 @@
finally:
socket.setdefaulttimeout(None)
self.assertIsNone(u.fp._sock.fp._sock.gettimeout())
+ u.close()
def test_http_timeout(self):
url = "http://www.example.com"
with test_support.transient_internet(url):
u = _urlopen_with_retry(url, timeout=120)
self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 120)
+ u.close()
- FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/"
+ FTP_HOST = 'ftp://ftp.debian.org/debian/'
def test_ftp_basic(self):
self.assertIsNone(socket.getdefaulttimeout())
with test_support.transient_internet(self.FTP_HOST, timeout=None):
u = _urlopen_with_retry(self.FTP_HOST)
self.assertIsNone(u.fp.fp._sock.gettimeout())
+ u.close()
def test_ftp_default_timeout(self):
self.assertIsNone(socket.getdefaulttimeout())
@@ -301,6 +303,7 @@
finally:
socket.setdefaulttimeout(None)
self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
+ u.close()
def test_ftp_no_timeout(self):
self.assertIsNone(socket.getdefaulttimeout(),)
@@ -311,11 +314,16 @@
finally:
socket.setdefaulttimeout(None)
self.assertIsNone(u.fp.fp._sock.gettimeout())
+ u.close()
def test_ftp_timeout(self):
with test_support.transient_internet(self.FTP_HOST):
- u = _urlopen_with_retry(self.FTP_HOST, timeout=60)
+ try:
+ u = _urlopen_with_retry(self.FTP_HOST, timeout=60)
+ except:
+ raise
self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
+ u.close()
def test_main():
diff --git a/lib_pypy/_tkinter/tklib.py b/lib_pypy/_tkinter/tklib.py
--- a/lib_pypy/_tkinter/tklib.py
+++ b/lib_pypy/_tkinter/tklib.py
@@ -1,7 +1,7 @@
# C bindings with libtcl and libtk.
from cffi import FFI
-import sys
+import sys, os
tkffi = FFI()
@@ -135,9 +135,12 @@
linklibs = ['tcl', 'tk']
libdirs = []
else:
- incdirs=['/usr/include/tcl']
- linklibs=['tcl', 'tk']
- libdirs = []
+ for _ver in ['', '8.6', '8.5', '']:
+ incdirs = ['/usr/include/tcl' + _ver]
+ linklibs = ['tcl' + _ver, 'tk' + _ver]
+ libdirs = []
+ if os.path.isdir(incdirs[0]):
+ break
tklib = tkffi.verify("""
#include <tcl.h>
diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py
--- a/lib_pypy/pyrepl/simple_interact.py
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -33,6 +33,16 @@
return False
return True
+def _strip_final_indent(text):
+ # kill spaces and tabs at the end, but only if they follow '\n'.
+ # meant to remove the auto-indentation only (although it would of
+ # course also remove explicitly-added indentation).
+ short = text.rstrip(' \t')
+ n = len(short)
+ if n > 0 and text[n-1] == '\n':
+ return short
+ return text
+
def run_multiline_interactive_console(mainmodule=None):
import code
if mainmodule is None:
@@ -41,7 +51,7 @@
def more_lines(unicodetext):
# ooh, look at the hack:
- src = "#coding:utf-8\n"+unicodetext.encode('utf-8')
+ src = "#coding:utf-8\n"+_strip_final_indent(unicodetext).encode('utf-8')
try:
code = console.compile(src, '<stdin>', 'single')
except (OverflowError, SyntaxError, ValueError):
@@ -58,7 +68,7 @@
returns_unicode=True)
except EOFError:
break
- more = console.push(statement)
+ more = console.push(_strip_final_indent(statement))
assert not more
except KeyboardInterrupt:
console.write("\nKeyboardInterrupt\n")
diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst
--- a/pypy/doc/getting-started-dev.rst
+++ b/pypy/doc/getting-started-dev.rst
@@ -207,12 +207,17 @@
large amount of options that can be used to customize pyinteractive.py).
As an example of using PyPy from the command line, you could type::
- python pyinteractive.py -c "from test import pystone; pystone.main(10)"
+ python pyinteractive.py --withmod-time -c "from test import pystone; pystone.main(10)"
Alternatively, as with regular Python, you can simply give a
script name on the command line::
- python pyinteractive.py ../../lib-python/2.7/test/pystone.py 10
+ python pyinteractive.py --withmod-time ../../lib-python/2.7/test/pystone.py 10
+
+The ``--withmod-xxx`` option enables the built-in module ``xxx``. By
+default almost none of them are, because initializing them takes time.
+If you want anyway to enable all built-in modules, you can use
+``--allworkingmodules``.
See our :doc:`configuration sections <config/index>` for details about what all the commandline
options do.
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
@@ -5,9 +5,65 @@
.. this is a revision shortly after release-2.5.1
.. startrev: cb01edcb59414d9d93056e54ed060673d24e67c1
+issue2005:
+ignore errors on closing random file handles while importing a module (cpython compatibility)
+
+issue2013:
+added constants to _ssl for TLS 1.1 and 1.2
+
+issue2014:
+Add PyLong_FromUnicode to cpyext.
+
+issue2017:
+On non-Linux-x86 platforms, reduced the memory impact of
+creating a lot of greenlets/tasklets. Particularly useful on Win32 and
+on ARM, where you used to get a MemoryError after only 2500-5000
+greenlets (the 32-bit address space is exhausted).
+
+Update gdb_pypy for python3 (gdb comatability)
+
+Merged rstrategies into rpython which provides a library for Storage Strategies
+
+Support unicode strings in numpy.dtype creation i.e. np.dtype(u'int64')
+
+Various rpython cleanups for vmprof support
+
+issue2019:
+Fix isspace as called by rpython unicode.strip()
+
+issue2023:
+In the cpyext 'Concrete Object Layer' API,
+don't call methods on the object (which can be overriden),
+but directly on the concrete base type.
+
+issue2029:
+Hide the default_factory attribute in a dict
+
+issue2027:
+Better document pyinteractive and add --withmod-time
+
.. branch: gc-incminimark-pinning-improve
+
+branch gc-incminimark-pinning-improve:
Object Pinning is now used in `bz2` and `rzlib` (therefore also affects
Python's `zlib`). In case the data to compress/decompress is inside the nursery
(incminimark) it no longer needs to create a non-moving copy of it. This saves
one `malloc` and copying the data. Additionally a new GC environment variable
is introduced (`PYPY_GC_MAX_PINNED`) primarily for debugging purposes.
+
+.. branch: refactor-pycall
+
+branch refactor-pycall:
+Make `*`-unpacking in RPython function calls completely equivalent to passing
+the tuple's elements as arguments. In other words, `f(*(a, b))` now behaves
+exactly like `f(a, b)`.
+
+.. branch: issue2018
+branch issue2018:
+Allow prebuilt rpython dict with function values
+
+.. branch: vmprof
+.. Merged but then backed out, hopefully it will return as vmprof2
+
+.. branch: object-dtype2
+Extend numpy dtypes to allow using objects with associated garbage collection hook
diff --git a/pypy/goal/targetnumpystandalone.py b/pypy/goal/targetnumpystandalone.py
deleted file mode 100644
--- a/pypy/goal/targetnumpystandalone.py
+++ /dev/null
@@ -1,43 +0,0 @@
-
-""" Usage:
-
-./targetnumpystandalone-c <bytecode> array_size
-
-Will execute a give numpy bytecode. Arrays will be ranges (in float) modulo 10,
-constants would be consecutive starting from one.
-
-Bytecode should contain letters 'a' 'l' and 'f' so far and be correct
-"""
-
-import time
-from pypy.module.micronumpy.compile import numpy_compile
-from rpython.jit.codewriter.policy import JitPolicy
-from rpython.rtyper.annlowlevel import hlstr
-
-def entry_point(argv):
- if len(argv) != 3:
- print __doc__
- return 1
- try:
- size = int(argv[2])
- except ValueError:
- print "INVALID LITERAL FOR INT:", argv[2]
- print __doc__
- return 3
- t0 = time.time()
- main(argv[0], size)
- print "bytecode:", argv[0], "size:", size
- print "took:", time.time() - t0
- return 0
-
-def main(bc, size):
- if not isinstance(bc, str):
- bc = hlstr(bc) # for tests
- a = numpy_compile(bc, size)
- a = a.compute()
-
-def target(*args):
- return entry_point, None
-
-def jitpolicy(driver):
- return JitPolicy()
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -1,5 +1,6 @@
"""Python control flow graph generation and bytecode assembly."""
+import os
from rpython.rlib import rfloat
from rpython.rlib.objectmodel import we_are_translated
@@ -9,6 +10,10 @@
from pypy.tool import stdlib_opcode as ops
+class StackDepthComputationError(Exception):
+ pass
+
+
class Instruction(object):
"""Represents a single opcode."""
@@ -55,11 +60,13 @@
reaches the end of the block, it continues to next_block.
"""
+ marked = False
+ have_return = False
+ auto_inserted_return = False
+
def __init__(self):
self.instructions = []
self.next_block = None
- self.marked = False
- self.have_return = False
def _post_order_see(self, stack, nextblock):
if nextblock.marked == 0:
@@ -384,7 +391,11 @@
# look into a block when all the previous blocks have been done.
self._max_depth = 0
for block in blocks:
- self._do_stack_depth_walk(block)
+ depth = self._do_stack_depth_walk(block)
+ if block.auto_inserted_return and depth != 0:
+ os.write(2, "StackDepthComputationError in %s at %s:%s\n" % (
+ self.compile_info.filename, self.name, self.first_lineno))
+ raise StackDepthComputationError # fatal error
return self._max_depth
def _next_stack_depth_walk(self, nextblock, depth):
@@ -393,20 +404,21 @@
def _do_stack_depth_walk(self, block):
depth = block.initial_depth
- done = False
for instr in block.instructions:
depth += _opcode_stack_effect(instr.opcode, instr.arg)
if depth >= self._max_depth:
self._max_depth = depth
+ jump_op = instr.opcode
if instr.has_jump:
target_depth = depth
- jump_op = instr.opcode
if jump_op == ops.FOR_ITER:
target_depth -= 2
elif (jump_op == ops.SETUP_FINALLY or
jump_op == ops.SETUP_EXCEPT or
jump_op == ops.SETUP_WITH):
- target_depth += 3
+ if jump_op == ops.SETUP_WITH:
+ target_depth -= 1 # ignore the w_result just pushed
+ target_depth += 3 # add [exc_type, exc, unroller]
if target_depth > self._max_depth:
self._max_depth = target_depth
elif (jump_op == ops.JUMP_IF_TRUE_OR_POP or
@@ -415,10 +427,14 @@
self._next_stack_depth_walk(instr.jump[0], target_depth)
if jump_op == ops.JUMP_ABSOLUTE or jump_op == ops.JUMP_FORWARD:
# Nothing more can occur.
- done = True
break
- if block.next_block and not done:
- self._next_stack_depth_walk(block.next_block, depth)
+ elif jump_op == ops.RETURN_VALUE or jump_op == ops.RAISE_VARARGS:
+ # Nothing more can occur.
+ break
+ else:
+ if block.next_block:
+ self._next_stack_depth_walk(block.next_block, depth)
+ return depth
def _build_lnotab(self, blocks):
"""Build the line number table for tracebacks and tracing."""
@@ -471,6 +487,7 @@
if self.add_none_to_final_return:
self.load_const(self.space.w_None)
self.emit_op(ops.RETURN_VALUE)
+ self.current_block.auto_inserted_return = True
# Set the first lineno if it is not already explicitly set.
if self.first_lineno == -1:
if self.first_block.instructions:
@@ -563,10 +580,10 @@
ops.INPLACE_OR: -1,
ops.INPLACE_XOR: -1,
- ops.SLICE+0: 1,
- ops.SLICE+1: 0,
- ops.SLICE+2: 0,
- ops.SLICE+3: -1,
+ ops.SLICE+0: 0,
+ ops.SLICE+1: -1,
+ ops.SLICE+2: -1,
+ ops.SLICE+3: -2,
ops.STORE_SLICE+0: -2,
ops.STORE_SLICE+1: -3,
ops.STORE_SLICE+2: -3,
@@ -576,7 +593,7 @@
ops.DELETE_SLICE+2: -2,
ops.DELETE_SLICE+3: -3,
- ops.STORE_SUBSCR: -2,
+ ops.STORE_SUBSCR: -3,
ops.DELETE_SUBSCR: -2,
ops.GET_ITER: 0,
@@ -593,7 +610,9 @@
ops.WITH_CLEANUP: -1,
ops.POP_BLOCK: 0,
- ops.END_FINALLY: -1,
+ ops.END_FINALLY: -3, # assume always 3: we pretend that SETUP_FINALLY
+ # pushes 3. In truth, it would only push 1 and
+ # the corresponding END_FINALLY only pops 1.
ops.SETUP_WITH: 1,
ops.SETUP_FINALLY: 0,
ops.SETUP_EXCEPT: 0,
@@ -604,7 +623,6 @@
ops.YIELD_VALUE: 0,
ops.BUILD_CLASS: -2,
ops.BUILD_MAP: 1,
- ops.BUILD_SET: 1,
ops.COMPARE_OP: -1,
ops.LOOKUP_METHOD: 1,
@@ -659,6 +677,9 @@
def _compute_BUILD_LIST(arg):
return 1 - arg
+def _compute_BUILD_SET(arg):
+ return 1 - arg
+
def _compute_MAKE_CLOSURE(arg):
return -arg - 1
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
@@ -772,6 +772,60 @@
code = compile_with_astcompiler(source, 'exec', self.space)
assert code.co_stacksize == 2
+ def test_stackeffect_bug3(self):
+ source = """if 1:
+ try: pass
+ finally: pass
+ try: pass
+ finally: pass
+ try: pass
+ finally: pass
+ try: pass
+ finally: pass
+ try: pass
+ finally: pass
+ try: pass
+ finally: pass
+ """
+ code = compile_with_astcompiler(source, 'exec', self.space)
+ assert code.co_stacksize == 3
+
+ def test_stackeffect_bug4(self):
+ source = """if 1:
+ with a: pass
+ with a: pass
+ with a: pass
+ with a: pass
+ with a: pass
+ with a: pass
+ """
+ code = compile_with_astcompiler(source, 'exec', self.space)
+ assert code.co_stacksize == 4
+
+ def test_stackeffect_bug5(self):
+ source = """if 1:
+ a[:]; a[:]; a[:]; a[:]; a[:]; a[:]
+ a[1:]; a[1:]; a[1:]; a[1:]; a[1:]; a[1:]
+ a[:2]; a[:2]; a[:2]; a[:2]; a[:2]; a[:2]
+ a[1:2]; a[1:2]; a[1:2]; a[1:2]; a[1:2]; a[1:2]
+ """
+ code = compile_with_astcompiler(source, 'exec', self.space)
+ assert code.co_stacksize == 3
+
+ def test_stackeffect_bug6(self):
+ source = """if 1:
+ {1}; {1}; {1}; {1}; {1}; {1}; {1}
+ """
+ code = compile_with_astcompiler(source, 'exec', self.space)
+ assert code.co_stacksize == 1
+
+ def test_stackeffect_bug7(self):
+ source = '''def f():
+ for i in a:
+ return
+ '''
+ code = compile_with_astcompiler(source, 'exec', self.space)
+
def test_lambda(self):
yield self.st, "y = lambda x: x", "y(4)", 4
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -374,14 +374,11 @@
return space.wrap(self.name)
def fset_func_name(self, space, w_name):
- try:
+ if space.isinstance_w(w_name, space.w_str):
self.name = space.str_w(w_name)
- except OperationError, e:
- if e.match(space, space.w_TypeError):
- raise OperationError(space.w_TypeError,
- space.wrap("func_name must be set "
- "to a string object"))
- raise
+ else:
+ raise OperationError(space.w_TypeError,
+ space.wrap("__name__ must be set to a string object"))
def fdel_func_doc(self, space):
self.w_doc = space.w_None
diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -107,6 +107,12 @@
__name__ = "bar"
assert f.__module__ == "foo"''' in {}
+ def test_set_name(self):
+ def f(): pass
+ f.__name__ = 'g'
+ assert f.func_name == 'g'
+ raises(TypeError, "f.__name__ = u'g'")
+
class AppTestFunction:
def test_simple_call(self):
diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py
--- a/pypy/module/_collections/app_defaultdict.py
+++ b/pypy/module/_collections/app_defaultdict.py
@@ -11,6 +11,7 @@
class defaultdict(dict):
+ __slots__ = ['default_factory']
def __init__(self, *args, **kwds):
if len(args) > 0:
@@ -20,7 +21,7 @@
raise TypeError("first argument must be callable")
else:
default_factory = None
- self.default_factory = default_factory
+ defaultdict.default_factory.__set__(self, default_factory)
super(defaultdict, self).__init__(*args, **kwds)
def __missing__(self, key):
@@ -33,15 +34,15 @@
return "defaultdict(...)"
try:
recurse.add(id(self))
- return "defaultdict(%s, %s)" % (repr(self.default_factory), super(defaultdict, self).__repr__())
+ return "defaultdict(%s, %s)" % (self.default_factory,
+ super(defaultdict, self).__repr__())
finally:
recurse.remove(id(self))
def copy(self):
return type(self)(self.default_factory, self)
- def __copy__(self):
- return self.copy()
+ __copy__ = copy
def __reduce__(self):
"""
@@ -55,4 +56,5 @@
This API is used by pickle.py and copy.py.
"""
- return (type(self), (self.default_factory,), None, None, self.iteritems())
+ return (type(self), (self.default_factory,), None, None,
+ defaultdict.iteritems(self))
diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py
--- a/pypy/module/_collections/test/test_defaultdict.py
+++ b/pypy/module/_collections/test/test_defaultdict.py
@@ -54,3 +54,25 @@
assert len(d2) == 1
assert d2[2] == 3
assert d2[3] == 42
+
+ def test_no_dict(self):
+ import _collections
+ assert not hasattr(_collections.defaultdict(), '__dict__')
+
+ def test_no_setattr(self):
+ import _collections
+ class D(_collections.defaultdict):
+ def __setattr__(self, attr, name):
+ raise AssertionError
+ d = D(int)
+ assert d['5'] == 0
+ d['6'] += 3
+ assert d['6'] == 3
+
+ def test_default_factory(self):
+ import _collections
+ f = lambda: 42
+ d = _collections.defaultdict(f)
+ assert d.default_factory is f
+ d.default_factory = lambda: 43
+ assert d['5'] == 43
diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -91,39 +91,39 @@
@cpython_api([PyObject], lltype.Void)
def PyDict_Clear(space, w_obj):
"""Empty an existing dictionary of all key-value pairs."""
- space.call_method(w_obj, "clear")
+ space.call_method(space.w_dict, "clear", w_obj)
@cpython_api([PyObject], PyObject)
def PyDict_Copy(space, w_obj):
"""Return a new dictionary that contains the same key-value pairs as p.
"""
- return space.call_method(w_obj, "copy")
+ return space.call_method(space.w_dict, "copy", w_obj)
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
def PyDict_Update(space, w_obj, w_other):
"""This is the same as PyDict_Merge(a, b, 1) in C, or a.update(b) in
Python. Return 0 on success or -1 if an exception was raised.
"""
- space.call_method(w_obj, "update", w_other)
+ space.call_method(space.w_dict, "update", w_obj, w_other)
return 0
@cpython_api([PyObject], PyObject)
def PyDict_Keys(space, w_obj):
"""Return a PyListObject containing all the keys from the dictionary,
as in the dictionary method dict.keys()."""
- return space.call_method(w_obj, "keys")
+ return space.call_method(space.w_dict, "keys", w_obj)
@cpython_api([PyObject], PyObject)
def PyDict_Values(space, w_obj):
"""Return a PyListObject containing all the values from the
dictionary p, as in the dictionary method dict.values()."""
- return space.call_method(w_obj, "values")
+ return space.call_method(space.w_dict, "values", w_obj)
@cpython_api([PyObject], PyObject)
def PyDict_Items(space, w_obj):
"""Return a PyListObject containing all the items from the
dictionary, as in the dictionary method dict.items()."""
- return space.call_method(w_obj, "items")
+ return space.call_method(space.w_dict, "items", w_obj)
@cpython_api([PyObject, Py_ssize_tP, PyObjectP, PyObjectP], rffi.INT_real, error=CANNOT_FAIL)
def PyDict_Next(space, w_dict, ppos, pkey, pvalue):
@@ -175,7 +175,7 @@
# not complete.
try:
- w_iter = space.call_method(w_dict, "iteritems")
+ w_iter = space.call_method(space.w_dict, "iteritems", w_dict)
pos = ppos[0]
while pos:
space.call_method(w_iter, "next")
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -65,7 +65,7 @@
"""Insert the item item into list list in front of index index. Return
0 if successful; return -1 and set an exception if unsuccessful.
Analogous to list.insert(index, item)."""
- space.call_method(w_list, "insert", space.wrap(index), w_item)
+ space.call_method(space.w_list, "insert", w_list, space.wrap(index), w_item)
return 0
@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
@@ -98,7 +98,7 @@
failure. This is equivalent to list.sort()."""
if not isinstance(w_list, W_ListObject):
PyErr_BadInternalCall(space)
- space.call_method(w_list, "sort")
+ space.call_method(space.w_list, "sort", w_list)
return 0
@cpython_api([PyObject], rffi.INT_real, error=-1)
@@ -107,7 +107,7 @@
failure. This is the equivalent of list.reverse()."""
if not isinstance(w_list, W_ListObject):
PyErr_BadInternalCall(space)
- space.call_method(w_list, "reverse")
+ space.call_method(space.w_list, "reverse", w_list)
return 0
@cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -36,7 +36,7 @@
values of brand new frozensets before they are exposed to other code."""
if not PySet_Check(space, w_s):
PyErr_BadInternalCall(space)
- space.call_method(w_s, 'add', w_obj)
+ space.call_method(space.w_set, 'add', w_s, w_obj)
return 0
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
@@ -49,7 +49,7 @@
instance of set or its subtype."""
if not PySet_Check(space, w_s):
PyErr_BadInternalCall(space)
- space.call_method(w_s, 'discard', w_obj)
+ space.call_method(space.w_set, 'discard', w_s, w_obj)
return 0
@@ -59,12 +59,12 @@
object from the set. Return NULL on failure. Raise KeyError if the
set is empty. Raise a SystemError if set is an not an instance of
set or its subtype."""
- return space.call_method(w_set, "pop")
+ return space.call_method(space.w_set, "pop", w_set)
@cpython_api([PyObject], rffi.INT_real, error=-1)
def PySet_Clear(space, w_set):
"""Empty an existing set of all elements."""
- space.call_method(w_set, 'clear')
+ space.call_method(space.w_set, 'clear', w_set)
return 0
@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
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
@@ -30,6 +30,9 @@
for c in ['MAXDIMS', 'CLIP', 'WRAP', 'RAISE']:
interpleveldefs[c] = 'space.wrap(constants.%s)' % c
+ def startup(self, space):
+ from pypy.module.micronumpy.concrete import _setup
+ _setup()
class UMathModule(MixedModule):
appleveldefs = {}
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -34,11 +34,13 @@
@staticmethod
def from_shape(space, shape, dtype, order='C', w_instance=None, zero=True):
- from pypy.module.micronumpy import concrete
+ from pypy.module.micronumpy import concrete, descriptor, boxes
from pypy.module.micronumpy.strides import calc_strides
strides, backstrides = calc_strides(shape, dtype.base, order)
impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
backstrides, zero=zero)
+ if dtype == descriptor.get_dtype_cache(space).w_objectdtype:
+ impl.fill(space, boxes.W_ObjectBox(space.w_None))
if w_instance:
return wrap_impl(space, space.type(w_instance), w_instance, impl)
return W_NDimArray(impl)
@@ -123,7 +125,7 @@
def get_shape(self):
return self.implementation.get_shape()
- def get_dtype(self):
+ def get_dtype(self, space=None):
return self.implementation.dtype
def get_order(self):
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -607,6 +607,19 @@
# arr.storage[i] = arg[i]
return W_UnicodeBox(arr, 0, arr.dtype)
+class W_ObjectBox(W_GenericBox):
+ descr__new__, _get_dtype, descr_reduce = new_dtype_getter(NPY.OBJECT)
+
+ def __init__(self, w_obj):
+ self.w_obj = w_obj
+
+ def convert_to(self, space, dtype):
+ if dtype.is_bool():
+ return W_BoolBox(space.bool_w(self.w_obj))
+ return self # XXX
+
+ def descr__getattr__(self, space, w_key):
+ return space.getattr(self.w_obj, w_key)
W_GenericBox.typedef = TypeDef("numpy.generic",
__new__ = interp2app(W_GenericBox.descr__new__.im_func),
@@ -856,3 +869,9 @@
__new__ = interp2app(W_UnicodeBox.descr__new__unicode_box.im_func),
__len__ = interp2app(W_UnicodeBox.descr_len),
)
+
+W_ObjectBox.typedef = TypeDef("numpy.object_", W_ObjectBox.typedef,
+ __new__ = interp2app(W_ObjectBox.descr__new__.im_func),
+ __getattr__ = interp2app(W_ObjectBox.descr__getattr__),
+)
+
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -3,7 +3,7 @@
"""
import re
from pypy.interpreter import special
-from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
+from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root, ObjSpace
from pypy.interpreter.error import OperationError
from rpython.rlib.objectmodel import specialize, instantiate
from rpython.rlib.nonconst import NonConstant
@@ -47,7 +47,7 @@
def lookup(self, name):
return self.getdictvalue(self, name)
-class FakeSpace(object):
+class FakeSpace(ObjSpace):
w_ValueError = W_TypeObject("ValueError")
w_TypeError = W_TypeObject("TypeError")
w_IndexError = W_TypeObject("IndexError")
@@ -67,6 +67,7 @@
w_unicode = W_TypeObject("unicode")
w_complex = W_TypeObject("complex")
w_dict = W_TypeObject("dict")
+ w_object = W_TypeObject("object")
def __init__(self):
"""NOT_RPYTHON"""
@@ -88,7 +89,8 @@
return self.wrap(len(w_obj.items))
def getattr(self, w_obj, w_attr):
- return StringObject(NonConstant('foo'))
+ assert isinstance(w_attr, StringObject)
+ return w_obj.getdictvalue(self, w_attr.v)
def isinstance_w(self, w_obj, w_tp):
try:
diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -1,11 +1,11 @@
from pypy.interpreter.error import OperationError, oefmt
-from rpython.rlib import jit
+from rpython.rlib import jit, rgc
from rpython.rlib.buffer import Buffer
-from rpython.rlib.debug import make_sure_not_resized
+from rpython.rlib.debug import make_sure_not_resized, debug_print
from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage, \
raw_storage_getitem, raw_storage_setitem, RAW_STORAGE
-from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.micronumpy import support, loop
+from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
+from pypy.module.micronumpy import support, loop, constants as NPY
from pypy.module.micronumpy.base import convert_to_array, W_NDimArray, \
ArrayArgumentException
from pypy.module.micronumpy.iterators import ArrayIter
@@ -13,11 +13,13 @@
RecordChunk, calc_strides, calc_new_strides, shape_agreement,
calculate_broadcast_strides, calc_backstrides)
from rpython.rlib.objectmodel import keepalive_until_here
+from rpython.rtyper.annlowlevel import cast_gcref_to_instance
+from pypy.interpreter.baseobjspace import W_Root
class BaseConcreteArray(object):
_immutable_fields_ = ['dtype?', 'storage', 'start', 'size', 'shape[*]',
- 'strides[*]', 'backstrides[*]', 'order']
+ 'strides[*]', 'backstrides[*]', 'order', 'gcstruct']
start = 0
parent = None
flags = 0
@@ -326,13 +328,54 @@
return ArrayBuffer(self, readonly)
def astype(self, space, dtype):
- strides, backstrides = calc_strides(self.get_shape(), dtype,
- self.order)
+ # we want to create a new array, but must respect the strides
+ # in self. So find a factor of the itemtype.elsize, and use this
+ factor = float(dtype.elsize) / self.dtype.elsize
+ strides = [int(factor*s) for s in self.get_strides()]
+ backstrides = [int(factor*s) for s in self.get_backstrides()]
impl = ConcreteArray(self.get_shape(), dtype, self.order,
strides, backstrides)
loop.setslice(space, impl.get_shape(), impl, self)
return impl
+OBJECTSTORE = lltype.GcStruct('ObjectStore',
+ ('length', lltype.Signed),
+ ('step', lltype.Signed),
+ ('storage', llmemory.Address),
+ rtti=True)
+offset_of_storage = llmemory.offsetof(OBJECTSTORE, 'storage')
+offset_of_length = llmemory.offsetof(OBJECTSTORE, 'length')
+offset_of_step = llmemory.offsetof(OBJECTSTORE, 'step')
+
+V_OBJECTSTORE = lltype.nullptr(OBJECTSTORE)
+
+def customtrace(gc, obj, callback, arg):
+ #debug_print('in customtrace w/obj', obj)
+ length = (obj + offset_of_length).signed[0]
+ step = (obj + offset_of_step).signed[0]
+ storage = (obj + offset_of_storage).address[0]
+ #debug_print('tracing', length, 'objects in ndarray.storage')
+ i = 0
+ while i < length:
+ gc._trace_callback(callback, arg, storage)
+ storage += step
+ i += 1
+
+lambda_customtrace = lambda: customtrace
+
+def _setup():
+ rgc.register_custom_trace_hook(OBJECTSTORE, lambda_customtrace)
+
+ at jit.dont_look_inside
+def _create_objectstore(storage, length, elsize):
+ gcstruct = lltype.malloc(OBJECTSTORE)
+ # JIT does not support cast_ptr_to_adr
+ gcstruct.storage = llmemory.cast_ptr_to_adr(storage)
+ #print 'create gcstruct',gcstruct,'with storage',storage,'as',gcstruct.storage
+ gcstruct.length = length
+ gcstruct.step = elsize
+ return gcstruct
+
class ConcreteArrayNotOwning(BaseConcreteArray):
def __init__(self, shape, dtype, order, strides, backstrides, storage, start=0):
@@ -347,10 +390,11 @@
self.backstrides = backstrides
self.storage = storage
self.start = start
+ self.gcstruct = V_OBJECTSTORE
def fill(self, space, box):
self.dtype.itemtype.fill(self.storage, self.dtype.elsize,
- box, 0, self.size, 0)
+ box, 0, self.size, 0, self.gcstruct)
def set_shape(self, space, orig_array, new_shape):
strides, backstrides = calc_strides(new_shape, self.dtype,
@@ -374,17 +418,24 @@
def base(self):
return None
-
class ConcreteArray(ConcreteArrayNotOwning):
def __init__(self, shape, dtype, order, strides, backstrides,
storage=lltype.nullptr(RAW_STORAGE), zero=True):
+ gcstruct = V_OBJECTSTORE
if storage == lltype.nullptr(RAW_STORAGE):
- storage = dtype.itemtype.malloc(support.product(shape) *
- dtype.elsize, zero=zero)
+ length = support.product(shape)
+ if dtype.num == NPY.OBJECT:
+ storage = dtype.itemtype.malloc(length * dtype.elsize, zero=True)
+ gcstruct = _create_objectstore(storage, length, dtype.elsize)
+ else:
+ storage = dtype.itemtype.malloc(length * dtype.elsize, zero=zero)
ConcreteArrayNotOwning.__init__(self, shape, dtype, order, strides, backstrides,
storage)
+ self.gcstruct = gcstruct
def __del__(self):
+ if self.gcstruct:
+ self.gcstruct.length = 0
free_raw_storage(self.storage, track_allocation=False)
@@ -423,6 +474,7 @@
parent = parent.parent # one level only
self.parent = parent
self.storage = parent.storage
+ self.gcstruct = parent.gcstruct
self.order = parent.order
self.dtype = dtype
self.size = support.product(shape) * self.dtype.elsize
@@ -480,6 +532,7 @@
class VoidBoxStorage(BaseConcreteArray):
def __init__(self, size, dtype):
self.storage = alloc_raw_storage(size)
+ self.gcstruct = V_OBJECTSTORE
self.dtype = dtype
self.size = size
diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py
--- a/pypy/module/micronumpy/ctors.py
+++ b/pypy/module/micronumpy/ctors.py
@@ -38,6 +38,34 @@
raise oefmt(space.w_ValueError,
"object __array__ method not producing an array")
+def try_interface_method(space, w_object):
+ try:
+ w_interface = space.getattr(w_object, space.wrap("__array_interface__"))
+ except OperationError, e:
+ if e.match(space, space.w_AttributeError):
+ return None
+ raise
+ if w_interface is None:
+ # happens from compile.py
+ return None
+ version = space.int_w(space.finditem(w_interface, space.wrap("version")))
+ if version < 3:
+ raise oefmt(space.w_NotImplementedError,
+ "__array_interface__ version %d not supported", version)
+ # make a view into the data
+ w_shape = space.finditem(w_interface, space.wrap('shape'))
+ w_dtype = space.finditem(w_interface, space.wrap('typestr'))
+ w_descr = space.finditem(w_interface, space.wrap('descr'))
+ data_w = space.listview(space.finditem(w_interface, space.wrap('data')))
+ w_strides = space.finditem(w_interface, space.wrap('strides'))
+ shape = [space.int_w(i) for i in space.listview(w_shape)]
+ dtype = descriptor.decode_w_dtype(space, w_dtype)
+ rw = space.is_true(data_w[1])
+ #print 'create view from shape',shape,'dtype',dtype,'descr',w_descr,'data',data_w[0],'rw',rw
+ raise oefmt(space.w_NotImplementedError,
+ "creating array from __array_interface__ not supported yet")
+ return
+
@unwrap_spec(ndmin=int, copy=bool, subok=bool)
def array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False,
@@ -63,7 +91,11 @@
# continue with w_array, but do further operations in place
w_object = w_array
copy = False
-
+ if not isinstance(w_object, W_NDimArray):
+ w_array = try_interface_method(space, w_object)
+ if w_array is not None:
+ w_object = w_array
+ copy = False
dtype = descriptor.decode_w_dtype(space, w_dtype)
if space.is_none(w_order):
diff --git a/pypy/module/micronumpy/descriptor.py b/pypy/module/micronumpy/descriptor.py
--- a/pypy/module/micronumpy/descriptor.py
+++ b/pypy/module/micronumpy/descriptor.py
@@ -6,7 +6,7 @@
from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
interp_attrproperty, interp_attrproperty_w)
from rpython.rlib import jit
-from rpython.rlib.objectmodel import specialize, compute_hash
+from rpython.rlib.objectmodel import specialize, compute_hash, we_are_translated
from rpython.rlib.rarithmetic import r_longlong, r_ulonglong
from pypy.module.micronumpy import types, boxes, base, support, constants as NPY
from pypy.module.micronumpy.appbridge import get_appbridge_cache
@@ -56,7 +56,7 @@
self.char = char
self.w_box_type = w_box_type
if byteorder is None:
- if itemtype.get_element_size() == 1:
+ if itemtype.get_element_size() == 1 or isinstance(itemtype, types.ObjectType):
byteorder = NPY.IGNORE
else:
byteorder = NPY.NATIVE
@@ -112,6 +112,9 @@
def is_str(self):
return self.num == NPY.STRING
+ def is_object(self):
+ return self.num == NPY.OBJECT
+
def is_str_or_unicode(self):
return self.num == NPY.STRING or self.num == NPY.UNICODE
@@ -428,7 +431,7 @@
self.names.append(name)
self.fields[name] = offset, dtype
- self.itemtype = types.RecordType()
+ self.itemtype = types.RecordType(space)
if self.is_flexible():
self.elsize = size
@@ -443,7 +446,7 @@
endian = NPY.OPPBYTE if self.is_native() else NPY.NATBYTE
elif newendian != NPY.IGNORE:
endian = newendian
- itemtype = self.itemtype.__class__(endian in (NPY.NATIVE, NPY.NATBYTE))
+ itemtype = self.itemtype.__class__(space, endian in (NPY.NATIVE, NPY.NATBYTE))
fields = self.fields
if fields is None:
fields = {}
@@ -482,7 +485,7 @@
fields[fldname] = (offset, subdtype)
offset += subdtype.elsize
names.append(fldname)
- return W_Dtype(types.RecordType(), NPY.VOID, NPY.VOIDLTR, NPY.VOIDLTR,
+ return W_Dtype(types.RecordType(space), NPY.VOID, NPY.VOIDLTR, NPY.VOIDLTR,
space.gettypefor(boxes.W_VoidBox),
names=names, fields=fields, elsize=offset)
@@ -493,8 +496,17 @@
def dtype_from_spec(space, w_spec):
- w_lst = get_appbridge_cache(space).call_method(space,
- 'numpy.core._internal', '_commastring', Arguments(space, [w_spec]))
+
+ if we_are_translated():
+ w_lst = get_appbridge_cache(space).call_method(space,
+ 'numpy.core._internal', '_commastring', Arguments(space, [w_spec]))
+ else:
+ # testing, handle manually
+ if space.eq_w(w_spec, space.wrap('u4,u4,u4')):
+ w_lst = space.newlist([space.wrap('u4')]*3)
+ else:
+ raise oefmt(space.w_RuntimeError,
+ "cannot parse w_spec")
if not space.isinstance_w(w_lst, space.w_list) or space.len_w(w_lst) < 1:
raise oefmt(space.w_RuntimeError,
"_commastring is not returning a list with len >= 1")
@@ -541,15 +553,17 @@
if size == 1:
return subdtype
size *= subdtype.elsize
- return W_Dtype(types.VoidType(), NPY.VOID, NPY.VOIDLTR, NPY.VOIDLTR,
+ return W_Dtype(types.VoidType(space), NPY.VOID, NPY.VOIDLTR, NPY.VOIDLTR,
space.gettypefor(boxes.W_VoidBox),
shape=shape, subdtype=subdtype, elsize=size)
if space.is_none(w_dtype):
return cache.w_float64dtype
- elif space.isinstance_w(w_dtype, w_subtype):
+ if space.isinstance_w(w_dtype, w_subtype):
return w_dtype
- elif space.isinstance_w(w_dtype, space.w_str):
+ if space.isinstance_w(w_dtype, space.w_unicode):
+ w_dtype = space.wrap(space.str_w(w_dtype)) # may raise if invalid
+ if space.isinstance_w(w_dtype, space.w_str):
name = space.str_w(w_dtype)
if _check_for_commastring(name):
return dtype_from_spec(space, w_dtype)
@@ -585,8 +599,7 @@
if w_dtype is dtype.w_box_type:
return dtype
if space.isinstance_w(w_dtype, space.w_type):
- raise oefmt(space.w_NotImplementedError,
- "cannot create dtype with type '%N'", w_dtype)
+ return cache.w_objectdtype
raise oefmt(space.w_TypeError, "data type not understood")
@@ -653,7 +666,7 @@
def new_string_dtype(space, size, char=NPY.STRINGLTR):
return W_Dtype(
- types.StringType(),
+ types.StringType(space),
elsize=size,
num=NPY.STRING,
kind=NPY.STRINGLTR,
@@ -663,7 +676,7 @@
def new_unicode_dtype(space, size):
- itemtype = types.UnicodeType()
+ itemtype = types.UnicodeType(space)
return W_Dtype(
itemtype,
elsize=size * itemtype.get_element_size(),
@@ -676,7 +689,7 @@
def new_void_dtype(space, size):
return W_Dtype(
- types.VoidType(),
+ types.VoidType(space),
elsize=size,
num=NPY.VOID,
kind=NPY.VOIDLTR,
@@ -688,126 +701,126 @@
class DtypeCache(object):
def __init__(self, space):
self.w_booldtype = W_Dtype(
- types.Bool(),
+ types.Bool(space),
num=NPY.BOOL,
kind=NPY.GENBOOLLTR,
char=NPY.BOOLLTR,
w_box_type=space.gettypefor(boxes.W_BoolBox),
)
self.w_int8dtype = W_Dtype(
- types.Int8(),
+ types.Int8(space),
num=NPY.BYTE,
kind=NPY.SIGNEDLTR,
char=NPY.BYTELTR,
w_box_type=space.gettypefor(boxes.W_Int8Box),
)
self.w_uint8dtype = W_Dtype(
- types.UInt8(),
+ types.UInt8(space),
num=NPY.UBYTE,
kind=NPY.UNSIGNEDLTR,
char=NPY.UBYTELTR,
w_box_type=space.gettypefor(boxes.W_UInt8Box),
)
self.w_int16dtype = W_Dtype(
- types.Int16(),
+ types.Int16(space),
num=NPY.SHORT,
kind=NPY.SIGNEDLTR,
char=NPY.SHORTLTR,
w_box_type=space.gettypefor(boxes.W_Int16Box),
)
self.w_uint16dtype = W_Dtype(
- types.UInt16(),
+ types.UInt16(space),
num=NPY.USHORT,
kind=NPY.UNSIGNEDLTR,
char=NPY.USHORTLTR,
w_box_type=space.gettypefor(boxes.W_UInt16Box),
)
self.w_int32dtype = W_Dtype(
- types.Int32(),
+ types.Int32(space),
num=NPY.INT,
kind=NPY.SIGNEDLTR,
char=NPY.INTLTR,
w_box_type=space.gettypefor(boxes.W_Int32Box),
)
self.w_uint32dtype = W_Dtype(
- types.UInt32(),
+ types.UInt32(space),
num=NPY.UINT,
kind=NPY.UNSIGNEDLTR,
char=NPY.UINTLTR,
w_box_type=space.gettypefor(boxes.W_UInt32Box),
)
self.w_longdtype = W_Dtype(
- types.Long(),
+ types.Long(space),
num=NPY.LONG,
kind=NPY.SIGNEDLTR,
char=NPY.LONGLTR,
w_box_type=space.gettypefor(boxes.W_LongBox),
)
self.w_ulongdtype = W_Dtype(
- types.ULong(),
+ types.ULong(space),
num=NPY.ULONG,
kind=NPY.UNSIGNEDLTR,
char=NPY.ULONGLTR,
w_box_type=space.gettypefor(boxes.W_ULongBox),
)
self.w_int64dtype = W_Dtype(
- types.Int64(),
+ types.Int64(space),
num=NPY.LONGLONG,
kind=NPY.SIGNEDLTR,
char=NPY.LONGLONGLTR,
w_box_type=space.gettypefor(boxes.W_Int64Box),
)
self.w_uint64dtype = W_Dtype(
- types.UInt64(),
+ types.UInt64(space),
num=NPY.ULONGLONG,
kind=NPY.UNSIGNEDLTR,
char=NPY.ULONGLONGLTR,
w_box_type=space.gettypefor(boxes.W_UInt64Box),
)
self.w_float32dtype = W_Dtype(
- types.Float32(),
+ types.Float32(space),
num=NPY.FLOAT,
kind=NPY.FLOATINGLTR,
char=NPY.FLOATLTR,
w_box_type=space.gettypefor(boxes.W_Float32Box),
)
self.w_float64dtype = W_Dtype(
- types.Float64(),
+ types.Float64(space),
num=NPY.DOUBLE,
kind=NPY.FLOATINGLTR,
char=NPY.DOUBLELTR,
w_box_type=space.gettypefor(boxes.W_Float64Box),
)
self.w_floatlongdtype = W_Dtype(
- types.FloatLong(),
+ types.FloatLong(space),
num=NPY.LONGDOUBLE,
kind=NPY.FLOATINGLTR,
char=NPY.LONGDOUBLELTR,
w_box_type=space.gettypefor(boxes.W_FloatLongBox),
)
self.w_complex64dtype = W_Dtype(
- types.Complex64(),
+ types.Complex64(space),
num=NPY.CFLOAT,
kind=NPY.COMPLEXLTR,
char=NPY.CFLOATLTR,
w_box_type=space.gettypefor(boxes.W_Complex64Box),
)
self.w_complex128dtype = W_Dtype(
- types.Complex128(),
+ types.Complex128(space),
num=NPY.CDOUBLE,
kind=NPY.COMPLEXLTR,
char=NPY.CDOUBLELTR,
w_box_type=space.gettypefor(boxes.W_Complex128Box),
)
self.w_complexlongdtype = W_Dtype(
- types.ComplexLong(),
+ types.ComplexLong(space),
num=NPY.CLONGDOUBLE,
kind=NPY.COMPLEXLTR,
char=NPY.CLONGDOUBLELTR,
w_box_type=space.gettypefor(boxes.W_ComplexLongBox),
)
self.w_stringdtype = W_Dtype(
- types.StringType(),
+ types.StringType(space),
elsize=0,
num=NPY.STRING,
kind=NPY.STRINGLTR,
@@ -815,7 +828,7 @@
w_box_type=space.gettypefor(boxes.W_StringBox),
)
self.w_unicodedtype = W_Dtype(
- types.UnicodeType(),
+ types.UnicodeType(space),
elsize=0,
num=NPY.UNICODE,
kind=NPY.UNICODELTR,
@@ -823,7 +836,7 @@
w_box_type=space.gettypefor(boxes.W_UnicodeBox),
)
self.w_voiddtype = W_Dtype(
- types.VoidType(),
+ types.VoidType(space),
elsize=0,
num=NPY.VOID,
kind=NPY.VOIDLTR,
@@ -831,26 +844,33 @@
w_box_type=space.gettypefor(boxes.W_VoidBox),
)
self.w_float16dtype = W_Dtype(
- types.Float16(),
+ types.Float16(space),
num=NPY.HALF,
kind=NPY.FLOATINGLTR,
char=NPY.HALFLTR,
w_box_type=space.gettypefor(boxes.W_Float16Box),
)
self.w_intpdtype = W_Dtype(
- types.Long(),
+ types.Long(space),
num=NPY.LONG,
kind=NPY.SIGNEDLTR,
char=NPY.INTPLTR,
w_box_type=space.gettypefor(boxes.W_LongBox),
)
self.w_uintpdtype = W_Dtype(
- types.ULong(),
+ types.ULong(space),
num=NPY.ULONG,
kind=NPY.UNSIGNEDLTR,
char=NPY.UINTPLTR,
w_box_type=space.gettypefor(boxes.W_ULongBox),
)
+ self.w_objectdtype = W_Dtype(
+ types.ObjectType(space),
+ num=NPY.OBJECT,
+ kind=NPY.OBJECTLTR,
+ char=NPY.OBJECTLTR,
+ w_box_type=space.gettypefor(boxes.W_ObjectBox),
+ )
aliases = {
NPY.BOOL: ['bool_', 'bool8'],
NPY.BYTE: ['byte'],
@@ -869,6 +889,7 @@
NPY.CLONGDOUBLE: ['clongdouble', 'clongfloat'],
NPY.STRING: ['string_', 'str'],
NPY.UNICODE: ['unicode_'],
+ NPY.OBJECT: ['object_'],
}
self.alternate_constructors = {
NPY.BOOL: [space.w_bool],
@@ -887,6 +908,8 @@
NPY.UNICODE: [space.w_unicode],
NPY.VOID: [space.gettypefor(boxes.W_GenericBox)],
#space.w_buffer, # XXX no buffer in space
+ NPY.OBJECT: [space.gettypefor(boxes.W_ObjectBox),
+ space.w_object],
}
float_dtypes = [self.w_float16dtype, self.w_float32dtype,
self.w_float64dtype, self.w_floatlongdtype]
@@ -906,7 +929,7 @@
self.w_int64dtype, self.w_uint64dtype,
] + float_dtypes + complex_dtypes + [
self.w_stringdtype, self.w_unicodedtype, self.w_voiddtype,
- self.w_intpdtype, self.w_uintpdtype,
+ self.w_intpdtype, self.w_uintpdtype, self.w_objectdtype,
]
self.float_dtypes_by_num_bytes = sorted(
(dtype.elsize, dtype)
@@ -958,6 +981,7 @@
'USHORT': self.w_uint16dtype,
'FLOAT': self.w_float32dtype,
'BOOL': self.w_booldtype,
+ 'OBJECT': self.w_objectdtype,
}
typeinfo_partial = {
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -202,11 +202,16 @@
return self
elif isinstance(w_idx, W_NDimArray) and w_idx.get_dtype().is_bool() \
and w_idx.ndims() > 0:
- return self.getitem_filter(space, w_idx)
- try:
- return self.implementation.descr_getitem(space, self, w_idx)
- except ArrayArgumentException:
- return self.getitem_array_int(space, w_idx)
+ w_ret = self.getitem_filter(space, w_idx)
+ else:
+ try:
+ w_ret = self.implementation.descr_getitem(space, self, w_idx)
+ except ArrayArgumentException:
+ w_ret = self.getitem_array_int(space, w_idx)
+ if isinstance(w_ret, boxes.W_ObjectBox):
+ #return the W_Root object, not a scalar
+ w_ret = w_ret.w_obj
+ return w_ret
def getitem(self, space, index_list):
return self.implementation.getitem_index(space, index_list)
@@ -550,6 +555,7 @@
else:
strides = self.descr_get_strides(space)
space.setitem_str(w_d, 'strides', strides)
+ space.setitem_str(w_d, 'version', space.wrap(3))
return w_d
w_pypy_data = None
@@ -845,7 +851,7 @@
"new type not compatible with array."))
# Strides, shape does not change
v = impl.astype(space, dtype)
- return wrap_impl(space, w_type, self, v)
+ return wrap_impl(space, w_type, self, v)
strides = impl.get_strides()
if dims == 1 or strides[0] <strides[-1]:
# Column-major, resize first dimension
@@ -1205,7 +1211,7 @@
"improper dtype '%R'", dtype)
self.implementation = W_NDimArray.from_shape_and_storage(
space, [space.int_w(i) for i in space.listview(shape)],
- rffi.str2charp(space.str_w(storage), track_allocation=False),
+ rffi.str2charp(space.str_w(storage), track_allocation=False),
dtype, storage_bytes=space.len_w(storage), owning=True).implementation
def descr___array_finalize__(self, space, w_obj):
diff --git a/pypy/module/micronumpy/test/dummy_module.py b/pypy/module/micronumpy/test/dummy_module.py
--- a/pypy/module/micronumpy/test/dummy_module.py
+++ b/pypy/module/micronumpy/test/dummy_module.py
@@ -20,7 +20,7 @@
for t in types:
globals()[t] = dtype(t).type
-types = ['bool', 'int', 'float', 'complex', 'str', 'string', 'unicode']
+types = ['bool', 'int', 'float', 'complex', 'str', 'string', 'unicode', 'object']
for t in types:
globals()[t + '_'] = dtype(t).type
del types
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -58,6 +58,7 @@
assert exc.value[0] == "there are no fields defined"
assert dtype('int8').num == 1
+ assert dtype(u'int8').num == 1
assert dtype('int8').name == 'int8'
assert dtype('void').name == 'void'
assert dtype(int).fields is None
@@ -472,11 +473,13 @@
class O(object):
pass
for o in [object, O]:
- if '__pypy__' not in sys.builtin_module_names:
+ print np.dtype(o).byteorder
+ if self.ptr_size == 4:
+ assert np.dtype(o).str == '|O4'
+ elif self.ptr_size == 8:
assert np.dtype(o).str == '|O8'
else:
- exc = raises(NotImplementedError, "np.dtype(o)")
- assert exc.value[0] == "cannot create dtype with type '%s'" % o.__name__
+ assert False,'self._ptr_size unknown'
class AppTestTypes(BaseAppTestDtypes):
def test_abstract_types(self):
@@ -1348,15 +1351,4 @@
assert a[0] == 1
assert (a + a)[1] == 4
-class AppTestObjectDtypes(BaseNumpyAppTest):
- def test_scalar_from_object(self):
- from numpy import array
- import sys
- class Polynomial(object):
- pass
- if '__pypy__' in sys.builtin_module_names:
- exc = raises(NotImplementedError, array, Polynomial())
- assert exc.value.message.find('unable to create dtype from objects') >= 0
- else:
- a = array(Polynomial())
- assert a.shape == ()
+
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -17,6 +17,7 @@
def __init__(self):
self.base = self
self.elsize = 1
+ self.num = 0
def create_slice(space, a, chunks):
@@ -2182,7 +2183,8 @@
assert b.dtype == 'bool'
a = arange(6, dtype='f4').reshape(2,3)
- b = a.astype('i4')
+ b = a.T.astype('i4')
+ assert (a.T.strides == b.strides)
a = array('x').astype('S3').dtype
assert a.itemsize == 3
@@ -3150,11 +3152,7 @@
assert b[35] == 200
b[[slice(25, 30)]] = range(5)
assert all(a[:5] == range(5))
- import sys
- if '__pypy__' not in sys.builtin_module_names:
- raises(TypeError, 'b[[[slice(25, 125)]]]')
- else:
- raises(NotImplementedError, 'b[[[slice(25, 125)]]]')
+ raises(IndexError, 'b[[[slice(25, 125)]]]')
def test_cumsum(self):
from numpy import arange
diff --git a/pypy/module/micronumpy/test/test_object_arrays.py b/pypy/module/micronumpy/test/test_object_arrays.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_object_arrays.py
@@ -0,0 +1,162 @@
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestObjectDtypes(BaseNumpyAppTest):
+ def test_scalar_from_object(self):
+ from numpy import array
+ import sys
+ class Polynomial(object):
+ def whatami(self):
+ return 'an object'
+ a = array(Polynomial())
+ assert a.shape == ()
+ assert a.sum().whatami() == 'an object'
+
+ def test_uninitialized_object_array_is_filled_by_None(self):
+ import numpy as np
+
+ a = np.ndarray([5], dtype="O")
+
+ assert a[0] == None
+
+ def test_object_arrays_add(self):
+ import numpy as np
+
+ a = np.array(["foo"], dtype=object)
+ b = np.array(["bar"], dtype=object)
+ raises(TypeError, np.add, a, 1)
+ res = a + b
+ assert res[0] == "foobar"
+
+ def test_bool_func(self):
+ import numpy as np
+ a = np.array(["foo"], dtype=object)
+ b = a and complex(1, -1)
+ assert b == complex(1, -1)
+ b = np.array(complex(1, -1)) and a
+ assert (b == a).all()
+ c = np.array([1, 2, 3])
+ assert (a[0] != c[0])
+ assert (c[0] != a[0])
+ assert (a[0] > c[0])
+ assert (not a[0] < c[0])
+ assert (c[0] < a[0])
+ assert (not c[0] > a[0])
+
+ def test_logical_ufunc(self):
+ import numpy as np
+ import sys
+
+ if '__pypy__' in sys.builtin_module_names:
+ skip('need to refactor use of raw_xxx_op in types to make this work')
+ a = np.array(["foo"], dtype=object)
+ b = np.array([1], dtype=object)
+ d = np.array([complex(1, 10)], dtype=object)
+ c = np.logical_and(a, 1)
+ assert c.dtype == np.dtype('object')
+ assert c == 1
+ c = np.logical_and(b, complex(1, -1))
+ assert c.dtype == np.dtype('object')
+ assert c == complex(1, -1)
+ c = np.logical_and(d, b)
+ assert c == 1
+ c = b & 1
+ assert c.dtype == np.dtype('object')
+ assert (c == 1).all()
+ c = np.array(1) & b
+ assert (c == b).all()
+
+ def test_reduce(self):
+ import numpy as np
+ class O(object):
+ def whatami(self):
+ return 'an object'
+ fiveOs = [O()] * 5
+ a = np.array(fiveOs, dtype=object)
+ print np.maximum
+ b = np.maximum.reduce(a)
+ assert b is not None
+
+ def test_complex_op(self):
+ import numpy as np
+ import sys
+ a = np.array(['abc', 'def'], dtype=object)
+ b = np.array([1, 2, 3], dtype=object)
+ c = np.array([complex(1, 1), complex(1, -1)], dtype=object)
+ for arg in (a,b,c):
+ assert (arg == np.real(arg)).all()
+ assert (0 == np.imag(arg)).all()
+ if '__pypy__' in sys.builtin_module_names:
+ skip('not implemented yet')
+ raises(AttributeError, np.conj, a)
+ res = np.conj(b)
+ assert (res == b).all()
+ res = np.conj(c)
+ assert res[0] == c[1] and res[1] == c[0]
+
+ def test_keep_object_alive(self):
+ # only translated does it really test the gc
+ import numpy as np
+ import gc
+ class O(object):
+ def whatami(self):
+ return 'an object'
+ fiveOs = [O()] * 5
+ a = np.array(fiveOs, dtype=object)
+ del fiveOs
+ gc.collect()
+ assert a[2].whatami() == 'an object'
+
+ def test_array_interface(self):
+ import numpy as np
+ import sys
+ class DummyArray(object):
+ def __init__(self, interface, base=None):
+ self.__array_interface__ = interface
+ self.base = base
+ a = np.array([(1, 2, 3)], dtype='u4,u4,u4')
+ b = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype='u4,u4,u4')
+ interface = dict(a.__array_interface__)
+ interface['shape'] = tuple([3])
+ interface['strides'] = tuple([0])
+ if '__pypy__' in sys.builtin_module_names:
+ skip('not implemented yet')
+ c = np.array(DummyArray(interface, base=a))
+ c.dtype = a.dtype
+ #print c
+ assert (c == np.array([(1, 2, 3), (1, 2, 3), (1, 2, 3)], dtype='u4,u4,u4') ).all()
+
+ def test_for_object_scalar_creation(self):
+ import numpy as np
+ import sys
+ a = np.object_()
+ b = np.object_(3)
+ b2 = np.object_(3.0)
+ c = np.object_([4, 5])
+ d = np.array([None])[0]
+ assert a is None
+ assert type(b) is int
+ assert type(b2) is float
+ assert type(c) is np.ndarray
+ assert c.dtype == object
+ assert type(d) is type(None)
+ if '__pypy__' in sys.builtin_module_names:
+ skip('not implemented yet')
+ e = np.object_([None, {}, []])
+ assert e.dtype == object
+
+ def test_mem_array_creation_invalid_specification(self):
+ # while not specifically testing object dtype, this
+ # test segfaulted during ObjectType.store due to
+ # missing gc hooks
+ import numpy as np
+ import sys
+ ytype = np.object_
+ if '__pypy__' in sys.builtin_module_names:
+ ytype = str
+ dt = np.dtype([('x', int), ('y', ytype)])
+ # Correct way
+ a = np.array([(1, 'object')], dt)
+ # Wrong way - should complain about writing buffer to object dtype
+ raises(ValueError, np.array, [1, 'object'], dt)
+
diff --git a/pypy/module/micronumpy/test/test_selection.py b/pypy/module/micronumpy/test/test_selection.py
--- a/pypy/module/micronumpy/test/test_selection.py
+++ b/pypy/module/micronumpy/test/test_selection.py
@@ -12,14 +12,11 @@
exp = sorted(range(len(exp)), key=exp.__getitem__)
c = a.copy()
res = a.argsort()
- assert (res == exp).all(), '%r\n%r\n%r' % (a,res,exp)
+ assert (res == exp).all(), 'Failed sortng %r\na=%r\nres=%r\nexp=%r' % (dtype,a,res,exp)
assert (a == c).all() # not modified
a = arange(100, dtype=dtype)
assert (a.argsort() == a).all()
- import sys
- if '__pypy__' in sys.builtin_module_names:
- raises(NotImplementedError, 'arange(10,dtype="float16").argsort()')
def test_argsort_ndim(self):
from numpy import array
@@ -63,14 +60,13 @@
'i2', complex]:
a = array([6, 4, -1, 3, 8, 3, 256+20, 100, 101], dtype=dtype)
exp = sorted(list(a))
- res = a.copy()
- res.sort()
- assert (res == exp).all(), '%r\n%r\n%r' % (a,res,exp)
+ a.sort()
+ assert (a == exp).all(), 'Failed sorting %r\n%r\n%r' % (dtype, a, exp)
a = arange(100, dtype=dtype)
c = a.copy()
a.sort()
- assert (a == c).all()
+ assert (a == c).all(), 'Failed sortng %r\na=%r\nc=%r' % (dtype,a,c)
def test_sort_nonnative(self):
from numpy import array
@@ -222,6 +218,7 @@
def test_sort_objects(self):
# test object array sorts.
+ skip('object type not supported yet')
from numpy import empty
try:
a = empty((101,), dtype=object)
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
@@ -397,11 +397,11 @@
for i in range(3):
assert min_c_b[i] == min(b[i], c)
- def test_scalar(self):
+ def test_all_available(self):
# tests that by calling all available ufuncs on scalars, none will
# raise uncaught interp-level exceptions, (and crash the test)
# and those that are uncallable can be accounted for.
- # test on the four base-class dtypes: int, bool, float, complex
+ # test on the base-class dtypes: int, bool, float, complex, object
# We need this test since they have no common base class.
import numpy as np
def find_uncallable_ufuncs(dtype):
@@ -412,6 +412,11 @@
if isinstance(u, np.ufunc):
try:
u(* [array] * u.nin)
+ except AttributeError:
+ pass
+ except NotImplementedError:
+ print s
+ uncallable.add(s)
except TypeError:
assert s not in uncallable
uncallable.add(s)
@@ -427,6 +432,9 @@
'fabs', 'fmod', 'invert', 'mod',
'logaddexp', 'logaddexp2', 'left_shift', 'right_shift',
'copysign', 'signbit', 'ceil', 'floor', 'trunc'])
+ assert find_uncallable_ufuncs('object') == set(
+ ['isnan', 'logaddexp2', 'copysign', 'isfinite', 'signbit',
+ 'isinf', 'logaddexp'])
def test_int_only(self):
from numpy import bitwise_and, array
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -9,6 +9,7 @@
from pypy.module.micronumpy.compile import FakeSpace, Parser, InterpreterState
from pypy.module.micronumpy.base import W_NDimArray
+py.test.skip('move these to pypyjit/test_pypy_c/test_micronumpy')
class TestNumpyJit(LLJitMixin):
graph = None
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
@@ -3,8 +3,9 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.objspace.std.floatobject import float2string
from pypy.objspace.std.complexobject import str_format
+from pypy.interpreter.baseobjspace import W_Root, ObjSpace
from rpython.rlib import clibffi, jit, rfloat, rcomplex
-from rpython.rlib.objectmodel import specialize
+from rpython.rlib.objectmodel import specialize, we_are_translated
from rpython.rlib.rarithmetic import widen, byteswap, r_ulonglong, \
most_neg_value_of, LONG_BIT
from rpython.rlib.rawstorage import (alloc_raw_storage,
@@ -14,10 +15,12 @@
pack_float80, unpack_float80)
from rpython.rlib.rstruct.nativefmttable import native_is_bigendian
from rpython.rlib.rstruct.runpack import runpack
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.annlowlevel import cast_instance_to_gcref,\
+ cast_gcref_to_instance
+from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
from rpython.tool.sourcetools import func_with_new_name
from pypy.module.micronumpy import boxes
-from pypy.module.micronumpy.concrete import SliceArray, VoidBoxStorage
+from pypy.module.micronumpy.concrete import SliceArray, VoidBoxStorage, V_OBJECTSTORE
from pypy.module.micronumpy.strides import calc_strides
degToRad = math.pi / 180.0
@@ -109,10 +112,12 @@
return dispatcher
class BaseType(object):
- _immutable_fields_ = ['native']
+ _immutable_fields_ = ['native', 'space']
- def __init__(self, native=True):
+ def __init__(self, space, native=True):
+ assert isinstance(space, ObjSpace)
self.native = native
+ self.space = space
def __repr__(self):
return self.__class__.__name__
@@ -191,7 +196,7 @@
with arr as storage:
self._write(storage, i, offset, self.unbox(box))
- def fill(self, storage, width, box, start, stop, offset):
+ def fill(self, storage, width, box, start, stop, offset, gcstruct):
value = self.unbox(box)
for i in xrange(start, stop, width):
self._write(storage, i, offset, value)
@@ -306,7 +311,7 @@
@raw_unary_op
def rint(self, v):
- float64 = Float64()
+ float64 = Float64(self.space)
return float64.rint(float64.box(v))
class Bool(BaseType, Primitive):
@@ -399,7 +404,7 @@
def round(self, v, decimals=0):
if decimals != 0:
return v
- return Float64().box(self.unbox(v))
+ return Float64(self.space).box(self.unbox(v))
class Integer(Primitive):
_mixin_ = True
@@ -444,7 +449,7 @@
self.T is rffi.LONG or self.T is rffi.LONGLONG):
if v2 == -1 and v1 == self.for_computation(most_neg_value_of(self.T)):
return self.box(0)
- return self.box(v1 // v2)
+ return self.box(v1 / v2)
@simple_binary_op
def mod(self, v1, v2):
@@ -1152,7 +1157,7 @@
with arr as storage:
self._write(storage, i, offset, self.unbox(box))
- def fill(self, storage, width, box, start, stop, offset):
+ def fill(self, storage, width, box, start, stop, offset, gcstruct):
value = self.unbox(box)
for i in xrange(start, stop, width):
self._write(storage, i, offset, value)
@@ -1253,25 +1258,25 @@
def ge(self, v1, v2):
return self._lt(v2, v1) or self._eq(v2, v1)
- def _bool(self, v):
+ def _cbool(self, v):
return bool(v[0]) or bool(v[1])
@raw_binary_op
def logical_and(self, v1, v2):
- return self._bool(v1) and self._bool(v2)
+ return self._cbool(v1) and self._cbool(v2)
@raw_binary_op
def logical_or(self, v1, v2):
- return self._bool(v1) or self._bool(v2)
+ return self._cbool(v1) or self._cbool(v2)
@raw_unary_op
def logical_not(self, v):
- return not self._bool(v)
+ return not self._cbool(v)
@raw_binary_op
def logical_xor(self, v1, v2):
- a = self._bool(v1)
- b = self._bool(v2)
+ a = self._cbool(v1)
+ b = self._cbool(v2)
return (not b and a) or (not a and b)
def min(self, v1, v2):
@@ -1629,6 +1634,283 @@
BoxType = boxes.W_ComplexLongBox
ComponentBoxType = boxes.W_FloatLongBox
+_all_objs_for_tests = [] # for tests
+
+class ObjectType(Primitive, BaseType):
+ T = lltype.Signed
+ BoxType = boxes.W_ObjectBox
+
+ def get_element_size(self):
+ return rffi.sizeof(lltype.Signed)
+
+ def coerce(self, space, dtype, w_item):
+ if isinstance(w_item, boxes.W_ObjectBox):
+ return w_item
+ return boxes.W_ObjectBox(w_item)
+
+ def coerce_subtype(self, space, w_subtype, w_item):
+ # return the item itself
+ return self.unbox(self.box(w_item))
+
+ def store(self, arr, i, offset, box):
+ if arr.gcstruct is V_OBJECTSTORE:
+ raise oefmt(self.space.w_NotImplementedError,
+ "cannot store object in array with no gc hook")
+ self._write(arr.storage, i, offset, self.unbox(box),
+ arr.gcstruct)
+
+ def read(self, arr, i, offset, dtype=None):
+ return self.box(self._read(arr.storage, i, offset))
+
+ def byteswap(self, w_v):
+ return w_v
+
+ @jit.dont_look_inside
+ def _write(self, storage, i, offset, w_obj, gcstruct):
+ # no GC anywhere in this function!
+ if we_are_translated():
+ from rpython.rlib import rgc
+ rgc.ll_writebarrier(gcstruct)
+ value = rffi.cast(lltype.Signed, cast_instance_to_gcref(w_obj))
+ else:
More information about the pypy-commit
mailing list