[pypy-commit] pypy py3k: merge default
pjenvey
noreply at buildbot.pypy.org
Wed Jul 16 07:58:54 CEST 2014
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r72449:487697aaa730
Date: 2014-07-14 18:29 -0700
http://bitbucket.org/pypy/pypy/changeset/487697aaa730/
Log: merge default
diff too long, truncating to 2000 out of 6441 lines
diff --git a/lib-python/2.7/ctypes/__init__.py b/lib-python/2.7/ctypes/__init__.py
--- a/lib-python/2.7/ctypes/__init__.py
+++ b/lib-python/2.7/ctypes/__init__.py
@@ -389,12 +389,13 @@
func.__name__ = name_or_ordinal
return func
-class PyDLL(CDLL):
- """This class represents the Python library itself. It allows to
- access Python API functions. The GIL is not released, and
- Python exceptions are handled correctly.
- """
- _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
+# Not in PyPy
+#class PyDLL(CDLL):
+# """This class represents the Python library itself. It allows to
+# access Python API functions. The GIL is not released, and
+# Python exceptions are handled correctly.
+# """
+# _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
if _os.name in ("nt", "ce"):
@@ -447,15 +448,8 @@
return self._dlltype(name)
cdll = LibraryLoader(CDLL)
-pydll = LibraryLoader(PyDLL)
-
-if _os.name in ("nt", "ce"):
- pythonapi = PyDLL("python dll", None, _sys.dllhandle)
-elif _sys.platform == "cygwin":
- pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
-else:
- pythonapi = PyDLL(None)
-
+# not on PyPy
+#pydll = LibraryLoader(PyDLL)
if _os.name in ("nt", "ce"):
windll = LibraryLoader(WinDLL)
diff --git a/lib-python/2.7/ctypes/test/test_values.py b/lib-python/2.7/ctypes/test/test_values.py
--- a/lib-python/2.7/ctypes/test/test_values.py
+++ b/lib-python/2.7/ctypes/test/test_values.py
@@ -4,6 +4,7 @@
import unittest
from ctypes import *
+from ctypes.test import xfail
import _ctypes_test
@@ -23,7 +24,8 @@
class Win_ValuesTestCase(unittest.TestCase):
"""This test only works when python itself is a dll/shared library"""
-
+
+ @xfail
def test_optimizeflag(self):
# This test accesses the Py_OptimizeFlag intger, which is
# exported by the Python dll.
@@ -40,6 +42,7 @@
else:
self.assertEqual(opt, 2)
+ @xfail
def test_frozentable(self):
# Python exports a PyImport_FrozenModules symbol. This is a
# pointer to an array of struct _frozen entries. The end of the
@@ -75,6 +78,7 @@
from ctypes import _pointer_type_cache
del _pointer_type_cache[struct_frozen]
+ @xfail
def test_undefined(self):
self.assertRaises(ValueError, c_int.in_dll, pydll, "Undefined_Symbol")
diff --git a/lib-python/2.7/test/test_gdbm.py b/lib-python/2.7/test/test_gdbm.py
--- a/lib-python/2.7/test/test_gdbm.py
+++ b/lib-python/2.7/test/test_gdbm.py
@@ -98,6 +98,17 @@
self.assertTrue(key in self.g)
self.assertTrue(self.g.has_key(key))
+ def test_unicode_key(self):
+ key = u'ab'
+ value = u'cd'
+ self.g = gdbm.open(filename, 'cf')
+ self.g[key] = value
+ self.g.close()
+ self.g = gdbm.open(filename, 'r')
+ self.assertEquals(self.g[key], value)
+ self.assertTrue(key in self.g)
+ self.assertTrue(self.g.has_key(key))
+
def test_main():
run_unittest(TestGdbm)
diff --git a/lib-python/2.7/timeit.py b/lib-python/2.7/timeit.py
--- a/lib-python/2.7/timeit.py
+++ b/lib-python/2.7/timeit.py
@@ -55,11 +55,6 @@
import gc
import sys
import time
-try:
- import itertools
-except ImportError:
- # Must be an older Python version (see timeit() below)
- itertools = None
__all__ = ["Timer"]
@@ -81,7 +76,8 @@
def inner(_it, _timer):
%(setup)s
_t0 = _timer()
- for _i in _it:
+ while _it > 0:
+ _it -= 1
%(stmt)s
_t1 = _timer()
return _t1 - _t0
@@ -96,7 +92,8 @@
def inner(_it, _timer, _func=func):
setup()
_t0 = _timer()
- for _i in _it:
+ while _it > 0:
+ _it -= 1
_func()
_t1 = _timer()
return _t1 - _t0
@@ -133,9 +130,19 @@
else:
raise ValueError("setup is neither a string nor callable")
self.src = src # Save for traceback display
- code = compile(src, dummy_src_name, "exec")
- exec code in globals(), ns
- self.inner = ns["inner"]
+ def make_inner():
+ # PyPy tweak: recompile the source code each time before
+ # calling inner(). There are situations like Issue #1776
+ # where PyPy tries to reuse the JIT code from before,
+ # but that's not going to work: the first thing the
+ # function does is the "-s" statement, which may declare
+ # new classes (here a namedtuple). We end up with
+ # bridges from the inner loop; more and more of them
+ # every time we call inner().
+ code = compile(src, dummy_src_name, "exec")
+ exec code in globals(), ns
+ return ns["inner"]
+ self.make_inner = make_inner
elif hasattr(stmt, '__call__'):
self.src = None
if isinstance(setup, basestring):
@@ -144,7 +151,8 @@
exec _setup in globals(), ns
elif not hasattr(setup, '__call__'):
raise ValueError("setup is neither a string nor callable")
- self.inner = _template_func(setup, stmt)
+ inner = _template_func(setup, stmt)
+ self.make_inner = lambda: inner
else:
raise ValueError("stmt is neither a string nor callable")
@@ -185,15 +193,12 @@
to one million. The main statement, the setup statement and
the timer function to be used are passed to the constructor.
"""
- if itertools:
- it = itertools.repeat(None, number)
- else:
- it = [None] * number
+ inner = self.make_inner()
gcold = gc.isenabled()
if '__pypy__' not in sys.builtin_module_names:
gc.disable() # only do that on CPython
try:
- timing = self.inner(it, self.timer)
+ timing = inner(number, self.timer)
finally:
if gcold:
gc.enable()
diff --git a/lib_pypy/_gdbm.py b/lib_pypy/_gdbm.py
--- a/lib_pypy/_gdbm.py
+++ b/lib_pypy/_gdbm.py
@@ -75,8 +75,8 @@
def _raise_from_errno(self):
if ffi.errno:
- raise error(os.strerror(ffi.errno))
- raise error(lib.gdbm_strerror(lib.gdbm_errno))
+ raise error(ffi.errno, os.strerror(ffi.errno))
+ raise error(lib.gdbm_errno, lib.gdbm_strerror(lib.gdbm_errno))
def __len__(self):
if self.size < 0:
@@ -151,7 +151,7 @@
def _check_closed(self):
if not self.ll_dbm:
- raise error("GDBM object has already been closed")
+ raise error(0, "GDBM object has already been closed")
__del__ = close
@@ -180,7 +180,7 @@
elif flags[0] == 'n':
iflags = lib.GDBM_NEWDB
else:
- raise error("First flag must be one of 'r', 'w', 'c' or 'n'")
+ raise error(0, "First flag must be one of 'r', 'w', 'c' or 'n'")
for flag in flags[1:]:
if flag == 'f':
iflags |= lib.GDBM_FAST
@@ -189,7 +189,7 @@
elif flag == 'u':
iflags |= lib.GDBM_NOLOCK
else:
- raise error("Flag '%s' not supported" % flag)
+ raise error(0, "Flag '%s' not supported" % flag)
return gdbm(filename, iflags, mode)
open_flags = "rwcnfsu"
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,5 +4,5 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "0.8.2"
-__version_info__ = (0, 8, 2)
+__version__ = "0.8.6"
+__version_info__ = (0, 8, 6)
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -55,8 +55,7 @@
# _cffi_backend.so compiled.
import _cffi_backend as backend
from . import __version__
- assert (backend.__version__ == __version__ or
- backend.__version__ == __version__[:3])
+ assert backend.__version__ == __version__
# (If you insist you can also try to pass the option
# 'backend=backend_ctypes.CTypesBackend()', but don't
# rely on it! It's probably not going to work well.)
diff --git a/lib_pypy/cffi/vengine_gen.py b/lib_pypy/cffi/vengine_gen.py
--- a/lib_pypy/cffi/vengine_gen.py
+++ b/lib_pypy/cffi/vengine_gen.py
@@ -435,14 +435,14 @@
enumerator, enumerator, enumvalue))
prnt(' char buf[64];')
prnt(' if ((%s) < 0)' % enumerator)
- prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % enumerator)
+ prnt(' sprintf(buf, "%%ld", (long)(%s));' % enumerator)
prnt(' else')
- prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
+ prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' %
enumerator)
- prnt(' snprintf(out_error, 255,'
+ prnt(' sprintf(out_error,'
' "%s has the real value %s, not %s",')
prnt(' "%s", buf, "%d");' % (
- enumerator, enumvalue))
+ enumerator[:100], enumvalue))
prnt(' return -1;')
prnt(' }')
prnt(' return 0;')
diff --git a/pypy/doc/ctypes-implementation.rst b/pypy/doc/ctypes-implementation.rst
--- a/pypy/doc/ctypes-implementation.rst
+++ b/pypy/doc/ctypes-implementation.rst
@@ -72,13 +72,11 @@
Here is a list of the limitations and missing features of the
current implementation:
-* ``ctypes.pythonapi`` lets you access the CPython C API emulation layer
- of PyPy, at your own risks and without doing anything sensible about
- the GIL. Since PyPy 2.3, these functions are also named with an extra
- "Py", for example ``PyPyInt_FromLong()``. Basically, don't use this,
- but it might more or less work in simple cases if you do. (Obviously,
- assuming the PyObject pointers you get have any particular fields in
- any particular order is just going to crash.)
+* ``ctypes.pythonapi`` is missing. In previous versions, it was present
+ and redirected to the `cpyext` C API emulation layer, but our
+ implementation did not do anything sensible about the GIL and the
+ functions were named with an extra "Py", for example
+ ``PyPyInt_FromLong()``. It was removed for being unhelpful.
* We copy Python strings instead of having pointers to raw buffers
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -171,16 +171,21 @@
You might be interested in our `benchmarking site`_ and our
`jit documentation`_.
-Note that the JIT has a very high warm-up cost, meaning that the
-programs are slow at the beginning. If you want to compare the timings
-with CPython, even relatively simple programs need to run *at least* one
-second, preferrably at least a few seconds. Large, complicated programs
-need even more time to warm-up the JIT.
+`Your tests are not a benchmark`_: tests tend to be slow under PyPy
+because they run exactly once; if they are good tests, they exercise
+various corner cases in your code. This is a bad case for JIT
+compilers. Note also that our JIT has a very high warm-up cost, meaning
+that any program is slow at the beginning. If you want to compare the
+timings with CPython, even relatively simple programs need to run *at
+least* one second, preferrably at least a few seconds. Large,
+complicated programs need even more time to warm-up the JIT.
.. _`benchmarking site`: http://speed.pypy.org
.. _`jit documentation`: jit/index.html
+.. _`your tests are not a benchmark`: http://alexgaynor.net/2013/jul/15/your-tests-are-not-benchmark/
+
---------------------------------------------------------------
Couldn't the JIT dump and reload already-compiled machine code?
---------------------------------------------------------------
@@ -465,9 +470,13 @@
This is documented (here__ and here__). It needs 4 GB of RAM to run
"rpython targetpypystandalone" on top of PyPy, a bit more when running
-on CPython. If you have less than 4 GB it will just swap forever (or
-fail if you don't have enough swap). On 32-bit, divide the numbers by
-two.
+on top of CPython. If you have less than 4 GB free, it will just swap
+forever (or fail if you don't have enough swap). And we mean *free:*
+if the machine has 4 GB *in total,* then it will swap.
+
+On 32-bit, divide the numbers by two. (We didn't try recently, but in
+the past it was possible to compile a 32-bit version on a 2 GB Linux
+machine with nothing else running: no Gnome/KDE, for example.)
.. __: http://pypy.org/download.html#building-from-source
.. __: https://pypy.readthedocs.org/en/latest/getting-started-python.html#translating-the-pypy-python-interpreter
diff --git a/pypy/doc/jit-hooks.rst b/pypy/doc/jit-hooks.rst
--- a/pypy/doc/jit-hooks.rst
+++ b/pypy/doc/jit-hooks.rst
@@ -34,7 +34,7 @@
aborted due to some reason.
The hook will be invoked with the siagnture:
- ``hook(jitdriver_name, greenkey, reason)``
+ ``hook(jitdriver_name, greenkey, reason, oplist)``
Reason is a string, the meaning of other arguments is the same
as attributes on JitLoopInfo object
diff --git a/pypy/doc/objspace-proxies.rst b/pypy/doc/objspace-proxies.rst
--- a/pypy/doc/objspace-proxies.rst
+++ b/pypy/doc/objspace-proxies.rst
@@ -26,6 +26,16 @@
Transparent Proxies
================================
+.. warning::
+
+ This is a feature that was tried experimentally long ago, and we
+ found no really good use cases. The basic functionality is still
+ there, but we don't recommend using it. Some of the examples below
+ might not work any more (e.g. you can't tproxy a list object any
+ more). The rest can be done by hacking in standard Python. If
+ anyone is interested in working on tproxy again, he is welcome, but
+ we don't regard this as an interesting extension.
+
PyPy's Transparent Proxies allow routing of operations on objects
to a callable. Application level code can customize objects without
interfering with the type system - ``type(proxied_list) is list`` holds true
diff --git a/pypy/doc/stm.rst b/pypy/doc/stm.rst
--- a/pypy/doc/stm.rst
+++ b/pypy/doc/stm.rst
@@ -28,7 +28,8 @@
Introduction
============
-``pypy-stm`` is a variant of the regular PyPy interpreter. With caveats_
+``pypy-stm`` is a variant of the regular PyPy interpreter. (This
+version supports Python 2.7; see below for `Python 3`_.) With caveats_
listed below, it should be in theory within 20%-50% slower than a
regular PyPy, comparing the JIT version in both cases (but see below!).
It is called
@@ -92,9 +93,9 @@
We're busy fixing them as we find them; feel free to `report bugs`_.
* It runs with an overhead as low as 20% on examples like "richards".
- There are also other examples with higher overheads --up to 10x for
- "translate.py"-- which we are still trying to understand. One suspect
- is our partial GC implementation, see below.
+ There are also other examples with higher overheads --currently up to
+ 2x for "translate.py"-- which we are still trying to understand.
+ One suspect is our partial GC implementation, see below.
* Currently limited to 1.5 GB of RAM (this is just a parameter in
`core.h`__). Memory overflows are not correctly handled; they cause
@@ -111,9 +112,8 @@
* The GC is new; although clearly inspired by PyPy's regular GC, it
misses a number of optimizations for now. Programs allocating large
- numbers of small objects that don't immediately die, as well as
- programs that modify large lists or dicts, suffer from these missing
- optimizations.
+ numbers of small objects that don't immediately die (surely a common
+ situation) suffer from these missing optimizations.
* The GC has no support for destructors: the ``__del__`` method is never
called (including on file objects, which won't be closed for you).
@@ -138,6 +138,25 @@
+Python 3
+========
+
+In this document I describe "pypy-stm", which is based on PyPy's Python
+2.7 interpreter. Supporting Python 3 should take about half an
+afternoon of work. Obviously, what I *don't* mean is that by tomorrow
+you can have a finished and polished "pypy3-stm" product. General py3k
+work is still missing; and general stm work is also still missing. But
+they are rather independent from each other, as usual in PyPy. The
+required afternoon of work will certainly be done one of these days now
+that the internal interfaces seem to stabilize.
+
+The same is true for other languages implemented in the RPython
+framework, although the amount of work to put there might vary, because
+the STM framework within RPython is currently targeting the PyPy
+interpreter and other ones might have slightly different needs.
+
+
+
User Guide
==========
@@ -490,8 +509,6 @@
The last two lines are special; they are an internal marker read by
``transactional_memory.print_abort_info()``.
-These statistics are not printed out for the main thread, for now.
-
Reference to implementation details
-----------------------------------
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
@@ -30,3 +30,23 @@
x86-64, the JIT backend has a special optimization that lets it emit
directly a single MOV from a %gs- or %fs-based address. It seems
actually to give a good boost in performance.
+
+.. branch: fast-gil
+A faster way to handle the GIL, particularly in JIT code. The GIL is
+now a composite of two concepts: a global number (it's just set from
+1 to 0 and back around CALL_RELEASE_GIL), and a real mutex. If there
+are threads waiting to acquire the GIL, one of them is actively
+checking the global number every 0.1 ms to 1 ms. Overall, JIT loops
+full of external function calls now run a bit faster (if no thread was
+started yet), or a *lot* faster (if threads were started already).
+
+.. branch: jit-get-errno
+Optimize the errno handling in the JIT, notably around external
+function calls. Linux-only.
+
+.. branch: disable_pythonapi
+Remove non-functioning ctypes.pyhonapi and ctypes.PyDLL, document this
+incompatibility with cpython. Recast sys.dllhandle to an int.
+
+.. branch: scalar-operations
+Fix performance regression on ufunc(<scalar>, <scalar>) in numpy.
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -132,19 +132,23 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Download http://www.gzip.org/zlib/zlib-1.2.3.tar.gz and extract it in
-the base directory. Then compile::
+the base directory. Then compile as a static library::
cd zlib-1.2.3
nmake -f win32\Makefile.msc
- copy zlib1.dll <somewhere in the PATH>\zlib.dll
+ copy zlib1.lib <somewhere in LIB>
+ copy zlib.h zconf.h <somewhere in INCLUDE>
The bz2 compression library
~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Get the same version of bz2 used by python and compile as a static library::
svn export http://svn.python.org/projects/external/bzip2-1.0.6
cd bzip2-1.0.6
nmake -f makefile.msc
- copy bzip.dll <somewhere in the PATH>\bzip.dll
+ copy libbz2.lib <somewhere in LIB>
+ copy bzlib.h <somewhere in INCLUDE>
+
The sqlite3 database library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -166,7 +170,8 @@
is actually enough for pypy).
Then, copy the file ``win32\bin\release\libexpat.dll`` somewhere in
-your PATH.
+your PATH, ``win32\bin\release\libexpat.lib`` somewhere in LIB, and
+both ``lib\expat.h`` and ``lib\expat_external.h`` somewhere in INCLUDE.
The OpenSSL library
~~~~~~~~~~~~~~~~~~~
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -654,8 +654,11 @@
else:
# translated case follows. self.threadlocals is either from
# 'pypy.interpreter.miscutils' or 'pypy.module.thread.threadlocals'.
- # the result is assumed to be non-null: enter_thread() was called.
- return self.threadlocals.get_ec()
+ # the result is assumed to be non-null: enter_thread() was called
+ # by space.startup().
+ ec = self.threadlocals.get_ec()
+ assert ec is not None
+ return ec
def _freeze_(self):
return True
@@ -957,6 +960,13 @@
"""
return self.unpackiterable(w_iterable, expected_length)
+ def listview_no_unpack(self, w_iterable):
+ """ Same as listview() if cheap. If 'w_iterable' is something like
+ a generator, for example, then return None instead.
+ May return None anyway.
+ """
+ return None
+
def listview_bytes(self, w_list):
""" Return a list of unwrapped strings out of a list of strings. If the
argument is not a list or does not contain only strings, return None.
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -499,6 +499,13 @@
"""
+class UserDelCallback(object):
+ def __init__(self, w_obj, callback, descrname):
+ self.w_obj = w_obj
+ self.callback = callback
+ self.descrname = descrname
+ self.next = None
+
class UserDelAction(AsyncAction):
"""An action that invokes all pending app-level __del__() method.
This is done as an action instead of immediately when the
@@ -509,13 +516,19 @@
def __init__(self, space):
AsyncAction.__init__(self, space)
- self.dying_objects = []
+ self.dying_objects = None
+ self.dying_objects_last = None
self.finalizers_lock_count = 0
self.enabled_at_app_level = True
self._invoke_immediately = False
def register_callback(self, w_obj, callback, descrname):
- self.dying_objects.append((w_obj, callback, descrname))
+ cb = UserDelCallback(w_obj, callback, descrname)
+ if self.dying_objects_last is None:
+ self.dying_objects = cb
+ else:
+ self.dying_objects_last.next = cb
+ self.dying_objects_last = cb
if not self._invoke_immediately:
self.fire()
else:
@@ -532,13 +545,33 @@
# avoid too deep recursions of the kind of __del__ being called
# while in the middle of another __del__ call.
pending = self.dying_objects
- self.dying_objects = []
+ self.dying_objects = None
+ self.dying_objects_last = None
space = self.space
- for i in range(len(pending)):
- w_obj, callback, descrname = pending[i]
- pending[i] = (None, None, None)
+ while pending is not None:
try:
- callback(w_obj)
+ pending.callback(pending.w_obj)
except OperationError, e:
- e.write_unraisable(space, descrname, w_obj)
+ e.write_unraisable(space, pending.descrname, pending.w_obj)
e.clear(space) # break up reference cycles
+ pending = pending.next
+ #
+ # Note: 'dying_objects' used to be just a regular list instead
+ # of a chained list. This was the cause of "leaks" if we have a
+ # program that constantly creates new objects with finalizers.
+ # Here is why: say 'dying_objects' is a long list, and there
+ # are n instances in it. Then we spend some time in this
+ # function, possibly triggering more GCs, but keeping the list
+ # of length n alive. Then the list is suddenly freed at the
+ # end, and we return to the user program. At this point the
+ # GC limit is still very high, because just before, there was
+ # a list of length n alive. Assume that the program continues
+ # to allocate a lot of instances with finalizers. The high GC
+ # limit means that it could allocate a lot of instances before
+ # reaching it --- possibly more than n. So the whole procedure
+ # repeats with higher and higher values of n.
+ #
+ # This does not occur in the current implementation because
+ # there is no list of length n: if n is large, then the GC
+ # will run several times while walking the list, but it will
+ # see lower and lower memory usage, with no lower bound of n.
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -61,6 +61,13 @@
return self.send_ex(w_arg)
def send_ex(self, w_arg, operr=None):
+ pycode = self.pycode
+ if jit.we_are_jitted() and should_not_inline(pycode):
+ generatorentry_driver.jit_merge_point(gen=self, w_arg=w_arg,
+ operr=operr, pycode=pycode)
+ return self._send_ex(w_arg, operr)
+
+ def _send_ex(self, w_arg, operr):
space = self.space
if self.running:
raise OperationError(space.w_ValueError,
@@ -72,8 +79,7 @@
if operr is None:
operr = OperationError(space.w_StopIteration, space.w_None)
raise operr
- # XXX it's not clear that last_instr should be promoted at all
- # but as long as it is necessary for call_assembler, let's do it early
+
last_instr = jit.promote(frame.last_instr)
if last_instr == -1:
if w_arg and not space.is_w(w_arg, space.w_None):
@@ -219,3 +225,38 @@
"interrupting generator of ")
break
block = block.previous
+
+
+
+def get_printable_location_genentry(bytecode):
+ return '%s <generator>' % (bytecode.get_repr(),)
+generatorentry_driver = jit.JitDriver(greens=['pycode'],
+ reds=['gen', 'w_arg', 'operr'],
+ get_printable_location =
+ get_printable_location_genentry,
+ name='generatorentry')
+
+from pypy.tool.stdlib_opcode import HAVE_ARGUMENT, opmap
+YIELD_VALUE = opmap['YIELD_VALUE']
+
+ at jit.elidable_promote()
+def should_not_inline(pycode):
+ # Should not inline generators with more than one "yield",
+ # as an approximative fix (see issue #1782). There are cases
+ # where it slows things down; for example calls to a simple
+ # generator that just produces a few simple values with a few
+ # consecutive "yield" statements. It fixes the near-infinite
+ # slow-down in issue #1782, though...
+ count_yields = 0
+ code = pycode.co_code
+ n = len(code)
+ i = 0
+ while i < n:
+ c = code[i]
+ op = ord(c)
+ if op == YIELD_VALUE:
+ count_yields += 1
+ i += 1
+ if op >= HAVE_ARGUMENT:
+ i += 2
+ return count_yields >= 2
diff --git a/pypy/interpreter/test/test_generator.py b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -300,3 +300,20 @@
yield 1
raise StopIteration
assert tuple(f()) == (1,)
+
+
+def test_should_not_inline(space):
+ from pypy.interpreter.generator import should_not_inline
+ w_co = space.appexec([], '''():
+ def g(x):
+ yield x + 5
+ return g.func_code
+ ''')
+ assert should_not_inline(w_co) == False
+ w_co = space.appexec([], '''():
+ def g(x):
+ yield x + 5
+ yield x + 6
+ return g.func_code
+ ''')
+ assert should_not_inline(w_co) == True
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -74,13 +74,12 @@
'hidden_applevel' : 'interp_magic.hidden_applevel',
'lookup_special' : 'interp_magic.lookup_special',
'do_what_I_mean' : 'interp_magic.do_what_I_mean',
- 'list_strategy' : 'interp_magic.list_strategy',
'validate_fd' : 'interp_magic.validate_fd',
'resizelist_hint' : 'interp_magic.resizelist_hint',
'newlist_hint' : 'interp_magic.newlist_hint',
'add_memory_pressure' : 'interp_magic.add_memory_pressure',
'newdict' : 'interp_dict.newdict',
- 'dictstrategy' : 'interp_dict.dictstrategy',
+ 'strategy' : 'interp_magic.strategy', # dict,set,list
'set_debug' : 'interp_magic.set_debug',
'locals_to_fast' : 'interp_magic.locals_to_fast',
'normalize_exc' : 'interp_magic.normalize_exc',
diff --git a/pypy/module/__pypy__/interp_dict.py b/pypy/module/__pypy__/interp_dict.py
--- a/pypy/module/__pypy__/interp_dict.py
+++ b/pypy/module/__pypy__/interp_dict.py
@@ -1,7 +1,6 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import unwrap_spec
-from pypy.objspace.std.dictmultiobject import W_DictMultiObject
@unwrap_spec(type=str)
def newdict(space, type):
@@ -31,13 +30,3 @@
return space.newdict(strdict=True)
else:
raise oefmt(space.w_TypeError, "unknown type of dict %s", type)
-
-def dictstrategy(space, w_obj):
- """ dictstrategy(dict)
-
- show the underlaying strategy used by a dict object
- """
- if not isinstance(w_obj, W_DictMultiObject):
- raise OperationError(space.w_TypeError,
- space.wrap("expecting dict object"))
- return space.wrap('%r' % (w_obj.strategy,))
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -2,7 +2,9 @@
from pypy.interpreter.gateway import WrappedDefault, unwrap_spec
from pypy.interpreter.pyframe import PyFrame
from rpython.rlib.objectmodel import we_are_translated
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject
from pypy.objspace.std.listobject import W_ListObject
+from pypy.objspace.std.setobject import W_BaseSetObject
from pypy.objspace.std.typeobject import MethodCache
from pypy.objspace.std.mapdict import MapAttrCache
from rpython.rlib import rposix, rgc
@@ -74,12 +76,23 @@
def do_what_I_mean(space):
return space.wrap(42)
-def list_strategy(space, w_list):
- if isinstance(w_list, W_ListObject):
- return space.wrap(w_list.strategy._applevel_repr)
+
+def strategy(space, w_obj):
+ """ strategy(dict or list or set)
+
+ Return the underlying strategy currently used by a dict, list or set object
+ """
+ if isinstance(w_obj, W_DictMultiObject):
+ name = w_obj.strategy.__class__.__name__
+ elif isinstance(w_obj, W_ListObject):
+ name = w_obj.strategy.__class__.__name__
+ elif isinstance(w_obj, W_BaseSetObject):
+ name = w_obj.strategy.__class__.__name__
else:
- w_msg = space.wrap("Can only get the list strategy of a list")
- raise OperationError(space.w_TypeError, w_msg)
+ raise OperationError(space.w_TypeError,
+ space.wrap("expecting dict or list or set object"))
+ return space.wrap(name)
+
@unwrap_spec(fd='c_int')
def validate_fd(space, fd):
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -75,24 +75,38 @@
assert x == 42
def test_list_strategy(self):
- from __pypy__ import list_strategy
+ from __pypy__ import strategy
l = [1, 2, 3]
- assert list_strategy(l) == "int"
- l = list(range(1, 2))
- assert list_strategy(l) == "int"
+ assert strategy(l) == "IntegerListStrategy"
l = [b"a", b"b", b"c"]
- assert list_strategy(l) == "bytes"
- l = ["a", "b", "c"]
- assert list_strategy(l) == "unicode"
+ assert strategy(l) == "BytesListStrategy"
+ l = [u"a", u"b", u"c"]
+ assert strategy(l) == "UnicodeListStrategy"
l = [1.1, 2.2, 3.3]
- assert list_strategy(l) == "float"
+ assert strategy(l) == "FloatListStrategy"
l = [1, "b", 3]
- assert list_strategy(l) == "object"
+ assert strategy(l) == "ObjectListStrategy"
l = []
- assert list_strategy(l) == "empty"
+ assert strategy(l) == "EmptyListStrategy"
o = 5
- raises(TypeError, list_strategy, 5)
+ raises(TypeError, strategy, 5)
+
+ def test_dict_strategy(self):
+ from __pypy__ import strategy
+
+ d = {}
+ assert strategy(d) == "EmptyDictStrategy"
+ d = {1: None, 5: None}
+ assert strategy(d) == "IntDictStrategy"
+
+ def test_set_strategy(self):
+ from __pypy__ import strategy
+
+ s = set()
+ assert strategy(s) == "EmptySetStrategy"
+ s = set([2, 3, 4])
+ assert strategy(s) == "IntegerSetStrategy"
def test_normalize_exc(self):
from __pypy__ import normalize_exc
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -8,7 +8,7 @@
appleveldefs = {
}
interpleveldefs = {
- '__version__': 'space.wrap("0.8.2")',
+ '__version__': 'space.wrap("0.8.6")',
'load_library': 'libraryobj.load_library',
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -4,7 +4,7 @@
import sys
-from rpython.rlib import jit, clibffi, jit_libffi
+from rpython.rlib import jit, clibffi, jit_libffi, rgc
from rpython.rlib.jit_libffi import (CIF_DESCRIPTION, CIF_DESCRIPTION_P,
FFI_TYPE, FFI_TYPE_P, FFI_TYPE_PP, SIZE_OF_FFI_ARG)
from rpython.rlib.objectmodel import we_are_translated, instantiate
@@ -63,6 +63,7 @@
CifDescrBuilder(fvarargs, self.ctitem).rawallocate(ctypefunc)
return ctypefunc
+ @rgc.must_be_light_finalizer
def __del__(self):
if self.cif_descr:
lltype.free(self.cif_descr, flavor='raw')
@@ -156,8 +157,8 @@
data = rffi.ptradd(buffer, cif_descr.exchange_args[i])
flag = get_mustfree_flag(data)
if flag == 1:
- raw_string = rffi.cast(rffi.CCHARPP, data)[0]
- lltype.free(raw_string, flavor='raw')
+ raw_cdata = rffi.cast(rffi.CCHARPP, data)[0]
+ lltype.free(raw_cdata, flavor='raw')
lltype.free(buffer, flavor='raw')
return w_res
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -3188,4 +3188,4 @@
def test_version():
# this test is here mostly for PyPy
- assert __version__ == "0.8.2"
+ assert __version__ == "0.8.6"
diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -467,10 +467,6 @@
space.wrap("<_io.TextIOWrapper %s%sencoding=%r>"), w_args
)
- def isatty_w(self, space):
- self._check_init(space)
- return space.call_method(self.w_buffer, "isatty")
-
def readable_w(self, space):
self._check_init(space)
return space.call_method(self.w_buffer, "readable")
@@ -483,6 +479,10 @@
self._check_init(space)
return space.call_method(self.w_buffer, "seekable")
+ def isatty_w(self, space):
+ self._check_init(space)
+ return space.call_method(self.w_buffer, "isatty")
+
def fileno_w(self, space):
self._check_init(space)
return space.call_method(self.w_buffer, "fileno")
@@ -1065,10 +1065,10 @@
close = interp2app(W_TextIOWrapper.close_w),
line_buffering = interp_attrproperty("line_buffering", W_TextIOWrapper),
- isatty = interp2app(W_TextIOWrapper.isatty_w),
readable = interp2app(W_TextIOWrapper.readable_w),
writable = interp2app(W_TextIOWrapper.writable_w),
seekable = interp2app(W_TextIOWrapper.seekable_w),
+ isatty = interp2app(W_TextIOWrapper.isatty_w),
fileno = interp2app(W_TextIOWrapper.fileno_w),
_dealloc_warn = interp2app(W_TextIOWrapper._dealloc_warn_w),
name = GetSetProperty(W_TextIOWrapper.name_get_w),
diff --git a/pypy/module/_io/test/test_textio.py b/pypy/module/_io/test/test_textio.py
--- a/pypy/module/_io/test/test_textio.py
+++ b/pypy/module/_io/test/test_textio.py
@@ -31,6 +31,12 @@
t = _io.TextIOWrapper(b)
assert t.readable()
assert t.seekable()
+ #
+ class CustomFile(object):
+ def isatty(self): return 'YES'
+ readable = writable = seekable = lambda self: False
+ t = _io.TextIOWrapper(CustomFile())
+ assert t.isatty() == 'YES'
def test_default_implementations(self):
import _io
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
@@ -11,7 +11,7 @@
from rpython.rlib.rtimer import read_timestamp, _is_64_bit
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.conftest import cdir
+from rpython.translator import cdir
from rpython.rlib.rarithmetic import r_longlong
import time, sys
diff --git a/pypy/module/_socket/__init__.py b/pypy/module/_socket/__init__.py
--- a/pypy/module/_socket/__init__.py
+++ b/pypy/module/_socket/__init__.py
@@ -6,8 +6,8 @@
}
interpleveldefs = {
- 'SocketType': 'interp_socket.W_RSocket',
- 'socket' : 'interp_socket.W_RSocket',
+ 'SocketType': 'interp_socket.W_Socket',
+ 'socket' : 'interp_socket.W_Socket',
'error' : 'interp_socket.get_error(space, "error")',
'herror' : 'interp_socket.get_error(space, "herror")',
'gaierror' : 'interp_socket.get_error(space, "gaierror")',
diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -1,9 +1,13 @@
+from rpython.rlib import rsocket
+from rpython.rlib.rsocket import SocketError, INVALID_SOCKET
+
+from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
from pypy.module._socket.interp_socket import (
- converted_error, W_RSocket, addr_as_object, fill_from_object, get_error)
-from rpython.rlib import rsocket
-from rpython.rlib.rsocket import SocketError, INVALID_SOCKET
-from pypy.interpreter.error import OperationError
+ converted_error, W_Socket, addr_as_object, fill_from_object, get_error,
+ ipaddr_from_object
+)
+
def gethostname(space):
"""gethostname() -> string
@@ -156,10 +160,13 @@
AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
"""
try:
- sock1, sock2 = rsocket.socketpair(family, type, proto, W_RSocket)
+ sock1, sock2 = rsocket.socketpair(family, type, proto)
except SocketError, e:
raise converted_error(space, e)
- return space.newtuple([space.wrap(sock1), space.wrap(sock2)])
+ return space.newtuple([
+ space.wrap(W_Socket(sock1)),
+ space.wrap(W_Socket(sock2))
+ ])
# The following 4 functions refuse all negative numbers, like CPython 2.6.
# They could also check that the argument is not too large, but CPython 2.6
diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -1,13 +1,18 @@
+from rpython.rlib import rsocket
+from rpython.rlib.rarithmetic import intmask
+from rpython.rlib.rsocket import (
+ RSocket, AF_INET, SOCK_STREAM, SocketError, SocketErrorWithErrno,
+ RSocketError
+)
+from rpython.rtyper.lltypesystem import lltype, rffi
+
+from pypy.interpreter import gateway
from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from rpython.rlib.rarithmetic import intmask
-from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.rlib import rsocket
-from rpython.rlib.rsocket import RSocket, AF_INET, SOCK_STREAM
-from rpython.rlib.rsocket import SocketError, SocketErrorWithErrno, RSocketError
-from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter import gateway
+from pypy.interpreter.typedef import (
+ GetSetProperty, TypeDef, interp_attrproperty, make_weakref_descr
+)
# XXX Hack to seperate rpython and pypy
@@ -128,13 +133,16 @@
return addr
-class W_RSocket(W_Root, RSocket):
+class W_Socket(W_Root):
# for _dealloc_warn
space = None
+ def __init__(self, sock):
+ self.sock = sock
+
def descr_new(space, w_subtype, __args__):
- sock = space.allocate_instance(W_RSocket, w_subtype)
+ sock = space.allocate_instance(W_Socket, w_subtype)
return space.wrap(sock)
@unwrap_spec(family=int, type=int, proto=int,
@@ -143,10 +151,11 @@
w_fileno=None):
try:
if not space.is_w(w_fileno, space.w_None):
- W_RSocket.__init__(self, family, type, proto,
- fd=space.c_filedescriptor_w(w_fileno))
+ sock = RSocket(family, type, proto,
+ fd=space.c_filedescriptor_w(w_fileno))
else:
- W_RSocket.__init__(self, family, type, proto)
+ sock = RSocket(family, type, proto)
+ W_Socket.__init__(self, sock)
self.space = space
except SocketError, e:
raise converted_error(space, e)
@@ -154,16 +163,26 @@
def __del__(self):
self.clear_all_weakrefs()
if self.space:
- self.enqueue_for_destruction(self.space, W_RSocket.destructor,
+ self.enqueue_for_destruction(self.space, W_Socket.destructor,
'internal __del__ of ')
def destructor(self):
- assert isinstance(self, W_RSocket)
+ assert isinstance(self, W_Socket)
if self.fd != rsocket.INVALID_SOCKET:
try:
self._dealloc_warn()
finally:
self.close_w(self.space)
+ # --XXX--
+
+ def get_type_w(self, space):
+ return space.wrap(self.sock.type)
+
+ def get_proto_w(self, space):
+ return space.wrap(self.sock.proto)
+
+ def get_family_w(self, space):
+ return space.wrap(self.sock.family)
def _dealloc_warn(self):
space = self.space
@@ -184,20 +203,20 @@
For IP sockets, the address info is a pair (hostaddr, port).
"""
try:
- fd, addr = self.accept()
+ fd, addr = self.sock.accept()
return space.newtuple([space.wrap(fd),
addr_as_object(addr, fd, space)])
- except SocketError, e:
+ except SocketError as e:
raise converted_error(space, e)
# convert an Address into an app-level object
def addr_as_object(self, space, address):
- return addr_as_object(address, self.fd, space)
+ return addr_as_object(address, self.sock.fd, space)
# convert an app-level object into an Address
# based on the current socket's family
def addr_from_object(self, space, w_address):
- return addr_from_object(self.family, space, w_address)
+ return addr_from_object(self.sock.family, space, w_address)
def bind_w(self, space, w_addr):
"""bind(address)
@@ -207,8 +226,8 @@
sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])
"""
try:
- self.bind(self.addr_from_object(space, w_addr))
- except SocketError, e:
+ self.sock.bind(self.addr_from_object(space, w_addr))
+ except SocketError as e:
raise converted_error(space, e)
def close_w(self, space):
@@ -217,7 +236,7 @@
Close the socket. It cannot be used after this call.
"""
try:
- self.close()
+ self.sock.close()
except SocketError:
# cpython doesn't return any errors on close
pass
@@ -229,8 +248,8 @@
is a pair (host, port).
"""
try:
- self.connect(self.addr_from_object(space, w_addr))
- except SocketError, e:
+ self.sock.connect(self.addr_from_object(space, w_addr))
+ except SocketError as e:
raise converted_error(space, e)
def connect_ex_w(self, space, w_addr):
@@ -241,9 +260,9 @@
"""
try:
addr = self.addr_from_object(space, w_addr)
- except SocketError, e:
+ except SocketError as e:
raise converted_error(space, e)
- error = self.connect_ex(addr)
+ error = self.sock.connect_ex(addr)
return space.wrap(error)
def fileno_w(self, space):
@@ -251,7 +270,7 @@
Return the integer file descriptor of the socket.
"""
- return space.wrap(intmask(self.fd))
+ return space.wrap(intmask(self.sock.fd))
def detach_w(self, space):
"""detach()
@@ -269,9 +288,9 @@
info is a pair (hostaddr, port).
"""
try:
- addr = self.getpeername()
- return addr_as_object(addr, self.fd, space)
- except SocketError, e:
+ addr = self.sock.getpeername()
+ return addr_as_object(addr, self.sock.fd, space)
+ except SocketError as e:
raise converted_error(space, e)
def getsockname_w(self, space):
@@ -281,9 +300,9 @@
info is a pair (hostaddr, port).
"""
try:
- addr = self.getsockname()
- return addr_as_object(addr, self.fd, space)
- except SocketError, e:
+ addr = self.sock.getsockname()
+ return addr_as_object(addr, self.sock.fd, space)
+ except SocketError as e:
raise converted_error(space, e)
@unwrap_spec(level=int, optname=int)
@@ -296,11 +315,11 @@
"""
if w_buflen is None:
try:
- return space.wrap(self.getsockopt_int(level, optname))
- except SocketError, e:
+ return space.wrap(self.sock.getsockopt_int(level, optname))
+ except SocketError as e:
raise converted_error(space, e)
buflen = space.int_w(w_buflen)
- return space.wrapbytes(self.getsockopt(level, optname, buflen))
+ return space.wrapbytes(self.sock.getsockopt(level, optname, buflen))
def gettimeout_w(self, space):
"""gettimeout() -> timeout
@@ -308,7 +327,7 @@
Returns the timeout in floating seconds associated with socket
operations. A timeout of None indicates that timeouts on socket
"""
- timeout = self.gettimeout()
+ timeout = self.sock.gettimeout()
if timeout < 0.0:
return space.w_None
return space.wrap(timeout)
@@ -322,8 +341,8 @@
will allow before refusing new connections.
"""
try:
- self.listen(backlog)
- except SocketError, e:
+ self.sock.listen(backlog)
+ except SocketError as e:
raise converted_error(space, e)
@unwrap_spec(buffersize='nonnegint', flags=int)
@@ -336,8 +355,8 @@
the remote end is closed and all data is read, return the empty string.
"""
try:
- data = self.recv(buffersize, flags)
- except SocketError, e:
+ data = self.sock.recv(buffersize, flags)
+ except SocketError as e:
raise converted_error(space, e)
return space.wrapbytes(data)
@@ -348,13 +367,13 @@
Like recv(buffersize, flags) but also return the sender's address info.
"""
try:
- data, addr = self.recvfrom(buffersize, flags)
+ data, addr = self.sock.recvfrom(buffersize, flags)
if addr:
- w_addr = addr_as_object(addr, self.fd, space)
+ w_addr = addr_as_object(addr, self.sock.fd, space)
else:
w_addr = space.w_None
return space.newtuple([space.wrapbytes(data), w_addr])
- except SocketError, e:
+ except SocketError as e:
raise converted_error(space, e)
@unwrap_spec(data='bufferstr', flags=int)
@@ -366,8 +385,8 @@
sent; this may be less than len(data) if the network is busy.
"""
try:
- count = self.send(data, flags)
- except SocketError, e:
+ count = self.sock.send(data, flags)
+ except SocketError as e:
raise converted_error(space, e)
return space.wrap(count)
@@ -381,8 +400,9 @@
to tell how much data has been sent.
"""
try:
- self.sendall(data, flags, space.getexecutioncontext().checksignals)
- except SocketError, e:
+ self.sock.sendall(
+ data, flags, space.getexecutioncontext().checksignals)
+ except SocketError as e:
raise converted_error(space, e)
@unwrap_spec(data='bufferstr')
@@ -402,8 +422,8 @@
w_addr = w_param3
try:
addr = self.addr_from_object(space, w_addr)
- count = self.sendto(data, flags, addr)
- except SocketError, e:
+ count = self.sock.sendto(data, flags, addr)
+ except SocketError as e:
raise converted_error(space, e)
return space.wrap(count)
@@ -415,7 +435,7 @@
setblocking(True) is equivalent to settimeout(None);
setblocking(False) is equivalent to settimeout(0.0).
"""
- self.setblocking(flag)
+ self.sock.setblocking(flag)
@unwrap_spec(level=int, optname=int)
def setsockopt_w(self, space, level, optname, w_optval):
@@ -429,13 +449,13 @@
except:
optval = space.bytes_w(w_optval)
try:
- self.setsockopt(level, optname, optval)
- except SocketError, e:
+ self.sock.setsockopt(level, optname, optval)
+ except SocketError as e:
raise converted_error(space, e)
return
try:
- self.setsockopt_int(level, optname, optval)
- except SocketError, e:
+ self.sock.setsockopt_int(level, optname, optval)
+ except SocketError as e:
raise converted_error(space, e)
def settimeout_w(self, space, w_timeout):
@@ -453,7 +473,7 @@
if timeout < 0.0:
raise OperationError(space.w_ValueError,
space.wrap('Timeout value out of range'))
- self.settimeout(timeout)
+ self.sock.settimeout(timeout)
@unwrap_spec(nbytes=int, flags=int)
def recv_into_w(self, space, w_buffer, nbytes=0, flags=0):
@@ -462,8 +482,8 @@
if nbytes == 0 or nbytes > lgt:
nbytes = lgt
try:
- return space.wrap(self.recvinto(rwbuffer, nbytes, flags))
- except SocketError, e:
+ return space.wrap(self.sock.recvinto(rwbuffer, nbytes, flags))
+ except SocketError as e:
raise converted_error(space, e)
@unwrap_spec(nbytes=int, flags=int)
@@ -473,13 +493,13 @@
if nbytes == 0 or nbytes > lgt:
nbytes = lgt
try:
- readlgt, addr = self.recvfrom_into(rwbuffer, nbytes, flags)
+ readlgt, addr = self.sock.recvfrom_into(rwbuffer, nbytes, flags)
if addr:
- w_addr = addr_as_object(addr, self.fd, space)
+ w_addr = addr_as_object(addr, self.sock.fd, space)
else:
w_addr = space.w_None
return space.newtuple([space.wrap(readlgt), w_addr])
- except SocketError, e:
+ except SocketError as e:
raise converted_error(space, e)
@unwrap_spec(cmd=int)
@@ -511,7 +531,7 @@
option_ptr.c_keepaliveinterval = space.uint_w(w_interval)
res = _c.WSAIoctl(
- self.fd, cmd, value_ptr, value_size,
+ self.sock.fd, cmd, value_ptr, value_size,
rffi.NULL, 0, recv_ptr, rffi.NULL, rffi.NULL)
if res < 0:
raise converted_error(space, rsocket.last_error())
@@ -532,8 +552,8 @@
(flag == SHUT_RDWR).
"""
try:
- self.shutdown(how)
- except SocketError, e:
+ self.sock.shutdown(how)
+ except SocketError as e:
raise converted_error(space, e)
#------------------------------------------------------------
@@ -609,10 +629,10 @@
socketmethods = {}
for methodname in socketmethodnames:
- method = getattr(W_RSocket, methodname + '_w')
+ method = getattr(W_Socket, methodname + '_w')
socketmethods[methodname] = interp2app(method)
-W_RSocket.typedef = TypeDef("_socket.socket",
+W_Socket.typedef = TypeDef("_socket.socket",
__doc__ = """\
socket([family[, type[, proto]]]) -> socket object
@@ -648,10 +668,10 @@
shutdown(how) -- shut down traffic in one or both directions
[*] not available on all platforms!""",
- __new__ = interp2app(W_RSocket.descr_new.im_func),
- __init__ = interp2app(W_RSocket.descr_init),
- type = interp_attrproperty('type', W_RSocket),
- proto = interp_attrproperty('proto', W_RSocket),
- family = interp_attrproperty('family', W_RSocket),
+ __new__ = interp2app(W_Socket.descr_new.im_func),
+ __init__ = interp2app(W_Socket.descr_init),
+ type = interp_attrproperty('type', W_Socket),
+ proto = interp_attrproperty('proto', W_Socket),
+ family = interp_attrproperty('family', W_Socket),
** socketmethods
)
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -434,47 +434,47 @@
lgt = rwbuffer.getlength()
if num_bytes < 0 or num_bytes > lgt:
num_bytes = lgt
- raw_buf, gc_buf = rffi.alloc_buffer(num_bytes)
- while True:
- err = 0
- count = libssl_SSL_read(self.ssl, raw_buf, num_bytes)
- err = libssl_SSL_get_error(self.ssl, count)
+ with rffi.scoped_alloc_buffer(num_bytes) as buf:
+ while True:
+ err = 0
- if err == SSL_ERROR_WANT_READ:
- sockstate = check_socket_and_wait_for_timeout(
- space, w_socket, False)
- elif err == SSL_ERROR_WANT_WRITE:
- sockstate = check_socket_and_wait_for_timeout(
- space, w_socket, True)
- elif (err == SSL_ERROR_ZERO_RETURN and
- libssl_SSL_get_shutdown(self.ssl) == SSL_RECEIVED_SHUTDOWN):
- rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
- if space.is_none(w_buf):
- return space.wrapbytes('')
+ count = libssl_SSL_read(self.ssl, buf.raw, num_bytes)
+ err = libssl_SSL_get_error(self.ssl, count)
+
+ if err == SSL_ERROR_WANT_READ:
+ sockstate = check_socket_and_wait_for_timeout(self.space,
+ self.w_socket, False)
+ elif err == SSL_ERROR_WANT_WRITE:
+ sockstate = check_socket_and_wait_for_timeout(self.space,
+ self.w_socket, True)
+ elif (err == SSL_ERROR_ZERO_RETURN and
+ libssl_SSL_get_shutdown(self.ssl) == SSL_RECEIVED_SHUTDOWN):
+ if space.is_none(w_buf):
+ return space.wrapbytes('')
+ else:
+ return space.wrap(0)
else:
- return space.wrap(0)
- else:
- sockstate = SOCKET_OPERATION_OK
+ sockstate = SOCKET_OPERATION_OK
- if sockstate == SOCKET_HAS_TIMED_OUT:
- raise ssl_error(space, "The read operation timed out")
- elif sockstate == SOCKET_IS_NONBLOCKING:
- break
+ if sockstate == SOCKET_HAS_TIMED_OUT:
+ raise ssl_error(self.space, "The read operation timed out")
+ elif sockstate == SOCKET_IS_NONBLOCKING:
+ break
- if err == SSL_ERROR_WANT_READ or err == SSL_ERROR_WANT_WRITE:
- continue
- else:
- break
+ if err == SSL_ERROR_WANT_READ or err == SSL_ERROR_WANT_WRITE:
+ continue
+ else:
+ break
- if count <= 0:
- raise _ssl_seterror(space, self, count)
+ if count <= 0:
+ raise _ssl_seterror(self.space, self, count)
- result = rffi.str_from_buffer(raw_buf, gc_buf, num_bytes, count)
- rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+ result = buf.str(count)
+
if rwbuffer is not None:
rwbuffer.setslice(0, result)
- return space.wrap(count)
+ return self.space.wrap(count)
else:
return space.wrapbytes(result)
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -242,8 +242,11 @@
Convert the array to an array of machine values and return the
bytes representation.
"""
+ size = self.len
+ if size == 0:
+ return space.wrap('')
cbuf = self._charbuf_start()
- s = rffi.charpsize2str(cbuf, self.len * self.itemsize)
+ s = rffi.charpsize2str(cbuf, size * self.itemsize)
self._charbuf_stop()
return self.space.wrapbytes(s)
@@ -668,6 +671,10 @@
def make_array(mytype):
W_ArrayBase = globals()['W_ArrayBase']
+ unpack_driver = jit.JitDriver(name='unpack_array',
+ greens=['tp'],
+ reds=['self', 'w_iterator'])
+
class W_Array(W_ArrayBase):
itemsize = mytype.bytes
typecode = mytype.typecode
@@ -712,6 +719,10 @@
return rffi.cast(mytype.itemtype, item)
#
# "regular" case: it fits in an rpython integer (lltype.Signed)
+ # or it is a float
+ return self.item_from_int_or_float(item)
+
+ def item_from_int_or_float(self, item):
result = rffi.cast(mytype.itemtype, item)
if mytype.canoverflow:
if rffi.cast(lltype.Signed, result) != item:
@@ -724,8 +735,8 @@
% mytype.bytes)
if not mytype.signed:
msg = 'un' + msg # 'signed' => 'unsigned'
- raise OperationError(space.w_OverflowError,
- space.wrap(msg))
+ raise OperationError(self.space.w_OverflowError,
+ self.space.wrap(msg))
return result
def __del__(self):
@@ -772,27 +783,65 @@
def fromsequence(self, w_seq):
space = self.space
oldlen = self.len
- try:
- new = space.len_w(w_seq)
- self.setlen(self.len + new)
- except OperationError:
- pass
+ newlen = oldlen
- i = 0
- try:
- if mytype.typecode == 'u':
- myiter = space.unpackiterable
- else:
- myiter = space.listview
- for w_i in myiter(w_seq):
- if oldlen + i >= self.len:
- self.setlen(oldlen + i + 1)
- self.buffer[oldlen + i] = self.item_w(w_i)
- i += 1
- except OperationError:
- self.setlen(oldlen + i)
- raise
- self.setlen(oldlen + i)
+ # optimized case for arrays of integers or floats
+ if mytype.unwrap == 'int_w':
+ lst = space.listview_int(w_seq)
+ elif mytype.unwrap == 'float_w':
+ lst = space.listview_float(w_seq)
+ else:
+ lst = None
+ if lst is not None:
+ self.setlen(oldlen + len(lst))
+ try:
+ buf = self.buffer
+ for num in lst:
+ buf[newlen] = self.item_from_int_or_float(num)
+ newlen += 1
+ except OperationError:
+ self.setlen(newlen)
+ raise
+ return
+
+ # this is the common case: w_seq is a list or a tuple
+ lst_w = space.listview_no_unpack(w_seq)
+ if lst_w is not None:
+ self.setlen(oldlen + len(lst_w))
+ buf = self.buffer
+ try:
+ for w_num in lst_w:
+ # note: self.item_w() might invoke arbitrary code.
+ # In case it resizes the same array, then strange
+ # things may happen, but as we don't reload 'buf'
+ # we know that one is big enough for all items
+ # (so at least we avoid crashes)
+ buf[newlen] = self.item_w(w_num)
+ newlen += 1
+ except OperationError:
+ if buf == self.buffer:
+ self.setlen(newlen)
+ raise
+ return
+
+ self._fromiterable(w_seq)
+
+ def _fromiterable(self, w_seq):
+ # a more careful case if w_seq happens to be a very large
+ # iterable: don't copy the items into some intermediate list
+ w_iterator = self.space.iter(w_seq)
+ tp = self.space.type(w_iterator)
+ while True:
+ unpack_driver.jit_merge_point(tp=tp, self=self,
+ w_iterator=w_iterator)
+ space = self.space
+ try:
+ w_item = space.next(w_iterator)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break # done
+ self.descr_append(space, w_item)
def extend(self, w_iterable, accept_different_array=False):
space = self.space
@@ -835,8 +884,9 @@
def descr_append(self, space, w_x):
x = self.item_w(w_x)
- self.setlen(self.len + 1)
- self.buffer[self.len - 1] = x
+ index = self.len
+ self.setlen(index + 1)
+ self.buffer[index] = x
# List interface
def descr_count(self, space, w_val):
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -404,6 +404,10 @@
raises(ValueError, self.array('i').tounicode)
assert self.array('u', 'hello').tounicode() == 'hello'
+ def test_empty_tostring(self):
+ a = self.array('l')
+ assert a.tostring() == b''
+
def test_buffer(self):
a = self.array('h', b'Hi')
buf = memoryview(a)
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -10,7 +10,7 @@
from rpython.rtyper.lltypesystem import ll2ctypes
from rpython.rtyper.annlowlevel import llhelper
from rpython.rlib.objectmodel import we_are_translated
-from rpython.conftest import cdir
+from rpython.translator import cdir
from rpython.translator.tool.cbuild import ExternalCompilationInfo
from rpython.translator.gensupp import NameManager
from rpython.tool.udir import udir
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
@@ -46,11 +46,11 @@
IndexError exception."""
if not isinstance(w_list, W_ListObject):
PyErr_BadInternalCall(space)
- wrappeditems = w_list.getitems()
- if index < 0 or index >= len(wrappeditems):
+ if index < 0 or index >= w_list.length():
raise OperationError(space.w_IndexError, space.wrap(
"list index out of range"))
- return borrow_from(w_list, wrappeditems[index])
+ w_item = w_list.getitem(index)
+ return borrow_from(w_list, w_item)
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -207,12 +207,7 @@
import sys
if sys.platform != "win32" or sys.version_info < (2, 6):
skip("Windows Python >= 2.6 only")
- assert sys.dllhandle
- assert sys.dllhandle.getaddressindll('PyPyErr_NewException')
- import ctypes # slow
- PyUnicode_GetDefaultEncoding = ctypes.pythonapi.PyPyUnicode_GetDefaultEncoding
- PyUnicode_GetDefaultEncoding.restype = ctypes.c_char_p
- assert PyUnicode_GetDefaultEncoding() == 'ascii'
+ assert isinstance(sys.dllhandle, int)
class AppTestCpythonExtensionBase(LeakCheckingTest):
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
@@ -560,8 +560,8 @@
def test_copy(self, space, api):
w_x = space.wrap(u"abcd\u0660")
- target_chunk, _ = rffi.alloc_unicodebuffer(space.int_w(space.len(w_x)))
- #lltype.malloc(Py_UNICODE, space.int_w(space.len(w_x)), flavor='raw')
+ count1 = space.int_w(space.len(w_x))
+ target_chunk = lltype.malloc(rffi.CWCHARP.TO, count1, flavor='raw')
x_chunk = api.PyUnicode_AS_UNICODE(w_x)
api.Py_UNICODE_COPY(target_chunk, x_chunk, 4)
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
@@ -12,7 +12,7 @@
'scalar' : 'ctors.build_scalar',
'array': 'ctors.array',
'zeros': 'ctors.zeros',
- 'empty': 'ctors.zeros',
+ 'empty': 'ctors.empty',
'empty_like': 'ctors.empty_like',
'fromstring': 'ctors.fromstring',
'frombuffer': 'ctors.frombuffer',
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
@@ -18,7 +18,12 @@
pass
-class W_NDimArray(W_Root):
+class W_NumpyObject(W_Root):
+ """Base class for ndarrays and scalars (aka boxes)."""
+ _attrs_ = []
+
+
+class W_NDimArray(W_NumpyObject):
__metaclass__ = extendabletype
def __init__(self, implementation):
@@ -28,12 +33,12 @@
self.implementation = implementation
@staticmethod
- def from_shape(space, shape, dtype, order='C', w_instance=None):
+ def from_shape(space, shape, dtype, order='C', w_instance=None, zero=True):
from pypy.module.micronumpy import concrete
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)
+ backstrides, zero=zero)
if w_instance:
return wrap_impl(space, space.type(w_instance), w_instance, impl)
return W_NDimArray(impl)
@@ -85,6 +90,14 @@
w_val = dtype.coerce(space, space.wrap(0))
return convert_to_array(space, w_val)
+ @staticmethod
+ def from_scalar(space, w_scalar):
+ """Convert a scalar into a 0-dim array"""
+ dtype = w_scalar.get_dtype(space)
+ w_arr = W_NDimArray.from_shape(space, [], dtype)
+ w_arr.set_scalar_value(w_scalar)
+ return w_arr
+
def convert_to_array(space, w_obj):
from pypy.module.micronumpy.ctors import array
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
@@ -1,4 +1,3 @@
-from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.mixedmodule import MixedModule
@@ -14,7 +13,7 @@
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.tool.sourcetools import func_with_new_name
from pypy.module.micronumpy import constants as NPY
-from pypy.module.micronumpy.base import W_NDimArray
+from pypy.module.micronumpy.base import W_NDimArray, W_NumpyObject
from pypy.module.micronumpy.concrete import VoidBoxStorage
from pypy.module.micronumpy.flagsobj import W_FlagsObject
@@ -126,7 +125,7 @@
return ret
-class W_GenericBox(W_Root):
+class W_GenericBox(W_NumpyObject):
_attrs_ = ['w_flags']
def descr__new__(space, w_subtype, __args__):
@@ -136,6 +135,12 @@
def get_dtype(self, space):
return self._get_dtype(space)
+ def is_scalar(self):
+ return True
+
+ def get_scalar_value(self):
+ return self
+
def item(self, space):
return self.get_dtype(space).itemtype.to_builtin_type(space, self)
@@ -148,6 +153,13 @@
raise OperationError(space.w_IndexError, space.wrap(
"invalid index to scalar variable"))
+ '''
+ def descr_iter(self, space):
+ # Making numpy scalar non-iterable with a valid __getitem__ method
+ raise oefmt(space.w_TypeError,
+ "'%T' object is not iterable", self)
+ '''
+
def descr_str(self, space):
return space.wrap(self.get_dtype(space).itemtype.str_format(self))
@@ -539,6 +551,7 @@
__new__ = interp2app(W_GenericBox.descr__new__.im_func),
__getitem__ = interp2app(W_GenericBox.descr_getitem),
+ #__iter__ = interp2app(W_GenericBox.descr_iter),
__str__ = interp2app(W_GenericBox.descr_str),
__repr__ = interp2app(W_GenericBox.descr_str),
__format__ = interp2app(W_GenericBox.descr_format),
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
@@ -369,9 +369,11 @@
class ConcreteArray(ConcreteArrayNotOwning):
- def __init__(self, shape, dtype, order, strides, backstrides, storage=lltype.nullptr(RAW_STORAGE)):
+ def __init__(self, shape, dtype, order, strides, backstrides,
+ storage=lltype.nullptr(RAW_STORAGE), zero=True):
if storage == lltype.nullptr(RAW_STORAGE):
- storage = dtype.itemtype.malloc(support.product(shape) * dtype.elsize)
+ storage = dtype.itemtype.malloc(support.product(shape) *
+ dtype.elsize, zero=zero)
ConcreteArrayNotOwning.__init__(self, shape, dtype, order, strides, backstrides,
storage)
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
@@ -4,7 +4,8 @@
from rpython.rlib.rstring import strip_spaces
from rpython.rtyper.lltypesystem import lltype, rffi
from pypy.module.micronumpy import descriptor, loop
-from pypy.module.micronumpy.base import W_NDimArray, convert_to_array
+from pypy.module.micronumpy.base import (
+ W_NDimArray, convert_to_array, W_NumpyObject)
from pypy.module.micronumpy.converters import shape_converter
@@ -24,24 +25,44 @@
return box
+def try_array_method(space, w_object, w_dtype=None):
+ w___array__ = space.lookup(w_object, "__array__")
+ if w___array__ is None:
+ return None
+ if w_dtype is None:
+ w_dtype = space.w_None
+ w_array = space.get_and_call_function(w___array__, w_object, w_dtype)
+ if isinstance(w_array, W_NDimArray):
+ return w_array
+ else:
+ raise oefmt(space.w_ValueError,
+ "object __array__ method not producing an array")
+
+
@unwrap_spec(ndmin=int, copy=bool, subok=bool)
def array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False,
ndmin=0):
+ w_res = _array(space, w_object, w_dtype, copy, w_order, subok)
+ shape = w_res.get_shape()
+ if len(shape) < ndmin:
+ shape = [1] * (ndmin - len(shape)) + shape
+ impl = w_res.implementation.set_shape(space, w_res, shape)
+ if w_res is w_object:
+ return W_NDimArray(impl)
+ else:
+ w_res.implementation = impl
+ return w_res
+
+def _array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False):
from pypy.module.micronumpy import strides
# for anything that isn't already an array, try __array__ method first
if not isinstance(w_object, W_NDimArray):
- w___array__ = space.lookup(w_object, "__array__")
- if w___array__ is not None:
- if space.is_none(w_dtype):
- w_dtype = space.w_None
- w_array = space.get_and_call_function(w___array__, w_object, w_dtype)
- if isinstance(w_array, W_NDimArray):
- # feed w_array back into array() for other properties
- return array(space, w_array, w_dtype, False, w_order, subok, ndmin)
- else:
- raise oefmt(space.w_ValueError,
- "object __array__ method not producing an array")
+ w_array = try_array_method(space, w_object, w_dtype)
+ if w_array is not None:
+ # continue with w_array, but do further operations in place
+ w_object = w_array
+ copy = False
dtype = descriptor.decode_w_dtype(space, w_dtype)
@@ -57,19 +78,10 @@
# arrays with correct dtype
if isinstance(w_object, W_NDimArray) and \
(space.is_none(w_dtype) or w_object.get_dtype() is dtype):
- shape = w_object.get_shape()
if copy:
- w_ret = w_object.descr_copy(space)
+ return w_object.descr_copy(space)
else:
- if ndmin <= len(shape):
- return w_object
- new_impl = w_object.implementation.set_shape(space, w_object, shape)
- w_ret = W_NDimArray(new_impl)
- if ndmin > len(shape):
- shape = [1] * (ndmin - len(shape)) + shape
- w_ret.implementation = w_ret.implementation.set_shape(space,
- w_ret, shape)
- return w_ret
+ return w_object
# not an array or incorrect dtype
shape, elems_w = strides.find_shape_and_elems(space, w_object, dtype)
@@ -81,8 +93,6 @@
# promote S0 -> S1, U0 -> U1
dtype = descriptor.variable_dtype(space, dtype.char + '1')
- if ndmin > len(shape):
- shape = [1] * (ndmin - len(shape)) + shape
w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
if len(elems_w) == 1:
w_arr.set_scalar_value(dtype.coerce(space, elems_w[0]))
@@ -91,13 +101,46 @@
return w_arr
-def zeros(space, w_shape, w_dtype=None, w_order=None):
+def numpify(space, w_object):
+ """Convert the object to a W_NumpyObject"""
+ # XXX: code duplication with _array()
+ from pypy.module.micronumpy import strides
+ if isinstance(w_object, W_NumpyObject):
+ return w_object
+ # for anything that isn't already an array, try __array__ method first
+ w_array = try_array_method(space, w_object)
+ if w_array is not None:
+ return w_array
+
+ shape, elems_w = strides.find_shape_and_elems(space, w_object, None)
+ dtype = strides.find_dtype_for_seq(space, elems_w, None)
+ if dtype is None:
+ dtype = descriptor.get_dtype_cache(space).w_float64dtype
+ elif dtype.is_str_or_unicode() and dtype.elsize < 1:
+ # promote S0 -> S1, U0 -> U1
+ dtype = descriptor.variable_dtype(space, dtype.char + '1')
+
+ if len(elems_w) == 1:
+ return dtype.coerce(space, elems_w[0])
+ else:
+ w_arr = W_NDimArray.from_shape(space, shape, dtype)
+ loop.assign(space, w_arr, elems_w)
+ return w_arr
+
+
+def _zeros_or_empty(space, w_shape, w_dtype, w_order, zero):
More information about the pypy-commit
mailing list