[pypy-commit] pypy default: Merged pypy/pypy into default
anton_gulenko
noreply at buildbot.pypy.org
Wed Apr 22 12:20:47 CEST 2015
Author: anton_gulenko <anton.gulenko at googlemail.com>
Branch:
Changeset: r76870:fe4c27d34d37
Date: 2015-03-07 16:20 +0100
http://bitbucket.org/pypy/pypy/changeset/fe4c27d34d37/
Log: Merged pypy/pypy into default
diff too long, truncating to 2000 out of 4777 lines
diff --git a/lib_pypy/cffi.egg-info b/lib_pypy/cffi.egg-info
--- a/lib_pypy/cffi.egg-info
+++ b/lib_pypy/cffi.egg-info
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: cffi
-Version: 0.8.6+
+Version: 0.9.0
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
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,8 +4,8 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "0.8.6+"
-__version_info__ = (0, 8, 6, "plus")
+__version__ = "0.9.0"
+__version_info__ = (0, 9, 0)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/gdbm.py b/lib_pypy/gdbm.py
--- a/lib_pypy/gdbm.py
+++ b/lib_pypy/gdbm.py
@@ -20,9 +20,11 @@
} datum;
datum gdbm_fetch(void*, datum);
+datum pygdbm_fetch(void*, char*, int);
int gdbm_delete(void*, datum);
int gdbm_store(void*, datum, datum, int);
int gdbm_exists(void*, datum);
+int pygdbm_exists(void*, char*, int);
int gdbm_reorganize(void*);
@@ -37,19 +39,29 @@
''')
try:
+ verify_code = '''
+ #include "gdbm.h"
+
+ static datum pygdbm_fetch(GDBM_FILE gdbm_file, char *dptr, int dsize) {
+ datum key = {dptr, dsize};
+ return gdbm_fetch(gdbm_file, key);
+ }
+
+ static int pygdbm_exists(GDBM_FILE gdbm_file, char *dptr, int dsize) {
+ datum key = {dptr, dsize};
+ return gdbm_exists(gdbm_file, key);
+ }
+
+ '''
if sys.platform.startswith('freebsd'):
import os.path
_localbase = os.environ.get('LOCALBASE', '/usr/local')
- lib = ffi.verify('''
- #include "gdbm.h"
- ''', libraries=['gdbm'],
+ lib = ffi.verify(verify_code, libraries=['gdbm'],
include_dirs=[os.path.join(_localbase, 'include')],
library_dirs=[os.path.join(_localbase, 'lib')]
)
else:
- lib = ffi.verify('''
- #include "gdbm.h"
- ''', libraries=['gdbm'])
+ lib = ffi.verify(verify_code, libraries=['gdbm'])
except cffi.VerificationError as e:
# distutils does not preserve the actual message,
# but the verification is simple enough that the
@@ -59,6 +71,13 @@
class error(Exception):
pass
+def _checkstr(key):
+ if isinstance(key, unicode):
+ key = key.encode("ascii")
+ if not isinstance(key, str):
+ raise TypeError("gdbm mappings have string indices only")
+ return key
+
def _fromstr(key):
if isinstance(key, unicode):
key = key.encode("ascii")
@@ -107,12 +126,14 @@
def __contains__(self, key):
self._check_closed()
- return lib.gdbm_exists(self.ll_dbm, _fromstr(key))
+ key = _checkstr(key)
+ return lib.pygdbm_exists(self.ll_dbm, key, len(key))
has_key = __contains__
def __getitem__(self, key):
self._check_closed()
- drec = lib.gdbm_fetch(self.ll_dbm, _fromstr(key))
+ key = _checkstr(key)
+ drec = lib.pygdbm_fetch(self.ll_dbm, key, len(key))
if not drec.dptr:
raise KeyError(key)
res = str(ffi.buffer(drec.dptr, drec.dsize))
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -73,7 +73,6 @@
assume_immutable_completions = False
use_brackets = False
sort_in_column = True
- tab_insert_spaces_if_stem_is_empty = False
def error(self, msg="none"):
pass # don't show error messages by default
@@ -87,7 +86,7 @@
return ''.join(b[p+1:self.pos])
def get_completions(self, stem):
- if len(stem) == 0 and self.tab_insert_spaces_if_stem_is_empty:
+ if len(stem) == 0 and self.more_lines is not None:
b = self.buffer
p = self.pos
while p > 0 and b[p - 1] != '\n':
@@ -141,12 +140,16 @@
def collect_keymap(self):
return super(ReadlineAlikeReader, self).collect_keymap() + (
- (r'\n', 'maybe-accept'),)
+ (r'\n', 'maybe-accept'),
+ (r'\<backspace>', 'backspace-dedent'),
+ )
def __init__(self, console):
super(ReadlineAlikeReader, self).__init__(console)
self.commands['maybe_accept'] = maybe_accept
self.commands['maybe-accept'] = maybe_accept
+ self.commands['backspace_dedent'] = backspace_dedent
+ self.commands['backspace-dedent'] = backspace_dedent
def after_command(self, cmd):
super(ReadlineAlikeReader, self).after_command(cmd)
@@ -164,6 +167,28 @@
if self.pos > len(self.buffer):
self.pos = len(self.buffer)
+def _get_this_line_indent(buffer, pos):
+ indent = 0
+ while pos > 0 and buffer[pos - 1] in " \t":
+ indent += 1
+ pos -= 1
+ if pos > 0 and buffer[pos - 1] == "\n":
+ return indent
+ return 0
+
+def _get_previous_line_indent(buffer, pos):
+ prevlinestart = pos
+ while prevlinestart > 0 and buffer[prevlinestart - 1] != "\n":
+ prevlinestart -= 1
+ prevlinetext = prevlinestart
+ while prevlinetext < pos and buffer[prevlinetext] in " \t":
+ prevlinetext += 1
+ if prevlinetext == pos:
+ indent = None
+ else:
+ indent = prevlinetext - prevlinestart
+ return prevlinestart, indent
+
class maybe_accept(commands.Command):
def do(self):
r = self.reader
@@ -172,13 +197,39 @@
# if there are already several lines and the cursor
# is not on the last one, always insert a new \n.
text = r.get_unicode()
- if "\n" in r.buffer[r.pos:]:
+ if ("\n" in r.buffer[r.pos:] or
+ (r.more_lines is not None and r.more_lines(text))):
+ #
+ # auto-indent the next line like the previous line
+ prevlinestart, indent = _get_previous_line_indent(r.buffer, r.pos)
r.insert("\n")
- elif r.more_lines is not None and r.more_lines(text):
- r.insert("\n")
+ if indent:
+ for i in range(prevlinestart, prevlinestart + indent):
+ r.insert(r.buffer[i])
else:
self.finish = 1
+class backspace_dedent(commands.Command):
+ def do(self):
+ r = self.reader
+ b = r.buffer
+ if r.pos > 0:
+ repeat = 1
+ if b[r.pos - 1] != "\n":
+ indent = _get_this_line_indent(b, r.pos)
+ if indent > 0:
+ ls = r.pos - indent
+ while ls > 0:
+ ls, pi = _get_previous_line_indent(b, ls - 1)
+ if pi is not None and pi < indent:
+ repeat = indent - pi
+ break
+ r.pos -= repeat
+ del b[r.pos:r.pos + repeat]
+ r.dirty = 1
+ else:
+ self.reader.error("can't backspace at start")
+
# ____________________________________________________________
class _ReadlineWrapper(object):
@@ -212,15 +263,14 @@
boolean value is true.
"""
reader = self.get_reader()
- saved = reader.more_lines, reader.tab_insert_spaces_if_stem_is_empty
+ saved = reader.more_lines
try:
reader.more_lines = more_lines
reader.ps1 = reader.ps2 = ps1
reader.ps3 = reader.ps4 = ps2
- reader.tab_insert_spaces_if_stem_is_empty = True
return reader.readline(returns_unicode=returns_unicode)
finally:
- reader.more_lines, reader.tab_insert_spaces_if_stem_is_empty = saved
+ reader.more_lines = saved
def parse_and_bind(self, string):
pass # XXX we don't support parsing GNU-readline-style init files
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -36,7 +36,7 @@
def pytest_addoption(parser):
from rpython.conftest import pytest_addoption
pytest_addoption(parser)
-
+
group = parser.getgroup("pypy options")
group.addoption('-A', '--runappdirect', action="store_true",
default=False, dest="runappdirect",
@@ -44,6 +44,9 @@
group.addoption('--direct', action="store_true",
default=False, dest="rundirect",
help="run pexpect tests directly")
+ group.addoption('--raise-operr', action="store_true",
+ default=False, dest="raise_operr",
+ help="Show the interp-level OperationError in app-level tests")
def pytest_funcarg__space(request):
from pypy.tool.pytest.objspace import gettestobjspace
diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst
--- a/pypy/doc/embedding.rst
+++ b/pypy/doc/embedding.rst
@@ -36,7 +36,8 @@
"PyPy home directory". The arguments are:
* ``home``: NULL terminated path to an executable inside the pypy directory
- (can be a .so name, can be made up)
+ (can be a .so name, can be made up). Used to look up the standard
+ library, and is also set as ``sys.executable``.
* ``verbose``: if non-zero, it will print error messages to stderr
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
@@ -39,3 +39,30 @@
Reason is a string, the meaning of other arguments is the same
as attributes on JitLoopInfo object
+.. function:: enable_debug()
+
+ Start recording debugging counters for ``get_stats_snapshot``
+
+.. function:: disable_debug()
+
+ Stop recording debugging counters for ``get_stats_snapshot``
+
+.. function:: get_stats_snapshot()
+
+ Get the jit status in the specific moment in time. Note that this
+ is eager - the attribute access is not lazy, if you need new stats
+ you need to call this function again. You might want to call
+ ``enable_debug`` to get more information. It returns an instance
+ of ``JitInfoSnapshot``
+
+.. class:: JitInfoSnapshot
+
+ A class describing current snapshot. Usable attributes:
+
+ * ``counters`` - internal JIT integer counters
+
+ * ``counter_times`` - internal JIT float counters, notably time spent
+ TRACING and in the JIT BACKEND
+
+ * ``loop_run_times`` - counters for number of times loops are run, only
+ works when ``enable_debug`` is called.
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,10 @@
.. branch: alt_errno
Add an alternative location to save LastError, errno around ctypes,
cffi external calls so things like pdb will not overwrite it
+
+.. branch: nonquadratic-heapcache
+Speed up the warmup times of the JIT by removing a quadratic algorithm in the
+heapcache.
+
+.. branch: online-transforms-2
+Simplify flow graphs on the fly during annotation phase.
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -106,6 +106,9 @@
space.call_function(w_pathsetter, w_path)
# import site
try:
+ space.setattr(space.getbuiltinmodule('sys'),
+ space.wrap('executable'),
+ space.wrap(home))
import_ = space.getattr(space.getbuiltinmodule('__builtin__'),
space.wrap('__import__'))
space.call_function(import_, space.wrap('site'))
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -1,5 +1,5 @@
#! /usr/bin/env python
-# App-level version of py.py.
+# This is pure Python code that handles the main entry point into "pypy".
# See test/test_app_main.
# Missing vs CPython: -d, -t, -v, -x, -3
@@ -157,10 +157,13 @@
current = group
raise SystemExit
+def get_sys_executable():
+ return getattr(sys, 'executable', 'pypy')
+
def print_help(*args):
import os
print 'usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...' % (
- sys.executable,)
+ get_sys_executable(),)
print USAGE1,
if 'pypyjit' in sys.builtin_module_names:
print "--jit options: advanced JIT options: try 'off' or 'help'"
@@ -171,7 +174,7 @@
try:
import pypyjit
except ImportError:
- print >> sys.stderr, "No jit support in %s" % (sys.executable,)
+ print >> sys.stderr, "No jit support in %s" % (get_sys_executable(),)
return
items = sorted(pypyjit.defaults.items())
print 'Advanced JIT options: a comma-separated list of OPTION=VALUE:'
@@ -209,7 +212,7 @@
raise SystemExit
if 'pypyjit' not in sys.builtin_module_names:
print >> sys.stderr, ("Warning: No jit support in %s" %
- (sys.executable,))
+ (get_sys_executable(),))
else:
import pypyjit
pypyjit.set_param(jitparam)
@@ -219,8 +222,8 @@
def print_error(msg):
print >> sys.stderr, msg
- print >> sys.stderr, 'usage: %s [options]' % (sys.executable,)
- print >> sys.stderr, 'Try `%s -h` for more information.' % (sys.executable,)
+ print >> sys.stderr, 'usage: %s [options]' % (get_sys_executable(),)
+ print >> sys.stderr, 'Try `%s -h` for more information.' % (get_sys_executable(),)
def fdopen(fd, mode, bufsize=-1):
try:
@@ -514,6 +517,10 @@
elif not sys.stdout.isatty():
set_fully_buffered_io()
+ if we_are_translated():
+ import __pypy__
+ __pypy__.save_module_content_for_future_reload(sys)
+
mainmodule = type(sys)('__main__')
sys.modules['__main__'] = mainmodule
diff --git a/pypy/interpreter/mixedmodule.py b/pypy/interpreter/mixedmodule.py
--- a/pypy/interpreter/mixedmodule.py
+++ b/pypy/interpreter/mixedmodule.py
@@ -55,7 +55,10 @@
if self.w_initialdict is None:
Module.init(self, space)
if not self.lazy and self.w_initialdict is None:
- self.w_initialdict = space.call_method(self.w_dict, 'items')
+ self.save_module_content_for_future_reload()
+
+ def save_module_content_for_future_reload(self):
+ self.w_initialdict = self.space.call_method(self.w_dict, 'items')
def get_applevel_name(cls):
@@ -119,7 +122,7 @@
w_value = self.get(name)
space.setitem(self.w_dict, space.new_interned_str(name), w_value)
self.lazy = False
- self.w_initialdict = space.call_method(self.w_dict, 'items')
+ self.save_module_content_for_future_reload()
return self.w_dict
def _cleanup_(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
@@ -373,7 +373,7 @@
config = make_config(None)
space = make_objspace(config)
w_executable = space.wrap('executable')
- assert space.str_w(space.getattr(space.sys, w_executable)) == 'py.py'
+ assert space.findattr(space.sys, w_executable) is None
space.setattr(space.sys, w_executable, space.wrap('foobar'))
assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar'
space.startup()
diff --git a/pypy/interpreter/test/test_targetpypy.py b/pypy/interpreter/test/test_targetpypy.py
--- a/pypy/interpreter/test/test_targetpypy.py
+++ b/pypy/interpreter/test/test_targetpypy.py
@@ -8,7 +8,7 @@
entry_point = get_entry_point(config)[0]
entry_point(['pypy-c' , '-S', '-c', 'print 3'])
-def test_exeucte_source(space):
+def test_execute_source(space):
_, d = create_entry_point(space, None)
execute_source = d['pypy_execute_source']
lls = rffi.str2charp("import sys; sys.modules['xyz'] = 3")
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
@@ -82,6 +82,8 @@
'strategy' : 'interp_magic.strategy', # dict,set,list
'set_debug' : 'interp_magic.set_debug',
'locals_to_fast' : 'interp_magic.locals_to_fast',
+ 'save_module_content_for_future_reload':
+ 'interp_magic.save_module_content_for_future_reload',
}
if sys.platform == 'win32':
interpleveldefs['get_console_cp'] = 'interp_magic.get_console_cp'
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
@@ -1,6 +1,7 @@
from pypy.interpreter.error import OperationError, wrap_oserror
from pypy.interpreter.gateway import unwrap_spec
from pypy.interpreter.pyframe import PyFrame
+from pypy.interpreter.mixedmodule import MixedModule
from rpython.rlib.objectmodel import we_are_translated
from pypy.objspace.std.dictmultiobject import W_DictMultiObject
from pypy.objspace.std.listobject import W_ListObject
@@ -130,3 +131,7 @@
def locals_to_fast(space, w_frame):
assert isinstance(w_frame, PyFrame)
w_frame.locals2fast()
+
+ at unwrap_spec(w_module=MixedModule)
+def save_module_content_for_future_reload(space, w_module):
+ w_module.save_module_content_for_future_reload()
diff --git a/pypy/module/__pypy__/test/test_magic.py b/pypy/module/__pypy__/test/test_magic.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/test/test_magic.py
@@ -0,0 +1,15 @@
+
+class AppTestMagic:
+ spaceconfig = dict(usemodules=['__pypy__'])
+
+ def test_save_module_content_for_future_reload(self):
+ import sys, __pypy__
+ d = sys.dont_write_bytecode
+ sys.dont_write_bytecode = "hello world"
+ __pypy__.save_module_content_for_future_reload(sys)
+ sys.dont_write_bytecode = d
+ reload(sys)
+ assert sys.dont_write_bytecode == "hello world"
+ #
+ sys.dont_write_bytecode = d
+ __pypy__.save_module_content_for_future_reload(sys)
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.6+")',
+ '__version__': 'space.wrap("0.9.0")',
'load_library': 'libraryobj.load_library',
diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py
--- a/pypy/module/_cffi_backend/cbuffer.py
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -81,4 +81,5 @@
if size < 0:
raise oefmt(space.w_TypeError,
"don't know the size pointed to by '%s'", ctype.name)
- return space.wrap(MiniBuffer(LLBuffer(w_cdata._cdata, size), w_cdata))
+ ptr = w_cdata.unsafe_escaping_ptr() # w_cdata kept alive by MiniBuffer()
+ return space.wrap(MiniBuffer(LLBuffer(ptr, size), w_cdata))
diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -48,9 +48,12 @@
raise oefmt(space.w_NotImplementedError,
"%s: callback with unsupported argument or "
"return type or with '...'", self.getfunctype().name)
- res = clibffi.c_ffi_prep_closure(self.get_closure(), cif_descr.cif,
- invoke_callback,
- rffi.cast(rffi.VOIDP, self.unique_id))
+ with self as ptr:
+ closure_ptr = rffi.cast(clibffi.FFI_CLOSUREP, ptr)
+ unique_id = rffi.cast(rffi.VOIDP, self.unique_id)
+ res = clibffi.c_ffi_prep_closure(closure_ptr, cif_descr.cif,
+ invoke_callback,
+ unique_id)
if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK:
raise OperationError(space.w_SystemError,
space.wrap("libffi failed to build this callback"))
@@ -62,12 +65,9 @@
from pypy.module.thread.os_thread import setup_threads
setup_threads(space)
- def get_closure(self):
- return rffi.cast(clibffi.FFI_CLOSUREP, self._cdata)
-
#@rgc.must_be_light_finalizer
def __del__(self):
- clibffi.closureHeap.free(self.get_closure())
+ clibffi.closureHeap.free(rffi.cast(clibffi.FFI_CLOSUREP, self._ptr))
if self.ll_error:
lltype.free(self.ll_error, flavor='raw')
@@ -106,7 +106,7 @@
fresult = self.getfunctype().ctitem
if fresult.size > 0:
misc._raw_memcopy(self.ll_error, ll_res, fresult.size)
- keepalive_until_here(self)
+ keepalive_until_here(self) # to keep self.ll_error alive
global_callback_mapping = rweakref.RWeakValueDictionary(int, W_CDataCallback)
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -14,21 +14,37 @@
class W_CData(W_Root):
- _attrs_ = ['space', '_cdata', 'ctype', '_lifeline_']
- _immutable_fields_ = ['_cdata', 'ctype']
- _cdata = lltype.nullptr(rffi.CCHARP.TO)
+ _attrs_ = ['space', '_ptr', 'ctype', '_lifeline_']
+ _immutable_fields_ = ['_ptr', 'ctype']
+ _ptr = lltype.nullptr(rffi.CCHARP.TO)
- def __init__(self, space, cdata, ctype):
+ def __init__(self, space, ptr, ctype):
from pypy.module._cffi_backend import ctypeobj
- assert lltype.typeOf(cdata) == rffi.CCHARP
+ assert lltype.typeOf(ptr) == rffi.CCHARP
assert isinstance(ctype, ctypeobj.W_CType)
self.space = space
- self._cdata = cdata # don't forget keepalive_until_here!
+ self._ptr = ptr # don't access directly! use "with cdata as ptr:"
self.ctype = ctype
+ def __enter__(self):
+ """Use 'with cdata as ptr:' to access the raw memory. It will
+ stay alive at least until the end of the 'with' block.
+ """
+ return self._ptr
+
+ def __exit__(self, *args):
+ keepalive_until_here(self)
+
+ def unsafe_escaping_ptr(self):
+ """Generally unsafe: escape the pointer to raw memory.
+ If 'self' is a subclass that frees the pointer in a destructor,
+ it may be freed under your feet at any time.
+ """
+ return self._ptr
+
def _repr_extra(self):
- extra = self.ctype.extra_repr(self._cdata)
- keepalive_until_here(self)
+ with self as ptr:
+ extra = self.ctype.extra_repr(ptr)
return extra
def _repr_extra_owning(self):
@@ -54,11 +70,13 @@
self.ctype.name, extra1, extra2))
def nonzero(self):
- return self.space.wrap(bool(self._cdata))
+ with self as ptr:
+ nonzero = bool(ptr)
+ return self.space.wrap(nonzero)
def int(self, space):
- w_result = self.ctype.cast_to_int(self._cdata)
- keepalive_until_here(self)
+ with self as ptr:
+ w_result = self.ctype.cast_to_int(ptr)
return w_result
def long(self, space):
@@ -69,8 +87,8 @@
return w_result
def float(self):
- w_result = self.ctype.float(self._cdata)
- keepalive_until_here(self)
+ with self as ptr:
+ w_result = self.ctype.float(ptr)
return w_result
def len(self):
@@ -88,20 +106,19 @@
def _cmp(self, w_other):
from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitive
space = self.space
- cdata1 = self._cdata
- if isinstance(w_other, W_CData):
- cdata2 = w_other._cdata
- else:
+ if not isinstance(w_other, W_CData):
return space.w_NotImplemented
- if requires_ordering:
- if (isinstance(self.ctype, W_CTypePrimitive) or
- isinstance(w_other.ctype, W_CTypePrimitive)):
- raise OperationError(space.w_TypeError,
- space.wrap("cannot do comparison on a primitive cdata"))
- cdata1 = rffi.cast(lltype.Unsigned, cdata1)
- cdata2 = rffi.cast(lltype.Unsigned, cdata2)
- return space.newbool(op(cdata1, cdata2))
+ with self as ptr1, w_other as ptr2:
+ if requires_ordering:
+ if (isinstance(self.ctype, W_CTypePrimitive) or
+ isinstance(w_other.ctype, W_CTypePrimitive)):
+ raise OperationError(space.w_TypeError, space.wrap(
+ "cannot do comparison on a primitive cdata"))
+ ptr1 = rffi.cast(lltype.Unsigned, ptr1)
+ ptr2 = rffi.cast(lltype.Unsigned, ptr2)
+ result = op(ptr1, ptr2)
+ return space.newbool(result)
#
return func_with_new_name(_cmp, name)
@@ -113,7 +130,8 @@
ge = _make_comparison('ge')
def hash(self):
- h = rffi.cast(lltype.Signed, self._cdata)
+ ptr = self.unsafe_escaping_ptr()
+ h = rffi.cast(lltype.Signed, ptr)
# To hash pointers in dictionaries. Assumes that h shows some
# alignment (to 4, 8, maybe 16 bytes), so we use the following
# formula to avoid the trailing bits being always 0.
@@ -128,26 +146,27 @@
i = space.getindex_w(w_index, space.w_IndexError)
ctype = self.ctype._check_subscript_index(self, i)
w_o = self._do_getitem(ctype, i)
- keepalive_until_here(self)
return w_o
def _do_getitem(self, ctype, i):
ctitem = ctype.ctitem
- return ctitem.convert_to_object(
- rffi.ptradd(self._cdata, i * ctitem.size))
+ with self as ptr:
+ return ctitem.convert_to_object(
+ rffi.ptradd(ptr, i * ctitem.size))
def setitem(self, w_index, w_value):
space = self.space
if space.isinstance_w(w_index, space.w_slice):
- self._do_setslice(w_index, w_value)
+ with self as ptr:
+ self._do_setslice(w_index, w_value, ptr)
else:
i = space.getindex_w(w_index, space.w_IndexError)
ctype = self.ctype._check_subscript_index(self, i)
ctitem = ctype.ctitem
- ctitem.convert_from_object(
- rffi.ptradd(self._cdata, i * ctitem.size),
- w_value)
- keepalive_until_here(self)
+ with self as ptr:
+ ctitem.convert_from_object(
+ rffi.ptradd(ptr, i * ctitem.size),
+ w_value)
def _do_getslicearg(self, w_slice):
from pypy.module._cffi_backend.ctypeptr import W_CTypePointer
@@ -188,14 +207,15 @@
ctarray = newtype.new_array_type(space, ctptr, space.w_None)
ctptr.cache_array_type = ctarray
#
- p = rffi.ptradd(self._cdata, start * ctarray.ctitem.size)
- return W_CDataSliced(space, p, ctarray, length)
+ ptr = self.unsafe_escaping_ptr()
+ ptr = rffi.ptradd(ptr, start * ctarray.ctitem.size)
+ return W_CDataSliced(space, ptr, ctarray, length)
- def _do_setslice(self, w_slice, w_value):
+ def _do_setslice(self, w_slice, w_value, ptr):
ctptr, start, length = self._do_getslicearg(w_slice)
ctitem = ctptr.ctitem
ctitemsize = ctitem.size
- cdata = rffi.ptradd(self._cdata, start * ctitemsize)
+ target = rffi.ptradd(ptr, start * ctitemsize)
#
if isinstance(w_value, W_CData):
from pypy.module._cffi_backend import ctypearray
@@ -204,9 +224,8 @@
ctv.ctitem is ctitem and
w_value.get_array_length() == length):
# fast path: copying from exactly the correct type
- s = w_value._cdata
- rffi.c_memcpy(cdata, s, ctitemsize * length)
- keepalive_until_here(w_value)
+ with w_value as source:
+ rffi.c_memcpy(target, source, ctitemsize * length)
return
#
# A fast path for <char[]>[0:N] = "somestring".
@@ -221,7 +240,7 @@
raise oefmt(space.w_ValueError,
"need a string of length %d, got %d",
length, len(value))
- copy_string_to_raw(llstr(value), cdata, 0, length)
+ copy_string_to_raw(llstr(value), target, 0, length)
return
#
w_iter = space.iter(w_value)
@@ -233,8 +252,8 @@
raise
raise oefmt(space.w_ValueError,
"need %d values to unpack, got %d", length, i)
- ctitem.convert_from_object(cdata, w_item)
- cdata = rffi.ptradd(cdata, ctitemsize)
+ ctitem.convert_from_object(target, w_item)
+ target = rffi.ptradd(target, ctitemsize)
try:
space.next(w_iter)
except OperationError, e:
@@ -247,7 +266,8 @@
def _add_or_sub(self, w_other, sign):
space = self.space
i = sign * space.getindex_w(w_other, space.w_OverflowError)
- return self.ctype.add(self._cdata, i)
+ ptr = self.unsafe_escaping_ptr()
+ return self.ctype.add(ptr, i)
def add(self, w_other):
return self._add_or_sub(w_other, +1)
@@ -268,9 +288,11 @@
self.ctype.name, ct.name)
#
itemsize = ct.ctitem.size
- if itemsize <= 0: itemsize = 1
- diff = (rffi.cast(lltype.Signed, self._cdata) -
- rffi.cast(lltype.Signed, w_other._cdata)) // itemsize
+ if itemsize <= 0:
+ itemsize = 1
+ with self as ptr1, w_other as ptr2:
+ diff = (rffi.cast(lltype.Signed, ptr1) -
+ rffi.cast(lltype.Signed, ptr2)) // itemsize
return space.wrap(diff)
#
return self._add_or_sub(w_other, -1)
@@ -279,17 +301,19 @@
return self.ctype.getcfield(self.space.str_w(w_attr))
def getattr(self, w_attr):
- w_res = self.getcfield(w_attr).read(self._cdata)
- keepalive_until_here(self)
+ cfield = self.getcfield(w_attr)
+ with self as ptr:
+ w_res = cfield.read(ptr)
return w_res
def setattr(self, w_attr, w_value):
- self.getcfield(w_attr).write(self._cdata, w_value)
- keepalive_until_here(self)
+ cfield = self.getcfield(w_attr)
+ with self as ptr:
+ cfield.write(ptr, w_value)
def call(self, args_w):
- w_result = self.ctype.call(self._cdata, args_w)
- keepalive_until_here(self)
+ with self as ptr:
+ w_result = self.ctype.call(ptr, args_w)
return w_result
def iter(self):
@@ -311,21 +335,21 @@
@specialize.argtype(1)
def write_raw_signed_data(self, source):
- misc.write_raw_signed_data(self._cdata, source, self.ctype.size)
- keepalive_until_here(self)
+ with self as ptr:
+ misc.write_raw_signed_data(ptr, source, self.ctype.size)
@specialize.argtype(1)
def write_raw_unsigned_data(self, source):
- misc.write_raw_unsigned_data(self._cdata, source, self.ctype.size)
- keepalive_until_here(self)
+ with self as ptr:
+ misc.write_raw_unsigned_data(ptr, source, self.ctype.size)
def write_raw_float_data(self, source):
- misc.write_raw_float_data(self._cdata, source, self.ctype.size)
- keepalive_until_here(self)
+ with self as ptr:
+ misc.write_raw_float_data(ptr, source, self.ctype.size)
def convert_to_object(self):
- w_obj = self.ctype.convert_to_object(self._cdata)
- keepalive_until_here(self)
+ with self as ptr:
+ w_obj = self.ctype.convert_to_object(ptr)
return w_obj
def get_array_length(self):
@@ -353,7 +377,7 @@
@rgc.must_be_light_finalizer
def __del__(self):
- lltype.free(self._cdata, flavor='raw')
+ lltype.free(self._ptr, flavor='raw')
class W_CDataNewOwning(W_CDataMem):
diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -8,7 +8,6 @@
from pypy.interpreter.typedef import TypeDef
from rpython.rtyper.lltypesystem import rffi
-from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rarithmetic import ovfcheck
from pypy.module._cffi_backend import cdataobj
@@ -49,8 +48,8 @@
cdata = cdataobj.W_CDataNewOwning(space, datasize, self)
#
if not space.is_w(w_init, space.w_None):
- self.convert_from_object(cdata._cdata, w_init)
- keepalive_until_here(cdata)
+ with cdata as ptr:
+ self.convert_from_object(ptr, w_init)
return cdata
def _check_subscript_index(self, w_cdata, i):
@@ -119,8 +118,8 @@
self.ctitem = ctitem
self.cdata = cdata
length = cdata.get_array_length()
- self._next = cdata._cdata
- self._stop = rffi.ptradd(cdata._cdata, length * ctitem.size)
+ self._next = cdata.unsafe_escaping_ptr()
+ self._stop = rffi.ptradd(self._next, length * ctitem.size)
def iter_w(self):
return self.space.wrap(self)
diff --git a/pypy/module/_cffi_backend/ctypeenum.py b/pypy/module/_cffi_backend/ctypeenum.py
--- a/pypy/module/_cffi_backend/ctypeenum.py
+++ b/pypy/module/_cffi_backend/ctypeenum.py
@@ -2,8 +2,6 @@
Enums.
"""
-from rpython.rlib.objectmodel import keepalive_until_here
-
from pypy.module._cffi_backend import misc
from pypy.module._cffi_backend.ctypeprim import (W_CTypePrimitiveSigned,
W_CTypePrimitiveUnsigned)
@@ -47,8 +45,8 @@
return '%s: %s' % (value, s)
def string(self, cdataobj, maxlen):
- value = self._get_value(cdataobj._cdata)
- keepalive_until_here(cdataobj)
+ with cdataobj as ptr:
+ value = self._get_value(ptr)
try:
s = self.enumvalues2erators[value]
except KeyError:
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -177,8 +177,8 @@
raise oefmt(space.w_AttributeError,
"cdata '%s' has no attribute '%s'", self.name, attr)
- def copy_and_convert_to_object(self, cdata):
- return self.convert_to_object(cdata)
+ def copy_and_convert_to_object(self, source):
+ return self.convert_to_object(source)
# __________ app-level attributes __________
def dir(self):
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
@@ -5,7 +5,6 @@
import sys
from rpython.rlib.rarithmetic import r_uint, r_ulonglong, intmask
-from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib import jit
from rpython.rtyper.lltypesystem import lltype, rffi
@@ -53,7 +52,8 @@
space = self.space
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, ctypeptr.W_CTypePtrOrArray)):
- value = rffi.cast(lltype.Signed, w_ob._cdata)
+ ptr = w_ob.unsafe_escaping_ptr()
+ value = rffi.cast(lltype.Signed, ptr)
value = self._cast_result(value)
elif space.isinstance_w(w_ob, space.w_str):
value = self.cast_str(w_ob)
@@ -81,8 +81,8 @@
def string(self, cdataobj, maxlen):
if self.size == 1:
- s = cdataobj._cdata[0]
- keepalive_until_here(cdataobj)
+ with cdataobj as ptr:
+ s = ptr[0]
return self.space.wrap(s)
return W_CType.string(self, cdataobj, maxlen)
@@ -116,7 +116,8 @@
return s[0]
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePrimitiveChar)):
- return w_ob._cdata[0]
+ with w_ob as ptr:
+ return ptr[0]
raise self._convert_error("string of length 1", w_ob)
def convert_from_object(self, cdata, w_ob):
@@ -137,8 +138,8 @@
return self.space.wrap(s)
def string(self, cdataobj, maxlen):
- w_res = self.convert_to_object(cdataobj._cdata)
- keepalive_until_here(cdataobj)
+ with cdataobj as ptr:
+ w_res = self.convert_to_object(ptr)
return w_res
def _convert_to_unichar(self, w_ob):
@@ -149,7 +150,8 @@
return s[0]
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePrimitiveUniChar)):
- return rffi.cast(rffi.CWCHARP, w_ob._cdata)[0]
+ with w_ob as ptr:
+ return rffi.cast(rffi.CWCHARP, ptr)[0]
raise self._convert_error("unicode string of length 1", w_ob)
def convert_from_object(self, cdata, w_ob):
@@ -219,13 +221,15 @@
if self.size == rffi.sizeof(rffi.LONG):
from rpython.rlib.rrawarray import populate_list_from_raw_array
res = []
- buf = rffi.cast(rffi.LONGP, w_cdata._cdata)
length = w_cdata.get_array_length()
- populate_list_from_raw_array(res, buf, length)
+ with w_cdata as ptr:
+ buf = rffi.cast(rffi.LONGP, ptr)
+ populate_list_from_raw_array(res, buf, length)
return res
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)
+ with w_cdata as ptr:
+ misc.unpack_list_from_raw_array(res, ptr, self.size)
return res
return None
@@ -308,8 +312,8 @@
def unpack_list_of_int_items(self, w_cdata):
if self.value_fits_long:
res = [0] * w_cdata.get_array_length()
- misc.unpack_unsigned_list_from_raw_array(res, w_cdata._cdata,
- self.size)
+ with w_cdata as ptr:
+ misc.unpack_unsigned_list_from_raw_array(res, ptr, self.size)
return res
return None
@@ -363,8 +367,8 @@
if not isinstance(self, W_CTypePrimitiveLongDouble):
w_cdata.write_raw_float_data(value)
else:
- self._to_longdouble_and_write(value, w_cdata._cdata)
- keepalive_until_here(w_cdata)
+ with w_cdata as ptr:
+ self._to_longdouble_and_write(value, ptr)
return w_cdata
def cast_to_int(self, cdata):
@@ -387,13 +391,15 @@
if self.size == rffi.sizeof(rffi.DOUBLE):
from rpython.rlib.rrawarray import populate_list_from_raw_array
res = []
- buf = rffi.cast(rffi.DOUBLEP, w_cdata._cdata)
length = w_cdata.get_array_length()
- populate_list_from_raw_array(res, buf, length)
+ with w_cdata as ptr:
+ buf = rffi.cast(rffi.DOUBLEP, ptr)
+ populate_list_from_raw_array(res, buf, length)
return res
elif self.size == rffi.sizeof(rffi.FLOAT):
res = [0.0] * w_cdata.get_array_length()
- misc.unpack_cfloat_list_from_raw_array(res, w_cdata._cdata)
+ with w_cdata as ptr:
+ misc.unpack_cfloat_list_from_raw_array(res, ptr)
return res
return None
@@ -423,8 +429,8 @@
def cast(self, w_ob):
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble)):
- w_cdata = self.convert_to_object(w_ob._cdata)
- keepalive_until_here(w_ob)
+ with w_ob as ptr:
+ w_cdata = self.convert_to_object(ptr)
return w_cdata
else:
return W_CTypePrimitiveFloat.cast(self, w_ob)
@@ -451,16 +457,16 @@
def convert_to_object(self, cdata):
w_cdata = cdataobj.W_CDataMem(self.space, self.size, self)
- self._copy_longdouble(cdata, w_cdata._cdata)
- keepalive_until_here(w_cdata)
+ with w_cdata as ptr:
+ self._copy_longdouble(cdata, ptr)
return w_cdata
def convert_from_object(self, cdata, w_ob):
space = self.space
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble)):
- self._copy_longdouble(w_ob._cdata, cdata)
- keepalive_until_here(w_ob)
+ with w_ob as ptr:
+ self._copy_longdouble(ptr, cdata)
else:
value = space.float_w(space.float(w_ob))
self._to_longdouble_and_write(value, cdata)
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -3,7 +3,6 @@
"""
from rpython.rlib import rposix
-from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rtyper.annlowlevel import llstr, llunicode
from rpython.rtyper.lltypesystem import lltype, rffi
@@ -49,7 +48,7 @@
space = self.space
if (isinstance(w_ob, cdataobj.W_CData) and
isinstance(w_ob.ctype, W_CTypePtrOrArray)):
- value = w_ob._cdata
+ value = w_ob.unsafe_escaping_ptr()
else:
value = misc.as_unsigned_long(space, w_ob, strict=False)
value = rffi.cast(rffi.CCHARP, value)
@@ -108,34 +107,33 @@
def string(self, cdataobj, maxlen):
space = self.space
if isinstance(self.ctitem, ctypeprim.W_CTypePrimitive):
- cdata = cdataobj._cdata
- if not cdata:
- raise oefmt(space.w_RuntimeError, "cannot use string() on %s",
- space.str_w(cdataobj.repr()))
- #
- from pypy.module._cffi_backend import ctypearray
- length = maxlen
- if length < 0 and isinstance(self, ctypearray.W_CTypeArray):
- length = cdataobj.get_array_length()
- #
- # pointer to a primitive type of size 1: builds and returns a str
- if self.ctitem.size == rffi.sizeof(lltype.Char):
- if length < 0:
- s = rffi.charp2str(cdata)
- else:
- s = rffi.charp2strn(cdata, length)
- keepalive_until_here(cdataobj)
- return space.wrap(s)
- #
- # pointer to a wchar_t: builds and returns a unicode
- if self.is_unichar_ptr_or_array():
- cdata = rffi.cast(rffi.CWCHARP, cdata)
- if length < 0:
- u = rffi.wcharp2unicode(cdata)
- else:
- u = rffi.wcharp2unicoden(cdata, length)
- keepalive_until_here(cdataobj)
- return space.wrap(u)
+ with cdataobj as ptr:
+ if not ptr:
+ raise oefmt(space.w_RuntimeError,
+ "cannot use string() on %s",
+ space.str_w(cdataobj.repr()))
+ #
+ from pypy.module._cffi_backend import ctypearray
+ length = maxlen
+ if length < 0 and isinstance(self, ctypearray.W_CTypeArray):
+ length = cdataobj.get_array_length()
+ #
+ # pointer to a primitive type of size 1: builds and returns a str
+ if self.ctitem.size == rffi.sizeof(lltype.Char):
+ if length < 0:
+ s = rffi.charp2str(ptr)
+ else:
+ s = rffi.charp2strn(ptr, length)
+ return space.wrap(s)
+ #
+ # pointer to a wchar_t: builds and returns a unicode
+ if self.is_unichar_ptr_or_array():
+ cdata = rffi.cast(rffi.CWCHARP, ptr)
+ if length < 0:
+ u = rffi.wcharp2unicode(cdata)
+ else:
+ u = rffi.wcharp2unicoden(cdata, length)
+ return space.wrap(u)
#
return W_CType.string(self, cdataobj, maxlen)
@@ -162,7 +160,7 @@
if not (self.can_cast_anything or other.can_cast_anything):
raise self._convert_error("compatible pointer", w_ob)
- rffi.cast(rffi.CCHARPP, cdata)[0] = w_ob._cdata
+ rffi.cast(rffi.CCHARPP, cdata)[0] = w_ob.unsafe_escaping_ptr()
def _alignof(self):
from pypy.module._cffi_backend import newtype
@@ -206,8 +204,8 @@
lltype.nullptr(rffi.CCHARP.TO), w_init, datasize)
#
cdatastruct = cdataobj.W_CDataNewOwning(space, datasize, ctitem)
- cdata = cdataobj.W_CDataPtrToStructOrUnion(space,
- cdatastruct._cdata,
+ ptr = cdatastruct.unsafe_escaping_ptr()
+ cdata = cdataobj.W_CDataPtrToStructOrUnion(space, ptr,
self, cdatastruct)
else:
if self.is_char_or_unichar_ptr_or_array():
@@ -215,8 +213,8 @@
cdata = cdataobj.W_CDataNewOwning(space, datasize, self)
#
if not space.is_w(w_init, space.w_None):
- ctitem.convert_from_object(cdata._cdata, w_init)
- keepalive_until_here(cdata)
+ with cdata as ptr:
+ ctitem.convert_from_object(ptr, w_init)
return cdata
def _check_subscript_index(self, w_cdata, i):
@@ -332,8 +330,9 @@
ctype2 = cdata.ctype
if (isinstance(ctype2, W_CTypeStructOrUnion) or
isinstance(ctype2, W_CTypePtrOrArray)):
- ptrdata = rffi.ptradd(cdata._cdata, offset)
- return cdataobj.W_CData(space, ptrdata, self)
+ ptr = cdata.unsafe_escaping_ptr()
+ ptr = rffi.ptradd(ptr, offset)
+ return cdataobj.W_CData(space, ptr, self)
else:
raise OperationError(space.w_TypeError,
space.wrap("expected a cdata struct/union/array/pointer"
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -7,7 +7,6 @@
from pypy.interpreter.typedef import TypeDef, interp_attrproperty
from rpython.rlib import jit
-from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong, intmask
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rtyper.lltypesystem import lltype, rffi
@@ -57,12 +56,12 @@
self.check_complete()
return cdataobj.W_CData(space, cdata, self)
- def copy_and_convert_to_object(self, cdata):
+ def copy_and_convert_to_object(self, source):
space = self.space
self.check_complete()
ob = cdataobj.W_CDataNewOwning(space, self.size, self)
- misc._raw_memcopy(cdata, ob._cdata, self.size)
- keepalive_until_here(ob)
+ with ob as target:
+ misc._raw_memcopy(source, target, self.size)
return ob
def typeoffsetof_field(self, fieldname, following):
@@ -80,8 +79,8 @@
def _copy_from_same(self, cdata, w_ob):
if isinstance(w_ob, cdataobj.W_CData):
if w_ob.ctype is self and self.size >= 0:
- misc._raw_memcopy(w_ob._cdata, cdata, self.size)
- keepalive_until_here(w_ob)
+ with w_ob as ptr:
+ misc._raw_memcopy(ptr, cdata, self.size)
return True
return False
diff --git a/pypy/module/_cffi_backend/ctypevoid.py b/pypy/module/_cffi_backend/ctypevoid.py
--- a/pypy/module/_cffi_backend/ctypevoid.py
+++ b/pypy/module/_cffi_backend/ctypevoid.py
@@ -13,5 +13,5 @@
def __init__(self, space):
W_CType.__init__(self, space, -1, "void", len("void"))
- def copy_and_convert_to_object(self, cdata):
+ def copy_and_convert_to_object(self, source):
return self.space.w_None
diff --git a/pypy/module/_cffi_backend/handle.py b/pypy/module/_cffi_backend/handle.py
--- a/pypy/module/_cffi_backend/handle.py
+++ b/pypy/module/_cffi_backend/handle.py
@@ -34,8 +34,9 @@
raise oefmt(space.w_TypeError,
"expected a 'cdata' object with a 'void *' out of "
"new_handle(), got '%s'", ctype.name)
- index = rffi.cast(lltype.Signed, w_cdata._cdata)
- original_cdataobj = get(space).fetch_handle(index - 1)
+ with w_cdata as ptr:
+ index = rffi.cast(lltype.Signed, ptr)
+ original_cdataobj = get(space).fetch_handle(index - 1)
#
if isinstance(original_cdataobj, cdataobj.W_CDataHandle):
return original_cdataobj.w_keepalive
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
@@ -3,7 +3,7 @@
from pypy.interpreter.error import OperationError
from rpython.rlib import jit
-from rpython.rlib.objectmodel import keepalive_until_here, specialize
+from rpython.rlib.objectmodel import specialize
from rpython.rlib.rarithmetic import r_uint, r_ulonglong
from rpython.rlib.unroll import unrolling_iterable
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
@@ -272,11 +272,11 @@
from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveLongDouble
is_cdata = isinstance(w_ob, W_CData)
if is_cdata and isinstance(w_ob.ctype, W_CTypePrimitiveFloat):
- if isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble):
- result = is_nonnull_longdouble(w_ob._cdata)
- else:
- result = is_nonnull_float(w_ob._cdata, w_ob.ctype.size)
- keepalive_until_here(w_ob)
+ with w_ob as ptr:
+ if isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble):
+ result = is_nonnull_longdouble(ptr)
+ else:
+ result = is_nonnull_float(ptr, w_ob.ctype.size)
return result
#
if not is_cdata and space.lookup(w_ob, '__float__') is not None:
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
@@ -3249,4 +3249,4 @@
def test_version():
# this test is here mostly for PyPy
- assert __version__ == "0.8.6+"
+ assert __version__ == "0.9.0"
diff --git a/pypy/module/_random/test/test_random.py b/pypy/module/_random/test/test_random.py
--- a/pypy/module/_random/test/test_random.py
+++ b/pypy/module/_random/test/test_random.py
@@ -102,3 +102,10 @@
self.x = x
r = R(x=15)
assert r.x == 15
+
+ def test_exact_result(self):
+ # this passes on CPython 2.7.9 on Linux 32 and Linux 64
+ import _random
+ rnd = _random.Random(-3**31)
+ x = rnd.random()
+ assert x == 0.8181851342382107
diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py
--- a/pypy/module/_rawffi/array.py
+++ b/pypy/module/_rawffi/array.py
@@ -15,7 +15,7 @@
from pypy.module._rawffi.interp_rawffi import unpack_shape_with_length
from pypy.module._rawffi.interp_rawffi import read_ptr, write_ptr
from rpython.rlib.rarithmetic import r_uint
-from rpython.rlib import rgc
+from rpython.rlib import rgc, clibffi
class W_Array(W_DataShape):
@@ -84,14 +84,11 @@
class W_ArrayInstance(W_DataInstance):
def __init__(self, space, shape, length, address=r_uint(0)):
- # Workaround for a strange behavior of libffi: make sure that
- # we always have at least 8 bytes. For W_ArrayInstances that are
- # used as the result value of a function call, ffi_call() writes
- # 8 bytes into it even if the function's result type asks for less.
- # This strange behavior is documented.
memsize = shape.size * length
- if memsize < 8:
- memsize = 8
+ # For W_ArrayInstances that are used as the result value of a
+ # function call, ffi_call() writes 8 bytes into it even if the
+ # function's result type asks for less.
+ memsize = clibffi.adjust_return_size(memsize)
W_DataInstance.__init__(self, space, memsize, address)
self.length = length
self.shape = shape
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
@@ -495,6 +495,7 @@
try:
if self.resshape is not None:
result = self.resshape.allocate(space, 1, autofree=True)
+ # adjust_return_size() was used here on result.ll_buffer
self.ptr.call(args_ll, result.ll_buffer)
return space.wrap(result)
else:
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
@@ -1,4 +1,4 @@
-from rpython.rlib import jit
+from rpython.rlib import jit, rgc
from rpython.rlib.buffer import Buffer
from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rlib.rarithmetic import ovfcheck, widen
@@ -698,11 +698,9 @@
self.space.wrap(msg))
return result
+ @rgc.must_be_light_finalizer
def __del__(self):
- # note that we don't call clear_all_weakrefs here because
- # an array with freed buffer is ok to see - it's just empty with 0
- # length
- self.setlen(0)
+ lltype.free(self.buffer, flavor='raw')
def setlen(self, size, zero=False, overallocate=True):
if size > 0:
diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py
--- a/pypy/module/cppyy/capi/loadable_capi.py
+++ b/pypy/module/cppyy/capi/loadable_capi.py
@@ -259,7 +259,8 @@
if not objectmodel.we_are_translated():
leakfinder.remember_free(c_call.ctype.cif_descr._obj0)
state.capi_calls[name] = c_call
- return c_call.ctype.rcall(c_call._cdata, args)
+ with c_call as ptr:
+ return c_call.ctype.rcall(ptr, args)
def _cdata_to_cobject(space, w_cdata):
return rffi.cast(C_OBJECT, space.uint_w(w_cdata))
@@ -271,8 +272,9 @@
return rffi.cast(rffi.LONG, space.int_w(w_cdata))
def _cdata_to_ptr(space, w_cdata): # TODO: this is both a hack and dreadfully slow
- return rffi.cast(rffi.VOIDP,
- space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False)._cdata)
+ w_cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False)
+ ptr = w_cdata.unsafe_escaping_ptr()
+ return rffi.cast(rffi.VOIDP, ptr)
def c_load_dictionary(name):
return libffi.CDLL(name)
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
@@ -46,7 +46,7 @@
@staticmethod
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):
+ w_base=None, writable=True, strides=None, start=0):
from pypy.module.micronumpy import concrete
from pypy.module.micronumpy.strides import (calc_strides,
calc_backstrides)
@@ -75,8 +75,9 @@
raise OperationError(space.w_ValueError,
space.wrap("Cannot have owning=True when specifying a buffer"))
if writable:
- impl = concrete.ConcreteArrayWithBase(shape, dtype, order, strides,
- backstrides, storage, w_base)
+ impl = concrete.ConcreteArrayWithBase(shape, dtype, order,
+ strides, backstrides, storage, w_base,
+ start=start)
else:
impl = concrete.ConcreteNonWritableArrayWithBase(shape, dtype, order,
strides, backstrides,
@@ -128,6 +129,9 @@
def get_order(self):
return self.implementation.order
+ def get_start(self):
+ return self.implementation.start
+
def ndims(self):
return len(self.get_shape())
ndims._always_inline_ = True
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
@@ -12,6 +12,7 @@
from pypy.module.micronumpy.strides import (Chunk, Chunks, NewAxisChunk,
RecordChunk, calc_strides, calc_new_strides, shape_agreement,
calculate_broadcast_strides, calc_backstrides)
+from rpython.rlib.objectmodel import keepalive_until_here
class BaseConcreteArray(object):
@@ -312,12 +313,15 @@
l_w = [w_res.descr_getitem(space, space.wrap(d)) for d in range(nd)]
return space.newtuple(l_w)
- def get_storage_as_int(self, space):
- return rffi.cast(lltype.Signed, self.storage) + self.start
-
- def get_storage(self):
+ ##def get_storage(self):
+ ## return self.storage
+ ## use a safer context manager
+ def __enter__(self):
return self.storage
+ def __exit__(self, typ, value, traceback):
+ keepalive_until_here(self)
+
def get_buffer(self, space, readonly):
return ArrayBuffer(self, readonly)
@@ -331,7 +335,7 @@
class ConcreteArrayNotOwning(BaseConcreteArray):
- def __init__(self, shape, dtype, order, strides, backstrides, storage):
+ def __init__(self, shape, dtype, order, strides, backstrides, storage, start=0):
make_sure_not_resized(shape)
make_sure_not_resized(strides)
make_sure_not_resized(backstrides)
@@ -342,6 +346,7 @@
self.strides = strides
self.backstrides = backstrides
self.storage = storage
+ self.start = start
def fill(self, space, box):
self.dtype.itemtype.fill(self.storage, self.dtype.elsize,
@@ -350,7 +355,7 @@
def set_shape(self, space, orig_array, new_shape):
strides, backstrides = calc_strides(new_shape, self.dtype,
self.order)
- return SliceArray(0, strides, backstrides, new_shape, self,
+ return SliceArray(self.start, strides, backstrides, new_shape, self,
orig_array)
def set_dtype(self, space, dtype):
@@ -384,9 +389,10 @@
class ConcreteArrayWithBase(ConcreteArrayNotOwning):
- def __init__(self, shape, dtype, order, strides, backstrides, storage, orig_base):
+ def __init__(self, shape, dtype, order, strides, backstrides, storage,
+ orig_base, start=0):
ConcreteArrayNotOwning.__init__(self, shape, dtype, order,
- strides, backstrides, storage)
+ strides, backstrides, storage, start)
self.orig_base = orig_base
def base(self):
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
@@ -99,10 +99,12 @@
for i in range(w_object.get_size()):
elems_w[i] = w_object.implementation.getitem(i * elsize)
else:
- sz = support.product(w_object.get_shape()) * dtype.elsize
- return W_NDimArray.from_shape_and_storage(space,
- w_object.get_shape(),w_object.implementation.storage,
- dtype, storage_bytes=sz, w_base=w_object)
+ imp = w_object.implementation
+ with imp as storage:
+ sz = support.product(w_object.get_shape()) * dtype.elsize
+ return W_NDimArray.from_shape_and_storage(space,
+ w_object.get_shape(), storage, dtype, storage_bytes=sz,
+ w_base=w_object, start=imp.start)
else:
# not an array
shape, elems_w = strides.find_shape_and_elems(space, w_object, dtype)
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
@@ -604,14 +604,15 @@
iter, state = arr.create_iter()
w_res_str = W_NDimArray.from_shape(space, [1], arr.get_dtype(), order='C')
itemsize = arr.get_dtype().elsize
- res_str_casted = rffi.cast(rffi.CArrayPtr(lltype.Char),
- w_res_str.implementation.get_storage_as_int(space))
- while not iter.done(state):
- w_res_str.implementation.setitem(0, iter.getitem(state))
- for i in range(itemsize):
- builder.append(res_str_casted[i])
- state = iter.next(state)
- return builder.build()
+ with w_res_str.implementation as storage:
+ res_str_casted = rffi.cast(rffi.CArrayPtr(lltype.Char),
+ support.get_storage_as_int(storage))
+ while not iter.done(state):
+ w_res_str.implementation.setitem(0, iter.getitem(state))
+ for i in range(itemsize):
+ builder.append(res_str_casted[i])
+ state = iter.next(state)
+ return builder.build()
getitem_int_driver = jit.JitDriver(name = 'numpy_getitem_int',
greens = ['shapelen', 'indexlen',
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -532,20 +532,25 @@
self.get_dtype(), storage_bytes=sz, w_base=self)
def descr_array_iface(self, space):
- addr = self.implementation.get_storage_as_int(space)
- # will explode if it can't
- w_d = space.newdict()
- space.setitem_str(w_d, 'data',
- space.newtuple([space.wrap(addr), space.w_False]))
- space.setitem_str(w_d, 'shape', self.descr_get_shape(space))
- space.setitem_str(w_d, 'typestr', self.get_dtype().descr_get_str(space))
- if self.implementation.order == 'C':
- # Array is contiguous, no strides in the interface.
- strides = space.w_None
- else:
- strides = self.descr_get_strides(space)
- space.setitem_str(w_d, 'strides', strides)
- return w_d
+ '''
+ Note: arr.__array__.data[0] is a pointer so arr must be kept alive
+ while it is in use
+ '''
+ with self.implementation as storage:
+ addr = support.get_storage_as_int(storage, self.get_start())
+ # will explode if it can't
+ w_d = space.newdict()
+ space.setitem_str(w_d, 'data',
+ space.newtuple([space.wrap(addr), space.w_False]))
+ space.setitem_str(w_d, 'shape', self.descr_get_shape(space))
+ space.setitem_str(w_d, 'typestr', self.get_dtype().descr_get_str(space))
+ if self.implementation.order == 'C':
+ # Array is contiguous, no strides in the interface.
+ strides = space.w_None
+ else:
+ strides = self.descr_get_strides(space)
+ space.setitem_str(w_d, 'strides', strides)
+ return w_d
w_pypy_data = None
@@ -1165,7 +1170,8 @@
builder.append(box.raw_str())
state = iter.next(state)
else:
- builder.append_charpsize(self.implementation.get_storage(),
+ with self.implementation as storage:
+ builder.append_charpsize(storage,
self.implementation.get_storage_size())
state = space.newtuple([
diff --git a/pypy/module/micronumpy/selection.py b/pypy/module/micronumpy/selection.py
--- a/pypy/module/micronumpy/selection.py
+++ b/pypy/module/micronumpy/selection.py
@@ -33,14 +33,14 @@
self.values = values
self.indexes = indexes
- def getitem(self, item):
+ def getitem(self, idx):
if count < 2:
- v = raw_storage_getitem(TP, self.values, item * self.stride_size
+ v = raw_storage_getitem(TP, self.values, idx * self.stride_size
+ self.start)
else:
v = []
for i in range(count):
- _v = raw_storage_getitem(TP, self.values, item * self.stride_size
+ _v = raw_storage_getitem(TP, self.values, idx * self.stride_size
+ self.start + step * i)
v.append(_v)
if comp_type == 'int':
@@ -52,7 +52,7 @@
else:
raise NotImplementedError('cannot reach')
return (v, raw_storage_getitem(lltype.Signed, self.indexes,
- item * self.index_stride_size +
+ idx * self.index_stride_size +
self.index_start))
def setitem(self, idx, item):
@@ -134,37 +134,37 @@
# create array of indexes
dtype = descriptor.get_dtype_cache(space).w_longdtype
index_arr = W_NDimArray.from_shape(space, arr.get_shape(), dtype)
- storage = index_arr.implementation.get_storage()
- if len(arr.get_shape()) == 1:
- for i in range(arr.get_size()):
- raw_storage_setitem(storage, i * INT_SIZE, i)
- r = Repr(INT_SIZE, itemsize, arr.get_size(), arr.get_storage(),
- storage, 0, arr.start)
- ArgSort(r).sort()
- else:
- shape = arr.get_shape()
- if axis < 0:
- axis = len(shape) + axis
- if axis < 0 or axis >= len(shape):
- raise oefmt(space.w_IndexError, "Wrong axis %d", axis)
- arr_iter = AllButAxisIter(arr, axis)
- arr_state = arr_iter.reset()
- index_impl = index_arr.implementation
- index_iter = AllButAxisIter(index_impl, axis)
- index_state = index_iter.reset()
- stride_size = arr.strides[axis]
- index_stride_size = index_impl.strides[axis]
- axis_size = arr.shape[axis]
- while not arr_iter.done(arr_state):
- for i in range(axis_size):
- raw_storage_setitem(storage, i * index_stride_size +
- index_state.offset, i)
- r = Repr(index_stride_size, stride_size, axis_size,
- arr.get_storage(), storage, index_state.offset, arr_state.offset)
+ with index_arr.implementation as storage, arr as arr_storage:
+ if len(arr.get_shape()) == 1:
+ for i in range(arr.get_size()):
+ raw_storage_setitem(storage, i * INT_SIZE, i)
+ r = Repr(INT_SIZE, itemsize, arr.get_size(), arr_storage,
+ storage, 0, arr.start)
ArgSort(r).sort()
- arr_state = arr_iter.next(arr_state)
- index_state = index_iter.next(index_state)
- return index_arr
+ else:
+ shape = arr.get_shape()
+ if axis < 0:
+ axis = len(shape) + axis
+ if axis < 0 or axis >= len(shape):
+ raise oefmt(space.w_IndexError, "Wrong axis %d", axis)
+ arr_iter = AllButAxisIter(arr, axis)
+ arr_state = arr_iter.reset()
+ index_impl = index_arr.implementation
+ index_iter = AllButAxisIter(index_impl, axis)
+ index_state = index_iter.reset()
+ stride_size = arr.strides[axis]
+ index_stride_size = index_impl.strides[axis]
+ axis_size = arr.shape[axis]
+ while not arr_iter.done(arr_state):
+ for i in range(axis_size):
+ raw_storage_setitem(storage, i * index_stride_size +
+ index_state.offset, i)
+ r = Repr(index_stride_size, stride_size, axis_size,
+ arr_storage, storage, index_state.offset, arr_state.offset)
+ ArgSort(r).sort()
+ arr_state = arr_iter.next(arr_state)
+ index_state = index_iter.next(index_state)
+ return index_arr
return argsort
@@ -282,25 +282,25 @@
axis = -1
else:
axis = space.int_w(w_axis)
- # create array of indexes
- if len(arr.get_shape()) == 1:
- r = Repr(itemsize, arr.get_size(), arr.get_storage(),
- arr.start)
- ArgSort(r).sort()
- else:
- shape = arr.get_shape()
- if axis < 0:
- axis = len(shape) + axis
- if axis < 0 or axis >= len(shape):
- raise oefmt(space.w_IndexError, "Wrong axis %d", axis)
- arr_iter = AllButAxisIter(arr, axis)
- arr_state = arr_iter.reset()
- stride_size = arr.strides[axis]
- axis_size = arr.shape[axis]
- while not arr_iter.done(arr_state):
- r = Repr(stride_size, axis_size, arr.get_storage(), arr_state.offset)
+ with arr as storage:
+ if len(arr.get_shape()) == 1:
+ r = Repr(itemsize, arr.get_size(), storage,
+ arr.start)
ArgSort(r).sort()
- arr_state = arr_iter.next(arr_state)
+ else:
+ shape = arr.get_shape()
+ if axis < 0:
+ axis = len(shape) + axis
+ if axis < 0 or axis >= len(shape):
+ raise oefmt(space.w_IndexError, "Wrong axis %d", axis)
+ arr_iter = AllButAxisIter(arr, axis)
+ arr_state = arr_iter.reset()
+ stride_size = arr.strides[axis]
+ axis_size = arr.shape[axis]
+ while not arr_iter.done(arr_state):
+ r = Repr(stride_size, axis_size, storage, arr_state.offset)
+ ArgSort(r).sort()
+ arr_state = arr_iter.next(arr_state)
return sort
diff --git a/pypy/module/micronumpy/support.py b/pypy/module/micronumpy/support.py
--- a/pypy/module/micronumpy/support.py
+++ b/pypy/module/micronumpy/support.py
@@ -1,6 +1,7 @@
from pypy.interpreter.error import OperationError, oefmt
from rpython.rlib import jit
from rpython.rlib.rarithmetic import ovfcheck
+from rpython.rtyper.lltypesystem import rffi, lltype
def issequence_w(space, w_obj):
@@ -147,3 +148,7 @@
if cur_core_dim == 0:
ufunc.core_enabled = False
return 0 # for historical reasons, any failures will raise
+
+def get_storage_as_int(storage, start=0):
+ return rffi.cast(lltype.Signed, storage) + start
+
diff --git a/pypy/module/micronumpy/test/test_subtype.py b/pypy/module/micronumpy/test/test_subtype.py
--- a/pypy/module/micronumpy/test/test_subtype.py
+++ b/pypy/module/micronumpy/test/test_subtype.py
@@ -2,7 +2,7 @@
class AppTestSupport(BaseNumpyAppTest):
- spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"])
+ spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii", "mmap"])
def setup_class(cls):
BaseNumpyAppTest.setup_class.im_func(cls)
@@ -476,3 +476,120 @@
a = self.SubType(array([[1, 2], [3, 4]]))
b = array(a, subok=False)
assert type(b) is ndarray
+
+ def test_numpypy_mmap(self):
+ # issue #21 on pypy/numpy
+ from numpy import array, ndarray, arange, dtype as dtypedescr
+ import mmap
+ import os.path
+ from tempfile import mkdtemp
+ import os.path as path
+ valid_filemodes = ["r", "c", "r+", "w+"]
+ writeable_filemodes = ["r+", "w+"]
+ mode_equivalents = {
+ "readonly":"r",
+ "copyonwrite":"c",
+ "readwrite":"r+",
+ "write":"w+"
+ }
+
+ class memmap(ndarray):
+ def __new__(subtype, filename, dtype='uint8', mode='r+', offset=0, shape=None, order='C'):
+ # Import here to minimize 'import numpy' overhead
+ try:
+ mode = mode_equivalents[mode]
+ except KeyError:
+ if mode not in valid_filemodes:
+ raise ValueError("mode must be one of %s" %
+ (valid_filemodes + list(mode_equivalents.keys())))
+
+ if hasattr(filename, 'read'):
+ fid = filename
+ own_file = False
+ else:
+ fid = open(filename, (mode == 'c' and 'r' or mode)+'b')
+ own_file = True
+
+ if (mode == 'w+') and shape is None:
+ raise ValueError("shape must be given")
+
+ fid.seek(0, 2)
+ flen = fid.tell()
+ descr = dtypedescr(dtype)
+ _dbytes = descr.itemsize
+
+ if shape is None:
+ bytes = flen - offset
+ if (bytes % _dbytes):
+ fid.close()
+ raise ValueError("Size of available data is not a "
+ "multiple of the data-type size.")
+ size = bytes // _dbytes
+ shape = (size,)
+ else:
+ if not isinstance(shape, tuple):
+ shape = (shape,)
+ size = 1
+ for k in shape:
+ size *= k
+
+ bytes = long(offset + size*_dbytes)
+
+ if mode == 'w+' or (mode == 'r+' and flen < bytes):
+ fid.seek(bytes - 1, 0)
+ fid.write('\0')
+ fid.flush()
+
+ if mode == 'c':
+ acc = mmap.ACCESS_COPY
+ elif mode == 'r':
+ acc = mmap.ACCESS_READ
+ else:
+ acc = mmap.ACCESS_WRITE
+
+ start = offset - offset % mmap.ALLOCATIONGRANULARITY
+ bytes -= start
+ offset -= start
+ mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
+
+ self = ndarray.__new__(subtype, shape, dtype=descr, buffer=mm,
+ offset=offset, order=order)
+ self._mmap = mm
+ self.offset = offset
+ self.mode = mode
+
+ if isinstance(filename, basestring):
+ self.filename = os.path.abspath(filename)
+ # py3 returns int for TemporaryFile().name
+ elif (hasattr(filename, "name") and
+ isinstance(filename.name, basestring)):
+ self.filename = os.path.abspath(filename.name)
+ # same as memmap copies (e.g. memmap + 1)
+ else:
+ self.filename = None
+
+ if own_file:
+ fid.close()
+
+ return self
+
+ def flush(self):
+ if self.base is not None and hasattr(self.base, 'flush'):
+ self.base.flush()
+
+ def asarray(obj, itemsize=None, order=None):
+ return array(obj, itemsize, copy=False, order=order)
+
+ filename = path.join(mkdtemp(), 'newfile.dat')
+ data = arange(10*10*36).reshape(10, 10, 36)
+ fp = memmap(filename, dtype='float32', mode='w+', shape=data.shape)
+ vals = [ 242, 507, 255, 505, 315, 316, 308, 506,
+ 309, 255, 211, 505, 315, 316, 308, 506,
+ 309, 255, 255, 711, 194, 232, 711, 711,
+ 709, 710, 709, 710, 882, 897, 711, 245,
+ 711, 711, 168, 245]
+ fp[:] = data
+ fp[5:6][:,4] = vals
+ a = asarray(fp[5:6][:,4])
+ assert (a == vals).all()
+
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -238,15 +238,15 @@
'getfield_gc': 5,
'getfield_gc_pure': 51,
'guard_class': 3,
- 'guard_false': 13,
+ 'guard_false': 12,
'guard_nonnull': 11,
'guard_nonnull_class': 3,
'guard_not_invalidated': 2,
'guard_true': 10,
- 'guard_value': 5,
+ 'guard_value': 6,
'int_add': 13,
'int_ge': 4,
- 'int_is_true': 4,
+ 'int_is_true': 3,
'int_is_zero': 4,
'int_le': 2,
'int_lt': 3,
@@ -616,15 +616,15 @@
'getfield_gc': 6,
'getfield_gc_pure': 63,
'guard_class': 5,
- 'guard_false': 20,
+ 'guard_false': 19,
'guard_nonnull': 6,
'guard_nonnull_class': 1,
'guard_not_invalidated': 3,
'guard_true': 16,
- 'guard_value': 2,
+ 'guard_value': 3,
'int_add': 24,
'int_ge': 4,
- 'int_is_true': 6,
+ 'int_is_true': 5,
'int_is_zero': 4,
'int_le': 5,
'int_lt': 7,
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -180,13 +180,16 @@
raw_storage_setitem_unaligned(storage, i + offset, value)
def read(self, arr, i, offset, dtype=None):
- return self.box(self._read(arr.storage, i, offset))
+ with arr as storage:
+ return self.box(self._read(storage, i, offset))
def read_bool(self, arr, i, offset):
- return bool(self.for_computation(self._read(arr.storage, i, offset)))
+ with arr as storage:
+ return bool(self.for_computation(self._read(storage, i, offset)))
def store(self, arr, i, offset, box):
- self._write(arr.storage, i, offset, self.unbox(box))
+ with arr as storage:
+ self._write(storage, i, offset, self.unbox(box))
def fill(self, storage, width, box, start, stop, offset):
value = self.unbox(box)
@@ -1080,8 +1083,9 @@
return bool(real) or bool(imag)
def read_bool(self, arr, i, offset):
- v = self.for_computation(self._read(arr.storage, i, offset))
- return bool(v[0]) or bool(v[1])
+ with arr as storage:
+ v = self.for_computation(self._read(storage, i, offset))
+ return bool(v[0]) or bool(v[1])
def get_element_size(self):
return 2 * rffi.sizeof(self.T)
@@ -1132,8 +1136,9 @@
return real, imag
def read(self, arr, i, offset, dtype=None):
- real, imag = self._read(arr.storage, i, offset)
- return self.box_complex(real, imag)
+ with arr as storage:
+ real, imag = self._read(storage, i, offset)
+ return self.box_complex(real, imag)
def _write(self, storage, i, offset, value):
real, imag = value
@@ -1144,7 +1149,8 @@
raw_storage_setitem_unaligned(storage, i + offset + rffi.sizeof(self.T), imag)
More information about the pypy-commit
mailing list