[pypy-commit] pypy default: Merged from pypy/pypy
anton_gulenko
noreply at buildbot.pypy.org
Wed Apr 22 12:20:56 CEST 2015
Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch:
Changeset: r76877:f26c00008203
Date: 2015-03-12 13:11 +0100
http://bitbucket.org/pypy/pypy/changeset/f26c00008203/
Log: Merged from pypy/pypy
diff too long, truncating to 2000 out of 13267 lines
diff --git a/lib_pypy/audioop.py b/lib_pypy/audioop.py
--- a/lib_pypy/audioop.py
+++ b/lib_pypy/audioop.py
@@ -480,6 +480,7 @@
state_d, prev_i, cur_i,
weightA, weightB)
result = ffi.buffer(rv)[:trim_index]
+ d = state_d[0]
samps = zip(prev_i, cur_i)
return (result, (d, tuple(samps)))
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.1
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.1"
+__version_info__ = (0, 9, 1)
# 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
@@ -6,8 +6,8 @@
.. startrev: 397b96217b85
-Fix non-blocking file reads sometimes raising EAGAIN even though they
-have buffered data waiting (b1c4fcb04a42)
+Non-blocking file reads sometimes raised EAGAIN even though they
+had buffered data waiting, fixed in b1c4fcb04a42
.. branch: vmprof
@@ -18,3 +18,22 @@
.. branch: stdlib-2.7.9
Update stdlib to version 2.7.9
+
+.. branch: fix-kqueue-error2
+Fix exception being raised by kqueue.control (CPython compatibility)
+
+.. branch: gitignore
+
+.. branch: framestate2
+Refactor rpython.flowspace.framestate.FrameState.
+
+.. 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/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -25,8 +25,8 @@
self.reason = reason
@specialize.memo()
-def encode_error_handler(space):
- # Fast version of the "strict" errors handler.
+def rpy_encode_error_handler():
+ # A RPython version of the "strict" error handler.
def raise_unicode_exception_encode(errors, encoding, msg, u,
startingpos, endingpos):
raise RUnicodeEncodeError(encoding, u, startingpos, endingpos, msg)
@@ -62,7 +62,10 @@
return result
def encode_utf8(space, uni):
+ # Note that this function never raises UnicodeEncodeError,
+ # since surrogate pairs are allowed.
+ # This is not the case with Python3.
return runicode.unicode_encode_utf_8(
uni, len(uni), "strict",
- errorhandler=encode_error_handler(space),
+ errorhandler=rpy_encode_error_handler(),
allow_surrogates=True)
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -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
@@ -2,13 +2,15 @@
from pypy.interpreter.mixedmodule import MixedModule
from rpython.rlib import rdynload
+VERSION = "0.9.1"
+
class Module(MixedModule):
appleveldefs = {
}
interpleveldefs = {
- '__version__': 'space.wrap("0.8.6+")',
+ '__version__': 'space.wrap("%s")' % VERSION,
'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)
@@ -210,6 +210,6 @@
space.threadlocals.leave_thread(space)
def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata):
- cerrno._errno_after(rffi.RFFI_ERR_ALL)
+ cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
_invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata)
- cerrno._errno_before(rffi.RFFI_ERR_ALL)
+ cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
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/cerrno.py b/pypy/module/_cffi_backend/cerrno.py
--- a/pypy/module/_cffi_backend/cerrno.py
+++ b/pypy/module/_cffi_backend/cerrno.py
@@ -13,18 +13,18 @@
_errno_after = rposix._errno_after
def get_errno(space):
- return space.wrap(rposix.get_saved_errno())
+ return space.wrap(rposix.get_saved_alterrno())
@unwrap_spec(errno=int)
def set_errno(space, errno):
- rposix.set_saved_errno(errno)
+ rposix.set_saved_alterrno(errno)
# ____________________________________________________________
@unwrap_spec(code=int)
def getwinerror(space, code=-1):
- from rpython.rlib.rwin32 import GetLastError_saved, FormatError
+ from rpython.rlib.rwin32 import GetLastError_alt_saved, FormatError
if code == -1:
- code = GetLastError_saved()
+ code = GetLastError_alt_saved()
message = FormatError(code)
return space.newtuple([space.wrap(code), space.wrap(message)])
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
@@ -2716,6 +2716,14 @@
assert data == b"Xhello\n"
posix.close(fdr)
+def test_errno_saved():
+ set_errno(42)
+ # a random function that will reset errno to 0 (at least on non-windows)
+ import os; os.stat('.')
+ #
+ res = get_errno()
+ assert res == 42
+
def test_GetLastError():
if sys.platform != "win32":
py.test.skip("GetLastError(): only for Windows")
@@ -3241,4 +3249,4 @@
def test_version():
# this test is here mostly for PyPy
- assert __version__ == "0.8.6+"
+ assert __version__ == "0.9.1"
diff --git a/pypy/module/_cffi_backend/test/test_file.py b/pypy/module/_cffi_backend/test/test_file.py
--- a/pypy/module/_cffi_backend/test/test_file.py
+++ b/pypy/module/_cffi_backend/test/test_file.py
@@ -15,3 +15,15 @@
"Update test/_backend_test_c.py by copying it from "
"https://bitbucket.org/cffi/cffi/raw/default/c/test_c.py "
"and killing the import lines at the start")
+
+def test_egginfo_version():
+ from pypy.module._cffi_backend import VERSION
+ line = "Version: %s\n" % VERSION
+ eggfile = py.path.local(__file__).join('..', '..', '..', '..', '..',
+ 'lib_pypy', 'cffi.egg-info')
+ assert line in eggfile.readlines()
+
+def test_app_version():
+ from pypy.module import _cffi_backend
+ from lib_pypy import cffi
+ assert _cffi_backend.VERSION == cffi.__version__
diff --git a/pypy/module/_random/interp_random.py b/pypy/module/_random/interp_random.py
--- a/pypy/module/_random/interp_random.py
+++ b/pypy/module/_random/interp_random.py
@@ -4,7 +4,7 @@
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.baseobjspace import W_Root
-from rpython.rlib.rarithmetic import r_uint, intmask
+from rpython.rlib.rarithmetic import r_uint, intmask, widen
from rpython.rlib import rbigint, rrandom, rstring
@@ -54,8 +54,8 @@
def getstate(self, space):
state = [None] * (rrandom.N + 1)
for i in range(rrandom.N):
- state[i] = space.newint(intmask(self._rnd.state[i]))
- state[rrandom.N] = space.newint(self._rnd.index)
+ state[i] = space.wrap(widen(self._rnd.state[i]))
+ state[rrandom.N] = space.newlong(self._rnd.index)
return space.newtuple(state)
def setstate(self, space, w_state):
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
@@ -41,6 +41,17 @@
# does not crash
rnd1.setstate((-1, ) * 624 + (0, ))
+ def test_state_repr(self):
+ # since app-level jumpahead salts with repr(state),
+ # it is important the repr is consistent with cpython
+ import _random
+ rnd = _random.Random()
+ rnd.seed(1234)
+ state = rnd.getstate()
+ s = repr(state)
+ assert len(s) == 7956
+ assert s.count('L') == 625
+
def test_seed(self):
import _random, sys
rnd = _random.Random()
@@ -102,3 +113,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:
@@ -608,19 +609,19 @@
return space.wrap(W_CDLL(space, name, cdll))
def get_errno(space):
- return space.wrap(rposix.get_saved_errno())
+ return space.wrap(rposix.get_saved_alterrno())
def set_errno(space, w_errno):
- rposix.set_saved_errno(space.int_w(w_errno))
+ rposix.set_saved_alterrno(space.int_w(w_errno))
if sys.platform == 'win32':
# see also
# https://bitbucket.org/pypy/pypy/issue/1944/ctypes-on-windows-getlasterror
def get_last_error(space):
- return space.wrap(rwin32.GetLastError_saved())
+ return space.wrap(rwin32.GetLastError_alt_saved())
@unwrap_spec(error=int)
def set_last_error(space, error):
- rwin32.SetLastError_saved(error)
+ rwin32.SetLastError_alt_saved(error)
else:
# always have at least a dummy version of these functions
# (https://bugs.pypy.org/issue1242)
diff --git a/pypy/module/_ssl/__init__.py b/pypy/module/_ssl/__init__.py
--- a/pypy/module/_ssl/__init__.py
+++ b/pypy/module/_ssl/__init__.py
@@ -51,6 +51,11 @@
super(Module, cls).buildloaders()
+ def setup_after_space_initialization(self):
+ """NOT_RPYTHON"""
+ from pypy.module._ssl.interp_ssl import PWINFO_STORAGE
+ PWINFO_STORAGE.clear()
+
def startup(self, space):
from rpython.rlib.ropenssl import init_ssl
init_ssl()
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
@@ -1,6 +1,8 @@
from rpython.rlib import rpoll, rsocket, rthread, rweakref
from rpython.rlib.rarithmetic import intmask, widen, r_uint
from rpython.rlib.ropenssl import *
+from pypy.module._socket import interp_socket
+from rpython.rlib._rsocket_rffi import MAX_FD_SIZE
from rpython.rlib.rposix import get_saved_errno
from rpython.rlib.rweakref import RWeakValueDictionary
from rpython.rlib.objectmodel import specialize, compute_unique_id
@@ -12,7 +14,6 @@
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.module._ssl.ssl_data import (
LIBRARY_CODES_TO_NAMES, ERROR_CODES_TO_NAMES)
-from pypy.module._socket import interp_socket
# user defined constants
@@ -79,7 +80,8 @@
constants["OP_CIPHER_SERVER_PREFERENCE"] = SSL_OP_CIPHER_SERVER_PREFERENCE
constants["OP_SINGLE_DH_USE"] = SSL_OP_SINGLE_DH_USE
constants["OP_SINGLE_ECDH_USE"] = SSL_OP_SINGLE_ECDH_USE
-constants["OP_NO_COMPRESSION"] = SSL_OP_NO_COMPRESSION
+if SSL_OP_NO_COMPRESSION is not None:
+ constants["OP_NO_COMPRESSION"] = SSL_OP_NO_COMPRESSION
constants["OPENSSL_VERSION_NUMBER"] = OPENSSL_VERSION_NUMBER
ver = OPENSSL_VERSION_NUMBER
@@ -886,9 +888,13 @@
libssl_AUTHORITY_INFO_ACCESS_free(info)
def _get_crl_dp(space, certificate):
- # Calls x509v3_cache_extensions and sets up crldp
- libssl_X509_check_ca(certificate)
- dps = certificate[0].c_crldp
+ if OPENSSL_VERSION_NUMBER >= 0x10001000:
+ # Calls x509v3_cache_extensions and sets up crldp
+ libssl_X509_check_ca(certificate)
+ dps = certificate[0].c_crldp
+ else:
+ dps = rffi.cast(stack_st_DIST_POINT, libssl_X509_get_ext_d2i(
+ certificate, NID_crl_distribution_points, None, None))
if not dps:
return None
diff --git a/pypy/module/_ssl/ssl_data.py b/pypy/module/_ssl/ssl_data.py
--- a/pypy/module/_ssl/ssl_data.py
+++ b/pypy/module/_ssl/ssl_data.py
@@ -369,7 +369,8 @@
LIBRARY_CODES_TO_NAMES[cconfig[code]] = code
ERROR_CODES_TO_NAMES = {}
for lib, code in error_codes:
- ERROR_CODES_TO_NAMES[cconfig[lib], cconfig[code]] = code
+ if cconfig[code] is not None:
+ ERROR_CODES_TO_NAMES[cconfig[lib], cconfig[code]] = code
ALERT_DESCRIPTION_CODES = {}
for name in AD_NAMES:
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -236,6 +236,9 @@
def test_npn_protocol(self):
import socket, _ssl, gc
+ if not _ssl.HAS_NPN:
+ skip("NPN requires OpenSSL 1.0.1 or greater")
+
ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
ctx._set_npn_protocols(b'\x08http/1.1\x06spdy/2')
ss = ctx._wrap_socket(self.s._sock, True,
@@ -307,12 +310,13 @@
os.path.dirname(__file__), 'dh512.pem'))
def test_load_cert_chain(self):
- import _ssl
+ import _ssl, errno
ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
ctx.load_cert_chain(self.keycert)
ctx.load_cert_chain(self.cert, self.key)
- raises(IOError, ctx.load_cert_chain, "inexistent.pem")
- raises(_ssl.SSLError, ctx.load_cert_chain, self.badcert)
+ exc = raises(IOError, ctx.load_cert_chain, "inexistent.pem")
+ assert exc.value.errno == errno.ENOENT
+ exc = raises(_ssl.SSLError, ctx.load_cert_chain, self.badcert)
raises(_ssl.SSLError, ctx.load_cert_chain, self.emptycert)
# Password protected key and cert
raises(_ssl.SSLError, ctx.load_cert_chain, self.cert_protected,
@@ -360,12 +364,14 @@
assert ctx.cert_store_stats() == {'x509_ca': 0, 'crl': 0, 'x509': 1}
def test_load_dh_params(self):
- import _ssl
+ import _ssl, errno
ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
ctx.load_dh_params(self.dh512)
raises(TypeError, ctx.load_dh_params)
raises(TypeError, ctx.load_dh_params, None)
raises(_ssl.SSLError, ctx.load_dh_params, self.keycert)
+ exc = raises(IOError, ctx.load_dh_params, "inexistent.pem")
+ assert exc.value.errno == errno.ENOENT
def test_set_ecdh_curve(self):
import _ssl
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,10 @@
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)
+ if self.buffer:
+ 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/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
#define PY_VERSION "2.7.9"
/* PyPy version as a string */
-#define PYPY_VERSION "2.6.0"
+#define PYPY_VERSION "2.6.0-alpha0"
/* Subversion Revision number of this file (not of the repository).
* Empty since Mercurial migration. */
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([
@@ -1456,6 +1462,7 @@
imag = GetSetProperty(W_NDimArray.descr_get_imag,
W_NDimArray.descr_set_imag),
conj = interp2app(W_NDimArray.descr_conj),
+ conjugate = interp2app(W_NDimArray.descr_conj),
argsort = interp2app(W_NDimArray.descr_argsort),
sort = interp2app(W_NDimArray.descr_sort),
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()
More information about the pypy-commit
mailing list