Author: Anton Gulenko <anton.gule...@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() + +@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() _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit