[pypy-commit] pypy py3.5: hg merge default

rlamy pypy.commits at gmail.com
Mon Nov 13 16:07:52 EST 2017


Author: Ronan Lamy <ronan.lamy at 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
 
- at given(st.binary(), st.binary(), st.binary())
+st_bytestring = st.binary() | st.binary().map(bytearray)
+
+ at 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)
 
- at given(st.binary(), st.binary(), st.binary())
+ at 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)
 
- at given(st.binary(), st.binary(), st.binary())
+ at 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)
 
- at given(st.binary(), st.binary(), st.binary())
+ at 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
 
- at given(st.binary(), st.binary())
+ at 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)
- at given(st.binary(), st.binary(), st.integers())
+ at 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)
- at given(st.binary(), st.binary(), st.integers(), st.integers())
+ at 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
 
- at given(st.binary(), st.binary())
+ at 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)
- at given(st.binary(), st.binary(), st.integers())
+ at 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)
- at given(st.binary(), st.binary(), st.integers(), st.integers())
+ at 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
 
+ at 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)


More information about the pypy-commit mailing list