Author: Ronan Lamy <ronan.l...@gmail.com> Branch: py3.5 Changeset: r93006:19326fb34a67 Date: 2017-11-13 21:07 +0000 http://bitbucket.org/pypy/pypy/changeset/19326fb34a67/
Log: hg merge default diff --git a/extra_tests/test_bytes.py b/extra_tests/test_bytes.py --- a/extra_tests/test_bytes.py +++ b/extra_tests/test_bytes.py @@ -1,25 +1,27 @@ from hypothesis import strategies as st from hypothesis import given, example -@given(st.binary(), st.binary(), st.binary()) +st_bytestring = st.binary() | st.binary().map(bytearray) + +@given(st_bytestring, st_bytestring, st_bytestring) def test_find(u, prefix, suffix): s = prefix + u + suffix assert 0 <= s.find(u) <= len(prefix) assert s.find(u, len(prefix), len(s) - len(suffix)) == len(prefix) -@given(st.binary(), st.binary(), st.binary()) +@given(st_bytestring, st_bytestring, st_bytestring) def test_index(u, prefix, suffix): s = prefix + u + suffix assert 0 <= s.index(u) <= len(prefix) assert s.index(u, len(prefix), len(s) - len(suffix)) == len(prefix) -@given(st.binary(), st.binary(), st.binary()) +@given(st_bytestring, st_bytestring, st_bytestring) def test_rfind(u, prefix, suffix): s = prefix + u + suffix assert s.rfind(u) >= len(prefix) assert s.rfind(u, len(prefix), len(s) - len(suffix)) == len(prefix) -@given(st.binary(), st.binary(), st.binary()) +@given(st_bytestring, st_bytestring, st_bytestring) def test_rindex(u, prefix, suffix): s = prefix + u + suffix assert s.rindex(u) >= len(prefix) @@ -34,20 +36,20 @@ start = max(start + len(u), 0) return start, end -@given(st.binary(), st.binary()) +@given(st_bytestring, st_bytestring) def test_startswith_basic(u, v): assert u.startswith(v) is (u[:len(v)] == v) @example(b'x', b'', 1) @example(b'x', b'', 2) -@given(st.binary(), st.binary(), st.integers()) +@given(st_bytestring, st_bytestring, st.integers()) def test_startswith_start(u, v, start): expected = u[start:].startswith(v) if v else (start <= len(u)) assert u.startswith(v, start) is expected @example(b'x', b'', 1, 0) @example(b'xx', b'', -1, 0) -@given(st.binary(), st.binary(), st.integers(), st.integers()) +@given(st_bytestring, st_bytestring, st.integers(), st.integers()) def test_startswith_3(u, v, start, end): if v: expected = u[start:end].startswith(v) @@ -56,7 +58,7 @@ expected = start0 <= len(u) and start0 <= end0 assert u.startswith(v, start, end) is expected -@given(st.binary(), st.binary()) +@given(st_bytestring, st_bytestring) def test_endswith_basic(u, v): if len(v) > len(u): assert u.endswith(v) is False @@ -65,14 +67,14 @@ @example(b'x', b'', 1) @example(b'x', b'', 2) -@given(st.binary(), st.binary(), st.integers()) +@given(st_bytestring, st_bytestring, st.integers()) def test_endswith_2(u, v, start): expected = u[start:].endswith(v) if v else (start <= len(u)) assert u.endswith(v, start) is expected @example(b'x', b'', 1, 0) @example(b'xx', b'', -1, 0) -@given(st.binary(), st.binary(), st.integers(), st.integers()) +@given(st_bytestring, st_bytestring, st.integers(), st.integers()) def test_endswith_3(u, v, start, end): if v: expected = u[start:end].endswith(v) diff --git a/lib-python/2.7/inspect.py b/lib-python/2.7/inspect.py --- a/lib-python/2.7/inspect.py +++ b/lib-python/2.7/inspect.py @@ -40,6 +40,10 @@ import linecache from operator import attrgetter from collections import namedtuple +try: + from cpyext import is_cpyext_function as _is_cpyext_function +except ImportError: + _is_cpyext_function = lambda obj: False # These constants are from Include/code.h. CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 0x1, 0x2, 0x4, 0x8 @@ -230,7 +234,7 @@ __doc__ documentation string __name__ original name of this function or method __self__ instance to which a method is bound, or None""" - return isinstance(object, types.BuiltinFunctionType) + return isinstance(object, types.BuiltinFunctionType) or _is_cpyext_function(object) def isroutine(object): """Return true if the object is any kind of function or method.""" diff --git a/lib-python/2.7/warnings.py b/lib-python/2.7/warnings.py --- a/lib-python/2.7/warnings.py +++ b/lib-python/2.7/warnings.py @@ -43,11 +43,12 @@ unicodetype = unicode except NameError: unicodetype = () + template = "%s: %s: %s\n" try: message = str(message) except UnicodeEncodeError: - pass - s = "%s: %s: %s\n" % (lineno, category.__name__, message) + template = unicode(template) + s = template % (lineno, category.__name__, message) line = linecache.getline(filename, lineno) if line is None else line if line: line = line.strip() diff --git a/pypy/interpreter/pyparser/future.py b/pypy/interpreter/pyparser/future.py --- a/pypy/interpreter/pyparser/future.py +++ b/pypy/interpreter/pyparser/future.py @@ -87,13 +87,17 @@ # permissive parsing of the given list of tokens; it relies on # the real parsing done afterwards to give errors. it.skip_newlines() - it.skip_name("r") or it.skip_name("u") or it.skip_name("ru") - if it.skip(pygram.tokens.STRING): - it.skip_newlines() - while (it.skip_name("from") and + docstring_possible = True + while True: + it.skip_name("r") or it.skip_name("u") or it.skip_name("ru") + if docstring_possible and it.skip(pygram.tokens.STRING): + it.skip_newlines() + docstring_possible = False + if not (it.skip_name("from") and it.skip_name("__future__") and it.skip_name("import")): + break it.skip(pygram.tokens.LPAR) # optionally # return in 'last_position' any line-column pair that points # somewhere inside the last __future__ import statement diff --git a/pypy/interpreter/pyparser/test/test_future.py b/pypy/interpreter/pyparser/test/test_future.py --- a/pypy/interpreter/pyparser/test/test_future.py +++ b/pypy/interpreter/pyparser/test/test_future.py @@ -193,3 +193,13 @@ 'from __future__ import with_statement;') f = run(s, (2, 23)) assert f == 0 + +def test_future_doc_future(): + # for some reason people do this :-[ + s = ''' +from __future__ import generators +"Docstring" +from __future__ import division + ''' + f = run(s, (4, 24)) + assert f == 0 diff --git a/pypy/module/_warnings/interp_warnings.py b/pypy/module/_warnings/interp_warnings.py --- a/pypy/module/_warnings/interp_warnings.py +++ b/pypy/module/_warnings/interp_warnings.py @@ -292,7 +292,7 @@ if space.isinstance_w(w_message, space.w_Warning): w_text = space.str(w_message) w_category = space.type(w_message) - elif (not space.isinstance_w(w_message, space.w_unicode) or + elif (not space.isinstance_w(w_message, space.w_unicode) and not space.isinstance_w(w_message, space.w_bytes)): w_text = space.str(w_message) w_message = space.call_function(w_category, w_message) diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py --- a/pypy/module/cpyext/__init__.py +++ b/pypy/module/cpyext/__init__.py @@ -4,6 +4,7 @@ class Module(MixedModule): interpleveldefs = { + 'is_cpyext_function': 'interp_cpyext.is_cpyext_function', } appleveldefs = { @@ -41,7 +42,6 @@ import pypy.module.cpyext.pyerrors import pypy.module.cpyext.typeobject import pypy.module.cpyext.object -import pypy.module.cpyext.buffer import pypy.module.cpyext.bytesobject import pypy.module.cpyext.bytearrayobject import pypy.module.cpyext.tupleobject @@ -50,6 +50,7 @@ import pypy.module.cpyext.longobject import pypy.module.cpyext.listobject import pypy.module.cpyext.sequence +import pypy.module.cpyext.buffer import pypy.module.cpyext.eval import pypy.module.cpyext.import_ import pypy.module.cpyext.mapping diff --git a/pypy/module/cpyext/interp_cpyext.py b/pypy/module/cpyext/interp_cpyext.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/interp_cpyext.py @@ -0,0 +1,4 @@ +from .methodobject import W_PyCFunctionObject + +def is_cpyext_function(space, w_arg): + return space.newbool(isinstance(w_arg, W_PyCFunctionObject)) diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -375,6 +375,11 @@ def test_export_function(self): import sys + if '__pypy__' in sys.modules: + from cpyext import is_cpyext_function + else: + import inspect + is_cpyext_function = inspect.isbuiltin body = """ PyObject* foo_pi(PyObject* self, PyObject *args) { @@ -396,6 +401,7 @@ assert 'foo' in sys.modules assert 'return_pi' in dir(module) assert module.return_pi is not None + assert is_cpyext_function(module.return_pi) assert module.return_pi() == 3.14 assert module.return_pi.__module__ == 'foo' diff --git a/pypy/module/cpyext/test/test_methodobject.py b/pypy/module/cpyext/test/test_methodobject.py --- a/pypy/module/cpyext/test/test_methodobject.py +++ b/pypy/module/cpyext/test/test_methodobject.py @@ -77,6 +77,23 @@ assert mod.isSameFunction(mod.getarg_O) raises(SystemError, mod.isSameFunction, 1) + def test_function_as_method(self): + # Unlike user functions, builtins don't become methods + mod = self.import_extension('foo', [ + ('f', 'METH_NOARGS', + ''' + return PyLong_FromLong(42); + '''), + ]) + class A(object): pass + A.f = mod.f + A.g = lambda: 42 + # Unbound method + assert A.f() == A.g() == 42 + # Bound method + assert A().f() == 42 + raises(TypeError, A().g) + def test_check(self): mod = self.import_extension('foo', [ ('check', 'METH_O', diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py --- a/pypy/objspace/std/bytearrayobject.py +++ b/pypy/objspace/std/bytearrayobject.py @@ -362,6 +362,7 @@ @specialize.argtype(1) def _inplace_add(self, other): + resizelist_hint(self._data, len(self._data) + len(other)) for i in range(len(other)): self._data.append(other[i]) diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ cffi>=1.4.0 +vmprof>=0.4.10 # required to parse log files in rvmprof tests # hypothesis is used for test generation on untranslated tests hypothesis diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py --- a/rpython/annotator/annrpython.py +++ b/rpython/annotator/annrpython.py @@ -15,10 +15,34 @@ typeof, s_ImpossibleValue, SomeInstance, intersection, difference) from rpython.annotator.bookkeeper import Bookkeeper from rpython.rtyper.normalizecalls import perform_normalizations +from collections import deque log = AnsiLogger("annrpython") +class ShuffleDict(object): + def __init__(self): + self._d = {} + self.keys = deque() + + def __setitem__(self, k, v): + if k in self._d: + self._d[k] = v + else: + self._d[k] = v + self.keys.append(k) + + def __getitem__(self, k): + return self._d[k] + + def popitem(self): + key = self.keys.popleft() + item = self._d.pop(key) + return (key, item) + + def __nonzero__(self): + return bool(self._d) + class RPythonAnnotator(object): """Block annotator for RPython. See description in doc/translation.txt.""" @@ -33,7 +57,7 @@ translator = TranslationContext() translator.annotator = self self.translator = translator - self.pendingblocks = {} # map {block: graph-containing-it} + self.pendingblocks = ShuffleDict() # map {block: graph-containing-it} self.annotated = {} # set of blocks already seen self.added_blocks = None # see processblock() below self.links_followed = {} # set of links that have ever been followed diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -39,9 +39,7 @@ CACHE_DIR = os.path.realpath(os.path.join(MAINDIR, '_cache')) PLATFORMS = [ - 'maemo', 'host', - 'distutils', 'arm', ] diff --git a/rpython/rlib/rvmprof/src/shared/machine.c b/rpython/rlib/rvmprof/src/shared/machine.c --- a/rpython/rlib/rvmprof/src/shared/machine.c +++ b/rpython/rlib/rvmprof/src/shared/machine.c @@ -28,7 +28,7 @@ #elif __linux__ return "linux"; #elif __FreeBSD__ - return "freebsd" + return "freebsd"; #else #error "Unknown compiler" #endif diff --git a/rpython/rlib/rvmprof/src/shared/vmp_stack.c b/rpython/rlib/rvmprof/src/shared/vmp_stack.c --- a/rpython/rlib/rvmprof/src/shared/vmp_stack.c +++ b/rpython/rlib/rvmprof/src/shared/vmp_stack.c @@ -29,6 +29,7 @@ static int (*unw_is_signal_frame)(unw_cursor_t *) = NULL; static int (*unw_getcontext)(unw_context_t *) = NULL; #else +#define UNW_LOCAL_ONLY #include <libunwind.h> #endif diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_common.c b/rpython/rlib/rvmprof/src/shared/vmprof_common.c --- a/rpython/rlib/rvmprof/src/shared/vmprof_common.c +++ b/rpython/rlib/rvmprof/src/shared/vmprof_common.c @@ -32,12 +32,21 @@ static size_t threads_size = 0; static size_t thread_count = 0; static size_t threads_size_step = 8; -#endif int vmprof_get_itimer_type(void) { return itimer_type; } +int vmprof_get_signal_type(void) { + return signal_type; +} +#endif + +#ifdef VMPROF_WINDOWS +#include "vmprof_win.h" +#endif + + int vmprof_is_enabled(void) { return is_enabled; } @@ -62,10 +71,6 @@ profile_interval_usec = value; } -int vmprof_get_signal_type(void) { - return signal_type; -} - char *vmprof_init(int fd, double interval, int memory, int proflines, const char *interp_name, int native, int real_time) { diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_common.h b/rpython/rlib/rvmprof/src/shared/vmprof_common.h --- a/rpython/rlib/rvmprof/src/shared/vmprof_common.h +++ b/rpython/rlib/rvmprof/src/shared/vmprof_common.h @@ -15,7 +15,9 @@ #include <pthread.h> #endif +#ifdef VMPROF_UNIX #include "vmprof_getpc.h" +#endif #ifdef VMPROF_LINUX #include <syscall.h> diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_memory.c b/rpython/rlib/rvmprof/src/shared/vmprof_memory.c --- a/rpython/rlib/rvmprof/src/shared/vmprof_memory.c +++ b/rpython/rlib/rvmprof/src/shared/vmprof_memory.c @@ -8,7 +8,7 @@ #include <mach/task_info.h> static mach_port_t mach_task; -#else +#elif defined(VMPROF_UNIX) #include <stdio.h> #include <stdlib.h> #include <sys/types.h> diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_unix.c b/rpython/rlib/rvmprof/src/shared/vmprof_unix.c --- a/rpython/rlib/rvmprof/src/shared/vmprof_unix.c +++ b/rpython/rlib/rvmprof/src/shared/vmprof_unix.c @@ -41,8 +41,6 @@ void vmprof_ignore_signals(int ignored) { if (ignored) { - /* set the last bit, and wait until concurrently-running signal - handlers finish */ __sync_add_and_fetch(&signal_handler_ignore, 1L); while (signal_handler_entries != 0L) { usleep(1); @@ -370,7 +368,7 @@ goto error; if (install_sigprof_timer() == -1) goto error; - vmprof_ignore_signals(0); + signal_handler_ignore = 0; return 0; error: @@ -394,7 +392,7 @@ int vmprof_disable(void) { - vmprof_ignore_signals(1); + signal_handler_ignore = 1; vmprof_set_profile_interval_usec(0); #ifdef VMP_SUPPORTS_NATIVE_PROFILING disable_cpyprof(); diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_win.c b/rpython/rlib/rvmprof/src/shared/vmprof_win.c --- a/rpython/rlib/rvmprof/src/shared/vmprof_win.c +++ b/rpython/rlib/rvmprof/src/shared/vmprof_win.c @@ -1,7 +1,7 @@ -// cannot include this header because it also has definitions -#include "windows.h" -#include "compat.h" -#include "vmp_stack.h" +#include "vmprof_win.h" + +volatile int thread_started = 0; +volatile int enabled = 0; HANDLE write_mutex; @@ -12,7 +12,20 @@ return 0; } -#include <tlhelp32.h> +int vmprof_register_virtual_function(char *code_name, intptr_t code_uid, + int auto_retry) +{ + char buf[2048]; + long namelen; + + namelen = (long)strnlen(code_name, 1023); + buf[0] = MARKER_VIRTUAL_IP; + *(intptr_t*)(buf + 1) = code_uid; + *(long*)(buf + 1 + sizeof(intptr_t)) = namelen; + memcpy(buf + 1 + sizeof(intptr_t) + sizeof(long), code_name, namelen); + vmp_write_all(buf, 1 + sizeof(intptr_t) + sizeof(long) + namelen); + return 0; +} int vmp_write_all(const char *buf, size_t bufsize) { @@ -40,3 +53,168 @@ return 0; } +HANDLE write_mutex; + +#include "vmprof_common.h" + +int vmprof_snapshot_thread(DWORD thread_id, PY_WIN_THREAD_STATE *tstate, prof_stacktrace_s *stack) +{ + HRESULT result; + HANDLE hThread; + int depth; + CONTEXT ctx; +#ifdef RPYTHON_LL2CTYPES + return 0; // not much we can do +#else +#if !defined(RPY_TLOFS_thread_ident) && defined(RPYTHON_VMPROF) + return 0; // we can't freeze threads, unsafe +#else + hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id); + if (!hThread) { + return -1; + } + result = SuspendThread(hThread); + if(result == 0xffffffff) + return -1; // possible, e.g. attached debugger or thread alread suspended + // find the correct thread +#ifdef RPYTHON_VMPROF + ctx.ContextFlags = CONTEXT_FULL; + if (!GetThreadContext(hThread, &ctx)) + return -1; + depth = get_stack_trace(tstate->vmprof_tl_stack, + stack->stack, MAX_STACK_DEPTH-2, ctx.Eip); + stack->depth = depth; + stack->stack[depth++] = thread_id; + stack->count = 1; + stack->marker = MARKER_STACKTRACE; + ResumeThread(hThread); + return depth; +#else + depth = vmp_walk_and_record_stack(tstate->frame, stack->stack, + MAX_STACK_DEPTH, 0, 0); + stack->depth = depth; + stack->stack[depth++] = (void*)((ULONG_PTR)thread_id); + stack->count = 1; + stack->marker = MARKER_STACKTRACE; + ResumeThread(hThread); + return depth; +#endif + +#endif +#endif +} + +#ifndef RPYTHON_VMPROF +static +PY_WIN_THREAD_STATE * get_current_thread_state(void) +{ +#if PY_MAJOR_VERSION < 3 + return _PyThreadState_Current; +#elif PY_VERSION_HEX < 0x03050200 + return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current); +#else + return _PyThreadState_UncheckedGet(); +#endif +} +#endif + +long __stdcall vmprof_mainloop(void *arg) +{ +#ifdef RPYTHON_LL2CTYPES + // for tests only + return 0; +#else + // it is not a test case! + PY_WIN_THREAD_STATE *tstate; + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + prof_stacktrace_s *stack = (prof_stacktrace_s*)malloc(SINGLE_BUF_SIZE); + int depth; +#ifndef RPYTHON_VMPROF + // cpython version + while (1) { + Sleep(vmprof_get_profile_interval_usec() * 1000); + if (!enabled) { + continue; + } + tstate = get_current_thread_state(); + if (!tstate) + continue; + depth = vmprof_snapshot_thread(tstate->thread_id, tstate, stack); + if (depth > 0) { + vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker), + SIZEOF_PROF_STACKTRACE + depth * sizeof(void*)); + } + } +#else + // pypy version + while (1) { + //Sleep(vmprof_get_profile_interval_usec() * 1000); + Sleep(10); + if (!enabled) { + continue; + } + _RPython_ThreadLocals_Acquire(); + tstate = _RPython_ThreadLocals_Head(); // the first one is one behind head + tstate = _RPython_ThreadLocals_Enum(tstate); + while (tstate) { + if (tstate->ready == 42) { + depth = vmprof_snapshot_thread(tstate->thread_ident, tstate, stack); + if (depth > 0) { + vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker), + depth * sizeof(void *) + + sizeof(struct prof_stacktrace_s) - + offsetof(struct prof_stacktrace_s, marker)); + } + } + tstate = _RPython_ThreadLocals_Enum(tstate); + } + _RPython_ThreadLocals_Release(); + } +#endif +#endif +} + +RPY_EXTERN +int vmprof_enable(int memory, int native, int real_time) +{ + if (!thread_started) { + if (!CreateThread(NULL, 0, vmprof_mainloop, NULL, 0, NULL)) { + return -1; + } + thread_started = 1; + } + enabled = 1; + return 0; +} + +RPY_EXTERN +int vmprof_disable(void) +{ + char marker = MARKER_TRAILER; + (void)vmp_write_time_now(MARKER_TRAILER); + + enabled = 0; + vmp_set_profile_fileno(-1); + return 0; +} + +RPY_EXTERN +void vmprof_ignore_signals(int ignored) +{ + enabled = !ignored; +} + +int vmp_native_enable(void) +{ + return 0; +} + +void vmp_native_disable(void) +{ +} + +int get_stack_trace(PY_WIN_THREAD_STATE * current, void** result, + int max_depth, intptr_t pc) +{ + return 0; +} diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_win.h b/rpython/rlib/rvmprof/src/shared/vmprof_win.h --- a/rpython/rlib/rvmprof/src/shared/vmprof_win.h +++ b/rpython/rlib/rvmprof/src/shared/vmprof_win.h @@ -3,20 +3,13 @@ #include "windows.h" #include "compat.h" #include "vmp_stack.h" - -HANDLE write_mutex; +#include <tlhelp32.h> int prepare_concurrent_bufs(void); -#include "vmprof_common.h" -#include <tlhelp32.h> - // This file has been inspired (but not copied from since the LICENSE // would not allow it) from verysleepy profiler -volatile int thread_started = 0; -volatile int enabled = 0; - int vmp_write_all(const char *buf, size_t bufsize); #ifdef RPYTHON_VMPROF @@ -26,178 +19,14 @@ #endif -RPY_EXTERN int vmprof_register_virtual_function(char *code_name, intptr_t code_uid, - int auto_retry) -{ - char buf[2048]; - long namelen; + int auto_retry); - namelen = (long)strnlen(code_name, 1023); - buf[0] = MARKER_VIRTUAL_IP; - *(intptr_t*)(buf + 1) = code_uid; - *(long*)(buf + 1 + sizeof(intptr_t)) = namelen; - memcpy(buf + 1 + sizeof(intptr_t) + sizeof(long), code_name, namelen); - vmp_write_all(buf, 1 + sizeof(intptr_t) + sizeof(long) + namelen); - return 0; -} - -int vmprof_snapshot_thread(DWORD thread_id, PY_WIN_THREAD_STATE *tstate, prof_stacktrace_s *stack) -{ - HRESULT result; - HANDLE hThread; - int depth; - CONTEXT ctx; -#ifdef RPYTHON_LL2CTYPES - return 0; // not much we can do -#else -#if !defined(RPY_TLOFS_thread_ident) && defined(RPYTHON_VMPROF) - return 0; // we can't freeze threads, unsafe -#else - hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id); - if (!hThread) { - return -1; - } - result = SuspendThread(hThread); - if(result == 0xffffffff) - return -1; // possible, e.g. attached debugger or thread alread suspended - // find the correct thread -#ifdef RPYTHON_VMPROF - ctx.ContextFlags = CONTEXT_FULL; - if (!GetThreadContext(hThread, &ctx)) - return -1; - depth = get_stack_trace(tstate->vmprof_tl_stack, - stack->stack, MAX_STACK_DEPTH-2, ctx.Eip); - stack->depth = depth; - stack->stack[depth++] = thread_id; - stack->count = 1; - stack->marker = MARKER_STACKTRACE; - ResumeThread(hThread); - return depth; -#else - depth = vmp_walk_and_record_stack(tstate->frame, stack->stack, - MAX_STACK_DEPTH, 0, 0); - stack->depth = depth; - stack->stack[depth++] = (void*)((ULONG_PTR)thread_id); - stack->count = 1; - stack->marker = MARKER_STACKTRACE; - ResumeThread(hThread); - return depth; -#endif - -#endif -#endif -} - -#ifndef RPYTHON_VMPROF -static -PY_WIN_THREAD_STATE * get_current_thread_state(void) -{ -#if PY_MAJOR_VERSION < 3 - return _PyThreadState_Current; -#elif PY_VERSION_HEX < 0x03050200 - return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current); -#else - return _PyThreadState_UncheckedGet(); -#endif -} -#endif - -long __stdcall vmprof_mainloop(void *arg) -{ -#ifdef RPYTHON_LL2CTYPES - // for tests only - return 0; -#else - // it is not a test case! - PY_WIN_THREAD_STATE *tstate; - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - prof_stacktrace_s *stack = (prof_stacktrace_s*)malloc(SINGLE_BUF_SIZE); - int depth; -#ifndef RPYTHON_VMPROF - // cpython version - while (1) { - Sleep(profile_interval_usec * 1000); - if (!enabled) { - continue; - } - tstate = get_current_thread_state(); - if (!tstate) - continue; - depth = vmprof_snapshot_thread(tstate->thread_id, tstate, stack); - if (depth > 0) { - vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker), - SIZEOF_PROF_STACKTRACE + depth * sizeof(void*)); - } - } -#else - // pypy version - while (1) { - //Sleep(profile_interval_usec * 1000); - Sleep(10); - if (!enabled) { - continue; - } - _RPython_ThreadLocals_Acquire(); - tstate = _RPython_ThreadLocals_Head(); // the first one is one behind head - tstate = _RPython_ThreadLocals_Enum(tstate); - while (tstate) { - if (tstate->ready == 42) { - depth = vmprof_snapshot_thread(tstate->thread_ident, tstate, stack); - if (depth > 0) { - vmp_write_all((char*)stack + offsetof(prof_stacktrace_s, marker), - depth * sizeof(void *) + - sizeof(struct prof_stacktrace_s) - - offsetof(struct prof_stacktrace_s, marker)); - } - } - tstate = _RPython_ThreadLocals_Enum(tstate); - } - _RPython_ThreadLocals_Release(); - } -#endif -#endif -} - -RPY_EXTERN -int vmprof_enable(int memory, int native, int real_time) -{ - if (!thread_started) { - if (!CreateThread(NULL, 0, vmprof_mainloop, NULL, 0, NULL)) { - return -1; - } - thread_started = 1; - } - enabled = 1; - return 0; -} - -RPY_EXTERN -int vmprof_disable(void) -{ - char marker = MARKER_TRAILER; - (void)vmp_write_time_now(MARKER_TRAILER); - - enabled = 0; - vmp_set_profile_fileno(-1); - return 0; -} - -RPY_EXTERN -void vmprof_ignore_signals(int ignored) -{ - enabled = !ignored; -} - -int vmp_native_enable(void) { - return 0; -} - -void vmp_native_disable(void) { -} - +PY_WIN_THREAD_STATE * get_current_thread_state(void); +int vmprof_enable(int memory, int native, int real_time); +int vmprof_disable(void); +void vmprof_ignore_signals(int ignored); +int vmp_native_enable(void); +void vmp_native_disable(void); int get_stack_trace(PY_WIN_THREAD_STATE * current, void** result, - int max_depth, intptr_t pc) -{ - return 0; -} + int max_depth, intptr_t pc); diff --git a/rpython/rlib/rvmprof/test/test_file.py b/rpython/rlib/rvmprof/test/test_file.py --- a/rpython/rlib/rvmprof/test/test_file.py +++ b/rpython/rlib/rvmprof/test/test_file.py @@ -2,25 +2,43 @@ import urllib2, py from os.path import join +RVMPROF = py.path.local(__file__).join('..', '..') def github_raw_file(repo, path, branch='master'): - return "https://raw.githubusercontent.com/{repo}/{branch}/{path}".format(**dict( - repo=repo, path=path, branch=branch - )) + url = "https://raw.githubusercontent.com/{repo}/{branch}/{path}" + return url.format(repo=repo, path=path, branch=branch) +def get_list_of_files(shared): + files = list(shared.visit('*.[ch]')) + # in PyPy we checkin the result of ./configure; as such, these files are + # not in github and can be skipped + files.remove(shared.join('libbacktrace', 'config-x86_32.h')) + files.remove(shared.join('libbacktrace', 'config-x86_64.h')) + files.remove(shared.join('libbacktrace', 'gstdint.h')) + return files def test_same_file(): - for root, dirs, files in os.walk('rpython/rlib/rvmprof/src/shared'): - for file in files: - if not (file.endswith(".c") or file.endswith(".h")): - continue - url = github_raw_file("vmprof/vmprof-python", "src/%s" % file) - source = urllib2.urlopen(url).read() - # - dest = py.path.local(join(root, file)).read() - if source != dest: - raise AssertionError("%s was updated, but changes were" - "not copied over to PyPy" % url) - else: - print("%s matches" % url) - break # do not walk dirs + shared = RVMPROF.join('src', 'shared') + files = get_list_of_files(shared) + assert files, 'cannot find any C file, probably the directory is wrong?' + no_matches = [] + print + for file in files: + path = file.relto(shared) + url = github_raw_file("vmprof/vmprof-python", "src/%s" % path) + source = urllib2.urlopen(url).read() + dest = file.read() + shortname = file.relto(RVMPROF) + if source == dest: + print '%s matches' % shortname + else: + print '%s does NOT match' % shortname + no_matches.append(file) + # + if no_matches: + print + print 'The following file dit NOT match' + for f in no_matches: + print ' ', f.relto(RVMPROF) + raise AssertionError("some files were updated on github, " + "but were not copied here") diff --git a/rpython/rlib/rvmprof/test/test_rvmprof.py b/rpython/rlib/rvmprof/test/test_rvmprof.py --- a/rpython/rlib/rvmprof/test/test_rvmprof.py +++ b/rpython/rlib/rvmprof/test/test_rvmprof.py @@ -1,214 +1,183 @@ import py, os +import pytest +import time from rpython.tool.udir import udir from rpython.rlib import rvmprof from rpython.translator.c.test.test_genc import compile -from rpython.rlib.objectmodel import we_are_translated -from rpython.rlib.nonconst import NonConstant from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.lltypesystem import rffi, lltype +@pytest.mark.usefixtures('init') +class RVMProfTest(object): -def test_vmprof_execute_code_1(): + ENTRY_POINT_ARGS = () - class MyCode: - pass - try: - rvmprof.register_code_object_class(MyCode, lambda code: 'some code') - except rvmprof.VMProfPlatformUnsupported: - pass + class MyCode(object): + def __init__(self, name='py:code:0:noname'): + self.name = name - @rvmprof.vmprof_execute_code("xcode1", lambda code, num: code) - def main(code, num): + def get_name(self): + return self.name + + @pytest.fixture + def init(self): + self.register() + self.rpy_entry_point = compile(self.entry_point, self.ENTRY_POINT_ARGS) + + def register(self): + rvmprof.register_code_object_class(self.MyCode, + self.MyCode.get_name) + + +class TestExecuteCode(RVMProfTest): + + def entry_point(self): + res = self.main(self.MyCode(), 5) + assert res == 42 + return 0 + + @rvmprof.vmprof_execute_code("xcode1", lambda self, code, num: code) + def main(self, code, num): print num return 42 - def f(): - res = main(MyCode(), 5) + def test(self): + assert self.entry_point() == 0 + assert self.rpy_entry_point() == 0 + + +class TestResultClass(RVMProfTest): + + class A: pass + + @rvmprof.vmprof_execute_code("xcode2", lambda self, num, code: code, + result_class=A) + def main(self, num, code): + print num + return self.A() + + def entry_point(self): + a = self.main(7, self.MyCode()) + assert isinstance(a, self.A) + return 0 + + def test(self): + assert self.entry_point() == 0 + assert self.rpy_entry_point() == 0 + + +class TestRegisterCode(RVMProfTest): + + @rvmprof.vmprof_execute_code("xcode1", lambda self, code, num: code) + def main(self, code, num): + print num + return 42 + + def entry_point(self): + code = self.MyCode() + rvmprof.register_code(code, lambda code: 'some code') + res = self.main(code, 5) assert res == 42 return 0 - assert f() == 0 - fn = compile(f, []) - assert fn() == 0 + def test(self): + assert self.entry_point() == 0 + assert self.rpy_entry_point() == 0 -def test_vmprof_execute_code_2(): +class RVMProfSamplingTest(RVMProfTest): - class MyCode: - pass - try: - rvmprof.register_code_object_class(MyCode, lambda code: 'some code') - except rvmprof.VMProfPlatformUnsupported: - pass + # the kernel will deliver SIGPROF at max 250 Hz. See also + # https://github.com/vmprof/vmprof-python/issues/163 + SAMPLING_INTERVAL = 1/250.0 - class A: - pass + @pytest.fixture + def init(self, tmpdir): + self.tmpdir = tmpdir + self.tmpfile = tmpdir.join('profile.vmprof') + self.tmpfilename = str(self.tmpfile) + super(RVMProfSamplingTest, self).init() - @rvmprof.vmprof_execute_code("xcode2", lambda num, code: code, - result_class=A) - def main(num, code): - print num - return A() + ENTRY_POINT_ARGS = (int, float) + def entry_point(self, value, delta_t): + code = self.MyCode('py:code:52:test_enable') + rvmprof.register_code(code, self.MyCode.get_name) + fd = os.open(self.tmpfilename, os.O_WRONLY | os.O_CREAT, 0666) + rvmprof.enable(fd, self.SAMPLING_INTERVAL) + start = time.time() + res = 0 + while time.time() < start+delta_t: + res = self.main(code, value) + rvmprof.disable() + os.close(fd) + return res - def f(): - a = main(7, MyCode()) - assert isinstance(a, A) - return 0 + def approx_equal(self, a, b, tolerance=0.1): + max_diff = (a+b)/2.0 * tolerance + return abs(a-b) < max_diff - assert f() == 0 - fn = compile(f, []) - assert fn() == 0 +class TestEnable(RVMProfSamplingTest): -def test_register_code(): - - class MyCode: - pass - try: - rvmprof.register_code_object_class(MyCode, lambda code: 'some code') - except rvmprof.VMProfPlatformUnsupported as e: - py.test.skip(str(e)) - - @rvmprof.vmprof_execute_code("xcode1", lambda code, num: code) - def main(code, num): - print num - return 42 - - def f(): - code = MyCode() - rvmprof.register_code(code, lambda code: 'some code') - res = main(code, 5) - assert res == 42 - return 0 - - assert f() == 0 - fn = compile(f, [], gcpolicy="minimark") - assert fn() == 0 - - -def test_enable(): - - class MyCode: - pass - def get_name(code): - return 'py:code:52:x' - try: - rvmprof.register_code_object_class(MyCode, get_name) - except rvmprof.VMProfPlatformUnsupported as e: - py.test.skip(str(e)) - - @rvmprof.vmprof_execute_code("xcode1", lambda code, num: code) - def main(code, num): - print num + @rvmprof.vmprof_execute_code("xcode1", lambda self, code, count: code) + def main(self, code, count): s = 0 - for i in range(num): + for i in range(count): s += (i << 1) - if s % 2123423423 == 0: - print s return s - tmpfilename = str(udir.join('test_rvmprof')) + def test(self): + from vmprof import read_profile + assert self.entry_point(10**4, 0.1) == 99990000 + assert self.tmpfile.check() + self.tmpfile.remove() + # + assert self.rpy_entry_point(10**4, 0.5) == 99990000 + assert self.tmpfile.check() + prof = read_profile(self.tmpfilename) + tree = prof.get_tree() + assert tree.name == 'py:code:52:test_enable' + assert self.approx_equal(tree.count, 0.5/self.SAMPLING_INTERVAL) - def f(): - if NonConstant(False): - # Hack to give os.open() the correct annotation - os.open('foo', 1, 1) - code = MyCode() - rvmprof.register_code(code, get_name) - fd = os.open(tmpfilename, os.O_WRONLY | os.O_CREAT, 0666) - if we_are_translated(): - num = 100000000 - period = 0.0001 + +class TestNative(RVMProfSamplingTest): + + @pytest.fixture + def init(self, tmpdir): + eci = ExternalCompilationInfo(compile_extra=['-g','-O0'], + separate_module_sources=[""" + RPY_EXTERN int native_func(int d) { + int j = 0; + if (d > 0) { + return native_func(d-1); + } else { + for (int i = 0; i < 42000; i++) { + j += 1; + } + } + return j; + } + """]) + self.native_func = rffi.llexternal("native_func", [rffi.INT], rffi.INT, + compilation_info=eci) + super(TestNative, self).init(tmpdir) + + @rvmprof.vmprof_execute_code("xcode1", lambda self, code, count: code) + def main(self, code, count): + if count > 0: + return self.main(code, count-1) else: - num = 10000 - period = 0.9 - rvmprof.enable(fd, period) - res = main(code, num) - #assert res == 499999500000 - rvmprof.disable() - os.close(fd) - return 0 + return self.native_func(100) - def check_profile(filename): - from vmprof import read_profile - - prof = read_profile(filename) - assert prof.get_tree().name.startswith("py:") - assert prof.get_tree().count - - assert f() == 0 - assert os.path.exists(tmpfilename) - fn = compile(f, [], gcpolicy="minimark") - assert fn() == 0 - try: - import vmprof - except ImportError: - py.test.skip("vmprof unimportable") - else: - check_profile(tmpfilename) - finally: - assert os.path.exists(tmpfilename) - os.unlink(tmpfilename) - -def test_native(): - eci = ExternalCompilationInfo(compile_extra=['-g','-O0'], - separate_module_sources=[""" - RPY_EXTERN int native_func(int d) { - int j = 0; - if (d > 0) { - return native_func(d-1); - } else { - for (int i = 0; i < 42000; i++) { - j += d; - } - } - return j; - } - """]) - - native_func = rffi.llexternal("native_func", [rffi.INT], rffi.INT, - compilation_info=eci) - - class MyCode: - pass - def get_name(code): - return 'py:code:52:x' - - try: - rvmprof.register_code_object_class(MyCode, get_name) - except rvmprof.VMProfPlatformUnsupported as e: - py.test.skip(str(e)) - - @rvmprof.vmprof_execute_code("xcode1", lambda code, num: code) - def main(code, num): - if num > 0: - return main(code, num-1) - else: - return native_func(100) - - tmpfilename = str(udir.join('test_rvmprof')) - - def f(): - if NonConstant(False): - # Hack to give os.open() the correct annotation - os.open('foo', 1, 1) - code = MyCode() - rvmprof.register_code(code, get_name) - fd = os.open(tmpfilename, os.O_RDWR | os.O_CREAT, 0666) - num = 10000 - period = 0.0001 - rvmprof.enable(fd, period, native=1) - for i in range(num): - res = main(code, 3) - rvmprof.disable() - os.close(fd) - return 0 - - def check_profile(filename): + def test(self): + # XXX: this test is known to fail since rev a4f077ba651c, but buildbot + # never ran it. FIXME. from vmprof import read_profile from vmprof.show import PrettyPrinter - - prof = read_profile(filename) + assert self.rpy_entry_point(3, 0.5) == 42000 + assert self.tmpfile.check() + # + prof = read_profile(self.tmpfilename) tree = prof.get_tree() p = PrettyPrinter() p._print_tree(tree) @@ -227,16 +196,3 @@ del not_found[i] break assert not_found == [] - - fn = compile(f, [], gcpolicy="incminimark", lldebug=True) - assert fn() == 0 - try: - import vmprof - except ImportError: - py.test.skip("vmprof unimportable") - else: - check_profile(tmpfilename) - finally: - assert os.path.exists(tmpfilename) - os.unlink(tmpfilename) - diff --git a/rpython/translator/c/test/test_standalone.py b/rpython/translator/c/test/test_standalone.py --- a/rpython/translator/c/test/test_standalone.py +++ b/rpython/translator/c/test/test_standalone.py @@ -1102,22 +1102,6 @@ assert out.strip() == 'ok' -class TestMaemo(TestStandalone): - def setup_class(cls): - py.test.skip("TestMaemo: tests skipped for now") - from rpython.translator.platform.maemo import check_scratchbox - check_scratchbox() - config = get_combined_translation_config(translating=True) - config.translation.platform = 'maemo' - cls.config = config - - def test_profopt(self): - py.test.skip("Unsupported") - - def test_prof_inline(self): - py.test.skip("Unsupported") - - class TestThread(object): gcrootfinder = 'shadowstack' config = None diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -320,24 +320,16 @@ else: host_factory = Cygwin64 else: - # pray - from rpython.translator.platform.distutils_platform import DistutilsPlatform - host_factory = DistutilsPlatform + raise ValueError('unknown sys.platform "%s"', sys.platform) platform = host = host_factory() def pick_platform(new_platform, cc): if new_platform == 'host': return host_factory(cc) - elif new_platform == 'maemo': - from rpython.translator.platform.maemo import Maemo - return Maemo(cc) elif new_platform == 'arm': from rpython.translator.platform.arm import ARM return ARM(cc) - elif new_platform == 'distutils': - from rpython.translator.platform.distutils_platform import DistutilsPlatform - return DistutilsPlatform() else: raise ValueError("platform = %s" % (new_platform,)) diff --git a/rpython/translator/platform/distutils_platform.py b/rpython/translator/platform/distutils_platform.py deleted file mode 100644 --- a/rpython/translator/platform/distutils_platform.py +++ /dev/null @@ -1,157 +0,0 @@ -import py, os, sys - -from rpython.translator.platform import Platform, log, CompilationError -from rpython.translator.tool import stdoutcapture - -def log_spawned_cmd(spawn): - def spawn_and_log(cmd, *args, **kwds): - log.execute(' '.join(cmd)) - return spawn(cmd, *args, **kwds) - return spawn_and_log - -CFLAGS = ['-O3'] - -if os.name != 'nt': - so_ext = 'so' -else: - so_ext = 'dll' - -class DistutilsPlatform(Platform): - """ This is a generic distutils platform. I hope it'll go away at some - point soon completely - """ - name = "distutils" - so_ext = so_ext - - def __init__(self, cc=None): - self.cc = cc - if self.name == "distutils": - self.name = sys.platform - - def _ensure_correct_math(self): - if self.name != 'win32': - return # so far - from distutils import sysconfig - gcv = sysconfig.get_config_vars() - opt = gcv.get('OPT') # not always existent - if opt and '/Op' not in opt: - opt += '/Op' - gcv['OPT'] = opt - - def compile(self, cfilenames, eci, outputfilename=None, standalone=True): - self._ensure_correct_math() - self.cfilenames = cfilenames - if standalone: - ext = '' - else: - ext = so_ext - self.standalone = standalone - self.libraries = list(eci.libraries) - self.include_dirs = list(eci.include_dirs) - self.library_dirs = list(eci.library_dirs) - self.compile_extra = list(eci.compile_extra) - self.link_extra = list(eci.link_extra) - self.frameworks = list(eci.frameworks) - if not self.name in ('win32', 'darwin', 'cygwin'): # xxx - if 'm' not in self.libraries: - self.libraries.append('m') - self.compile_extra += CFLAGS + ['-fomit-frame-pointer'] - if 'pthread' not in self.libraries: - self.libraries.append('pthread') - if self.name != 'sunos5': - self.compile_extra += ['-pthread'] - self.link_extra += ['-pthread'] - else: - self.compile_extra += ['-pthreads'] - self.link_extra += ['-lpthread'] - if self.name == 'win32': - self.link_extra += ['/DEBUG'] # generate .pdb file - if self.name == 'darwin': - # support Fink & Darwinports - for s in ('/sw/', '/opt/local/'): - if s + 'include' not in self.include_dirs and \ - os.path.exists(s + 'include'): - self.include_dirs.append(s + 'include') - if s + 'lib' not in self.library_dirs and \ - os.path.exists(s + 'lib'): - self.library_dirs.append(s + 'lib') - self.compile_extra += CFLAGS + ['-fomit-frame-pointer'] - for framework in self.frameworks: - self.link_extra += ['-framework', framework] - - if outputfilename is None: - self.outputfilename = py.path.local(cfilenames[0]).new(ext=ext) - else: - self.outputfilename = py.path.local(outputfilename) - self.eci = eci - import distutils.errors - basename = self.outputfilename.new(ext='') - data = '' - try: - saved_environ = os.environ.copy() - c = stdoutcapture.Capture(mixed_out_err=True) - try: - self._build() - finally: - # workaround for a distutils bugs where some env vars can - # become longer and longer every time it is used - for key, value in saved_environ.items(): - if os.environ.get(key) != value: - os.environ[key] = value - foutput, foutput = c.done() - data = foutput.read() - if data: - fdump = basename.new(ext='errors').open("wb") - fdump.write(data) - fdump.close() - except (distutils.errors.CompileError, - distutils.errors.LinkError): - raise CompilationError('', data) - except: - print >>sys.stderr, data - raise - return self.outputfilename - - def _build(self): - from distutils.ccompiler import new_compiler - from distutils import sysconfig - compiler = new_compiler(force=1) - if self.cc is not None: - for c in '''compiler compiler_so compiler_cxx - linker_exe linker_so'''.split(): - compiler.executables[c][0] = self.cc - if not self.standalone: - sysconfig.customize_compiler(compiler) # XXX - compiler.spawn = log_spawned_cmd(compiler.spawn) - objects = [] - for cfile in self.cfilenames: - cfile = py.path.local(cfile) - compile_extra = self.compile_extra[:] - - old = cfile.dirpath().chdir() - try: - res = compiler.compile([cfile.basename], - include_dirs=self.eci.include_dirs, - extra_preargs=compile_extra) - assert len(res) == 1 - cobjfile = py.path.local(res[0]) - assert cobjfile.check() - objects.append(str(cobjfile)) - finally: - old.chdir() - - if self.standalone: - cmd = compiler.link_executable - else: - cmd = compiler.link_shared_object - cmd(objects, str(self.outputfilename), - libraries=self.eci.libraries, - extra_preargs=self.link_extra, - library_dirs=self.eci.library_dirs) - - def _include_dirs_for_libffi(self): - return ['/usr/include/libffi'] - - def _library_dirs_for_libffi(self): - return ['/usr/lib/libffi'] - diff --git a/rpython/translator/platform/maemo.py b/rpython/translator/platform/maemo.py deleted file mode 100644 --- a/rpython/translator/platform/maemo.py +++ /dev/null @@ -1,95 +0,0 @@ -"""Support for Maemo.""" - -import py, os - -from rpython.tool.udir import udir -from rpython.translator.platform import ExecutionResult, log -from rpython.translator.platform.linux import Linux -from rpython.translator.platform.posix import GnuMakefile, _run_subprocess - -def check_scratchbox(): - # in order to work, that file must exist and be executable by us - if not os.access('/scratchbox/login', os.X_OK): - py.test.skip("No scratchbox detected") - -class Maemo(Linux): - name = "maemo" - - available_includedirs = ('/usr/include', '/tmp') - copied_cache = {} - - def _invent_new_name(self, basepath, base): - pth = basepath.join(base) - num = 0 - while pth.check(): - pth = basepath.join('%s_%d' % (base,num)) - num += 1 - return pth.ensure(dir=1) - - def _copy_files_to_new_dir(self, dir_from, pattern='*.[ch]'): - try: - return self.copied_cache[dir_from] - except KeyError: - new_dirpath = self._invent_new_name(udir, 'copied_includes') - files = py.path.local(dir_from).listdir(pattern) - for f in files: - f.copy(new_dirpath) - # XXX <hack for pypy> - srcdir = py.path.local(dir_from).join('src') - if srcdir.check(dir=1): - target = new_dirpath.join('src').ensure(dir=1) - for f in srcdir.listdir(pattern): - f.copy(target) - # XXX </hack for pypy> - self.copied_cache[dir_from] = new_dirpath - return new_dirpath - - def _preprocess_include_dirs(self, include_dirs): - """ Tweak includedirs so they'll be available through scratchbox - """ - res_incl_dirs = [] - for incl_dir in include_dirs: - incl_dir = py.path.local(incl_dir) - for available in self.available_includedirs: - if incl_dir.relto(available): - res_incl_dirs.append(str(incl_dir)) - break - else: - # we need to copy files to a place where it's accessible - res_incl_dirs.append(self._copy_files_to_new_dir(incl_dir)) - return res_incl_dirs - - def _execute_c_compiler(self, cc, args, outname): - log.execute('/scratchbox/login ' + cc + ' ' + ' '.join(args)) - args = [cc] + args - returncode, stdout, stderr = _run_subprocess('/scratchbox/login', args) - self._handle_error(returncode, stdout, stderr, outname) - - def execute(self, executable, args=[], env=None): - if isinstance(args, str): - args = str(executable) + ' ' + args - log.message('executing /scratchbox/login ' + args) - else: - args = [str(executable)] + args - log.message('executing /scratchbox/login ' + ' '.join(args)) - returncode, stdout, stderr = _run_subprocess('/scratchbox/login', args, - env) - return ExecutionResult(returncode, stdout, stderr) - - def _include_dirs_for_libffi(self): - # insanely obscure dir - return ['/usr/include/arm-linux-gnueabi/'] - - def _library_dirs_for_libffi(self): - # on the other hand, library lands in usual place... - return [] - - def execute_makefile(self, path_to_makefile, extra_opts=[]): - if isinstance(path_to_makefile, GnuMakefile): - path = path_to_makefile.makefile_dir - else: - path = path_to_makefile - log.execute('make %s in %s' % (" ".join(extra_opts), path)) - returncode, stdout, stderr = _run_subprocess( - '/scratchbox/login', ['make', '-C', str(path)] + extra_opts) - self._handle_error(returncode, stdout, stderr, path.join('make')) diff --git a/rpython/translator/platform/test/test_distutils.py b/rpython/translator/platform/test/test_distutils.py deleted file mode 100644 --- a/rpython/translator/platform/test/test_distutils.py +++ /dev/null @@ -1,17 +0,0 @@ - -from rpython.translator.platform.test.test_platform import TestPlatform as BasicTest -from rpython.translator.platform.distutils_platform import DistutilsPlatform -import py - -class TestDistutils(BasicTest): - platform = DistutilsPlatform() - - def test_nice_errors(self): - py.test.skip("Unsupported") - - def test_900_files(self): - py.test.skip('Makefiles not suppoerted') - - def test_precompiled_headers(self): - py.test.skip('Makefiles not suppoerted') - diff --git a/rpython/translator/platform/test/test_maemo.py b/rpython/translator/platform/test/test_maemo.py deleted file mode 100644 --- a/rpython/translator/platform/test/test_maemo.py +++ /dev/null @@ -1,37 +0,0 @@ - -""" File containing maemo platform tests -""" - -import py -from rpython.tool.udir import udir -from rpython.translator.platform.maemo import Maemo, check_scratchbox -from rpython.translator.platform.test.test_platform import TestPlatform as BasicTest -from rpython.translator.tool.cbuild import ExternalCompilationInfo - -class TestMaemo(BasicTest): - platform = Maemo() - strict_on_stderr = False - - def setup_class(cls): - py.test.skip("TestMaemo: tests skipped for now") - check_scratchbox() - - def test_includes_outside_scratchbox(self): - cfile = udir.join('test_includes_outside_scratchbox.c') - cfile.write(''' - #include <stdio.h> - #include "test.h" - int main() - { - printf("%d\\n", XXX_STUFF); - return 0; - } - ''') - includedir = py.path.local(__file__).dirpath().join('include') - eci = ExternalCompilationInfo(include_dirs=(includedir,)) - executable = self.platform.compile([cfile], eci) - res = self.platform.execute(executable) - self.check_res(res) - - def test_environment_inheritance(self): - py.test.skip("FIXME") diff --git a/rpython/translator/platform/test/test_platform.py b/rpython/translator/platform/test/test_platform.py --- a/rpython/translator/platform/test/test_platform.py +++ b/rpython/translator/platform/test/test_platform.py @@ -147,10 +147,13 @@ def test_is_host_build(): + from platform import machine from rpython.translator import platform assert platform.host == platform.platform assert platform.is_host_build() - platform.set_platform('maemo', None) - assert platform.host != platform.platform - assert not platform.is_host_build() + # do we support non-host builds? + if machine().startswith('arm'): + platform.set_platform('arm', None) + assert platform.host != platform.platform + assert not platform.is_host_build() diff --git a/rpython/translator/platform/test/test_posix.py b/rpython/translator/platform/test/test_posix.py --- a/rpython/translator/platform/test/test_posix.py +++ b/rpython/translator/platform/test/test_posix.py @@ -64,10 +64,3 @@ assert 'INCLUDEDIRS = %s/foo/baz/include' % include_prefix in Makefile assert 'LIBDIRS = %s/foo/baz/lib' % lib_prefix in Makefile -class TestMaemo(TestMakefile): - strict_on_stderr = False - - def setup_class(cls): - from rpython.translator.platform.maemo import check_scratchbox, Maemo - check_scratchbox() - cls.platform = Maemo() diff --git a/rpython/translator/translator.py b/rpython/translator/translator.py --- a/rpython/translator/translator.py +++ b/rpython/translator/translator.py @@ -141,6 +141,9 @@ if isinstance(func, FunctionGraph): return func result = [] + if hasattr(func, 'im_func'): + # make it possible to translate bound methods + func = func.im_func for graph in translator.graphs: if getattr(graph, 'func', None) is func: result.append(graph) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit