Author: Maciej Fijalkowski <[email protected]>
Branch: optresult
Changeset: r74903:30f34cca91d4
Date: 2014-12-12 18:43 +0200
http://bitbucket.org/pypy/pypy/changeset/30f34cca91d4/
Log: merge default
diff too long, truncating to 2000 out of 14889 lines
diff --git a/lib-python/2.7/sqlite3/test/dbapi.py
b/lib-python/2.7/sqlite3/test/dbapi.py
--- a/lib-python/2.7/sqlite3/test/dbapi.py
+++ b/lib-python/2.7/sqlite3/test/dbapi.py
@@ -478,6 +478,29 @@
except TypeError:
pass
+ def CheckCurDescription(self):
+ self.cu.execute("select * from test")
+
+ actual = self.cu.description
+ expected = [
+ ('id', None, None, None, None, None, None),
+ ('name', None, None, None, None, None, None),
+ ('income', None, None, None, None, None, None),
+ ]
+ self.assertEqual(expected, actual)
+
+ def CheckCurDescriptionVoidStatement(self):
+ self.cu.execute("insert into test(name) values (?)", ("foo",))
+ self.assertIsNone(self.cu.description)
+
+ def CheckCurDescriptionWithoutStatement(self):
+ cu = self.cx.cursor()
+ try:
+ self.assertIsNone(cu.description)
+ finally:
+ cu.close()
+
+
@unittest.skipUnless(threading, 'This test requires threading.')
class ThreadTests(unittest.TestCase):
def setUp(self):
diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py
--- a/lib-python/2.7/subprocess.py
+++ b/lib-python/2.7/subprocess.py
@@ -655,6 +655,21 @@
"""Create new Popen instance."""
_cleanup()
+ # --- PyPy hack, see _pypy_install_libs_after_virtualenv() ---
+ # match arguments passed by different versions of virtualenv
+ if args[1:] in (
+ ['-c', 'import sys; print(sys.prefix)'], # 1.6 10ba3f3c
+ ['-c', "\nimport sys\nprefix = sys.prefix\n" # 1.7 0e9342ce
+ "if sys.version_info[0] == 3:\n"
+ " prefix = prefix.encode('utf8')\n"
+ "if hasattr(sys.stdout, 'detach'):\n"
+ " sys.stdout = sys.stdout.detach()\n"
+ "elif hasattr(sys.stdout, 'buffer'):\n"
+ " sys.stdout = sys.stdout.buffer\nsys.stdout.write(prefix)\n"],
+ ['-c', 'import sys;out=sys.stdout;getattr(out, "buffer"'
+ ', out).write(sys.prefix.encode("utf-8"))']): # 1.7.2 a9454bce
+ _pypy_install_libs_after_virtualenv(args[0])
+
if not isinstance(bufsize, (int, long)):
raise TypeError("bufsize must be an integer")
@@ -1560,6 +1575,27 @@
self.send_signal(signal.SIGKILL)
+def _pypy_install_libs_after_virtualenv(target_executable):
+ # https://bitbucket.org/pypy/pypy/issue/1922/future-proofing-virtualenv
+ #
+ # PyPy 2.4.1 turned --shared on by default. This means the pypy binary
+ # depends on the 'libpypy-c.so' shared library to be able to run.
+ # The virtualenv code existing at the time did not account for this
+ # and would break. Try to detect that we're running under such a
+ # virtualenv in the "Testing executable with" phase and copy the
+ # library ourselves.
+ caller = sys._getframe(2)
+ if ('virtualenv_version' in caller.f_globals and
+ 'copyfile' in caller.f_globals):
+ dest_dir = sys.pypy_resolvedirof(target_executable)
+ src_dir = sys.pypy_resolvedirof(sys.executable)
+ for libname in ['libpypy-c.so']:
+ dest_library = os.path.join(dest_dir, libname)
+ src_library = os.path.join(src_dir, libname)
+ if os.path.exists(src_library):
+ caller.f_globals['copyfile'](src_library, dest_library)
+
+
def _demo_posix():
#
# Example 1: Simple redirection: Get process list
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -1175,8 +1175,11 @@
try:
return self.__description
except AttributeError:
- self.__description = self.__statement._get_description()
- return self.__description
+ try:
+ self.__description = self.__statement._get_description()
+ return self.__description
+ except AttributeError:
+ return None
description = property(__get_description)
def __get_lastrowid(self):
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -205,23 +205,28 @@
The above is true both in CPython and in PyPy. Differences
can occur about whether a built-in function or method will
call an overridden method of *another* object than ``self``.
-In PyPy, they are generally always called, whereas not in
-CPython. For example, in PyPy, ``dict1.update(dict2)``
-considers that ``dict2`` is just a general mapping object, and
-will thus call overridden ``keys()`` and ``__getitem__()``
-methods on it. So the following code prints ``42`` on PyPy
-but ``foo`` on CPython::
+In PyPy, they are often called in cases where CPython would not.
+Two examples::
- >>>> class D(dict):
- .... def __getitem__(self, key):
- .... return 42
- ....
- >>>>
- >>>> d1 = {}
- >>>> d2 = D(a='foo')
- >>>> d1.update(d2)
- >>>> print d1['a']
- 42
+ class D(dict):
+ def __getitem__(self, key):
+ return "%r from D" % (key,)
+
+ class A(object):
+ pass
+
+ a = A()
+ a.__dict__ = D()
+ a.foo = "a's own foo"
+ print a.foo
+ # CPython => a's own foo
+ # PyPy => 'foo' from D
+
+ glob = D(foo="base item")
+ loc = {}
+ exec "print foo" in glob, loc
+ # CPython => base item
+ # PyPy => 'foo' from D
Mutating classes of objects which are already used as dictionary keys
@@ -292,6 +297,9 @@
above types will return a value that is computed from the argument, and can
thus be larger than ``sys.maxint`` (i.e. it can be an arbitrary long).
+Notably missing from the list above are ``str`` and ``unicode``. If your
+code relies on comparing strings with ``is``, then it might break in PyPy.
+
Miscellaneous
-------------
diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst
--- a/pypy/doc/embedding.rst
+++ b/pypy/doc/embedding.rst
@@ -6,6 +6,10 @@
C. It was developed in collaboration with Roberto De Ioris from the `uwsgi`_
project. The `PyPy uwsgi plugin`_ is a good example of using the embedding API.
+**NOTE**: As of 1st of December, PyPy comes with ``--shared`` by default
+on linux, linux64 and windows. We will make it the default on all platforms
+by the time of the next release.
+
The first thing that you need is to compile PyPy yourself with the option
``--shared``. We plan to make ``--shared`` the default in the future. Consult
the `how to compile PyPy`_ doc for details. This will result in ``libpypy.so``
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -35,6 +35,13 @@
PyPy's bytearray type is very inefficient. It would be an interesting
task to look into possible optimizations on this.
+Implement AF_XXX packet types for PyPy
+--------------------------------------
+
+PyPy is missing AF_XXX types of sockets. Implementing it is easy-to-medium
+task. `bug report`_
+
+.. _`bug report`:
https://bitbucket.org/pypy/pypy/issue/1942/support-for-af_xxx-sockets#more
Implement copy-on-write list slicing
------------------------------------
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,15 +1,13 @@
-"""
-Python control flow graph generation and bytecode assembly.
-"""
+"""Python control flow graph generation and bytecode assembly."""
-from pypy.interpreter.astcompiler import ast, symtable
-from pypy.interpreter import pycode
+from rpython.rlib import rfloat
+from rpython.rlib.objectmodel import we_are_translated
+
+from pypy.interpreter.astcompiler import ast, misc, symtable
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.pycode import PyCode
from pypy.tool import stdlib_opcode as ops
-from pypy.interpreter.error import OperationError
-from rpython.rlib.objectmodel import we_are_translated
-from rpython.rlib import rfloat
-
class Instruction(object):
"""Represents a single opcode."""
@@ -21,14 +19,12 @@
self.has_jump = False
def size(self):
- """Return the size of bytes of this instruction when it is encoded."""
+ """Return the size of bytes of this instruction when it is
+ encoded.
+ """
if self.opcode >= ops.HAVE_ARGUMENT:
- if self.arg > 0xFFFF:
- return 6
- else:
- return 3
- else:
- return 1
+ return (6 if self.arg > 0xFFFF else 3)
+ return 1
def jump_to(self, target, absolute=False):
"""Indicate the target this jump instruction.
@@ -54,9 +50,9 @@
class Block(object):
"""A basic control flow block.
- It has one entry point and several possible exit points. Its instructions
- may be jumps to other blocks, or if control flow reaches the end of the
- block, it continues to next_block.
+ It has one entry point and several possible exit points. Its
+ instructions may be jumps to other blocks, or if control flow
+ reaches the end of the block, it continues to next_block.
"""
def __init__(self):
@@ -71,10 +67,10 @@
stack.append(nextblock)
def post_order(self):
- """Return this block and its children in post order.
- This means that the graph of blocks is first cleaned up to
- ignore back-edges, thus turning it into a DAG. Then the DAG
- is linearized. For example:
+ """Return this block and its children in post order. This means
+ that the graph of blocks is first cleaned up to ignore
+ back-edges, thus turning it into a DAG. Then the DAG is
+ linearized. For example:
A --> B -\ => [A, D, B, C]
\-> D ---> C
@@ -105,7 +101,9 @@
return resultblocks
def code_size(self):
- """Return the encoded size of all the instructions in this block."""
+ """Return the encoded size of all the instructions in this
+ block.
+ """
i = 0
for instr in self.instructions:
i += instr.size()
@@ -141,6 +139,7 @@
i += 1
return result
+
def _list_to_dict(l, offset=0):
result = {}
index = offset
@@ -300,11 +299,11 @@
def _resolve_block_targets(self, blocks):
"""Compute the arguments of jump instructions."""
last_extended_arg_count = 0
- # The reason for this loop is extended jumps. EXTENDED_ARG extends the
- # bytecode size, so it might invalidate the offsets we've already
given.
- # Thus we have to loop until the number of extended args is stable.
Any
- # extended jump at all is extremely rare, so performance is not too
- # concerning.
+ # The reason for this loop is extended jumps. EXTENDED_ARG
+ # extends the bytecode size, so it might invalidate the offsets
+ # we've already given. Thus we have to loop until the number of
+ # extended args is stable. Any extended jump at all is
+ # extremely rare, so performance is not too concerning.
while True:
extended_arg_count = 0
offset = 0
@@ -330,7 +329,8 @@
instr.opcode = ops.JUMP_ABSOLUTE
absolute = True
elif target_op == ops.RETURN_VALUE:
- # Replace JUMP_* to a RETURN into just a
RETURN
+ # Replace JUMP_* to a RETURN into
+ # just a RETURN
instr.opcode = ops.RETURN_VALUE
instr.arg = 0
instr.has_jump = False
@@ -345,7 +345,8 @@
instr.arg = jump_arg
if jump_arg > 0xFFFF:
extended_arg_count += 1
- if extended_arg_count == last_extended_arg_count and not
force_redo:
+ if (extended_arg_count == last_extended_arg_count and
+ not force_redo):
break
else:
last_extended_arg_count = extended_arg_count
@@ -360,12 +361,14 @@
while True:
try:
w_key = space.next(w_iter)
- except OperationError, e:
+ except OperationError as e:
if not e.match(space, space.w_StopIteration):
raise
break
w_index = space.getitem(w_consts, w_key)
- consts_w[space.int_w(w_index)] = space.getitem(w_key, first)
+ w_constant = space.getitem(w_key, first)
+ w_constant = misc.intern_if_common_string(space, w_constant)
+ consts_w[space.int_w(w_index)] = w_constant
return consts_w
def _get_code_flags(self):
@@ -433,15 +436,16 @@
continue
addr = offset - current_off
# Python assumes that lineno always increases with
- # increasing bytecode address (lnotab is unsigned char).
- # Depending on when SET_LINENO instructions are emitted
this
- # is not always true. Consider the code:
+ # increasing bytecode address (lnotab is unsigned
+ # char). Depending on when SET_LINENO instructions
+ # are emitted this is not always true. Consider the
+ # code:
# a = (1,
# b)
- # In the bytecode stream, the assignment to "a" occurs
after
- # the loading of "b". This works with the C Python
compiler
- # because it only generates a SET_LINENO instruction for
the
- # assignment.
+ # In the bytecode stream, the assignment to "a"
+ # occurs after the loading of "b". This works with
+ # the C Python compiler because it only generates a
+ # SET_LINENO instruction for the assignment.
if line or addr:
while addr > 255:
push(chr(255))
@@ -484,22 +488,22 @@
free_names = _list_from_dict(self.free_vars, len(cell_names))
flags = self._get_code_flags() | self.compile_info.flags
bytecode = ''.join([block.get_code() for block in blocks])
- return pycode.PyCode(self.space,
- self.argcount,
- len(self.var_names),
- stack_depth,
- flags,
- bytecode,
- list(consts_w),
- names,
- var_names,
- self.compile_info.filename,
- self.name,
- self.first_lineno,
- lnotab,
- free_names,
- cell_names,
- self.compile_info.hidden_applevel)
+ return PyCode(self.space,
+ self.argcount,
+ len(self.var_names),
+ stack_depth,
+ flags,
+ bytecode,
+ list(consts_w),
+ names,
+ var_names,
+ self.compile_info.filename,
+ self.name,
+ self.first_lineno,
+ lnotab,
+ free_names,
+ cell_names,
+ self.compile_info.hidden_applevel)
def _list_from_dict(d, offset=0):
@@ -510,134 +514,134 @@
_static_opcode_stack_effects = {
- ops.NOP : 0,
- ops.STOP_CODE : 0,
+ ops.NOP: 0,
+ ops.STOP_CODE: 0,
- ops.POP_TOP : -1,
- ops.ROT_TWO : 0,
- ops.ROT_THREE : 0,
- ops.ROT_FOUR : 0,
- ops.DUP_TOP : 1,
+ ops.POP_TOP: -1,
+ ops.ROT_TWO: 0,
+ ops.ROT_THREE: 0,
+ ops.ROT_FOUR: 0,
+ ops.DUP_TOP: 1,
- ops.UNARY_POSITIVE : 0,
- ops.UNARY_NEGATIVE : 0,
- ops.UNARY_NOT : 0,
- ops.UNARY_CONVERT : 0,
- ops.UNARY_INVERT : 0,
+ ops.UNARY_POSITIVE: 0,
+ ops.UNARY_NEGATIVE: 0,
+ ops.UNARY_NOT: 0,
+ ops.UNARY_CONVERT: 0,
+ ops.UNARY_INVERT: 0,
- ops.LIST_APPEND : -1,
- ops.SET_ADD : -1,
- ops.MAP_ADD : -2,
- ops.STORE_MAP : -2,
+ ops.LIST_APPEND: -1,
+ ops.SET_ADD: -1,
+ ops.MAP_ADD: -2,
+ ops.STORE_MAP: -2,
- ops.BINARY_POWER : -1,
- ops.BINARY_MULTIPLY : -1,
- ops.BINARY_DIVIDE : -1,
- ops.BINARY_MODULO : -1,
- ops.BINARY_ADD : -1,
- ops.BINARY_SUBTRACT : -1,
- ops.BINARY_SUBSCR : -1,
- ops.BINARY_FLOOR_DIVIDE : -1,
- ops.BINARY_TRUE_DIVIDE : -1,
- ops.BINARY_LSHIFT : -1,
- ops.BINARY_RSHIFT : -1,
- ops.BINARY_AND : -1,
- ops.BINARY_OR : -1,
- ops.BINARY_XOR : -1,
+ ops.BINARY_POWER: -1,
+ ops.BINARY_MULTIPLY: -1,
+ ops.BINARY_DIVIDE: -1,
+ ops.BINARY_MODULO: -1,
+ ops.BINARY_ADD: -1,
+ ops.BINARY_SUBTRACT: -1,
+ ops.BINARY_SUBSCR: -1,
+ ops.BINARY_FLOOR_DIVIDE: -1,
+ ops.BINARY_TRUE_DIVIDE: -1,
+ ops.BINARY_LSHIFT: -1,
+ ops.BINARY_RSHIFT: -1,
+ ops.BINARY_AND: -1,
+ ops.BINARY_OR: -1,
+ ops.BINARY_XOR: -1,
- ops.INPLACE_FLOOR_DIVIDE : -1,
- ops.INPLACE_TRUE_DIVIDE : -1,
- ops.INPLACE_ADD : -1,
- ops.INPLACE_SUBTRACT : -1,
- ops.INPLACE_MULTIPLY : -1,
- ops.INPLACE_DIVIDE : -1,
- ops.INPLACE_MODULO : -1,
- ops.INPLACE_POWER : -1,
- ops.INPLACE_LSHIFT : -1,
- ops.INPLACE_RSHIFT : -1,
- ops.INPLACE_AND : -1,
- ops.INPLACE_OR : -1,
- ops.INPLACE_XOR : -1,
+ ops.INPLACE_FLOOR_DIVIDE: -1,
+ ops.INPLACE_TRUE_DIVIDE: -1,
+ ops.INPLACE_ADD: -1,
+ ops.INPLACE_SUBTRACT: -1,
+ ops.INPLACE_MULTIPLY: -1,
+ ops.INPLACE_DIVIDE: -1,
+ ops.INPLACE_MODULO: -1,
+ ops.INPLACE_POWER: -1,
+ ops.INPLACE_LSHIFT: -1,
+ ops.INPLACE_RSHIFT: -1,
+ ops.INPLACE_AND: -1,
+ 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.STORE_SLICE+0 : -2,
- ops.STORE_SLICE+1 : -3,
- ops.STORE_SLICE+2 : -3,
- ops.STORE_SLICE+3 : -4,
- ops.DELETE_SLICE+0 : -1,
- ops.DELETE_SLICE+1 : -2,
- ops.DELETE_SLICE+2 : -2,
- ops.DELETE_SLICE+3 : -3,
+ ops.SLICE+0: 1,
+ ops.SLICE+1: 0,
+ ops.SLICE+2: 0,
+ ops.SLICE+3: -1,
+ ops.STORE_SLICE+0: -2,
+ ops.STORE_SLICE+1: -3,
+ ops.STORE_SLICE+2: -3,
+ ops.STORE_SLICE+3: -4,
+ ops.DELETE_SLICE+0: -1,
+ ops.DELETE_SLICE+1: -2,
+ ops.DELETE_SLICE+2: -2,
+ ops.DELETE_SLICE+3: -3,
- ops.STORE_SUBSCR : -2,
- ops.DELETE_SUBSCR : -2,
+ ops.STORE_SUBSCR: -2,
+ ops.DELETE_SUBSCR: -2,
- ops.GET_ITER : 0,
- ops.FOR_ITER : 1,
- ops.BREAK_LOOP : 0,
- ops.CONTINUE_LOOP : 0,
- ops.SETUP_LOOP : 0,
+ ops.GET_ITER: 0,
+ ops.FOR_ITER: 1,
+ ops.BREAK_LOOP: 0,
+ ops.CONTINUE_LOOP: 0,
+ ops.SETUP_LOOP: 0,
- ops.PRINT_EXPR : -1,
- ops.PRINT_ITEM : -1,
- ops.PRINT_NEWLINE : 0,
- ops.PRINT_ITEM_TO : -2,
- ops.PRINT_NEWLINE_TO : -1,
+ ops.PRINT_EXPR: -1,
+ ops.PRINT_ITEM: -1,
+ ops.PRINT_NEWLINE: 0,
+ ops.PRINT_ITEM_TO: -2,
+ ops.PRINT_NEWLINE_TO: -1,
- ops.WITH_CLEANUP : -1,
- ops.POP_BLOCK : 0,
- ops.END_FINALLY : -1,
- ops.SETUP_WITH : 1,
- ops.SETUP_FINALLY : 0,
- ops.SETUP_EXCEPT : 0,
+ ops.WITH_CLEANUP: -1,
+ ops.POP_BLOCK: 0,
+ ops.END_FINALLY: -1,
+ ops.SETUP_WITH: 1,
+ ops.SETUP_FINALLY: 0,
+ ops.SETUP_EXCEPT: 0,
- ops.LOAD_LOCALS : 1,
- ops.RETURN_VALUE : -1,
- ops.EXEC_STMT : -3,
- ops.YIELD_VALUE : 0,
- ops.BUILD_CLASS : -2,
- ops.BUILD_MAP : 1,
- ops.BUILD_SET : 1,
- ops.COMPARE_OP : -1,
+ ops.LOAD_LOCALS: 1,
+ ops.RETURN_VALUE: -1,
+ ops.EXEC_STMT: -3,
+ ops.YIELD_VALUE: 0,
+ ops.BUILD_CLASS: -2,
+ ops.BUILD_MAP: 1,
+ ops.BUILD_SET: 1,
+ ops.COMPARE_OP: -1,
- ops.LOOKUP_METHOD : 1,
+ ops.LOOKUP_METHOD: 1,
- ops.LOAD_NAME : 1,
- ops.STORE_NAME : -1,
- ops.DELETE_NAME : 0,
+ ops.LOAD_NAME: 1,
+ ops.STORE_NAME: -1,
+ ops.DELETE_NAME: 0,
- ops.LOAD_FAST : 1,
- ops.STORE_FAST : -1,
- ops.DELETE_FAST : 0,
+ ops.LOAD_FAST: 1,
+ ops.STORE_FAST: -1,
+ ops.DELETE_FAST: 0,
- ops.LOAD_ATTR : 0,
- ops.STORE_ATTR : -2,
- ops.DELETE_ATTR : -1,
+ ops.LOAD_ATTR: 0,
+ ops.STORE_ATTR: -2,
+ ops.DELETE_ATTR: -1,
- ops.LOAD_GLOBAL : 1,
- ops.STORE_GLOBAL : -1,
- ops.DELETE_GLOBAL : 0,
+ ops.LOAD_GLOBAL: 1,
+ ops.STORE_GLOBAL: -1,
+ ops.DELETE_GLOBAL: 0,
- ops.LOAD_CLOSURE : 1,
- ops.LOAD_DEREF : 1,
- ops.STORE_DEREF : -1,
+ ops.LOAD_CLOSURE: 1,
+ ops.LOAD_DEREF: 1,
+ ops.STORE_DEREF: -1,
- ops.LOAD_CONST : 1,
+ ops.LOAD_CONST: 1,
- ops.IMPORT_STAR : -1,
- ops.IMPORT_NAME : -1,
- ops.IMPORT_FROM : 1,
+ ops.IMPORT_STAR: -1,
+ ops.IMPORT_NAME: -1,
+ ops.IMPORT_FROM: 1,
- ops.JUMP_FORWARD : 0,
- ops.JUMP_ABSOLUTE : 0,
- ops.JUMP_IF_TRUE_OR_POP : 0,
- ops.JUMP_IF_FALSE_OR_POP : 0,
- ops.POP_JUMP_IF_TRUE : -1,
- ops.POP_JUMP_IF_FALSE : -1,
- ops.JUMP_IF_NOT_DEBUG : 0,
+ ops.JUMP_FORWARD: 0,
+ ops.JUMP_ABSOLUTE: 0,
+ ops.JUMP_IF_TRUE_OR_POP: 0,
+ ops.JUMP_IF_FALSE_OR_POP: 0,
+ ops.POP_JUMP_IF_TRUE: -1,
+ ops.POP_JUMP_IF_FALSE: -1,
+ ops.JUMP_IF_NOT_DEBUG: 0,
ops.BUILD_LIST_FROM_ARG: 1,
}
diff --git a/pypy/interpreter/astcompiler/misc.py
b/pypy/interpreter/astcompiler/misc.py
--- a/pypy/interpreter/astcompiler/misc.py
+++ b/pypy/interpreter/astcompiler/misc.py
@@ -106,3 +106,13 @@
except IndexError:
return name
return "_%s%s" % (klass[i:], name)
+
+
+def intern_if_common_string(space, w_const):
+ # only intern identifier-like strings
+ if not space.is_w(space.type(w_const), space.w_str):
+ return w_const
+ for c in space.str_w(w_const):
+ if not (c.isalnum() or c == '_'):
+ return w_const
+ return space.new_interned_w_str(w_const)
diff --git a/pypy/interpreter/astcompiler/optimize.py
b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -272,6 +272,11 @@
if w_const is None:
return tup
consts_w[i] = w_const
+ # intern the string constants packed into the tuple here,
+ # because assemble.py will see the result as just a tuple constant
+ for i in range(len(consts_w)):
+ consts_w[i] = misc.intern_if_common_string(
+ self.space, consts_w[i])
else:
consts_w = []
w_consts = self.space.newtuple(consts_w)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -14,7 +14,7 @@
UserDelAction)
from pypy.interpreter.error import OperationError, new_exception_class, oefmt
from pypy.interpreter.argument import Arguments
-from pypy.interpreter.miscutils import ThreadLocals
+from pypy.interpreter.miscutils import ThreadLocals, make_weak_value_dictionary
__all__ = ['ObjSpace', 'OperationError', 'W_Root']
@@ -384,7 +384,7 @@
self.builtin_modules = {}
self.reloading_modules = {}
- self.interned_strings = {}
+ self.interned_strings = make_weak_value_dictionary(self, str, W_Root)
self.actionflag = ActionFlag() # changed by the signal module
self.check_signal_action = None # changed by the signal module
self.user_del_action = UserDelAction(self)
@@ -777,25 +777,30 @@
return self.w_False
def new_interned_w_str(self, w_s):
+ assert isinstance(w_s, W_Root) # and is not None
s = self.str_w(w_s)
if not we_are_translated():
assert type(s) is str
- try:
- return self.interned_strings[s]
- except KeyError:
- pass
- self.interned_strings[s] = w_s
- return w_s
+ w_s1 = self.interned_strings.get(s)
+ if w_s1 is None:
+ w_s1 = w_s
+ self.interned_strings.set(s, w_s1)
+ return w_s1
def new_interned_str(self, s):
if not we_are_translated():
assert type(s) is str
- try:
- return self.interned_strings[s]
- except KeyError:
- pass
- w_s = self.interned_strings[s] = self.wrap(s)
- return w_s
+ w_s1 = self.interned_strings.get(s)
+ if w_s1 is None:
+ w_s1 = self.wrap(s)
+ self.interned_strings.set(s, w_s1)
+ return w_s1
+
+ def is_interned_str(self, s):
+ # interface for marshal_impl
+ if not we_are_translated():
+ assert type(s) is str
+ return self.interned_strings.get(s) is not None
def descr_self_interp_w(self, RequiredClass, w_obj):
if not isinstance(w_obj, RequiredClass):
diff --git a/pypy/interpreter/miscutils.py b/pypy/interpreter/miscutils.py
--- a/pypy/interpreter/miscutils.py
+++ b/pypy/interpreter/miscutils.py
@@ -31,3 +31,19 @@
def getallvalues(self):
return {0: self._value}
+
+
+def make_weak_value_dictionary(space, keytype, valuetype):
+ "NOT_RPYTHON"
+ if space.config.translation.rweakref:
+ from rpython.rlib.rweakref import RWeakValueDictionary
+ return RWeakValueDictionary(keytype, valuetype)
+ else:
+ class FakeWeakValueDict(object):
+ def __init__(self):
+ self._dict = {}
+ def get(self, key):
+ return self._dict.get(key, None)
+ def set(self, key, value):
+ self._dict[key] = value
+ return FakeWeakValueDict()
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -125,13 +125,14 @@
else:
return self.space.builtin
+ _NO_CELLS = []
+
@jit.unroll_safe
def initialize_frame_scopes(self, outer_func, code):
# regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
# class bodies only have CO_NEWLOCALS.
# CO_NEWLOCALS: make a locals dict unless optimized is also set
# CO_OPTIMIZED: no locals dict needed at all
- # NB: this method is overridden in nestedscope.py
flags = code.co_flags
if not (flags & pycode.CO_OPTIMIZED):
if flags & pycode.CO_NEWLOCALS:
@@ -144,7 +145,7 @@
nfreevars = len(code.co_freevars)
if not nfreevars:
if not ncellvars:
- self.cells = []
+ self.cells = self._NO_CELLS
return # no self.cells needed - fast path
elif outer_func is None:
space = self.space
diff --git a/pypy/interpreter/test/test_compiler.py
b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -970,7 +970,12 @@
sys.stdout = out
output = s.getvalue()
assert "CALL_METHOD" in output
-
+
+ def test_interned_strings(self):
+ source = """x = ('foo_bar42', 5); y = 'foo_bar42'; z = x[0]"""
+ exec source
+ assert y is z
+
class AppTestExceptions:
def test_indentation_error(self):
diff --git a/pypy/interpreter/test/test_objspace.py
b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -378,3 +378,41 @@
assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar'
space.startup()
assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar'
+
+ def test_interned_strings_are_weak(self):
+ import weakref, gc, random
+ space = self.space
+ assert space.config.translation.rweakref
+ w1 = space.new_interned_str("abcdef")
+ w2 = space.new_interned_str("abcdef")
+ assert w2 is w1
+ #
+ # check that 'w1' goes away if we don't hold a reference to it
+ rw1 = weakref.ref(w1)
+ del w1, w2
+ i = 10
+ while rw1() is not None:
+ i -= 1
+ assert i >= 0
+ gc.collect()
+ #
+ s = "foobar%r" % random.random()
+ w0 = space.wrap(s)
+ w1 = space.new_interned_w_str(w0)
+ assert w1 is w0
+ w2 = space.new_interned_w_str(w0)
+ assert w2 is w0
+ w3 = space.wrap(s)
+ assert w3 is not w0
+ w4 = space.new_interned_w_str(w3)
+ assert w4 is w0
+ #
+ # check that 'w0' goes away if we don't hold a reference to it
+ # (even if we hold a reference to 'w3')
+ rw0 = weakref.ref(w0)
+ del w0, w1, w2, w4
+ i = 10
+ while rw0() is not None:
+ i -= 1
+ assert i >= 0
+ gc.collect()
diff --git a/pypy/module/_cffi_backend/ctypeprim.py
b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -158,21 +158,14 @@
class W_CTypePrimitiveSigned(W_CTypePrimitive):
- _attrs_ = ['value_fits_long', 'vmin', 'vrangemax']
- _immutable_fields_ = ['value_fits_long', 'vmin', 'vrangemax']
+ _attrs_ = ['value_fits_long', 'value_smaller_than_long']
+ _immutable_fields_ = ['value_fits_long', 'value_smaller_than_long']
is_primitive_integer = True
def __init__(self, *args):
W_CTypePrimitive.__init__(self, *args)
self.value_fits_long = self.size <= rffi.sizeof(lltype.Signed)
- if self.size < rffi.sizeof(lltype.Signed):
- assert self.value_fits_long
- sh = self.size * 8
- self.vmin = r_uint(-1) << (sh - 1)
- self.vrangemax = (r_uint(1) << sh) - 1
- else:
- self.vmin = r_uint(0)
- self.vrangemax = r_uint(-1)
+ self.value_smaller_than_long = self.size < rffi.sizeof(lltype.Signed)
def cast_to_int(self, cdata):
return self.convert_to_object(cdata)
@@ -192,8 +185,17 @@
def convert_from_object(self, cdata, w_ob):
if self.value_fits_long:
value = misc.as_long(self.space, w_ob)
- if self.size < rffi.sizeof(lltype.Signed):
- if r_uint(value) - self.vmin > self.vrangemax:
+ if self.value_smaller_than_long:
+ size = self.size
+ if size == 1:
+ signextended = misc.signext(value, 1)
+ elif size == 2:
+ signextended = misc.signext(value, 2)
+ elif size == 4:
+ signextended = misc.signext(value, 4)
+ else:
+ raise AssertionError("unsupported size")
+ if value != signextended:
self._overflow(w_ob)
misc.write_raw_signed_data(cdata, value, self.size)
else:
@@ -221,7 +223,7 @@
length = w_cdata.get_array_length()
populate_list_from_raw_array(res, buf, length)
return res
- elif self.value_fits_long:
+ elif self.value_smaller_than_long:
res = [0] * w_cdata.get_array_length()
misc.unpack_list_from_raw_array(res, w_cdata._cdata, self.size)
return res
@@ -235,8 +237,8 @@
cdata = rffi.cast(rffi.LONGP, cdata)
copy_list_to_raw_array(int_list, cdata)
else:
- overflowed = misc.pack_list_to_raw_array_bounds(
- int_list, cdata, self.size, self.vmin, self.vrangemax)
+ overflowed = misc.pack_list_to_raw_array_bounds_signed(
+ int_list, cdata, self.size)
if overflowed != 0:
self._overflow(self.space.wrap(overflowed))
return True
@@ -314,8 +316,8 @@
def pack_list_of_items(self, cdata, w_ob):
int_list = self.space.listview_int(w_ob)
if int_list is not None:
- overflowed = misc.pack_list_to_raw_array_bounds(
- int_list, cdata, self.size, r_uint(0), self.vrangemax)
+ overflowed = misc.pack_list_to_raw_array_bounds_unsigned(
+ int_list, cdata, self.size, self.vrangemax)
if overflowed != 0:
self._overflow(self.space.wrap(overflowed))
return True
diff --git a/pypy/module/_cffi_backend/misc.py
b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -216,6 +216,19 @@
neg_msg = "can't convert negative number to unsigned"
ovf_msg = "long too big to convert"
[email protected](1)
+def signext(value, size):
+ # 'value' is sign-extended from 'size' bytes to a full integer.
+ # 'size' should be a constant smaller than a full integer size.
+ if size == rffi.sizeof(rffi.SIGNEDCHAR):
+ return rffi.cast(lltype.Signed, rffi.cast(rffi.SIGNEDCHAR, value))
+ elif size == rffi.sizeof(rffi.SHORT):
+ return rffi.cast(lltype.Signed, rffi.cast(rffi.SHORT, value))
+ elif size == rffi.sizeof(rffi.INT):
+ return rffi.cast(lltype.Signed, rffi.cast(rffi.INT, value))
+ else:
+ raise AssertionError("unsupported size")
+
# ____________________________________________________________
class _NotStandardObject(Exception):
@@ -334,13 +347,26 @@
# ____________________________________________________________
-def pack_list_to_raw_array_bounds(int_list, target, size, vmin, vrangemax):
+def pack_list_to_raw_array_bounds_signed(int_list, target, size):
for TP, TPP in _prim_signed_types:
if size == rffi.sizeof(TP):
ptr = rffi.cast(TPP, target)
for i in range(len(int_list)):
x = int_list[i]
- if r_uint(x) - vmin > vrangemax:
+ y = rffi.cast(TP, x)
+ if x != rffi.cast(lltype.Signed, y):
+ return x # overflow
+ ptr[i] = y
+ return 0
+ raise NotImplementedError("bad integer size")
+
+def pack_list_to_raw_array_bounds_unsigned(int_list, target, size, vrangemax):
+ for TP, TPP in _prim_signed_types:
+ if size == rffi.sizeof(TP):
+ ptr = rffi.cast(TPP, target)
+ for i in range(len(int_list)):
+ x = int_list[i]
+ if r_uint(x) > vrangemax:
return x # overflow
ptr[i] = rffi.cast(TP, x)
return 0
diff --git a/pypy/module/_file/test/test_file.py
b/pypy/module/_file/test/test_file.py
--- a/pypy/module/_file/test/test_file.py
+++ b/pypy/module/_file/test/test_file.py
@@ -304,7 +304,7 @@
py.test.skip("works with internals of _file impl on py.py")
state = [0]
def read(fd, n=None):
- if fd != 42:
+ if fd != 424242:
return cls.old_read(fd, n)
if state[0] == 0:
state[0] += 1
@@ -315,7 +315,7 @@
return ''
os.read = read
stdin = W_File(cls.space)
- stdin.file_fdopen(42, 'rb', 1)
+ stdin.file_fdopen(424242, 'rb', 1)
stdin.name = '<stdin>'
cls.w_stream = stdin
diff --git a/pypy/module/_rawffi/alt/interp_funcptr.py
b/pypy/module/_rawffi/alt/interp_funcptr.py
--- a/pypy/module/_rawffi/alt/interp_funcptr.py
+++ b/pypy/module/_rawffi/alt/interp_funcptr.py
@@ -14,6 +14,7 @@
from rpython.rlib.objectmodel import we_are_translated
from pypy.module._rawffi.alt.type_converter import FromAppLevelConverter,
ToAppLevelConverter
from pypy.module._rawffi.interp_rawffi import got_libffi_error,
wrap_dlopenerror
+from pypy.module._rawffi import lasterror
import os
if os.name == 'nt':
@@ -201,11 +202,23 @@
self.func = func
self.argchain = argchain
+ def before(self):
+ lasterror.restore_last_error(self.space)
+
+ def after(self):
+ lasterror.save_last_error(self.space)
+
def get_longlong(self, w_ffitype):
- return self.func.call(self.argchain, rffi.LONGLONG)
+ self.before()
+ x = self.func.call(self.argchain, rffi.LONGLONG)
+ self.after()
+ return x
def get_ulonglong(self, w_ffitype):
- return self.func.call(self.argchain, rffi.ULONGLONG)
+ self.before()
+ x = self.func.call(self.argchain, rffi.ULONGLONG)
+ self.after()
+ return x
def get_signed(self, w_ffitype):
# if the declared return type of the function is smaller than LONG,
@@ -216,64 +229,94 @@
# to space.wrap in order to get a nice applevel <int>.
#
restype = w_ffitype.get_ffitype()
+ self.before()
call = self.func.call
if restype is libffi.types.slong:
- return call(self.argchain, rffi.LONG)
+ x = call(self.argchain, rffi.LONG)
elif restype is libffi.types.sint:
- return rffi.cast(rffi.LONG, call(self.argchain, rffi.INT))
+ x = rffi.cast(rffi.LONG, call(self.argchain, rffi.INT))
elif restype is libffi.types.sshort:
- return rffi.cast(rffi.LONG, call(self.argchain, rffi.SHORT))
+ x = rffi.cast(rffi.LONG, call(self.argchain, rffi.SHORT))
elif restype is libffi.types.schar:
- return rffi.cast(rffi.LONG, call(self.argchain, rffi.SIGNEDCHAR))
+ x = rffi.cast(rffi.LONG, call(self.argchain, rffi.SIGNEDCHAR))
else:
- self.error(w_ffitype)
+ raise self.error(w_ffitype)
+ self.after()
+ return x
def get_unsigned(self, w_ffitype):
- return self.func.call(self.argchain, rffi.ULONG)
+ self.before()
+ x = self.func.call(self.argchain, rffi.ULONG)
+ self.after()
+ return x
def get_unsigned_which_fits_into_a_signed(self, w_ffitype):
# the same comment as get_signed apply
restype = w_ffitype.get_ffitype()
+ self.before()
call = self.func.call
if restype is libffi.types.uint:
assert not libffi.IS_32_BIT
# on 32bit machines, we should never get here, because it's a case
# which has already been handled by get_unsigned above.
- return rffi.cast(rffi.LONG, call(self.argchain, rffi.UINT))
+ x = rffi.cast(rffi.LONG, call(self.argchain, rffi.UINT))
elif restype is libffi.types.ushort:
- return rffi.cast(rffi.LONG, call(self.argchain, rffi.USHORT))
+ x = rffi.cast(rffi.LONG, call(self.argchain, rffi.USHORT))
elif restype is libffi.types.uchar:
- return rffi.cast(rffi.LONG, call(self.argchain, rffi.UCHAR))
+ x = rffi.cast(rffi.LONG, call(self.argchain, rffi.UCHAR))
else:
- self.error(w_ffitype)
+ raise self.error(w_ffitype)
+ self.after()
+ return x
def get_pointer(self, w_ffitype):
+ self.before()
ptrres = self.func.call(self.argchain, rffi.VOIDP)
+ self.after()
return rffi.cast(rffi.ULONG, ptrres)
def get_char(self, w_ffitype):
- return self.func.call(self.argchain, rffi.UCHAR)
+ self.before()
+ x = self.func.call(self.argchain, rffi.UCHAR)
+ self.after()
+ return x
def get_unichar(self, w_ffitype):
- return self.func.call(self.argchain, rffi.WCHAR_T)
+ self.before()
+ x = self.func.call(self.argchain, rffi.WCHAR_T)
+ self.after()
+ return x
def get_float(self, w_ffitype):
- return self.func.call(self.argchain, rffi.DOUBLE)
+ self.before()
+ x = self.func.call(self.argchain, rffi.DOUBLE)
+ self.after()
+ return x
def get_singlefloat(self, w_ffitype):
- return self.func.call(self.argchain, rffi.FLOAT)
+ self.before()
+ x = self.func.call(self.argchain, rffi.FLOAT)
+ self.after()
+ return x
def get_struct(self, w_ffitype, w_structdescr):
+ self.before()
addr = self.func.call(self.argchain, rffi.LONG, is_struct=True)
+ self.after()
return w_structdescr.fromaddress(self.space, addr)
def get_struct_rawffi(self, w_ffitype, w_structdescr):
+ self.before()
uintval = self.func.call(self.argchain, rffi.ULONG, is_struct=True)
+ self.after()
return w_structdescr.fromaddress(self.space, uintval)
def get_void(self, w_ffitype):
- return self.func.call(self.argchain, lltype.Void)
+ self.before()
+ x = self.func.call(self.argchain, lltype.Void)
+ self.after()
+ return x
def unpack_argtypes(space, w_argtypes, w_restype):
diff --git a/pypy/module/_rawffi/interp_rawffi.py
b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -18,6 +18,7 @@
from rpython.rlib.rarithmetic import intmask, r_uint
from pypy.module._rawffi.buffer import RawFFIBuffer
from pypy.module._rawffi.tracker import tracker
+from pypy.module._rawffi import lasterror
TYPEMAP = {
# XXX A mess with unsigned/signed/normal chars :-/
@@ -495,10 +496,14 @@
try:
if self.resshape is not None:
result = self.resshape.allocate(space, 1, autofree=True)
+ lasterror.restore_last_error(space)
self.ptr.call(args_ll, result.ll_buffer)
+ lasterror.save_last_error(space)
return space.wrap(result)
else:
+ lasterror.restore_last_error(space)
self.ptr.call(args_ll, lltype.nullptr(rffi.VOIDP.TO))
+ lasterror.save_last_error(space)
return space.w_None
except StackCheckError, e:
raise OperationError(space.w_ValueError, space.wrap(e.message))
@@ -615,12 +620,10 @@
if sys.platform == 'win32':
def get_last_error(space):
- from rpython.rlib.rwin32 import GetLastError
- return space.wrap(GetLastError())
+ return space.wrap(lasterror.fetch_last_error(space))
@unwrap_spec(error=int)
def set_last_error(space, error):
- from rpython.rlib.rwin32 import SetLastError
- SetLastError(error)
+ lasterror.store_last_error(space, error)
else:
# always have at least a dummy version of these functions
# (https://bugs.pypy.org/issue1242)
diff --git a/pypy/module/_rawffi/lasterror.py b/pypy/module/_rawffi/lasterror.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_rawffi/lasterror.py
@@ -0,0 +1,40 @@
+# For Windows only.
+# https://bitbucket.org/pypy/pypy/issue/1944/ctypes-on-windows-getlasterror
+
+import os
+
+_MS_WINDOWS = os.name == "nt"
+
+
+if _MS_WINDOWS:
+ from rpython.rlib import rwin32
+ from pypy.interpreter.executioncontext import ExecutionContext
+
+
+ ExecutionContext._rawffi_last_error = 0
+
+ def fetch_last_error(space):
+ ec = space.getexecutioncontext()
+ return ec._rawffi_last_error
+
+ def store_last_error(space, last_error):
+ ec = space.getexecutioncontext()
+ ec._rawffi_last_error = last_error
+
+ def restore_last_error(space):
+ ec = space.getexecutioncontext()
+ lasterror = ec._rawffi_last_error
+ rwin32.SetLastError(lasterror)
+
+ def save_last_error(space):
+ lasterror = rwin32.GetLastError()
+ ec = space.getexecutioncontext()
+ ec._rawffi_last_error = lasterror
+
+else:
+
+ def restore_last_error(space):
+ pass
+
+ def save_last_error(space):
+ pass
diff --git a/pypy/module/_rawffi/test/test__rawffi.py
b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -16,6 +16,7 @@
#include "src/precommondefs.h"
#include <stdlib.h>
#include <stdio.h>
+ #include <errno.h>
struct x
{
@@ -204,6 +205,24 @@
return inp;
}
+ RPY_EXPORTED
+ int check_errno(int incoming)
+ {
+ int old_errno = errno;
+ errno = incoming;
+ return old_errno;
+ }
+
+ #ifdef _WIN32
+ #include <Windows.h>
+ RPY_EXPORTED
+ int check_last_error(int incoming)
+ {
+ int old_errno = GetLastError();
+ SetLastError(incoming);
+ return old_errno;
+ }
+ #endif
'''))
eci = ExternalCompilationInfo(include_dirs=[cdir])
return str(platform.compile([c_file], eci, 'x', standalone=False))
@@ -1150,6 +1169,37 @@
raises(OverflowError, "arg1[0] = 10**900")
arg1.free()
+ def test_errno(self):
+ import _rawffi
+ lib = _rawffi.CDLL(self.lib_name)
+ A = _rawffi.Array('i')
+ f = lib.ptr('check_errno', ['i'], 'i')
+ _rawffi.set_errno(42)
+ arg = A(1)
+ arg[0] = 43
+ res = f(arg)
+ assert res[0] == 42
+ z = _rawffi.get_errno()
+ assert z == 43
+ arg.free()
+
+ def test_last_error(self):
+ import sys
+ if sys.platform != 'win32':
+ skip("Windows test")
+ import _rawffi
+ lib = _rawffi.CDLL(self.lib_name)
+ A = _rawffi.Array('i')
+ f = lib.ptr('check_last_error', ['i'], 'i')
+ _rawffi.set_last_error(42)
+ arg = A(1)
+ arg[0] = 43
+ res = f(arg)
+ assert res[0] == 42
+ z = _rawffi.get_last_error()
+ assert z == 43
+ arg.free()
+
class AppTestAutoFree:
spaceconfig = dict(usemodules=['_rawffi', 'struct'])
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
@@ -52,7 +52,8 @@
if not OPENSSL_NO_SSL2:
constants["PROTOCOL_SSLv2"] = PY_SSL_VERSION_SSL2
-constants["PROTOCOL_SSLv3"] = PY_SSL_VERSION_SSL3
+if not OPENSSL_NO_SSL3:
+ constants["PROTOCOL_SSLv3"] = PY_SSL_VERSION_SSL3
constants["PROTOCOL_SSLv23"] = PY_SSL_VERSION_SSL23
constants["PROTOCOL_TLSv1"] = PY_SSL_VERSION_TLS1
@@ -656,7 +657,7 @@
# set up context
if protocol == PY_SSL_VERSION_TLS1:
method = libssl_TLSv1_method()
- elif protocol == PY_SSL_VERSION_SSL3:
+ elif protocol == PY_SSL_VERSION_SSL3 and not OPENSSL_NO_SSL3:
method = libssl_SSLv3_method()
elif protocol == PY_SSL_VERSION_SSL2 and not OPENSSL_NO_SSL2:
method = libssl_SSLv2_method()
diff --git a/pypy/module/_ssl/thread_lock.py b/pypy/module/_ssl/thread_lock.py
--- a/pypy/module/_ssl/thread_lock.py
+++ b/pypy/module/_ssl/thread_lock.py
@@ -24,12 +24,19 @@
separate_module_source = """
#include <openssl/crypto.h>
+#ifndef _WIN32
+# include <pthread.h>
+#endif
static unsigned int _ssl_locks_count = 0;
static struct RPyOpaque_ThreadLock *_ssl_locks;
static unsigned long _ssl_thread_id_function(void) {
- return RPyThreadGetIdent();
+#ifdef _WIN32
+ return (unsigned long)GetCurrentThreadId();
+#else
+ return (unsigned long)pthread_self();
+#endif
}
static void _ssl_thread_locking_function(int mode, int n, const char *file,
diff --git a/pypy/module/cpyext/frameobject.py
b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -58,7 +58,7 @@
w_globals = from_ref(space, py_frame.c_f_globals)
frame = space.FrameClass(space, code, w_globals, outer_func=None)
- frame.f_lineno = py_frame.c_f_lineno
+ frame.f_lineno = rffi.getintfield(py_frame, 'c_f_lineno')
w_obj = space.wrap(frame)
track_reference(space, py_obj, w_obj)
return w_obj
diff --git a/pypy/module/cpyext/src/pythread.c
b/pypy/module/cpyext/src/pythread.c
--- a/pypy/module/cpyext/src/pythread.c
+++ b/pypy/module/cpyext/src/pythread.c
@@ -1,11 +1,18 @@
#include <Python.h>
+#ifndef _WIN32
+# include <pthread.h>
+#endif
#include "pythread.h"
#include "src/thread.h"
long
PyThread_get_thread_ident(void)
{
- return RPyThreadGetIdent();
+#ifdef _WIN32
+ return (long)GetCurrentThreadId();
+#else
+ return (long)pthread_self();
+#endif
}
PyThread_type_lock
diff --git a/pypy/module/marshal/interp_marshal.py
b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -144,7 +144,6 @@
atom_int(tc, int) puts code and int
atom_int64(tc, int64) puts code and int64
atom_str(tc, str) puts code, len and string
- atom_strlist(tc, strlist) puts code, len and list of strings
building blocks for compound types:
@@ -198,15 +197,6 @@
self.atom_int(typecode, len(x))
self.put(x)
- def atom_strlist(self, typecode, tc2, x):
- self.atom_int(typecode, len(x))
- atom_str = self.atom_str
- for item in x:
- # type(str) seems to be forbidden
- #if type(item) is not str:
- # self.raise_exc('object with wrong type in strlist')
- atom_str(tc2, item)
-
def start(self, typecode):
# type(char) not supported
self.put(typecode)
@@ -379,16 +369,6 @@
self.start(typecode)
return self.get_lng()
- def atom_strlist(self, typecode, tc2):
- self.start(typecode)
- lng = self.get_lng()
- res = [None] * lng
- idx = 0
- while idx < lng:
- res[idx] = self.atom_str(tc2)
- idx += 1
- return res
-
def start(self, typecode):
tc = self.get1()
if tc != typecode:
@@ -436,7 +416,6 @@
def get_w_obj(self, allow_null=False):
space = self.space
- w_ret = space.w_None # something not None
tc = self.get1()
w_ret = self._dispatch[ord(tc)](space, self, tc)
if w_ret is None and not allow_null:
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
@@ -1,7 +1,7 @@
from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, oefmt
from rpython.tool.pairtype import extendabletype
-
+from pypy.module.micronumpy import support
def wrap_impl(space, w_cls, w_instance, impl):
if w_cls is None or space.is_w(w_cls, space.gettypefor(W_NDimArray)):
@@ -44,11 +44,32 @@
return W_NDimArray(impl)
@staticmethod
- def from_shape_and_storage(space, shape, storage, dtype, order='C',
owning=False,
- w_subtype=None, w_base=None, writable=True):
+ def from_shape_and_storage(space, shape, storage, dtype, storage_bytes=-1,
+ order='C', owning=False, w_subtype=None,
+ w_base=None, writable=True, strides=None):
from pypy.module.micronumpy import concrete
- from pypy.module.micronumpy.strides import calc_strides
- strides, backstrides = calc_strides(shape, dtype, order)
+ from pypy.module.micronumpy.strides import (calc_strides,
+ calc_backstrides)
+ isize = dtype.elsize
+ if storage_bytes > 0 :
+ totalsize = support.product(shape) * isize
+ if totalsize > storage_bytes:
+ raise OperationError(space.w_TypeError, space.wrap(
+ "buffer is too small for requested array"))
+ else:
+ storage_bytes = support.product(shape) * isize
+ if strides is None:
+ strides, backstrides = calc_strides(shape, dtype, order)
+ else:
+ if len(strides) != len(shape):
+ raise oefmt(space.w_ValueError,
+ 'strides, if given, must be the same length as shape')
+ for i in range(len(strides)):
+ if strides[i] < 0 or strides[i]*shape[i] > storage_bytes:
+ raise oefmt(space.w_ValueError,
+ 'strides is incompatible with shape of requested '
+ 'array and size of buffer')
+ backstrides = calc_backstrides(strides, shape)
if w_base is not None:
if owning:
raise OperationError(space.w_ValueError,
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
@@ -59,9 +59,9 @@
_mixin_ = True
def reduce(self, space):
- numpypy = space.getbuiltinmodule("_numpypy")
- assert isinstance(numpypy, MixedModule)
- multiarray = numpypy.get("multiarray")
+ _numpypy = space.getbuiltinmodule("_numpypy")
+ assert isinstance(_numpypy, MixedModule)
+ multiarray = _numpypy.get("multiarray")
assert isinstance(multiarray, MixedModule)
scalar = multiarray.get("scalar")
@@ -167,7 +167,7 @@
if len(args_w) >= 1:
for w_arg in args_w:
try:
- idx = support.index_w(space, w_arg)
+ support.index_w(space, w_arg)
except OperationError:
raise oefmt(space.w_TypeError, "an integer is required")
raise oefmt(space.w_ValueError, "axes don't match array")
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
@@ -34,8 +34,8 @@
SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any",
- "unegative", "flat", "tostring","count_nonzero",
- "argsort"]
+ "unegative", "flat", "tostring", "count_nonzero",
+ "argsort", "cumsum", "logical_xor_reduce"]
TWO_ARG_FUNCTIONS = ["dot", 'take', 'searchsorted']
TWO_ARG_FUNCTIONS_OR_NONE = ['view', 'astype']
THREE_ARG_FUNCTIONS = ['where']
@@ -559,6 +559,11 @@
w_res = arr.descr_any(interp.space)
elif self.name == "all":
w_res = arr.descr_all(interp.space)
+ elif self.name == "cumsum":
+ w_res = arr.descr_cumsum(interp.space)
+ elif self.name == "logical_xor_reduce":
+ logical_xor = ufuncs.get(interp.space).logical_xor
+ w_res = logical_xor.reduce(interp.space, arr, None)
elif self.name == "unegative":
neg = ufuncs.get(interp.space).negative
w_res = neg.call(interp.space, [arr])
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
@@ -11,7 +11,7 @@
from pypy.module.micronumpy.iterators import ArrayIter
from pypy.module.micronumpy.strides import (Chunk, Chunks, NewAxisChunk,
RecordChunk, calc_strides, calc_new_strides, shape_agreement,
- calculate_broadcast_strides)
+ calculate_broadcast_strides, calc_backstrides)
class BaseConcreteArray(object):
@@ -47,6 +47,7 @@
def setitem(self, index, value):
self.dtype.itemtype.store(self, index, 0, value)
+ @jit.unroll_safe
def setslice(self, space, arr):
if len(arr.get_shape()) > 0 and len(self.get_shape()) == 0:
raise oefmt(space.w_ValueError,
@@ -78,10 +79,7 @@
self.get_strides(), self.order)
if new_strides is not None:
# We can create a view, strides somehow match up.
- ndims = len(new_shape)
- new_backstrides = [0] * ndims
- for nd in range(ndims):
- new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
+ new_backstrides = calc_backstrides(new_strides, new_shape)
assert isinstance(orig_array, W_NDimArray) or orig_array is None
return SliceArray(self.start, new_strides, new_backstrides,
new_shape, self, orig_array)
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
@@ -302,5 +302,5 @@
return a
else:
writable = not buf.readonly
- return W_NDimArray.from_shape_and_storage(space, [n], storage, dtype=dtype,
- w_base=w_buffer,
writable=writable)
+ return W_NDimArray.from_shape_and_storage(space, [n], storage,
storage_bytes=s,
+ dtype=dtype, w_base=w_buffer,
writable=writable)
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
@@ -286,7 +286,6 @@
def descr_hash(self, space):
return space.wrap(self._compute_hash(space, 0x345678))
-
def descr_str(self, space):
if self.fields:
return space.str(self.descr_get_descr(space))
diff --git a/pypy/module/micronumpy/flagsobj.py
b/pypy/module/micronumpy/flagsobj.py
--- a/pypy/module/micronumpy/flagsobj.py
+++ b/pypy/module/micronumpy/flagsobj.py
@@ -1,47 +1,30 @@
+from rpython.rlib import jit
+
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.module.micronumpy import constants as NPY
-
+from pypy.module.micronumpy.strides import is_c_contiguous, is_f_contiguous
def enable_flags(arr, flags):
arr.flags |= flags
-
def clear_flags(arr, flags):
arr.flags &= ~flags
-
def _update_contiguous_flags(arr):
- shape = arr.shape
- strides = arr.strides
-
- is_c_contig = True
- sd = arr.dtype.elsize
- for i in range(len(shape) - 1, -1, -1):
- dim = shape[i]
- if strides[i] != sd:
- is_c_contig = False
- break
- if dim == 0:
- break
- sd *= dim
+ is_c_contig = is_c_contiguous(arr)
if is_c_contig:
enable_flags(arr, NPY.ARRAY_C_CONTIGUOUS)
else:
clear_flags(arr, NPY.ARRAY_C_CONTIGUOUS)
- sd = arr.dtype.elsize
- for i in range(len(shape)):
- dim = shape[i]
- if strides[i] != sd:
- clear_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
- return
- if dim == 0:
- break
- sd *= dim
- enable_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
+ is_f_contig = is_f_contiguous(arr)
+ if is_f_contig:
+ enable_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
+ else:
+ clear_flags(arr, NPY.ARRAY_F_CONTIGUOUS)
class W_FlagsObject(W_Root):
diff --git a/pypy/module/micronumpy/flatiter.py
b/pypy/module/micronumpy/flatiter.py
--- a/pypy/module/micronumpy/flatiter.py
+++ b/pypy/module/micronumpy/flatiter.py
@@ -22,6 +22,9 @@
def get_shape(self):
return self.shape
+ def get_size(self):
+ return self.base().get_size()
+
def create_iter(self, shape=None, backward_broadcast=False):
assert isinstance(self.base(), W_NDimArray)
return self.base().create_iter()
@@ -41,8 +44,8 @@
return space.wrap(self.state.index)
def descr_coords(self, space):
- self.state = self.iter.update(self.state)
- return space.newtuple([space.wrap(c) for c in self.state.indices])
+ coords = self.iter.indices(self.state)
+ return space.newtuple([space.wrap(c) for c in coords])
def descr_iter(self):
return self
@@ -54,7 +57,7 @@
if self.iter.done(self.state):
raise OperationError(space.w_StopIteration, space.w_None)
w_res = self.iter.getitem(self.state)
- self.state = self.iter.next(self.state)
+ self.iter.next(self.state, mutate=True)
return w_res
def descr_getitem(self, space, w_idx):
@@ -71,7 +74,7 @@
base.get_order(), w_instance=base)
return loop.flatiter_getitem(res, self.iter, state, step)
finally:
- self.state = self.iter.reset(self.state)
+ self.iter.reset(self.state, mutate=True)
def descr_setitem(self, space, w_idx, w_value):
if not (space.isinstance_w(w_idx, space.w_int) or
@@ -91,7 +94,7 @@
arr = convert_to_array(space, w_value)
loop.flatiter_setitem(space, dtype, arr, self.iter, state, step,
length)
finally:
- self.state = self.iter.reset(self.state)
+ self.iter.reset(self.state, mutate=True)
W_FlatIterator.typedef = TypeDef("numpy.flatiter",
diff --git a/pypy/module/micronumpy/iterators.py
b/pypy/module/micronumpy/iterators.py
--- a/pypy/module/micronumpy/iterators.py
+++ b/pypy/module/micronumpy/iterators.py
@@ -41,16 +41,6 @@
from pypy.module.micronumpy.base import W_NDimArray
from pypy.module.micronumpy.flagsobj import _update_contiguous_flags
-class OpFlag(object):
- def __init__(self):
- self.rw = ''
- self.broadcast = True
- self.force_contig = False
- self.force_align = False
- self.native_byte_order = False
- self.tmp_copy = ''
- self.allocate = False
-
class PureShapeIter(object):
def __init__(self, shape, idx_w):
@@ -87,25 +77,24 @@
class IterState(object):
- _immutable_fields_ = ['iterator', 'index', 'indices', 'offset']
+ _immutable_fields_ = ['iterator', '_indices']
def __init__(self, iterator, index, indices, offset):
self.iterator = iterator
self.index = index
- self.indices = indices
+ self._indices = indices
self.offset = offset
class ArrayIter(object):
_immutable_fields_ = ['contiguous', 'array', 'size', 'ndim_m1',
'shape_m1[*]',
'strides[*]', 'backstrides[*]', 'factors[*]',
- 'slice_shape', 'slice_stride', 'slice_backstride',
- 'track_index', 'operand_type', 'slice_operand_type']
+ 'track_index']
track_index = True
- def __init__(self, array, size, shape, strides, backstrides,
op_flags=OpFlag()):
- from pypy.module.micronumpy import concrete
+ @jit.unroll_safe
+ def __init__(self, array, size, shape, strides, backstrides):
assert len(shape) == len(strides) == len(backstrides)
_update_contiguous_flags(array)
self.contiguous = (array.flags & NPY.ARRAY_C_CONTIGUOUS and
@@ -117,12 +106,6 @@
self.shape_m1 = [s - 1 for s in shape]
self.strides = strides
self.backstrides = backstrides
- self.slice_shape = 1
- self.slice_stride = -1
- if strides:
- self.slice_stride = strides[-1]
- self.slice_backstride = 1
- self.slice_operand_type = concrete.SliceArray
ndim = len(shape)
factors = [0] * ndim
@@ -132,32 +115,35 @@
else:
factors[ndim-i-1] = factors[ndim-i] * shape[ndim-i]
self.factors = factors
- if op_flags.rw == 'r':
- self.operand_type = concrete.ConcreteNonWritableArrayWithBase
- else:
- self.operand_type = concrete.ConcreteArrayWithBase
@jit.unroll_safe
- def reset(self, state=None):
+ def reset(self, state=None, mutate=False):
+ index = 0
if state is None:
indices = [0] * len(self.shape_m1)
else:
assert state.iterator is self
- indices = state.indices
+ indices = state._indices
for i in xrange(self.ndim_m1, -1, -1):
indices[i] = 0
- return IterState(self, 0, indices, self.array.start)
+ offset = self.array.start
+ if not mutate:
+ return IterState(self, index, indices, offset)
+ state.index = index
+ state.offset = offset
@jit.unroll_safe
- def next(self, state):
+ def next(self, state, mutate=False):
assert state.iterator is self
index = state.index
if self.track_index:
index += 1
- indices = state.indices
+ indices = state._indices
offset = state.offset
if self.contiguous:
offset += self.array.dtype.elsize
+ elif self.ndim_m1 == 0:
+ offset += self.strides[0]
else:
for i in xrange(self.ndim_m1, -1, -1):
idx = indices[i]
@@ -168,13 +154,18 @@
else:
indices[i] = 0
offset -= self.backstrides[i]
- return IterState(self, index, indices, offset)
+ if not mutate:
+ return IterState(self, index, indices, offset)
+ state.index = index
+ state.offset = offset
@jit.unroll_safe
def goto(self, index):
offset = self.array.start
if self.contiguous:
offset += index * self.array.dtype.elsize
+ elif self.ndim_m1 == 0:
+ offset += index * self.strides[0]
else:
current = index
for i in xrange(len(self.shape_m1)):
@@ -183,20 +174,20 @@
return IterState(self, index, None, offset)
@jit.unroll_safe
- def update(self, state):
+ def indices(self, state):
assert state.iterator is self
assert self.track_index
- if not self.contiguous:
- return state
+ indices = state._indices
+ if not (self.contiguous or self.ndim_m1 == 0):
+ return indices
current = state.index
- indices = state.indices
for i in xrange(len(self.shape_m1)):
if self.factors[i] != 0:
indices[i] = current / self.factors[i]
current %= self.factors[i]
else:
indices[i] = 0
- return IterState(self, state.index, indices, state.offset)
+ return indices
def done(self, state):
assert state.iterator is self
@@ -215,12 +206,6 @@
assert state.iterator is self
self.array.setitem(state.offset, elem)
- def getoperand(self, st, base):
- impl = self.operand_type
- res = impl([], self.array.dtype, self.array.order, [], [],
- self.array.storage, base)
- res.start = st.offset
- return res
def AxisIter(array, shape, axis, cumulative):
strides = array.get_strides()
@@ -244,42 +229,3 @@
size /= shape[axis]
shape[axis] = backstrides[axis] = 0
return ArrayIter(array, size, shape, array.strides, backstrides)
-
-class SliceIter(ArrayIter):
- '''
- used with external loops, getitem and setitem return a SliceArray
- view into the original array
- '''
- _immutable_fields_ = ['base', 'slice_shape[*]', 'slice_stride[*]',
'slice_backstride[*]']
-
- def __init__(self, array, size, shape, strides, backstrides, slice_shape,
- slice_stride, slice_backstride, op_flags, base):
- from pypy.module.micronumpy import concrete
- ArrayIter.__init__(self, array, size, shape, strides, backstrides,
op_flags)
- self.slice_shape = slice_shape
- self.slice_stride = slice_stride
- self.slice_backstride = slice_backstride
- self.base = base
- if op_flags.rw == 'r':
- self.slice_operand_type = concrete.NonWritableSliceArray
- else:
- self.slice_operand_type = concrete.SliceArray
-
- def getitem(self, state):
- # XXX cannot be called - must return a boxed value
- assert False
-
- def getitem_bool(self, state):
- # XXX cannot be called - must return a boxed value
- assert False
-
- def setitem(self, state, elem):
- # XXX cannot be called - must return a boxed value
- assert False
-
- def getoperand(self, state, base):
- assert state.iterator is self
- impl = self.slice_operand_type
- arr = impl(state.offset, [self.slice_stride], [self.slice_backstride],
- [self.slice_shape], self.array, self.base)
- return arr
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -42,23 +42,38 @@
# TODO handle __array_priorities__ and maybe flip the order
+ if w_lhs.get_size() == 1:
+ w_left = w_lhs.get_scalar_value().convert_to(space, calc_dtype)
+ left_iter = left_state = None
+ else:
+ w_left = None
+ left_iter, left_state = w_lhs.create_iter(shape)
+ left_iter.track_index = False
+
+ if w_rhs.get_size() == 1:
+ w_right = w_rhs.get_scalar_value().convert_to(space, calc_dtype)
+ right_iter = right_state = None
+ else:
+ w_right = None
+ right_iter, right_state = w_rhs.create_iter(shape)
+ right_iter.track_index = False
+
if out is None:
out = W_NDimArray.from_shape(space, shape, res_dtype,
w_instance=lhs_for_subtype)
- left_iter, left_state = w_lhs.create_iter(shape)
- right_iter, right_state = w_rhs.create_iter(shape)
out_iter, out_state = out.create_iter(shape)
- left_iter.track_index = right_iter.track_index = False
shapelen = len(shape)
while not out_iter.done(out_state):
call2_driver.jit_merge_point(shapelen=shapelen, func=func,
calc_dtype=calc_dtype,
res_dtype=res_dtype)
- w_left = left_iter.getitem(left_state).convert_to(space, calc_dtype)
- w_right = right_iter.getitem(right_state).convert_to(space, calc_dtype)
+ if left_iter:
+ w_left = left_iter.getitem(left_state).convert_to(space,
calc_dtype)
+ left_state = left_iter.next(left_state)
+ if right_iter:
+ w_right = right_iter.getitem(right_state).convert_to(space,
calc_dtype)
+ right_state = right_iter.next(right_state)
out_iter.setitem(out_state, func(calc_dtype, w_left,
w_right).convert_to(
space, res_dtype))
- left_state = left_iter.next(left_state)
- right_state = right_iter.next(right_state)
out_state = out_iter.next(out_state)
return out
@@ -68,11 +83,12 @@
reds='auto')
def call1(space, shape, func, calc_dtype, res_dtype, w_obj, out):
+ obj_iter, obj_state = w_obj.create_iter(shape)
+ obj_iter.track_index = False
+
if out is None:
out = W_NDimArray.from_shape(space, shape, res_dtype, w_instance=w_obj)
- obj_iter, obj_state = w_obj.create_iter(shape)
out_iter, out_state = out.create_iter(shape)
- obj_iter.track_index = False
shapelen = len(shape)
while not out_iter.done(out_state):
call1_driver.jit_merge_point(shapelen=shapelen, func=func,
@@ -88,10 +104,23 @@
reds = 'auto')
def setslice(space, shape, target, source):
+ if not shape:
+ dtype = target.dtype
+ val = source.getitem(source.start)
+ if dtype.is_str_or_unicode():
+ val = dtype.coerce(space, val)
+ else:
+ val = val.convert_to(space, dtype)
+ target.setitem(target.start, val)
+ return target
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit