[pypy-commit] pypy list-strategies: merge

cfbolz noreply at buildbot.pypy.org
Fri Sep 23 13:13:11 CEST 2011


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: list-strategies
Changeset: r47497:aac2064d18e3
Date: 2011-04-12 15:07 +0200
http://bitbucket.org/pypy/pypy/changeset/aac2064d18e3/

Log:	merge

diff too long, truncating to 10000 out of 21908 lines

diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,8 @@
 pypy/doc/*.html
 pypy/doc/config/*.html
 pypy/doc/discussion/*.html
+pypy/module/cpyext/src/*.o
+pypy/module/cpyext/test/*.o
 pypy/module/test_lib_pypy/ctypes_tests/*.o
 pypy/translator/c/src/dtoa.o
 pypy/translator/goal/pypy-c
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -17,7 +17,6 @@
 ^pypy/doc/.+\.html$
 ^pypy/doc/basicblock\.asc$
 ^pypy/doc/.+\.svninfo$
-^pypy/translator/c/src/dtoa.o$
 ^pypy/translator/c/src/libffi_msvc/.+\.obj$
 ^pypy/translator/c/src/libffi_msvc/.+\.dll$
 ^pypy/translator/c/src/libffi_msvc/.+\.lib$
@@ -52,6 +51,7 @@
 ^pypy/doc/discussion/.+\.html$
 ^include/.+\.h$
 ^include/.+\.inl$
+^pypy/doc/_build/.*$
 ^pypy/doc/config/.+\.html$
 ^pypy/doc/config/style\.css$
 ^pypy/doc/jit/.+\.html$
@@ -63,4 +63,4 @@
 ^pypy/doc/image/parsing_example.+\.png$
 ^compiled
 ^.git/
-^release/
\ No newline at end of file
+^release/
diff --git a/.hgsub b/.hgsub
deleted file mode 100644
--- a/.hgsub
+++ /dev/null
@@ -1,3 +0,0 @@
-greenlet = [svn]http://codespeak.net/svn/greenlet/trunk/c
-testrunner = [svn]http://codespeak.net/svn/pypy/build/testrunner
-lib_pypy/pyrepl = [svn]http://codespeak.net/svn/pyrepl/trunk/pyrepl/pyrepl
diff --git a/.hgsubstate b/.hgsubstate
deleted file mode 100644
--- a/.hgsubstate
+++ /dev/null
@@ -1,3 +0,0 @@
-80037 greenlet
-80348 lib_pypy/pyrepl
-80409 testrunner
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -108,6 +108,7 @@
     Anders Qvist
     Alan McIntyre
     Bert Freudenberg
+    Tav
 
     Heinrich-Heine University, Germany 
     Open End AB (formerly AB Strakt), Sweden
diff --git a/_pytest/__init__.py b/_pytest/__init__.py
--- a/_pytest/__init__.py
+++ b/_pytest/__init__.py
@@ -1,1 +1,2 @@
 #
+__version__ = '2.0.3.dev3'
diff --git a/_pytest/config.py b/_pytest/config.py
--- a/_pytest/config.py
+++ b/_pytest/config.py
@@ -252,6 +252,16 @@
         self.hook = self.pluginmanager.hook
         self._inicache = {}
 
+    @classmethod
+    def fromdictargs(cls, option_dict, args):
+        """ constructor useable for subprocesses. """
+        config = cls()
+        config._preparse(args, addopts=False)
+        config.option.__dict__.update(option_dict)
+        for x in config.option.plugins:
+            config.pluginmanager.consider_pluginarg(x)
+        return config
+
     def _onimportconftest(self, conftestmodule):
         self.trace("loaded conftestmodule %r" %(conftestmodule,))
         self.pluginmanager.consider_conftest(conftestmodule)
diff --git a/_pytest/core.py b/_pytest/core.py
--- a/_pytest/core.py
+++ b/_pytest/core.py
@@ -164,14 +164,17 @@
     def consider_preparse(self, args):
         for opt1,opt2 in zip(args, args[1:]):
             if opt1 == "-p":
-                if opt2.startswith("no:"):
-                    name = opt2[3:]
-                    if self.getplugin(name) is not None:
-                        self.unregister(None, name=name)
-                    self._name2plugin[name] = -1
-                else:
-                    if self.getplugin(opt2) is None:
-                        self.import_plugin(opt2)
+                self.consider_pluginarg(opt2)
+
+    def consider_pluginarg(self, arg):
+        if arg.startswith("no:"):
+            name = arg[3:]
+            if self.getplugin(name) is not None:
+                self.unregister(None, name=name)
+            self._name2plugin[name] = -1
+        else:
+            if self.getplugin(arg) is None:
+                self.import_plugin(arg)
 
     def consider_conftest(self, conftestmodule):
         if self.register(conftestmodule, name=conftestmodule.__file__):
diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py
--- a/_pytest/junitxml.py
+++ b/_pytest/junitxml.py
@@ -106,7 +106,13 @@
                 '<skipped message="expected test failure">%s</skipped>',
                 report.keywords['xfail'])
         else:
-            self.appendlog("<skipped/>")
+            filename, lineno, skipreason = report.longrepr
+            if skipreason.startswith("Skipped: "):
+                skipreason = skipreason[9:]
+            self.appendlog('<skipped type="pytest.skip" '
+                           'message="%s">%s</skipped>',
+                skipreason, "%s:%s: %s" % report.longrepr,
+                )
         self._closetestcase()
         self.skipped += 1
 
diff --git a/_pytest/python.py b/_pytest/python.py
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -70,11 +70,13 @@
     res = __multicall__.execute()
     if res is not None:
         return res
-    if collector._istestclasscandidate(name, obj):
+    if inspect.isclass(obj):
         #if hasattr(collector.obj, 'unittest'):
         #    return # we assume it's a mixin class for a TestCase derived one
-        Class = collector._getcustomclass("Class")
-        return Class(name, parent=collector)
+        if collector.classnamefilter(name):
+            if not hasinit(obj):
+                Class = collector._getcustomclass("Class")
+                return Class(name, parent=collector)
     elif collector.funcnamefilter(name) and hasattr(obj, '__call__'):
         if is_generator(obj):
             return Generator(name, parent=collector)
@@ -194,14 +196,6 @@
         return self.ihook.pytest_pycollect_makeitem(
             collector=self, name=name, obj=obj)
 
-    def _istestclasscandidate(self, name, obj):
-        if self.classnamefilter(name) and \
-           inspect.isclass(obj):
-            if hasinit(obj):
-                # XXX WARN
-                return False
-            return True
-
     def _genfunctions(self, name, funcobj):
         module = self.getparent(Module).obj
         clscol = self.getparent(Class)
diff --git a/_pytest/resultlog.py b/_pytest/resultlog.py
--- a/_pytest/resultlog.py
+++ b/_pytest/resultlog.py
@@ -74,7 +74,7 @@
         elif report.failed:
             longrepr = str(report.longrepr)
         elif report.skipped:
-            longrepr = str(report.longrepr[2])
+            longrepr = str(report.longrepr)
         self.log_outcome(report, code, longrepr)
 
     def pytest_collectreport(self, report):
diff --git a/dotviewer/conftest.py b/dotviewer/conftest.py
--- a/dotviewer/conftest.py
+++ b/dotviewer/conftest.py
@@ -6,4 +6,6 @@
         dest="pygame", default=False, 
         help="allow interactive tests using Pygame")
 
-option = py.test.config.option
+def pytest_configure(config):
+    global option
+    option = config.option
diff --git a/lib-python/TODO b/lib-python/TODO
--- a/lib-python/TODO
+++ b/lib-python/TODO
@@ -2,7 +2,7 @@
 ===================
 
 You can find the results of the most recent buildbot run at:
-http://buildbot.pypy.org/summary?branch=fast-forward
+http://buildbot.pypy.org/
 
 
 Probably easy tasks
@@ -39,18 +39,8 @@
 Medium tasks
 ------------
 
-- Ast objects should be picklable, see in pypy/module/_ast/test/test_ast.py:
-  test_pickle()
-
 - socket module has a couple of changes (including AF_TIPC packet range)
 
-- (test_lib2to3) When a "for" loop runs a generator function, if the loop is
-  exited before the end, the "finally" clause of the generator is not called
-  until the next gc collection.  In our case, in lib2to3/pytree.py,
-  WildcardPattern.match_seq() does not exhaust the generate_matches() generator,
-  and stderr is not restored.
-
-
 Longer tasks
 ------------
 
diff --git a/lib-python/modified-2.7.0/ctypes/test/test_internals.py b/lib-python/modified-2.7.0/ctypes/test/test_internals.py
--- a/lib-python/modified-2.7.0/ctypes/test/test_internals.py
+++ b/lib-python/modified-2.7.0/ctypes/test/test_internals.py
@@ -2,7 +2,6 @@
 import unittest
 from ctypes import *
 from sys import getrefcount as grc
-from ctypes.test import xfail
 
 # XXX This test must be reviewed for correctness!!!
 
@@ -29,13 +28,18 @@
         self.assertEqual(refcnt, grc(i))
         self.assertEqual(ci._objects, None)
 
-    @xfail
     def test_c_char_p(self):
         s = "Hello, World"
         refcnt = grc(s)
         cs = c_char_p(s)
         self.assertEqual(refcnt + 1, grc(s))
-        self.assertSame(cs._objects, s)
+        try:
+            # Moving gcs need to allocate a nonmoving buffer
+            cs._objects._obj
+        except AttributeError:
+            self.assertSame(cs._objects, s)
+        else:
+            self.assertSame(cs._objects._obj, s)
 
     def test_simple_struct(self):
         class X(Structure):
diff --git a/lib-python/modified-2.7.0/ctypes/test/test_loading.py b/lib-python/modified-2.7.0/ctypes/test/test_loading.py
--- a/lib-python/modified-2.7.0/ctypes/test/test_loading.py
+++ b/lib-python/modified-2.7.0/ctypes/test/test_loading.py
@@ -2,7 +2,7 @@
 import sys, unittest
 import os
 from ctypes.util import find_library
-from ctypes.test import is_resource_enabled
+from ctypes.test import is_resource_enabled, xfail
 
 libc_name = None
 if os.name == "nt":
@@ -75,6 +75,7 @@
             self.assertRaises(AttributeError, dll.__getitem__, 1234)
 
     if os.name == "nt":
+        @xfail
         def test_1703286_A(self):
             from _ctypes import LoadLibrary, FreeLibrary
             # On winXP 64-bit, advapi32 loads at an address that does
@@ -85,6 +86,7 @@
             handle = LoadLibrary("advapi32")
             FreeLibrary(handle)
 
+        @xfail
         def test_1703286_B(self):
             # Since on winXP 64-bit advapi32 loads like described
             # above, the (arbitrarily selected) CloseEventLog function
diff --git a/lib-python/modified-2.7.0/ctypes/test/test_parameters.py b/lib-python/modified-2.7.0/ctypes/test/test_parameters.py
--- a/lib-python/modified-2.7.0/ctypes/test/test_parameters.py
+++ b/lib-python/modified-2.7.0/ctypes/test/test_parameters.py
@@ -89,6 +89,8 @@
 
         pa = c_wchar_p.from_param(c_wchar_p(u"123"))
         self.assertEqual(type(pa), c_wchar_p)
+    if sys.platform == "win32":
+        test_cw_strings = xfail(test_cw_strings)
 
     @xfail
     def test_int_pointers(self):
diff --git a/lib-python/modified-2.7.0/distutils/command/build_ext.py b/lib-python/modified-2.7.0/distutils/command/build_ext.py
--- a/lib-python/modified-2.7.0/distutils/command/build_ext.py
+++ b/lib-python/modified-2.7.0/distutils/command/build_ext.py
@@ -184,7 +184,7 @@
             # the 'libs' directory is for binary installs - we assume that
             # must be the *native* platform.  But we don't really support
             # cross-compiling via a binary install anyway, so we let it go.
-            self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
+            self.library_dirs.append(os.path.join(sys.exec_prefix, 'include'))
             if self.debug:
                 self.build_temp = os.path.join(self.build_temp, "Debug")
             else:
@@ -192,8 +192,13 @@
 
             # Append the source distribution include and library directories,
             # this allows distutils on windows to work in the source tree
-            self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
-            if MSVC_VERSION == 9:
+            if 0:
+                # pypy has no PC directory
+                self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
+            if 1:
+                # pypy has no PCBuild directory
+                pass
+            elif MSVC_VERSION == 9:
                 # Use the .lib files for the correct architecture
                 if self.plat_name == 'win32':
                     suffix = ''
@@ -695,24 +700,14 @@
         shared extension.  On most platforms, this is just 'ext.libraries';
         on Windows and OS/2, we add the Python library (eg. python20.dll).
         """
-        # The python library is always needed on Windows.  For MSVC, this
-        # is redundant, since the library is mentioned in a pragma in
-        # pyconfig.h that MSVC groks.  The other Windows compilers all seem
-        # to need it mentioned explicitly, though, so that's what we do.
-        # Append '_d' to the python import library on debug builds.
+        # The python library is always needed on Windows.
         if sys.platform == "win32":
-            from distutils.msvccompiler import MSVCCompiler
-            if not isinstance(self.compiler, MSVCCompiler):
-                template = "python%d%d"
-                if self.debug:
-                    template = template + '_d'
-                pythonlib = (template %
-                       (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
-                # don't extend ext.libraries, it may be shared with other
-                # extensions, it is a reference to the original list
-                return ext.libraries + [pythonlib]
-            else:
-                return ext.libraries
+            template = "python%d%d"
+            pythonlib = (template %
+                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            # don't extend ext.libraries, it may be shared with other
+            # extensions, it is a reference to the original list
+            return ext.libraries + [pythonlib]
         elif sys.platform == "os2emx":
             # EMX/GCC requires the python library explicitly, and I
             # believe VACPP does as well (though not confirmed) - AIM Apr01
diff --git a/lib-python/modified-2.7.0/distutils/msvc9compiler.py b/lib-python/modified-2.7.0/distutils/msvc9compiler.py
--- a/lib-python/modified-2.7.0/distutils/msvc9compiler.py
+++ b/lib-python/modified-2.7.0/distutils/msvc9compiler.py
@@ -644,6 +644,7 @@
             temp_manifest = os.path.join(
                     build_temp,
                     os.path.basename(output_filename) + ".manifest")
+            ld_args.append('/MANIFEST')
             ld_args.append('/MANIFESTFILE:' + temp_manifest)
 
             if extra_preargs:
diff --git a/lib-python/modified-2.7.0/sqlite3/test/regression.py b/lib-python/modified-2.7.0/sqlite3/test/regression.py
--- a/lib-python/modified-2.7.0/sqlite3/test/regression.py
+++ b/lib-python/modified-2.7.0/sqlite3/test/regression.py
@@ -264,6 +264,16 @@
         """
         self.assertRaises(sqlite.Warning, self.con, 1)
 
+    def CheckUpdateDescriptionNone(self):
+        """
+        Call Cursor.update with an UPDATE query and check that it sets the
+        cursor's description to be None.
+        """
+        cur = self.con.cursor()
+        cur.execute("CREATE TABLE foo (id INTEGER)")
+        cur.execute("UPDATE foo SET id = 3 WHERE id = 1")
+        self.assertEqual(cur.description, None)
+
 def suite():
     regression_suite = unittest.makeSuite(RegressionTests, "Check")
     return unittest.TestSuite((regression_suite,))
diff --git a/lib_pypy/_pypy_wait.py b/lib_pypy/_pypy_wait.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_pypy_wait.py
@@ -0,0 +1,51 @@
+from ctypes import CDLL, c_int, POINTER, byref
+from ctypes.util import find_library
+from resource import _struct_rusage, struct_rusage
+
+__all__ = ["wait3", "wait4"]
+
+libc = CDLL(find_library("c"))
+c_wait3 = libc.wait3
+
+c_wait3.argtypes = [POINTER(c_int), c_int, POINTER(_struct_rusage)]
+
+c_wait4 = libc.wait4
+
+c_wait4.argtypes = [c_int, POINTER(c_int), c_int, POINTER(_struct_rusage)]
+
+def create_struct_rusage(c_struct):
+    return struct_rusage((
+        float(c_struct.ru_utime),
+        float(c_struct.ru_stime),
+        c_struct.ru_maxrss,
+        c_struct.ru_ixrss,
+        c_struct.ru_idrss,
+        c_struct.ru_isrss,
+        c_struct.ru_minflt,
+        c_struct.ru_majflt,
+        c_struct.ru_nswap,
+        c_struct.ru_inblock,
+        c_struct.ru_oublock,
+        c_struct.ru_msgsnd,
+        c_struct.ru_msgrcv,
+        c_struct.ru_nsignals,
+        c_struct.ru_nvcsw,
+        c_struct.ru_nivcsw))
+
+def wait3(options):
+    status = c_int()
+    _rusage = _struct_rusage()
+    pid = c_wait3(byref(status), c_int(options), byref(_rusage))
+
+    rusage = create_struct_rusage(_rusage)
+
+    return pid, status.value, rusage
+
+def wait4(pid, options):
+    status = c_int()
+    _rusage = _struct_rusage()
+    pid = c_wait4(c_int(pid), byref(status), c_int(options), byref(_rusage))
+
+    rusage = create_struct_rusage(_rusage)
+
+    return pid, status.value, rusage
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -31,9 +31,9 @@
 from threading import _get_ident as thread_get_ident
 
 names = "sqlite3.dll libsqlite3.so.0 libsqlite3.so libsqlite3.dylib".split()
-for name in names: 
+for name in names:
     try:
-        sqlite = cdll.LoadLibrary(name) 
+        sqlite = cdll.LoadLibrary(name)
         break
     except OSError:
         continue
@@ -232,7 +232,7 @@
     return unicode(x, 'utf-8')
 
 class Connection(object):
-    def __init__(self, database, isolation_level="", detect_types=0, timeout=None, *args, **kwargs):
+    def __init__(self, database, isolation_level="", detect_types=0, timeout=None, cached_statements=None, factory=None):
         self.db = c_void_p()
         if sqlite.sqlite3_open(database, byref(self.db)) != SQLITE_OK:
             raise OperationalError("Could not open database")
@@ -1032,6 +1032,8 @@
         self.statement = None
 
     def _get_description(self):
+        if self.kind == "DML":
+            return None
         desc = []
         for i in xrange(sqlite.sqlite3_column_count(self.statement)):
             name = sqlite.sqlite3_column_name(self.statement, i).split("[")[0].strip()
@@ -1140,7 +1142,7 @@
 
 def _convert_result(con, val):
     if val is None:
-        sqlite.sqlite3_result_null(con)        
+        sqlite.sqlite3_result_null(con)
     elif isinstance(val, (bool, int, long)):
         sqlite.sqlite3_result_int64(con, int(val))
     elif isinstance(val, str):
diff --git a/lib_pypy/pypy_test/test_os_wait.py b/lib_pypy/pypy_test/test_os_wait.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pypy_test/test_os_wait.py
@@ -0,0 +1,44 @@
+# Generates the resource cache
+from __future__ import absolute_import
+from lib_pypy.ctypes_config_cache import rebuild
+rebuild.rebuild_one('resource.ctc.py')
+
+import os
+
+from lib_pypy._pypy_wait import wait3, wait4
+
+if hasattr(os, 'wait3'):
+    def test_os_wait3():
+        exit_status = 0x33
+
+        if not hasattr(os, "fork"):
+            skip("Need fork() to test wait3()")
+
+        child = os.fork()
+        if child == 0: # in child
+            os._exit(exit_status)
+        else:
+            pid, status, rusage = wait3(0)
+            assert child == pid
+            assert os.WIFEXITED(status)
+            assert os.WEXITSTATUS(status) == exit_status
+            assert isinstance(rusage.ru_utime, float)
+            assert isinstance(rusage.ru_maxrss, int)
+
+if hasattr(os, 'wait4'):
+    def test_os_wait4():
+        exit_status = 0x33
+
+        if not hasattr(os, "fork"):
+            skip("Need fork() to test wait4()")
+
+        child = os.fork()
+        if child == 0: # in child
+            os._exit(exit_status)
+        else:
+            pid, status, rusage = wait4(child, 0)
+            assert child == pid
+            assert os.WIFEXITED(status)
+            assert os.WEXITSTATUS(status) == exit_status
+            assert isinstance(rusage.ru_utime, float)
+            assert isinstance(rusage.ru_maxrss, int)
diff --git a/lib_pypy/pyrepl/__init__.py b/lib_pypy/pyrepl/__init__.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/__init__.py
@@ -0,0 +1,19 @@
+#   Copyright 2000-2008 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/lib_pypy/pyrepl/cmdrepl.py b/lib_pypy/pyrepl/cmdrepl.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/cmdrepl.py
@@ -0,0 +1,118 @@
+#   Copyright 2000-2007 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Maciek Fijalkowski
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""Wedge pyrepl behaviour into cmd.Cmd-derived classes.
+
+replize, when given a subclass of cmd.Cmd, returns a class that
+behaves almost identically to the supplied class, except that it uses
+pyrepl instead if raw_input.
+
+It was designed to let you do this:
+
+>>> import pdb
+>>> from pyrepl import replize
+>>> pdb.Pdb = replize(pdb.Pdb)
+
+which is in fact done by the `pythoni' script that comes with
+pyrepl."""
+
+from __future__ import nested_scopes
+
+from pyrepl import completing_reader as cr, reader, completer
+from pyrepl.completing_reader import CompletingReader as CR
+import cmd
+
+class CmdReader(CR):
+    def collect_keymap(self):
+        return super(CmdReader, self).collect_keymap() + (
+            ("\\M-\\n", "invalid-key"),
+            ("\\n", "accept"))
+    
+    CR_init = CR.__init__
+    def __init__(self, completions):
+        self.CR_init(self)
+        self.completions = completions
+
+    def get_completions(self, stem):
+        if len(stem) != self.pos:
+            return []
+        return cr.uniqify([s for s in self.completions
+                           if s.startswith(stem)])
+
+def replize(klass, history_across_invocations=1):
+
+    """Return a subclass of the cmd.Cmd-derived klass that uses
+    pyrepl instead of readline.
+
+    Raises a ValueError if klass does not derive from cmd.Cmd.
+
+    The optional history_across_invocations parameter (default 1)
+    controls whether instances of the returned class share
+    histories."""
+
+    completions = [s[3:]
+                   for s in completer.get_class_members(klass)
+                   if s.startswith("do_")]
+
+    if not issubclass(klass, cmd.Cmd):
+        raise Exception
+#    if klass.cmdloop.im_class is not cmd.Cmd:
+#        print "this may not work"
+
+    class CmdRepl(klass):
+        k_init = klass.__init__
+
+        if history_across_invocations:
+            _CmdRepl__history = []
+            def __init__(self, *args, **kw):
+                self.k_init(*args, **kw)
+                self.__reader = CmdReader(completions)
+                self.__reader.history = CmdRepl._CmdRepl__history
+                self.__reader.historyi = len(CmdRepl._CmdRepl__history)
+        else:
+            def __init__(self, *args, **kw):
+                self.k_init(*args, **kw)
+                self.__reader = CmdReader(completions)
+        
+        def cmdloop(self, intro=None):
+            self.preloop()
+            if intro is not None:
+                self.intro = intro
+            if self.intro:
+                print self.intro
+            stop = None
+            while not stop:
+                if self.cmdqueue:
+                    line = self.cmdqueue[0]
+                    del self.cmdqueue[0]
+                else:
+                    try:
+                        self.__reader.ps1 = self.prompt
+                        line = self.__reader.readline()
+                    except EOFError:
+                        line = "EOF"
+                line = self.precmd(line)
+                stop = self.onecmd(line)
+                stop = self.postcmd(stop, line)
+            self.postloop()
+
+    CmdRepl.__name__ = "replize(%s.%s)"%(klass.__module__, klass.__name__)
+    return CmdRepl
+
diff --git a/lib_pypy/pyrepl/commands.py b/lib_pypy/pyrepl/commands.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/commands.py
@@ -0,0 +1,385 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Antonio Cuni
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import sys, os
+
+# Catgories of actions:
+#  killing
+#  yanking
+#  motion
+#  editing
+#  history
+#  finishing
+# [completion]
+
+class Command(object):
+    finish = 0
+    kills_digit_arg = 1
+    def __init__(self, reader, (event_name, event)):
+        self.reader = reader
+        self.event = event
+        self.event_name = event_name
+    def do(self):
+        pass
+
+class KillCommand(Command):
+    def kill_range(self, start, end):
+        if start == end:
+            return
+        r = self.reader
+        b = r.buffer
+        text = b[start:end]
+        del b[start:end]
+        if is_kill(r.last_command):
+            if start < r.pos:
+                r.kill_ring[-1] = text + r.kill_ring[-1]
+            else:
+                r.kill_ring[-1] = r.kill_ring[-1] + text
+        else:
+            r.kill_ring.append(text)
+        r.pos = start
+        r.dirty = 1
+
+class YankCommand(Command):
+    pass
+
+class MotionCommand(Command):
+    pass
+
+class EditCommand(Command):
+    pass
+
+class FinishCommand(Command):
+    finish = 1
+    pass
+
+def is_kill(command):
+    return command and issubclass(command, KillCommand)
+
+def is_yank(command):
+    return command and issubclass(command, YankCommand)
+
+# etc
+
+class digit_arg(Command):
+    kills_digit_arg = 0
+    def do(self):
+        r = self.reader
+        c = self.event[-1]
+        if c == "-":
+            if r.arg is not None:
+                r.arg = -r.arg
+            else:
+                r.arg = -1
+        else:
+            d = int(c)
+            if r.arg is None:
+                r.arg = d
+            else:
+                if r.arg < 0:
+                    r.arg = 10*r.arg - d
+                else:
+                    r.arg = 10*r.arg + d
+        r.dirty = 1
+
+class clear_screen(Command):
+    def do(self):
+        r = self.reader
+        r.console.clear()
+        r.dirty = 1
+
+class refresh(Command):
+    def do(self):
+        self.reader.dirty = 1
+
+class repaint(Command):
+    def do(self):
+        self.reader.dirty = 1
+        self.reader.console.repaint_prep()
+
+class kill_line(KillCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        eol = r.eol()
+        for c in b[r.pos:eol]:
+            if not c.isspace():
+                self.kill_range(r.pos, eol)
+                return
+        else:
+            self.kill_range(r.pos, eol+1)
+
+class unix_line_discard(KillCommand):
+    def do(self):
+        r = self.reader
+        self.kill_range(r.bol(), r.pos)
+
+# XXX unix_word_rubout and backward_kill_word should actually
+# do different things...
+
+class unix_word_rubout(KillCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            self.kill_range(r.bow(), r.pos)
+
+class kill_word(KillCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            self.kill_range(r.pos, r.eow())
+
+class backward_kill_word(KillCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            self.kill_range(r.bow(), r.pos)
+
+class yank(YankCommand):
+    def do(self):
+        r = self.reader
+        if not r.kill_ring:
+            r.error("nothing to yank")
+            return
+        r.insert(r.kill_ring[-1])
+
+class yank_pop(YankCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        if not r.kill_ring:
+            r.error("nothing to yank")
+            return
+        if not is_yank(r.last_command):
+            r.error("previous command was not a yank")
+            return
+        repl = len(r.kill_ring[-1])
+        r.kill_ring.insert(0, r.kill_ring.pop())
+        t = r.kill_ring[-1]
+        b[r.pos - repl:r.pos] = t
+        r.pos = r.pos - repl + len(t)
+        r.dirty = 1
+
+class interrupt(FinishCommand):
+    def do(self):
+        import signal
+        self.reader.console.finish()
+        os.kill(os.getpid(), signal.SIGINT)
+
+class suspend(Command):
+    def do(self):
+        import signal
+        r = self.reader
+        p = r.pos
+        r.console.finish()
+        os.kill(os.getpid(), signal.SIGSTOP)
+        ## this should probably be done
+        ## in a handler for SIGCONT?
+        r.console.prepare()
+        r.pos = p
+        r.posxy = 0, 0
+        r.dirty = 1
+        r.console.screen = []
+
+class up(MotionCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            bol1 = r.bol()
+            if bol1 == 0:
+                if r.historyi > 0:
+                    r.select_item(r.historyi - 1)
+                    return
+                r.pos = 0
+                r.error("start of buffer")
+                return
+            bol2 = r.bol(bol1-1)
+            line_pos = r.pos - bol1
+            if line_pos > bol1 - bol2 - 1:
+                r.sticky_y = line_pos
+                r.pos = bol1 - 1
+            else:
+                r.pos = bol2 + line_pos
+
+class down(MotionCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        for i in range(r.get_arg()):
+            bol1 = r.bol()
+            eol1 = r.eol()
+            if eol1 == len(b):
+                if r.historyi < len(r.history):
+                    r.select_item(r.historyi + 1)
+                    r.pos = r.eol(0)
+                    return
+                r.pos = len(b)
+                r.error("end of buffer")
+                return
+            eol2 = r.eol(eol1+1)
+            if r.pos - bol1 > eol2 - eol1 - 1:
+                r.pos = eol2
+            else:
+                r.pos = eol1 + (r.pos - bol1) + 1
+
+class left(MotionCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):        
+            p = r.pos - 1
+            if p >= 0:
+                r.pos = p
+            else:
+                self.reader.error("start of buffer")
+
+class right(MotionCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        for i in range(r.get_arg()):
+            p = r.pos + 1
+            if p <= len(b):
+                r.pos = p
+            else:
+                self.reader.error("end of buffer")
+
+class beginning_of_line(MotionCommand):
+    def do(self):
+        self.reader.pos = self.reader.bol()
+
+class end_of_line(MotionCommand):
+    def do(self):
+        r = self.reader
+        self.reader.pos = self.reader.eol()
+
+class home(MotionCommand):
+    def do(self):
+        self.reader.pos = 0
+        
+class end(MotionCommand):
+    def do(self):
+        self.reader.pos = len(self.reader.buffer)
+        
+class forward_word(MotionCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            r.pos = r.eow()
+    
+class backward_word(MotionCommand):
+    def do(self):
+        r = self.reader
+        for i in range(r.get_arg()):
+            r.pos = r.bow()
+
+class self_insert(EditCommand):
+    def do(self):
+        r = self.reader
+        r.insert(self.event * r.get_arg())
+
+class insert_nl(EditCommand):
+    def do(self):
+        r = self.reader
+        r.insert("\n" * r.get_arg())
+
+class transpose_characters(EditCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        s = r.pos - 1
+        if s < 0:
+            r.error("cannot transpose at start of buffer")
+        else:
+            if s == len(b):
+                s -= 1
+            t = min(s + r.get_arg(), len(b) - 1)
+            c = b[s]
+            del b[s]
+            b.insert(t, c)
+            r.pos = t
+            r.dirty = 1
+
+class backspace(EditCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        for i in range(r.get_arg()):
+            if r.pos > 0:
+                r.pos -= 1
+                del b[r.pos]
+                r.dirty = 1
+            else:
+                self.reader.error("can't backspace at start")
+
+class delete(EditCommand):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        if  ( r.pos == 0 and len(b) == 0 # this is something of a hack
+              and self.event[-1] == "\004"):
+            r.update_screen()
+            r.console.finish()
+            raise EOFError
+        for i in range(r.get_arg()):
+            if r.pos != len(b):
+                del b[r.pos]
+                r.dirty = 1
+            else:
+                self.reader.error("end of buffer")
+
+class accept(FinishCommand):
+    def do(self):
+        pass
+
+class help(Command):
+    def do(self):
+        self.reader.msg = self.reader.help_text
+        self.reader.dirty = 1
+
+class invalid_key(Command):
+    def do(self):
+        pending = self.reader.console.getpending()
+        s = ''.join(self.event) + pending.data
+        self.reader.error("`%r' not bound"%s)
+
+class invalid_command(Command):
+    def do(self):
+        s = self.event_name
+        self.reader.error("command `%s' not known"%s)
+
+class qIHelp(Command):
+    def do(self):
+        r = self.reader
+        r.insert((self.event + r.console.getpending().data) * r.get_arg())
+        r.pop_input_trans()
+
+from pyrepl import input
+
+class QITrans(object):
+    def push(self, evt):
+        self.evt = evt
+    def get(self):
+        return ('qIHelp', self.evt.raw)
+
+class quoted_insert(Command):
+    kills_digit_arg = 0
+    def do(self):
+        self.reader.push_input_trans(QITrans())
diff --git a/lib_pypy/pyrepl/completer.py b/lib_pypy/pyrepl/completer.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/completer.py
@@ -0,0 +1,87 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import __builtin__
+
+class Completer:
+    def __init__(self, ns):
+        self.ns = ns
+
+    def complete(self, text):
+        if "." in text:
+            return self.attr_matches(text)
+        else:
+            return self.global_matches(text)
+
+    def global_matches(self, text):
+        """Compute matches when text is a simple name.
+
+        Return a list of all keywords, built-in functions and names
+        currently defines in __main__ that match.
+
+        """
+        import keyword
+        matches = []
+        n = len(text)
+        for list in [keyword.kwlist,
+                     __builtin__.__dict__.keys(),
+                     self.ns.keys()]:
+            for word in list:
+                if word[:n] == text and word != "__builtins__":
+                    matches.append(word)
+        return matches
+
+    def attr_matches(self, text):
+        """Compute matches when text contains a dot.
+
+        Assuming the text is of the form NAME.NAME....[NAME], and is
+        evaluatable in the globals of __main__, it will be evaluated
+        and its attributes (as revealed by dir()) are used as possible
+        completions.  (For class instances, class members are are also
+        considered.)
+
+        WARNING: this can still invoke arbitrary C code, if an object
+        with a __getattr__ hook is evaluated.
+
+        """
+        import re
+        m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
+        if not m:
+            return []
+        expr, attr = m.group(1, 3)
+        object = eval(expr, self.ns)
+        words = dir(object)
+        if hasattr(object, '__class__'):
+            words.append('__class__')
+            words = words + get_class_members(object.__class__)
+        matches = []
+        n = len(attr)
+        for word in words:
+            if word[:n] == attr and word != "__builtins__":
+                matches.append("%s.%s" % (expr, word))
+        return matches
+
+def get_class_members(klass):
+    ret = dir(klass)
+    if hasattr(klass, '__bases__'):
+        for base in klass.__bases__:
+            ret = ret + get_class_members(base)
+    return ret
+
+
diff --git a/lib_pypy/pyrepl/completing_reader.py b/lib_pypy/pyrepl/completing_reader.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/completing_reader.py
@@ -0,0 +1,280 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Antonio Cuni
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl import commands, reader
+from pyrepl.reader import Reader
+
+def uniqify(l):
+    d = {}
+    for i in l:
+        d[i] = 1
+    r = d.keys()
+    r.sort()
+    return r
+
+def prefix(wordlist, j = 0):
+    d = {}
+    i = j
+    try:
+        while 1:
+            for word in wordlist:
+                d[word[i]] = 1
+            if len(d) > 1:
+                return wordlist[0][j:i]
+            i += 1
+            d = {}
+    except IndexError:
+        return wordlist[0][j:i]
+
+import re
+def stripcolor(s):
+    return stripcolor.regexp.sub('', s)
+stripcolor.regexp = re.compile(r"\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[m|K]")
+
+def real_len(s):
+    return len(stripcolor(s))
+
+def left_align(s, maxlen):
+    stripped = stripcolor(s)
+    if len(stripped) > maxlen:
+        # too bad, we remove the color
+        return stripped[:maxlen]
+    padding = maxlen - len(stripped)
+    return s + ' '*padding
+
+def build_menu(cons, wordlist, start, use_brackets, sort_in_column):
+    if use_brackets:
+        item = "[ %s ]"
+        padding = 4
+    else:
+        item = "%s  "
+        padding = 2
+    maxlen = min(max(map(real_len, wordlist)), cons.width - padding)
+    cols = cons.width / (maxlen + padding)
+    rows = (len(wordlist) - 1)/cols + 1
+
+    if sort_in_column:
+        # sort_in_column=False (default)     sort_in_column=True
+        #          A B C                       A D G
+        #          D E F                       B E 
+        #          G                           C F
+        #
+        # "fill" the table with empty words, so we always have the same amout
+        # of rows for each column
+        missing = cols*rows - len(wordlist)
+        wordlist = wordlist + ['']*missing
+        indexes = [(i%cols)*rows + i//cols for i in range(len(wordlist))]
+        wordlist = [wordlist[i] for i in indexes]
+    menu = []
+    i = start
+    for r in range(rows):
+        row = []
+        for col in range(cols):
+            row.append(item % left_align(wordlist[i], maxlen))
+            i += 1
+            if i >= len(wordlist):
+                break
+        menu.append( ''.join(row) )
+        if i >= len(wordlist):
+            i = 0
+            break
+        if r + 5 > cons.height:
+            menu.append("   %d more... "%(len(wordlist) - i))
+            break
+    return menu, i    
+
+# this gets somewhat user interface-y, and as a result the logic gets
+# very convoluted.
+#
+#  To summarise the summary of the summary:- people are a problem.
+#                  -- The Hitch-Hikers Guide to the Galaxy, Episode 12
+
+#### Desired behaviour of the completions commands.
+# the considerations are:
+# (1) how many completions are possible
+# (2) whether the last command was a completion
+# (3) if we can assume that the completer is going to return the same set of
+#     completions: this is controlled by the ``assume_immutable_completions``
+#     variable on the reader, which is True by default to match the historical
+#     behaviour of pyrepl, but e.g. False in the ReadlineAlikeReader to match
+#     more closely readline's semantics (this is needed e.g. by
+#     fancycompleter)
+#
+# if there's no possible completion, beep at the user and point this out.
+# this is easy.
+#
+# if there's only one possible completion, stick it in.  if the last thing
+# user did was a completion, point out that he isn't getting anywhere, but
+# only if the ``assume_immutable_completions`` is True.
+#
+# now it gets complicated.
+# 
+# for the first press of a completion key:
+#  if there's a common prefix, stick it in.
+
+#  irrespective of whether anything got stuck in, if the word is now
+#  complete, show the "complete but not unique" message
+
+#  if there's no common prefix and if the word is not now complete,
+#  beep.
+
+#        common prefix ->    yes          no
+#        word complete \/
+#            yes           "cbnu"      "cbnu"
+#            no              -          beep
+
+# for the second bang on the completion key
+#  there will necessarily be no common prefix
+#  show a menu of the choices.
+
+# for subsequent bangs, rotate the menu around (if there are sufficient
+# choices).
+
+class complete(commands.Command):
+    def do(self):
+        r = self.reader
+        stem = r.get_stem()
+        if r.assume_immutable_completions and \
+                r.last_command_is(self.__class__):
+            completions = r.cmpltn_menu_choices
+        else:
+            r.cmpltn_menu_choices = completions = \
+                                        r.get_completions(stem)
+        if len(completions) == 0:
+            r.error("no matches")
+        elif len(completions) == 1:
+            if r.assume_immutable_completions and \
+                   len(completions[0]) == len(stem) and \
+                   r.last_command_is(self.__class__):
+                r.msg = "[ sole completion ]"
+                r.dirty = 1
+            r.insert(completions[0][len(stem):])
+        else:
+            p = prefix(completions, len(stem))
+            if p <> '':
+                r.insert(p)
+            if r.last_command_is(self.__class__):
+                if not r.cmpltn_menu_vis:
+                    r.cmpltn_menu_vis = 1
+                r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
+                    r.console, completions, r.cmpltn_menu_end,
+                    r.use_brackets, r.sort_in_column)
+                r.dirty = 1
+            elif stem + p in completions:
+                r.msg = "[ complete but not unique ]"
+                r.dirty = 1
+            else:
+                r.msg = "[ not unique ]"
+                r.dirty = 1
+
+class self_insert(commands.self_insert):
+    def do(self):
+        commands.self_insert.do(self)
+        r = self.reader
+        if r.cmpltn_menu_vis:
+            stem = r.get_stem()
+            if len(stem) < 1:
+                r.cmpltn_reset()
+            else:
+                completions = [w for w in r.cmpltn_menu_choices
+                               if w.startswith(stem)]
+                if completions:
+                    r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
+                        r.console, completions, 0,
+                        r.use_brackets, r.sort_in_column)
+                else:
+                    r.cmpltn_reset()
+
+class CompletingReader(Reader):
+    """Adds completion support
+
+    Adds instance variables:
+      * cmpltn_menu, cmpltn_menu_vis, cmpltn_menu_end, cmpltn_choices:
+      *
+    """
+    # see the comment for the complete command
+    assume_immutable_completions = True
+    use_brackets = True # display completions inside []
+    sort_in_column = False
+    
+    def collect_keymap(self):
+        return super(CompletingReader, self).collect_keymap() + (
+            (r'\t', 'complete'),)
+    
+    def __init__(self, console):
+        super(CompletingReader, self).__init__(console)
+        self.cmpltn_menu = ["[ menu 1 ]", "[ menu 2 ]"]
+        self.cmpltn_menu_vis = 0
+        self.cmpltn_menu_end = 0
+        for c in [complete, self_insert]:
+            self.commands[c.__name__] = c
+            self.commands[c.__name__.replace('_', '-')] = c        
+
+    def after_command(self, cmd):
+        super(CompletingReader, self).after_command(cmd)
+        if not isinstance(cmd, complete) and not isinstance(cmd, self_insert):
+            self.cmpltn_reset()
+
+    def calc_screen(self):
+        screen = super(CompletingReader, self).calc_screen()
+        if self.cmpltn_menu_vis:
+            ly = self.lxy[1]
+            screen[ly:ly] = self.cmpltn_menu
+            self.screeninfo[ly:ly] = [(0, [])]*len(self.cmpltn_menu)
+            self.cxy = self.cxy[0], self.cxy[1] + len(self.cmpltn_menu)
+        return screen
+
+    def finish(self):
+        super(CompletingReader, self).finish()
+        self.cmpltn_reset()
+
+    def cmpltn_reset(self):
+        self.cmpltn_menu = []
+        self.cmpltn_menu_vis = 0
+        self.cmpltn_menu_end = 0
+        self.cmpltn_menu_choices = []        
+
+    def get_stem(self):
+        st = self.syntax_table
+        SW = reader.SYNTAX_WORD
+        b = self.buffer
+        p = self.pos - 1
+        while p >= 0 and st.get(b[p], SW) == SW:
+            p -= 1
+        return u''.join(b[p+1:self.pos])
+
+    def get_completions(self, stem):
+        return []
+
+def test():
+    class TestReader(CompletingReader):
+        def get_completions(self, stem):
+            return [s for l in map(lambda x:x.split(),self.history)
+                    for s in l if s and s.startswith(stem)]
+    reader = TestReader()
+    reader.ps1 = "c**> "
+    reader.ps2 = "c/*> "
+    reader.ps3 = "c|*> "
+    reader.ps4 = "c\*> "
+    while reader.readline():
+        pass
+
+if __name__=='__main__':
+    test()
diff --git a/lib_pypy/pyrepl/console.py b/lib_pypy/pyrepl/console.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/console.py
@@ -0,0 +1,93 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+class Event:
+    """An Event.  `evt' is 'key' or somesuch."""
+
+    def __init__(self, evt, data, raw=''):
+        self.evt = evt
+        self.data = data
+        self.raw = raw
+
+    def __repr__(self):
+        return 'Event(%r, %r)'%(self.evt, self.data)
+
+class Console:
+    """Attributes:
+
+    screen,
+    height,
+    width,
+    """
+    
+    def refresh(self, screen, xy):
+        pass
+
+    def prepare(self):
+        pass
+
+    def restore(self):
+        pass
+
+    def move_cursor(self, x, y):
+        pass
+
+    def set_cursor_vis(self, vis):
+        pass
+
+    def getheightwidth(self):
+        """Return (height, width) where height and width are the height
+        and width of the terminal window in characters."""
+        pass
+
+    def get_event(self, block=1):
+        """Return an Event instance.  Returns None if |block| is false
+        and there is no event pending, otherwise waits for the
+        completion of an event."""
+        pass
+
+    def beep(self):
+        pass
+
+    def clear(self):
+        """Wipe the screen"""
+        pass
+
+    def finish(self):
+        """Move the cursor to the end of the display and otherwise get
+        ready for end.  XXX could be merged with restore?  Hmm."""
+        pass
+
+    def flushoutput(self):
+        """Flush all output to the screen (assuming there's some
+        buffering going on somewhere)."""
+        pass
+
+    def forgetinput(self):
+        """Forget all pending, but not yet processed input."""
+        pass
+
+    def getpending(self):
+        """Return the characters that have been typed but not yet
+        processed."""
+        pass
+
+    def wait(self):
+        """Wait for an event."""
+        pass
diff --git a/lib_pypy/pyrepl/copy_code.py b/lib_pypy/pyrepl/copy_code.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/copy_code.py
@@ -0,0 +1,73 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import new
+
+def copy_code_with_changes(codeobject,
+                           argcount=None,
+                           nlocals=None,
+                           stacksize=None,
+                           flags=None,
+                           code=None,
+                           consts=None,
+                           names=None,
+                           varnames=None,
+                           filename=None,
+                           name=None,
+                           firstlineno=None,
+                           lnotab=None):
+    if argcount    is None: argcount    = codeobject.co_argcount
+    if nlocals     is None: nlocals     = codeobject.co_nlocals
+    if stacksize   is None: stacksize   = codeobject.co_stacksize
+    if flags       is None: flags       = codeobject.co_flags
+    if code        is None: code        = codeobject.co_code
+    if consts      is None: consts      = codeobject.co_consts
+    if names       is None: names       = codeobject.co_names
+    if varnames    is None: varnames    = codeobject.co_varnames
+    if filename    is None: filename    = codeobject.co_filename
+    if name        is None: name        = codeobject.co_name
+    if firstlineno is None: firstlineno = codeobject.co_firstlineno
+    if lnotab      is None: lnotab      = codeobject.co_lnotab
+    return new.code(argcount,
+                    nlocals,
+                    stacksize,
+                    flags,
+                    code,
+                    consts,
+                    names,
+                    varnames,
+                    filename,
+                    name,
+                    firstlineno,
+                    lnotab)
+
+code_attrs=['argcount',
+            'nlocals',
+            'stacksize',
+            'flags',
+            'code',
+            'consts',
+            'names',
+            'varnames',
+            'filename',
+            'name',
+            'firstlineno',
+            'lnotab']
+
+
diff --git a/lib_pypy/pyrepl/curses.py b/lib_pypy/pyrepl/curses.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/curses.py
@@ -0,0 +1,39 @@
+
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# Some try-import logic for two purposes: avoiding to bring in the whole
+# pure Python curses package if possible; and, in _curses is not actually
+# present, falling back to _minimal_curses (which is either a ctypes-based
+# pure Python module or a PyPy built-in module).
+try:
+    import _curses
+except ImportError:
+    try:
+        import _minimal_curses as _curses
+    except ImportError:
+        # Who knows, maybe some environment has "curses" but not "_curses".
+        # If not, at least the following import gives a clean ImportError.
+        import _curses
+
+setupterm = _curses.setupterm
+tigetstr = _curses.tigetstr
+tparm = _curses.tparm
+error = _curses.error
diff --git a/lib_pypy/pyrepl/fancy_termios.py b/lib_pypy/pyrepl/fancy_termios.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/fancy_termios.py
@@ -0,0 +1,52 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import termios
+
+class TermState:
+    def __init__(self, tuples):
+        self.iflag, self.oflag, self.cflag, self.lflag, \
+                    self.ispeed, self.ospeed, self.cc = tuples
+    def as_list(self):
+        return [self.iflag, self.oflag, self.cflag, self.lflag,
+                self.ispeed, self.ospeed, self.cc]
+
+    def copy(self):
+        return self.__class__(self.as_list())
+
+def tcgetattr(fd):
+    return TermState(termios.tcgetattr(fd))
+
+def tcsetattr(fd, when, attrs):
+    termios.tcsetattr(fd, when, attrs.as_list())
+
+class Term(TermState):
+    TS__init__ = TermState.__init__
+    def __init__(self, fd=0):
+        self.TS__init__(termios.tcgetattr(fd))
+        self.fd = fd
+        self.stack = []
+    def save(self):
+        self.stack.append( self.as_list() )
+    def set(self, when=termios.TCSANOW):
+        termios.tcsetattr(self.fd, when, self.as_list())
+    def restore(self):
+        self.TS__init__(self.stack.pop())
+        self.set()
+        
diff --git a/lib_pypy/pyrepl/historical_reader.py b/lib_pypy/pyrepl/historical_reader.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/historical_reader.py
@@ -0,0 +1,311 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl import reader, commands
+from pyrepl.reader import Reader as R
+
+isearch_keymap = tuple(
+    [('\\%03o'%c, 'isearch-end') for c in range(256) if chr(c) != '\\'] + \
+    [(c, 'isearch-add-character')
+     for c in map(chr, range(32, 127)) if c != '\\'] + \
+    [('\\%03o'%c, 'isearch-add-character')
+     for c in range(256) if chr(c).isalpha() and chr(c) != '\\'] + \
+    [('\\\\', 'self-insert'),
+     (r'\C-r', 'isearch-backwards'),
+     (r'\C-s', 'isearch-forwards'),
+     (r'\C-c', 'isearch-cancel'),
+     (r'\C-g', 'isearch-cancel'),
+     (r'\<backspace>', 'isearch-backspace')])
+
+del c
+
+ISEARCH_DIRECTION_NONE = ''
+ISEARCH_DIRECTION_BACKWARDS = 'r'
+ISEARCH_DIRECTION_FORWARDS = 'f'
+
+class next_history(commands.Command):
+    def do(self):
+        r = self.reader
+        if r.historyi == len(r.history):
+            r.error("end of history list")
+            return
+        r.select_item(r.historyi + 1)
+
+class previous_history(commands.Command):
+    def do(self):
+        r = self.reader
+        if r.historyi == 0:
+            r.error("start of history list")
+            return
+        r.select_item(r.historyi - 1)
+
+class restore_history(commands.Command):
+    def do(self):
+        r = self.reader
+        if r.historyi != len(r.history):
+            if r.get_unicode() != r.history[r.historyi]:
+                r.buffer = list(r.history[r.historyi])
+                r.pos = len(r.buffer)
+                r.dirty = 1
+
+class first_history(commands.Command):
+    def do(self):
+        self.reader.select_item(0)
+
+class last_history(commands.Command):
+    def do(self):
+        self.reader.select_item(len(self.reader.history))
+
+class operate_and_get_next(commands.FinishCommand):
+    def do(self):
+        self.reader.next_history = self.reader.historyi + 1
+
+class yank_arg(commands.Command):
+    def do(self):
+        r = self.reader
+        if r.last_command is self.__class__:
+            r.yank_arg_i += 1
+        else:
+            r.yank_arg_i = 0
+        if r.historyi < r.yank_arg_i:
+            r.error("beginning of history list")
+            return
+        a = r.get_arg(-1)
+        # XXX how to split?
+        words = r.get_item(r.historyi - r.yank_arg_i - 1).split()
+        if a < -len(words) or a >= len(words):
+            r.error("no such arg")
+            return
+        w = words[a]
+        b = r.buffer
+        if r.yank_arg_i > 0:
+            o = len(r.yank_arg_yanked)
+        else:
+            o = 0
+        b[r.pos - o:r.pos] = list(w)
+        r.yank_arg_yanked = w
+        r.pos += len(w) - o
+        r.dirty = 1
+
+class forward_history_isearch(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_FORWARDS
+        r.isearch_start = r.historyi, r.pos
+        r.isearch_term = ''
+        r.dirty = 1
+        r.push_input_trans(r.isearch_trans)
+        
+
+class reverse_history_isearch(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_BACKWARDS
+        r.dirty = 1
+        r.isearch_term = ''
+        r.push_input_trans(r.isearch_trans)
+        r.isearch_start = r.historyi, r.pos
+
+class isearch_cancel(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_NONE
+        r.pop_input_trans()
+        r.select_item(r.isearch_start[0])
+        r.pos = r.isearch_start[1]
+        r.dirty = 1
+
+class isearch_add_character(commands.Command):
+    def do(self):
+        r = self.reader
+        b = r.buffer
+        r.isearch_term += self.event[-1]
+        r.dirty = 1
+        p = r.pos + len(r.isearch_term) - 1
+        if b[p:p+1] != [r.isearch_term[-1]]:
+            r.isearch_next()
+
+class isearch_backspace(commands.Command):
+    def do(self):
+        r = self.reader
+        if len(r.isearch_term) > 0:
+            r.isearch_term = r.isearch_term[:-1]
+            r.dirty = 1
+        else:
+            r.error("nothing to rubout")
+
+class isearch_forwards(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_FORWARDS
+        r.isearch_next()
+
+class isearch_backwards(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_BACKWARDS
+        r.isearch_next()
+
+class isearch_end(commands.Command):
+    def do(self):
+        r = self.reader
+        r.isearch_direction = ISEARCH_DIRECTION_NONE
+        r.console.forgetinput()
+        r.pop_input_trans()
+        r.dirty = 1
+
+class HistoricalReader(R):
+    """Adds history support (with incremental history searching) to the
+    Reader class.
+
+    Adds the following instance variables:
+      * history:
+        a list of strings
+      * historyi:
+      * transient_history:
+      * next_history:
+      * isearch_direction, isearch_term, isearch_start:
+      * yank_arg_i, yank_arg_yanked:
+        used by the yank-arg command; not actually manipulated by any
+        HistoricalReader instance methods.
+    """
+
+    def collect_keymap(self):
+        return super(HistoricalReader, self).collect_keymap() + (
+            (r'\C-n', 'next-history'),
+            (r'\C-p', 'previous-history'),
+            (r'\C-o', 'operate-and-get-next'),
+            (r'\C-r', 'reverse-history-isearch'),
+            (r'\C-s', 'forward-history-isearch'),
+            (r'\M-r', 'restore-history'),
+            (r'\M-.', 'yank-arg'),
+            (r'\<page down>', 'last-history'),
+            (r'\<page up>', 'first-history'))
+
+
+    def __init__(self, console):
+        super(HistoricalReader, self).__init__(console)
+        self.history = []
+        self.historyi = 0
+        self.transient_history = {}
+        self.next_history = None
+        self.isearch_direction = ISEARCH_DIRECTION_NONE
+        for c in [next_history, previous_history, restore_history,
+                  first_history, last_history, yank_arg,
+                  forward_history_isearch, reverse_history_isearch,
+                  isearch_end, isearch_add_character, isearch_cancel,
+                  isearch_add_character, isearch_backspace,
+                  isearch_forwards, isearch_backwards, operate_and_get_next]:
+            self.commands[c.__name__] = c
+            self.commands[c.__name__.replace('_', '-')] = c
+        from pyrepl import input
+        self.isearch_trans = input.KeymapTranslator(
+            isearch_keymap, invalid_cls=isearch_end,
+            character_cls=isearch_add_character)
+        
+    def select_item(self, i):
+        self.transient_history[self.historyi] = self.get_unicode()
+        buf = self.transient_history.get(i)
+        if buf is None:
+            buf = self.history[i]
+        self.buffer = list(buf)
+        self.historyi = i
+        self.pos = len(self.buffer)
+        self.dirty = 1
+
+    def get_item(self, i):
+        if i <> len(self.history):
+            return self.transient_history.get(i, self.history[i])
+        else:
+            return self.transient_history.get(i, self.get_unicode())
+
+    def prepare(self):
+        super(HistoricalReader, self).prepare()
+        try:
+            self.transient_history = {}
+            if self.next_history is not None \
+               and self.next_history < len(self.history):
+                self.historyi = self.next_history
+                self.buffer[:] = list(self.history[self.next_history])
+                self.pos = len(self.buffer)
+                self.transient_history[len(self.history)] = ''
+            else:
+                self.historyi = len(self.history)
+            self.next_history = None
+        except:
+            self.restore()
+            raise
+
+    def get_prompt(self, lineno, cursor_on_line):
+        if cursor_on_line and self.isearch_direction <> ISEARCH_DIRECTION_NONE:
+            d = 'rf'[self.isearch_direction == ISEARCH_DIRECTION_FORWARDS]
+            return "(%s-search `%s') "%(d, self.isearch_term)
+        else:
+            return super(HistoricalReader, self).get_prompt(lineno, cursor_on_line)
+
+    def isearch_next(self):
+        st = self.isearch_term
+        p = self.pos
+        i = self.historyi
+        s = self.get_unicode()
+        forwards = self.isearch_direction == ISEARCH_DIRECTION_FORWARDS
+        while 1:
+            if forwards:
+                p = s.find(st, p + 1)
+            else:
+                p = s.rfind(st, 0, p + len(st) - 1)
+            if p != -1:
+                self.select_item(i)
+                self.pos = p
+                return
+            elif ((forwards and i == len(self.history) - 1)
+                  or (not forwards and i == 0)):
+                self.error("not found")
+                return
+            else:
+                if forwards:
+                    i += 1
+                    s = self.get_item(i)
+                    p = -1
+                else:
+                    i -= 1
+                    s = self.get_item(i)
+                    p = len(s)
+
+    def finish(self):
+        super(HistoricalReader, self).finish()
+        ret = self.get_unicode()
+        for i, t in self.transient_history.items():
+            if i < len(self.history) and i != self.historyi:
+                self.history[i] = t
+        if ret:
+            self.history.append(ret)
+
+def test():
+    from pyrepl.unix_console import UnixConsole
+    reader = HistoricalReader(UnixConsole())
+    reader.ps1 = "h**> "
+    reader.ps2 = "h/*> "
+    reader.ps3 = "h|*> "
+    reader.ps4 = "h\*> "
+    while reader.readline():
+        pass
+
+if __name__=='__main__':
+    test()
diff --git a/lib_pypy/pyrepl/input.py b/lib_pypy/pyrepl/input.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/input.py
@@ -0,0 +1,97 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# (naming modules after builtin functions is not such a hot idea...)
+
+# an KeyTrans instance translates Event objects into Command objects
+
+# hmm, at what level do we want [C-i] and [tab] to be equivalent?
+# [meta-a] and [esc a]?  obviously, these are going to be equivalent
+# for the UnixConsole, but should they be for PygameConsole?
+
+# it would in any situation seem to be a bad idea to bind, say, [tab]
+# and [C-i] to *different* things... but should binding one bind the
+# other?
+
+# executive, temporary decision: [tab] and [C-i] are distinct, but
+# [meta-key] is identified with [esc key].  We demand that any console
+# class does quite a lot towards emulating a unix terminal.
+
+from pyrepl import unicodedata_
+
+class InputTranslator(object):
+    def push(self, evt):
+        pass
+    def get(self):
+        pass
+    def empty(self):
+        pass
+
+class KeymapTranslator(InputTranslator):
+    def __init__(self, keymap, verbose=0,
+                 invalid_cls=None, character_cls=None):
+        self.verbose = verbose
+        from pyrepl.keymap import compile_keymap, parse_keys
+        self.keymap = keymap
+        self.invalid_cls = invalid_cls
+        self.character_cls = character_cls
+        d = {}
+        for keyspec, command in keymap:
+            keyseq = tuple(parse_keys(keyspec))
+            d[keyseq] = command
+        if self.verbose:
+            print d
+        self.k = self.ck = compile_keymap(d, ())
+        self.results = []
+        self.stack = []
+    def push(self, evt):
+        if self.verbose:
+            print "pushed", evt.data,
+        key = evt.data
+        d = self.k.get(key)
+        if isinstance(d, dict):
+            if self.verbose:
+                print "transition"
+            self.stack.append(key)
+            self.k = d
+        else:
+            if d is None:
+                if self.verbose:
+                    print "invalid"
+                if self.stack or len(key) > 1 or unicodedata_.category(key) == 'C':
+                    self.results.append(
+                        (self.invalid_cls, self.stack + [key]))
+                else:
+                    # small optimization:
+                    self.k[key] = self.character_cls
+                    self.results.append(
+                        (self.character_cls, [key]))
+            else:
+                if self.verbose:
+                    print "matched", d
+                self.results.append((d, self.stack + [key]))
+            self.stack = []
+            self.k = self.ck
+    def get(self):
+        if self.results:
+            return self.results.pop(0)
+        else:
+            return None
+    def empty(self):
+        return not self.results
diff --git a/lib_pypy/pyrepl/keymap.py b/lib_pypy/pyrepl/keymap.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/keymap.py
@@ -0,0 +1,186 @@
+#   Copyright 2000-2008 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+functions for parsing keyspecs
+
+Support for turning keyspecs into appropriate sequences.
+
+pyrepl uses it's own bastardized keyspec format, which is meant to be
+a strict superset of readline's \"KEYSEQ\" format (which is to say
+that if you can come up with a spec readline accepts that this
+doesn't, you've found a bug and should tell me about it).
+
+Note that this is the `\\C-o' style of readline keyspec, not the
+`Control-o' sort.
+
+A keyspec is a string representing a sequence of keypresses that can
+be bound to a command.
+
+All characters other than the backslash represent themselves.  In the
+traditional manner, a backslash introduces a escape sequence.
+
+The extension to readline is that the sequence \\<KEY> denotes the
+sequence of charaters produced by hitting KEY.
+
+Examples:
+
+`a'     - what you get when you hit the `a' key
+`\\EOA'  - Escape - O - A (up, on my terminal)
+`\\<UP>' - the up arrow key
+`\\<up>' - ditto (keynames are case insensitive)
+`\\C-o', `\\c-o'  - control-o
+`\\M-.'  - meta-period
+`\\E.'   - ditto (that's how meta works for pyrepl)
+`\\<tab>', `\\<TAB>', `\\t', `\\011', '\\x09', '\\X09', '\\C-i', '\\C-I'
+   - all of these are the tab character.  Can you think of any more?
+"""
+
+_escapes = {
+    '\\':'\\',
+    "'":"'",
+    '"':'"',
+    'a':'\a',
+    'b':'\h',
+    'e':'\033',
+    'f':'\f',
+    'n':'\n',
+    'r':'\r',
+    't':'\t',
+    'v':'\v'
+    }
+
+_keynames = {
+    'backspace': 'backspace',
+    'delete':    'delete',
+    'down':      'down',
+    'end':       'end',
+    'enter':     '\r',
+    'escape':    '\033',
+    'f1' : 'f1',   'f2' : 'f2',   'f3' : 'f3',   'f4' : 'f4',
+    'f5' : 'f5',   'f6' : 'f6',   'f7' : 'f7',   'f8' : 'f8',
+    'f9' : 'f9',   'f10': 'f10',  'f11': 'f11',  'f12': 'f12',
+    'f13': 'f13',  'f14': 'f14',  'f15': 'f15',  'f16': 'f16',
+    'f17': 'f17',  'f18': 'f18',  'f19': 'f19',  'f20': 'f20',
+    'home':      'home',
+    'insert':    'insert',
+    'left':      'left',
+    'page down': 'page down',
+    'page up':   'page up',
+    'return':    '\r',
+    'right':     'right',
+    'space':     ' ',
+    'tab':       '\t',
+    'up':        'up',
+    }
+
+class KeySpecError(Exception):
+    pass
+
+def _parse_key1(key, s):
+    ctrl = 0
+    meta = 0
+    ret = ''
+    while not ret and s < len(key):
+        if key[s] == '\\':
+            c = key[s+1].lower()
+            if _escapes.has_key(c):
+                ret = _escapes[c]
+                s += 2
+            elif c == "c":
+                if key[s + 2] != '-':
+                    raise KeySpecError, \
+                              "\\C must be followed by `-' (char %d of %s)"%(
+                        s + 2, repr(key))
+                if ctrl:
+                    raise KeySpecError, "doubled \\C- (char %d of %s)"%(
+                        s + 1, repr(key))
+                ctrl = 1
+                s += 3
+            elif c == "m":
+                if key[s + 2] != '-':
+                    raise KeySpecError, \
+                              "\\M must be followed by `-' (char %d of %s)"%(
+                        s + 2, repr(key))
+                if meta:
+                    raise KeySpecError, "doubled \\M- (char %d of %s)"%(
+                        s + 1, repr(key))
+                meta = 1
+                s += 3
+            elif c.isdigit():
+                n = key[s+1:s+4]
+                ret = chr(int(n, 8))
+                s += 4
+            elif c == 'x':
+                n = key[s+2:s+4]
+                ret = chr(int(n, 16))
+                s += 4
+            elif c == '<':
+                t = key.find('>', s)
+                if t == -1:
+                    raise KeySpecError, \
+                              "unterminated \\< starting at char %d of %s"%(
+                        s + 1, repr(key))                        
+                ret = key[s+2:t].lower()
+                if ret not in _keynames:
+                    raise KeySpecError, \
+                              "unrecognised keyname `%s' at char %d of %s"%(
+                        ret, s + 2, repr(key))
+                ret = _keynames[ret]
+                s = t + 1
+            else:
+                raise KeySpecError, \
+                          "unknown backslash escape %s at char %d of %s"%(
+                    `c`, s + 2, repr(key))
+        else:
+            ret = key[s]
+            s += 1
+    if ctrl:
+        if len(ret) > 1:
+            raise KeySpecError, "\\C- must be followed by a character"
+        ret = chr(ord(ret) & 0x1f)   # curses.ascii.ctrl()
+    if meta:
+        ret = ['\033', ret]
+    else:
+        ret = [ret]
+    return ret, s
+
+def parse_keys(key):
+    s = 0
+    r = []
+    while s < len(key):
+        k, s = _parse_key1(key, s)
+        r.extend(k)
+    return r
+
+def compile_keymap(keymap, empty=''):
+    r = {}
+    for key, value in keymap.items():
+        r.setdefault(key[0], {})[key[1:]] = value
+    for key, value in r.items():
+        if empty in value:
+            if len(value) <> 1:
+                raise KeySpecError, \
+                      "key definitions for %s clash"%(value.values(),)
+            else:
+                r[key] = value[empty]
+        else:
+            r[key] = compile_keymap(value, empty)
+    return r
diff --git a/lib_pypy/pyrepl/keymaps.py b/lib_pypy/pyrepl/keymaps.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/keymaps.py
@@ -0,0 +1,140 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+reader_emacs_keymap = tuple(
+    [(r'\C-a', 'beginning-of-line'),
+     (r'\C-b', 'left'),
+     (r'\C-c', 'interrupt'),
+     (r'\C-d', 'delete'),
+     (r'\C-e', 'end-of-line'),
+     (r'\C-f', 'right'),
+     (r'\C-g', 'cancel'),
+     (r'\C-h', 'backspace'),
+     (r'\C-j', 'self-insert'),
+     (r'\<return>', 'accept'),
+     (r'\C-k', 'kill-line'),
+     (r'\C-l', 'clear-screen'),
+#     (r'\C-m', 'accept'),
+     (r'\C-q', 'quoted-insert'),
+     (r'\C-t', 'transpose-characters'),
+     (r'\C-u', 'unix-line-discard'),
+     (r'\C-v', 'quoted-insert'),
+     (r'\C-w', 'unix-word-rubout'),
+     (r'\C-x\C-u', 'upcase-region'),
+     (r'\C-y', 'yank'),
+     (r'\C-z', 'suspend'),
+     
+     (r'\M-b', 'backward-word'),
+     (r'\M-c', 'capitalize-word'),
+     (r'\M-d', 'kill-word'),
+     (r'\M-f', 'forward-word'),
+     (r'\M-l', 'downcase-word'),
+     (r'\M-t', 'transpose-words'),
+     (r'\M-u', 'upcase-word'),
+     (r'\M-y', 'yank-pop'),
+     (r'\M--', 'digit-arg'),
+     (r'\M-0', 'digit-arg'),
+     (r'\M-1', 'digit-arg'),
+     (r'\M-2', 'digit-arg'),
+     (r'\M-3', 'digit-arg'),
+     (r'\M-4', 'digit-arg'),
+     (r'\M-5', 'digit-arg'),
+     (r'\M-6', 'digit-arg'),
+     (r'\M-7', 'digit-arg'),
+     (r'\M-8', 'digit-arg'),
+     (r'\M-9', 'digit-arg'),
+     (r'\M-\n', 'self-insert'),
+     (r'\<backslash>', 'self-insert')] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(32, 127)) if c <> '\\'] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(128, 256)) if c.isalpha()] + \
+    [(r'\<up>', 'up'),
+     (r'\<down>', 'down'),
+     (r'\<left>', 'left'),
+     (r'\<right>', 'right'),
+     (r'\<insert>', 'quoted-insert'),
+     (r'\<delete>', 'delete'),
+     (r'\<backspace>', 'backspace'),
+     (r'\M-\<backspace>', 'backward-kill-word'),
+     (r'\<end>', 'end'),
+     (r'\<home>', 'home'),
+     (r'\<f1>', 'help'),
+     (r'\EOF', 'end'),  # the entries in the terminfo database for xterms
+     (r'\EOH', 'home'), # seem to be wrong.  this is a less than ideal
+                        # workaround
+     ])
+
+hist_emacs_keymap = reader_emacs_keymap + (
+    (r'\C-n', 'next-history'),
+    (r'\C-p', 'previous-history'),
+    (r'\C-o', 'operate-and-get-next'),
+    (r'\C-r', 'reverse-history-isearch'),
+    (r'\C-s', 'forward-history-isearch'),
+    (r'\M-r', 'restore-history'),
+    (r'\M-.', 'yank-arg'),
+    (r'\<page down>', 'last-history'),
+    (r'\<page up>', 'first-history'))
+
+comp_emacs_keymap = hist_emacs_keymap + (
+    (r'\t', 'complete'),)
+
+python_emacs_keymap = comp_emacs_keymap + (
+    (r'\n', 'maybe-accept'),
+    (r'\M-\n', 'self-insert'))
+    
+reader_vi_insert_keymap = tuple(
+    [(c, 'self-insert')
+     for c in map(chr, range(32, 127)) if c <> '\\'] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(128, 256)) if c.isalpha()] + \
+    [(r'\C-d', 'delete'),
+     (r'\<backspace>', 'backspace'),
+     ('')])
+
+reader_vi_command_keymap = tuple(
+    [
+    ('E', 'enter-emacs-mode'),
+    ('R', 'enter-replace-mode'),
+    ('dw', 'delete-word'),
+    ('dd', 'delete-line'),
+    
+    ('h', 'left'),
+    ('i', 'enter-insert-mode'),
+    ('j', 'down'),
+    ('k', 'up'),
+    ('l', 'right'),
+    ('r', 'replace-char'),
+    ('w', 'forward-word'),
+    ('x', 'delete'),
+    ('.', 'repeat-edit'), # argh!
+    (r'\<insert>', 'enter-insert-mode'),
+     ] + 
+    [(c, 'digit-arg') for c in '01234567689'] +
+    [])
+   
+
+reader_keymaps = {
+    'emacs' : reader_emacs_keymap,
+    'vi-insert' : reader_vi_insert_keymap,
+    'vi-command' : reader_vi_command_keymap
+    }
+
+del c # from the listcomps
+
diff --git a/lib_pypy/pyrepl/module_lister.py b/lib_pypy/pyrepl/module_lister.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/module_lister.py
@@ -0,0 +1,70 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.completing_reader import uniqify
+import os, sys
+
+# for the completion support.
+# this is all quite nastily written.
+_packages = {}
+
+def _make_module_list_dir(dir, suffs, prefix=''):
+    l = []
+    for fname in os.listdir(dir):
+        file = os.path.join(dir, fname)
+        if os.path.isfile(file):
+            for suff in suffs:
+                if fname.endswith(suff):
+                    l.append( prefix + fname[:-len(suff)] )
+                    break
+        elif os.path.isdir(file) \
+             and os.path.exists(os.path.join(file, "__init__.py")):
+            l.append( prefix + fname )
+            _packages[prefix + fname] = _make_module_list_dir(
+                file, suffs, prefix + fname + '.' )
+    l = uniqify(l)
+    l.sort()
+    return l
+
+def _make_module_list():
+    import imp
+    suffs = [x[0] for x in imp.get_suffixes() if x[0] != '.pyc']
+    def compare(x, y):
+        c = -cmp(len(x), len(y))
+        if c:
+            return c
+        else:
+            return -cmp(x, y)
+    suffs.sort(compare)
+    _packages[''] = list(sys.builtin_module_names)
+    for dir in sys.path:
+        if dir == '':
+            dir = '.'
+        if os.path.isdir(dir):
+            _packages[''] += _make_module_list_dir(dir, suffs)
+    _packages[''].sort()
+
+def find_modules(stem):
+    l = stem.split('.')
+    pack = '.'.join(l[:-1])
+    try:
+        mods = _packages[pack]
+    except KeyError:
+        raise ImportError, "can't find \"%s\" package"%pack
+    return [mod for mod in mods if mod.startswith(stem)]
diff --git a/lib_pypy/pyrepl/pygame_console.py b/lib_pypy/pyrepl/pygame_console.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/pygame_console.py
@@ -0,0 +1,353 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# the pygame console is currently thoroughly broken.
+
+# there's a fundamental difference from the UnixConsole: here we're
+# the terminal emulator too, in effect.  This means, e.g., for pythoni
+# we really need a separate process (or thread) to monitor for ^C
+# during command execution and zap the executor process.  Making this
+# work on non-Unix is expected to be even more entertaining.
+
+from pygame.locals import *
+from pyrepl.console import Console, Event
+from pyrepl import pygame_keymap
+import pygame
+import types
+
+lmargin = 5
+rmargin = 5
+tmargin = 5
+bmargin = 5
+
+try:
+    bool
+except NameError:
+    def bool(x):
+        return not not x
+
+modcolors = {K_LCTRL:1,
+             K_RCTRL:1,
+             K_LMETA:1,
+             K_RMETA:1,
+             K_LALT:1,
+             K_RALT:1,
+             K_LSHIFT:1,
+             K_RSHIFT:1}
+
+class colors:
+    fg = 250,240,230
+    bg = 5, 5, 5
+    cursor = 230, 0, 230
+    margin = 5, 5, 15
+
+class FakeStdout:
+    def __init__(self, con):
+        self.con = con
+    def write(self, text):
+        self.con.write(text)
+    def flush(self):
+        pass
+
+class FakeStdin:
+    def __init__(self, con):
+        self.con = con
+    def read(self, n=None):
+        # argh!
+        raise NotImplementedError
+    def readline(self, n=None):
+        from reader import Reader
+        try:
+            # this isn't quite right: it will clobber any prompt that's
+            # been printed.  Not sure how to get around this...
+            return Reader(self.con).readline()
+        except EOFError:
+            return ''
+
+class PyGameConsole(Console):
+    """Attributes:
+
+    (keymap),
+    (fd),
+    screen,
+    height,
+    width,
+    """
+    
+    def __init__(self):
+        self.pygame_screen = pygame.display.set_mode((800, 600))
+        pygame.font.init()
+        pygame.key.set_repeat(500, 30)
+        self.font = pygame.font.Font(
+            "/usr/X11R6/lib/X11/fonts/TTF/luximr.ttf", 15)
+        self.fw, self.fh = self.fontsize = self.font.size("X")
+        self.cursor = pygame.Surface(self.fontsize)
+        self.cursor.fill(colors.cursor)
+        self.clear()
+        self.curs_vis = 1
+        self.height, self.width = self.getheightwidth()
+        pygame.display.update()
+        pygame.event.set_allowed(None)
+        pygame.event.set_allowed(KEYDOWN)
+        
+    def install_keymap(self, keymap):
+        """Install a given keymap.
+
+        keymap is a tuple of 2-element tuples; each small tuple is a
+        pair (keyspec, event-name).  The format for keyspec is
+        modelled on that used by readline (so read that manual for
+        now!)."""
+        self.k = self.keymap = pygame_keymap.compile_keymap(keymap)
+
+    def char_rect(self, x, y):
+        return self.char_pos(x, y), self.fontsize
+
+    def char_pos(self, x, y):
+        return (lmargin + x*self.fw,
+                tmargin + y*self.fh + self.cur_top + self.scroll)
+
+    def paint_margin(self):
+        s = self.pygame_screen
+        c = colors.margin
+        s.fill(c, [0, 0, 800, tmargin])
+        s.fill(c, [0, 0, lmargin, 600])
+        s.fill(c, [0, 600 - bmargin, 800, bmargin])
+        s.fill(c, [800 - rmargin, 0, lmargin, 600])
+
+    def refresh(self, screen, (cx, cy)):
+        self.screen = screen
+        self.pygame_screen.fill(colors.bg,
+                                [0, tmargin + self.cur_top + self.scroll,
+                                 800, 600])
+        self.paint_margin()
+
+        line_top = self.cur_top
+        width, height = self.fontsize
+        self.cxy = (cx, cy)
+        cp = self.char_pos(cx, cy)
+        if cp[1] < tmargin:
+            self.scroll = - (cy*self.fh + self.cur_top)
+            self.repaint()
+        elif cp[1] + self.fh > 600 - bmargin:
+            self.scroll += (600 - bmargin) - (cp[1] + self.fh)
+            self.repaint()
+        if self.curs_vis:
+            self.pygame_screen.blit(self.cursor, self.char_pos(cx, cy))
+        for line in screen:
+            if 0 <= line_top + self.scroll <= (600 - bmargin - tmargin - self.fh):
+                if line:
+                    ren = self.font.render(line, 1, colors.fg)
+                    self.pygame_screen.blit(ren, (lmargin,
+                                                  tmargin + line_top + self.scroll))
+            line_top += self.fh
+        pygame.display.update()
+
+    def prepare(self):
+        self.cmd_buf = ''
+        self.k = self.keymap
+        self.height, self.width = self.getheightwidth()
+        self.curs_vis = 1
+        self.cur_top = self.pos[0]
+        self.event_queue = []
+
+    def restore(self):
+        pass
+
+    def blit_a_char(self, linen, charn):
+        line = self.screen[linen]
+        if charn < len(line):
+            text = self.font.render(line[charn], 1, colors.fg)
+            self.pygame_screen.blit(text, self.char_pos(charn, linen))
+
+    def move_cursor(self, x, y):
+        cp = self.char_pos(x, y)
+        if cp[1] < tmargin or cp[1] + self.fh > 600 - bmargin:
+            self.event_queue.append(Event('refresh', '', ''))
+        else:
+            if self.curs_vis:
+                cx, cy = self.cxy
+                self.pygame_screen.fill(colors.bg, self.char_rect(cx, cy))
+                self.blit_a_char(cy, cx)
+                self.pygame_screen.blit(self.cursor, cp)
+                self.blit_a_char(y, x)
+                pygame.display.update()
+            self.cxy = (x, y)
+
+    def set_cursor_vis(self, vis):
+        self.curs_vis = vis
+        if vis:
+            self.move_cursor(*self.cxy)
+        else:
+            cx, cy = self.cxy
+            self.pygame_screen.fill(colors.bg, self.char_rect(cx, cy))
+            self.blit_a_char(cy, cx)
+            pygame.display.update()
+
+    def getheightwidth(self):
+        """Return (height, width) where height and width are the height
+        and width of the terminal window in characters."""
+        return ((600 - tmargin - bmargin)/self.fh,
+                (800 - lmargin - rmargin)/self.fw)
+
+    def tr_event(self, pyg_event):
+        shift = bool(pyg_event.mod & KMOD_SHIFT)
+        ctrl = bool(pyg_event.mod & KMOD_CTRL)
+        meta = bool(pyg_event.mod & (KMOD_ALT|KMOD_META))
+
+        try:
+            return self.k[(pyg_event.unicode, meta, ctrl)], pyg_event.unicode
+        except KeyError:
+            try:
+                return self.k[(pyg_event.key, meta, ctrl)], pyg_event.unicode
+            except KeyError:
+                return "invalid-key", pyg_event.unicode
+
+    def get_event(self, block=1):
+        """Return an Event instance.  Returns None if |block| is false
+        and there is no event pending, otherwise waits for the
+        completion of an event."""
+        while 1:
+            if self.event_queue:
+                return self.event_queue.pop(0)
+            elif block:
+                pyg_event = pygame.event.wait()
+            else:
+                pyg_event = pygame.event.poll()
+                if pyg_event.type == NOEVENT:
+                    return
+
+            if pyg_event.key in modcolors:
+                continue
+
+            k, c = self.tr_event(pyg_event)
+            self.cmd_buf += c.encode('ascii', 'replace')
+            self.k = k
+
+            if not isinstance(k, types.DictType):
+                e = Event(k, self.cmd_buf, [])
+                self.k = self.keymap
+                self.cmd_buf = ''
+                return e
+
+    def beep(self):
+        # uhh, can't be bothered now.
+        # pygame.sound.something, I guess.
+        pass
+
+    def clear(self):
+        """Wipe the screen"""
+        self.pygame_screen.fill(colors.bg)
+        #self.screen = []
+        self.pos = [0, 0]
+        self.grobs = []
+        self.cur_top = 0
+        self.scroll = 0
+
+    def finish(self):
+        """Move the cursor to the end of the display and otherwise get
+        ready for end.  XXX could be merged with restore?  Hmm."""
+        if self.curs_vis:
+            cx, cy = self.cxy
+            self.pygame_screen.fill(colors.bg, self.char_rect(cx, cy))
+            self.blit_a_char(cy, cx)
+        for line in self.screen:
+            self.write_line(line, 1)
+        if self.curs_vis:
+            self.pygame_screen.blit(self.cursor,
+                                    (lmargin + self.pos[1],
+                                     tmargin + self.pos[0] + self.scroll))
+        pygame.display.update()
+
+    def flushoutput(self):
+        """Flush all output to the screen (assuming there's some
+        buffering going on somewhere)"""
+        # no buffering here, ma'am (though perhaps there should be!)
+        pass
+
+    def forgetinput(self):
+        """Forget all pending, but not yet processed input."""
+        while pygame.event.poll().type <> NOEVENT:
+            pass
+    
+    def getpending(self):
+        """Return the characters that have been typed but not yet
+        processed."""
+        events = []
+        while 1:
+            event = pygame.event.poll()
+            if event.type == NOEVENT:
+                break
+            events.append(event)
+
+        return events
+
+    def wait(self):
+        """Wait for an event."""
+        raise Exception, "erp!"
+
+    def repaint(self):
+        # perhaps we should consolidate grobs?
+        self.pygame_screen.fill(colors.bg)
+        self.paint_margin()
+        for (y, x), surf, text in self.grobs:
+            if surf and 0 < y + self.scroll:
+                self.pygame_screen.blit(surf, (lmargin + x,
+                                               tmargin + y + self.scroll))
+        pygame.display.update()
+
+    def write_line(self, line, ret):
+        charsleft = (self.width*self.fw - self.pos[1])/self.fw
+        while len(line) > charsleft:
+            self.write_line(line[:charsleft], 1)
+            line = line[charsleft:]
+        if line:
+            ren = self.font.render(line, 1, colors.fg, colors.bg)
+            self.grobs.append((self.pos[:], ren, line))
+            self.pygame_screen.blit(ren,
+                                    (lmargin + self.pos[1],
+                                     tmargin + self.pos[0] + self.scroll))
+        else:
+            self.grobs.append((self.pos[:], None, line))
+        if ret:
+            self.pos[0] += self.fh
+            if tmargin + self.pos[0] + self.scroll + self.fh > 600 - bmargin:
+                self.scroll = 600 - bmargin - self.pos[0] - self.fh - tmargin
+                self.repaint()
+            self.pos[1] = 0
+        else:
+            self.pos[1] += self.fw*len(line)
+
+    def write(self, text):
+        lines = text.split("\n")
+        if self.curs_vis:
+            self.pygame_screen.fill(colors.bg,
+                                    (lmargin + self.pos[1],
+                                     tmargin + self.pos[0] + self.scroll,
+                                     self.fw, self.fh))
+        for line in lines[:-1]:
+            self.write_line(line, 1)
+        self.write_line(lines[-1], 0)
+        if self.curs_vis:
+            self.pygame_screen.blit(self.cursor,
+                                    (lmargin + self.pos[1],
+                                     tmargin + self.pos[0] + self.scroll))
+        pygame.display.update()
+
+    def flush(self):
+        pass
diff --git a/lib_pypy/pyrepl/pygame_keymap.py b/lib_pypy/pyrepl/pygame_keymap.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/pygame_keymap.py
@@ -0,0 +1,250 @@
+#   Copyright 2000-2008 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# keyspec parsing for a pygame console.  currently this is simply copy
+# n' change from the unix (ie. trad terminal) variant; probably some
+# refactoring will happen when I work out how it will work best.
+
+# A key is represented as *either*
+
+# a) a (keycode, meta, ctrl) sequence (used for special keys such as
+# f1, the up arrow key, etc)
+# b) a (unichar, meta, ctrl) sequence (used for printable chars)
+
+# Because we allow keystokes like '\\C-xu', I'll use the same trick as
+# the unix keymap module uses.
+
+# '\\C-a' --> (K_a, 0, 1)
+
+# XXX it's actually possible to test this module, so it should have a
+# XXX test suite.
+
+from pygame.locals import *
+
+_escapes = {
+    '\\': K_BACKSLASH,
+    "'" : K_QUOTE,
+    '"' : K_QUOTEDBL,
+#    'a' : '\a',
+    'b' : K_BACKSLASH,
+    'e' : K_ESCAPE,
+#    'f' : '\f',
+    'n' : K_RETURN,
+    'r' : K_RETURN,
+    't' : K_TAB,
+#    'v' : '\v'
+    }
+
+_keynames = {
+    'backspace' : K_BACKSPACE,
+    'delete'    : K_DELETE,
+    'down'      : K_DOWN,
+    'end'       : K_END,
+    'enter'     : K_KP_ENTER,
+    'escape'    : K_ESCAPE,
+    'f1' : K_F1, 'f2' : K_F2, 'f3' : K_F3, 'f4' : K_F4,
+    'f5' : K_F5, 'f6' : K_F6, 'f7' : K_F7, 'f8' : K_F8,
+    'f9' : K_F9, 'f10': K_F10,'f11': K_F11,'f12': K_F12,
+    'f13': K_F13,'f14': K_F14,'f15': K_F15,
+    'home'   : K_HOME,
+    'insert' : K_INSERT,
+    'left'   : K_LEFT,
+    'pgdown' : K_PAGEDOWN, 'page down' : K_PAGEDOWN,
+    'pgup'   : K_PAGEUP,   'page up'   : K_PAGEUP,
+    'return' : K_RETURN,
+    'right'  : K_RIGHT,
+    'space'  : K_SPACE,
+    'tab'    : K_TAB,
+    'up'     : K_UP,
+    }
+
+class KeySpecError(Exception):
+    pass
+
+def _parse_key1(key, s):
+    ctrl = 0
+    meta = 0
+    ret = ''
+    while not ret and s < len(key):
+        if key[s] == '\\':
+            c = key[s+1].lower()
+            if _escapes.has_key(c):
+                ret = _escapes[c]
+                s += 2
+            elif c == "c":
+                if key[s + 2] != '-':
+                    raise KeySpecError, \
+                              "\\C must be followed by `-' (char %d of %s)"%(
+                        s + 2, repr(key))
+                if ctrl:
+                    raise KeySpecError, "doubled \\C- (char %d of %s)"%(
+                        s + 1, repr(key))
+                ctrl = 1
+                s += 3
+            elif c == "m":
+                if key[s + 2] != '-':
+                    raise KeySpecError, \
+                              "\\M must be followed by `-' (char %d of %s)"%(
+                        s + 2, repr(key))
+                if meta:
+                    raise KeySpecError, "doubled \\M- (char %d of %s)"%(
+                        s + 1, repr(key))
+                meta = 1
+                s += 3
+            elif c.isdigit():
+                n = key[s+1:s+4]
+                ret = chr(int(n, 8))
+                s += 4
+            elif c == 'x':
+                n = key[s+2:s+4]
+                ret = chr(int(n, 16))
+                s += 4
+            elif c == '<':
+                t = key.find('>', s)
+                if t == -1:
+                    raise KeySpecError, \
+                              "unterminated \\< starting at char %d of %s"%(
+                        s + 1, repr(key))
+                try:
+                    ret = _keynames[key[s+2:t].lower()]
+                    s = t + 1
+                except KeyError:
+                    raise KeySpecError, \
+                              "unrecognised keyname `%s' at char %d of %s"%(
+                        key[s+2:t], s + 2, repr(key))
+                if ret is None:
+                    return None, s
+            else:
+                raise KeySpecError, \
+                          "unknown backslash escape %s at char %d of %s"%(
+                    `c`, s + 2, repr(key))
+        else:
+            if ctrl:
+                ret = chr(ord(key[s]) & 0x1f)   # curses.ascii.ctrl()
+                ret = unicode(ret)
+            else:
+                ret = unicode(key[s])
+            s += 1
+    return (ret, meta, ctrl), s
+
+def parse_keys(key):
+    s = 0
+    r = []
+    while s < len(key):
+        k, s = _parse_key1(key, s)
+        if k is None:
+            return None
+        r.append(k)
+    return tuple(r)
+
+def _compile_keymap(keymap):
+    r = {}
+    for key, value in keymap.items():
+        r.setdefault(key[0], {})[key[1:]] = value
+    for key, value in r.items():
+        if value.has_key(()):
+            if len(value) <> 1:
+                raise KeySpecError, \
+                          "key definitions for %s clash"%(value.values(),)
+            else:
+                r[key] = value[()]
+        else:
+            r[key] = _compile_keymap(value)
+    return r
+
+def compile_keymap(keymap):
+    r = {}
+    for key, value in keymap:
+        k = parse_keys(key)
+        if value is None and r.has_key(k):
+            del r[k]
+        if k is not None:
+            r[k] = value
+    return _compile_keymap(r)
+
+def keyname(key):
+    longest_match = ''
+    longest_match_name = ''
+    for name, keyseq in keyset.items():
+        if keyseq and key.startswith(keyseq) and \
+               len(keyseq) > len(longest_match):
+            longest_match = keyseq
+            longest_match_name = name
+    if len(longest_match) > 0:
+        return longest_match_name, len(longest_match)
+    else:
+        return None, 0
+
+_unescapes = {'\r':'\\r', '\n':'\\n', '\177':'^?'}
+
+#for k,v in _escapes.items():
+#    _unescapes[v] = k
+
+def unparse_key(keyseq):
+    if not keyseq:
+        return ''
+    name, s = keyname(keyseq)
+    if name:
+        if name <> 'escape' or s == len(keyseq):
+            return '\\<' + name + '>' + unparse_key(keyseq[s:])
+        else:
+            return '\\M-' + unparse_key(keyseq[1:])
+    else:
+        c = keyseq[0]
+        r = keyseq[1:]
+        if c == '\\':
+            p = '\\\\'
+        elif _unescapes.has_key(c):
+            p = _unescapes[c]
+        elif ord(c) < ord(' '):
+            p = '\\C-%s'%(chr(ord(c)+96),)
+        elif ord(' ') <= ord(c) <= ord('~'):
+            p = c
+        else:
+            p = '\\%03o'%(ord(c),)
+        return p + unparse_key(r)
+
+def _unparse_keyf(keyseq):
+    if not keyseq:
+        return []
+    name, s = keyname(keyseq)
+    if name:
+        if name <> 'escape' or s == len(keyseq):
+            return [name] + _unparse_keyf(keyseq[s:])
+        else:
+            rest = _unparse_keyf(keyseq[1:])
+            return ['M-'+rest[0]] + rest[1:]
+    else:
+        c = keyseq[0]
+        r = keyseq[1:]
+        if c == '\\':
+            p = '\\'
+        elif _unescapes.has_key(c):
+            p = _unescapes[c]
+        elif ord(c) < ord(' '):
+            p = 'C-%s'%(chr(ord(c)+96),)
+        elif ord(' ') <= ord(c) <= ord('~'):
+            p = c
+        else:
+            p = '\\%03o'%(ord(c),)
+        return [p] + _unparse_keyf(r)
+
+def unparse_keyf(keyseq):
+    return " ".join(_unparse_keyf(keyseq))
diff --git a/lib_pypy/pyrepl/python_reader.py b/lib_pypy/pyrepl/python_reader.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/python_reader.py
@@ -0,0 +1,392 @@
+#   Copyright 2000-2007 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Bob Ippolito
+#                       Maciek Fijalkowski
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# one impressive collections of imports:
+from pyrepl.completing_reader import CompletingReader
+from pyrepl.historical_reader import HistoricalReader
+from pyrepl import completing_reader, reader
+from pyrepl import copy_code, commands, completer
+from pyrepl import module_lister
+import new, sys, os, re, code, traceback
+import atexit, warnings
+try:
+    import cPickle as pickle
+except ImportError:
+    import pickle
+try:
+    import imp
+    imp.find_module("twisted")
+    from twisted.internet import reactor
+    from twisted.internet.abstract import FileDescriptor
+except ImportError:
+    default_interactmethod = "interact"
+else:
+    default_interactmethod = "twistedinteract"
+
+CommandCompiler = code.CommandCompiler
+
+def eat_it(*args):
+    """this function eats warnings, if you were wondering"""
+    pass
+
+class maybe_accept(commands.Command):
+    def do(self):
+        r = self.reader
+        text = r.get_unicode()
+        try:
+            # ooh, look at the hack:
+            code = r.compiler("#coding:utf-8\n"+text.encode('utf-8'))
+        except (OverflowError, SyntaxError, ValueError):
+            self.finish = 1
+        else:
+            if code is None:
+                r.insert("\n")
+            else:
+                self.finish = 1
+
+from_line_prog = re.compile(
+    "^from\s+(?P<mod>[A-Za-z_.0-9]*)\s+import\s+(?P<name>[A-Za-z_.0-9]*)")
+import_line_prog = re.compile(
+    "^(?:import|from)\s+(?P<mod>[A-Za-z_.0-9]*)\s*$")
+
+def mk_saver(reader):
+    def saver(reader=reader):
+        try:
+            file = open(os.path.expanduser("~/.pythoni.hist"), "w")
+        except IOError:
+            pass
+        else:
+            pickle.dump(reader.history, file)
+            file.close()
+    return saver
+
+class PythonicReader(CompletingReader, HistoricalReader):
+    def collect_keymap(self):
+        return super(PythonicReader, self).collect_keymap() + (
+            (r'\n', 'maybe-accept'),
+            (r'\M-\n', 'insert-nl'))
+    
+    def __init__(self, console, locals,
+                 compiler=None):
+        super(PythonicReader, self).__init__(console)
+        self.completer = completer.Completer(locals)
+        st = self.syntax_table
+        for c in "._0123456789":
+            st[c] = reader.SYNTAX_WORD
+        self.locals = locals
+        if compiler is None:
+            self.compiler = CommandCompiler()
+        else:
+            self.compiler = compiler
+        try:
+            file = open(os.path.expanduser("~/.pythoni.hist"))
+        except IOError:
+            pass
+        else:
+            try:
+                self.history = pickle.load(file)
+            except:
+                self.history = []
+            self.historyi = len(self.history)
+            file.close()
+        atexit.register(mk_saver(self))
+        for c in [maybe_accept]:
+            self.commands[c.__name__] = c
+            self.commands[c.__name__.replace('_', '-')] = c        
+    
+    def get_completions(self, stem):
+        b = self.get_unicode()
+        m = import_line_prog.match(b)
+        if m:
+            if not self._module_list_ready:
+                module_lister._make_module_list()
+                self._module_list_ready = True
+
+            mod = m.group("mod")
+            try:
+                return module_lister.find_modules(mod)
+            except ImportError:
+                pass
+        m = from_line_prog.match(b)
+        if m:
+            mod, name = m.group("mod", "name")
+            try:
+                l = module_lister._packages[mod]
+            except KeyError:
+                try:
+                    mod = __import__(mod, self.locals, self.locals, [''])
+                    return [x for x in dir(mod) if x.startswith(name)]
+                except ImportError:
+                    pass
+            else:
+                return [x[len(mod) + 1:]
+                        for x in l if x.startswith(mod + '.' + name)]
+        try:
+            l = completing_reader.uniqify(self.completer.complete(stem))
+            return l
+        except (NameError, AttributeError):
+            return []
+
+class ReaderConsole(code.InteractiveInterpreter):
+    II_init = code.InteractiveInterpreter.__init__
+    def __init__(self, console, locals=None):
+        if locals is None:
+            locals = {}
+        self.II_init(locals)
+        self.compiler = CommandCompiler()
+        self.compile = self.compiler.compiler
+        self.reader = PythonicReader(console, locals, self.compiler)
+        locals['Reader'] = self.reader
+
+    def run_user_init_file(self):
+        for key in "PYREPLSTARTUP", "PYTHONSTARTUP":
+            initfile = os.environ.get(key)
+            if initfile is not None and os.path.exists(initfile):
+                break
+        else:
+            return
+        try:
+            execfile(initfile, self.locals, self.locals)
+        except:
+            etype, value, tb = sys.exc_info()
+            traceback.print_exception(etype, value, tb.tb_next)
+
+    def execute(self, text):
+        try:
+            # ooh, look at the hack:            
+            code = self.compile("# coding:utf8\n"+text.encode('utf-8'),
+                                '<input>', 'single')
+        except (OverflowError, SyntaxError, ValueError):
+            self.showsyntaxerror("<input>")
+        else:
+            self.runcode(code)
+            sys.stdout.flush()
+
+    def interact(self):
+        while 1:
+            try: # catches EOFError's and KeyboardInterrupts during execution
+                try: # catches KeyboardInterrupts during editing
+                    try: # warning saver
+                        # can't have warnings spewed onto terminal
+                        sv = warnings.showwarning
+                        warnings.showwarning = eat_it
+                        l = unicode(self.reader.readline(), 'utf-8')
+                    finally:
+                        warnings.showwarning = sv
+                except KeyboardInterrupt:
+                    print "KeyboardInterrupt"
+                else:
+                    if l:
+                        self.execute(l)
+            except EOFError:
+                break
+            except KeyboardInterrupt:
+                continue
+
+    def prepare(self):
+        self.sv_sw = warnings.showwarning
+        warnings.showwarning = eat_it
+        self.reader.prepare()
+        self.reader.refresh() # we want :after methods...
+
+    def restore(self):
+        self.reader.restore()
+        warnings.showwarning = self.sv_sw
+
+    def handle1(self, block=1):
+        try:
+            r = 1
+            r = self.reader.handle1(block)
+        except KeyboardInterrupt:
+            self.restore()
+            print "KeyboardInterrupt"
+            self.prepare()
+        else:
+            if self.reader.finished:
+                text = self.reader.get_unicode()
+                self.restore()
+                if text:
+                    self.execute(text)
+                self.prepare()
+        return r
+
+    def tkfilehandler(self, file, mask):
+        try:
+            self.handle1(block=0)
+        except:
+            self.exc_info = sys.exc_info()
+
+    # how the <expletive> do you get this to work on Windows (without
+    # createfilehandler)?  threads, I guess
+    def really_tkinteract(self):
+        import _tkinter
+        _tkinter.createfilehandler(
+            self.reader.console.input_fd, _tkinter.READABLE,
+            self.tkfilehandler)
+        
+        self.exc_info = None
+        while 1:
+            # dooneevent will return 0 without blocking if there are
+            # no Tk windows, 1 after blocking until an event otherwise
+            # so the following does what we want (this wasn't expected
+            # to be obvious).
+            if not _tkinter.dooneevent(_tkinter.ALL_EVENTS):
+                self.handle1(block=1)
+            if self.exc_info:
+                type, value, tb = self.exc_info
+                self.exc_info = None
+                raise type, value, tb
+        
+    def tkinteract(self):
+        """Run a Tk-aware Python interactive session.
+
+        This function simulates the Python top-level in a way that
+        allows Tk's mainloop to run."""
+        
+        # attempting to understand the control flow of this function
+        # without help may cause internal injuries.  so, some
+        # explanation.
+
+        # The outer while loop is there to restart the interaction if
+        # the user types control-c when execution is deep in our
+        # innards.  I'm not sure this can't leave internals in an
+        # inconsistent state, but it's a good start.
+
+        # then the inside loop keeps calling self.handle1 until
+        # _tkinter gets imported; then control shifts to
+        # self.really_tkinteract, above.
+
+        # this function can only return via an exception; we mask
+        # EOFErrors (but they end the interaction) and
+        # KeyboardInterrupts cause a restart.  All other exceptions
+        # are likely bugs in pyrepl (well, 'cept for SystemExit, of
+        # course).
+        
+        while 1:
+            try:
+                try:
+                    self.prepare()
+                    try:
+                        while 1:
+                            if sys.modules.has_key("_tkinter"):
+                                self.really_tkinteract()
+                                # really_tkinteract is not expected to
+                                # return except via an exception, but:
+                                break
+                            self.handle1()
+                    except EOFError:
+                        pass
+                finally:
+                    self.restore()
+            except KeyboardInterrupt:
+                continue
+            else:
+                break
+
+    def twistedinteract(self):
+        from twisted.internet import reactor
+        from twisted.internet.abstract import FileDescriptor
+        import signal
+        outerself = self
+        class Me(FileDescriptor):
+            def fileno(self):
+                """ We want to select on FD 0 """
+                return 0
+
+            def doRead(self):
+                """called when input is ready"""
+                try:
+                    outerself.handle1()
+                except EOFError:
+                    reactor.stop()
+
+        reactor.addReader(Me())
+        reactor.callWhenRunning(signal.signal,
+                                signal.SIGINT,
+                                signal.default_int_handler)
+        self.prepare()
+        try:
+            reactor.run()
+        finally:
+            self.restore()
+        
+
+    def cocoainteract(self, inputfilehandle=None, outputfilehandle=None):
+        # only call this when there's a run loop already going!
+        # note that unlike the other *interact methods, this returns immediately
+        from cocoasupport import CocoaInteracter
+        self.cocoainteracter = CocoaInteracter.alloc().init(self, inputfilehandle, outputfilehandle)
+        
+        
+def main(use_pygame_console=0, interactmethod=default_interactmethod, print_banner=True, clear_main=True):
+    si, se, so = sys.stdin, sys.stderr, sys.stdout
+    try:
+        if 0 and use_pygame_console: # pygame currently borked
+            from pyrepl.pygame_console import PyGameConsole, FakeStdin, FakeStdout
+            con = PyGameConsole()
+            sys.stderr = sys.stdout = FakeStdout(con)
+            sys.stdin = FakeStdin(con)
+        else:
+            from pyrepl.unix_console import UnixConsole
+            try:
+                import locale
+            except ImportError:
+                encoding = None
+            else:
+                if hasattr(locale, 'nl_langinfo') \
+                       and hasattr(locale, 'CODESET'):
+                    encoding = locale.nl_langinfo(locale.CODESET)
+                elif os.environ.get('TERM_PROGRAM') == 'Apple_Terminal':
+                    # /me whistles innocently...
+                    code = int(os.popen(
+                        "defaults read com.apple.Terminal StringEncoding"
+                        ).read())
+                    if code == 4:
+                        encoding = 'utf-8'
+                        # More could go here -- and what's here isn't
+                        # bulletproof.  What would be?  AppleScript?
+                        # Doesn't seem to be possible.
+                    else:
+                        encoding = None
+                else:
+                    encoding = None # so you get ASCII...
+            con = UnixConsole(0, 1, None, encoding)
+        if print_banner:
+            print "Python", sys.version, "on", sys.platform
+            print 'Type "help", "copyright", "credits" or "license" '\
+                  'for more information.'
+        sys.path.insert(0, os.getcwd())
+
+        if clear_main and __name__ != '__main__':
+            mainmod = new.module('__main__')
+            sys.modules['__main__'] = mainmod
+        else:
+            mainmod = sys.modules['__main__']
+
+        rc = ReaderConsole(con, mainmod.__dict__)
+        rc.reader._module_list_ready = False
+        rc.run_user_init_file()
+        getattr(rc, interactmethod)()
+    finally:
+        sys.stdin, sys.stderr, sys.stdout = si, se, so
+
+if __name__ == '__main__':
+    main()
diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/reader.py
@@ -0,0 +1,614 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Antonio Cuni
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import types
+from pyrepl import unicodedata_
+from pyrepl import commands
+from pyrepl import input
+
+def _make_unctrl_map():
+    uc_map = {}
+    for c in map(unichr, range(256)):
+        if unicodedata_.category(c)[0] <> 'C':
+            uc_map[c] = c
+    for i in range(32):
+        c = unichr(i)
+        uc_map[c] = u'^' + unichr(ord('A') + i - 1)
+    uc_map['\t'] = '    ' # display TABs as 4 characters
+    uc_map['\177'] = u'^?'
+    for i in range(256):
+        c = unichr(i)
+        if not uc_map.has_key(c):
+            uc_map[c] = u'\\%03o'%i 
+    return uc_map
+
+# disp_str proved to be a bottleneck for large inputs, so it's been
+# rewritten in C; it's not required though.
+try:
+    raise ImportError # currently it's borked by the unicode support
+    
+    from _pyrepl_utils import disp_str, init_unctrl_map
+    
+    init_unctrl_map(_make_unctrl_map())
+
+    del init_unctrl_map
+except ImportError:
+    def _my_unctrl(c, u=_make_unctrl_map()):
+        if c in u:
+            return u[c]
+        else:
+            if unicodedata_.category(c).startswith('C'):
+                return '\u%04x'%(ord(c),)
+            else:
+                return c
+
+    def disp_str(buffer, join=''.join, uc=_my_unctrl):
+        """ disp_str(buffer:string) -> (string, [int])
+
+        Return the string that should be the printed represenation of
+        |buffer| and a list detailing where the characters of |buffer|
+        get used up.  E.g.:
+
+        >>> disp_str(chr(3))
+        ('^C', [1, 0])
+
+        the list always contains 0s or 1s at present; it could conceivably
+        go higher as and when unicode support happens."""
+        s = map(uc, buffer)
+        return (join(s),
+                map(ord, join(map(lambda x:'\001'+(len(x)-1)*'\000', s))))
+
+    del _my_unctrl
+
+del _make_unctrl_map
+
+# syntax classes:
+
+[SYNTAX_WHITESPACE,
+ SYNTAX_WORD,
+ SYNTAX_SYMBOL] = range(3)
+
+def make_default_syntax_table():
+    # XXX perhaps should use some unicodedata here?
+    st = {}
+    for c in map(unichr, range(256)):
+        st[c] = SYNTAX_SYMBOL
+    for c in [a for a in map(unichr, range(256)) if a.isalpha()]:
+        st[c] = SYNTAX_WORD
+    st[u'\n'] = st[u' '] = SYNTAX_WHITESPACE
+    return st
+
+default_keymap = tuple(
+    [(r'\C-a', 'beginning-of-line'),
+     (r'\C-b', 'left'),
+     (r'\C-c', 'interrupt'),
+     (r'\C-d', 'delete'),
+     (r'\C-e', 'end-of-line'),
+     (r'\C-f', 'right'),
+     (r'\C-g', 'cancel'),
+     (r'\C-h', 'backspace'),
+     (r'\C-j', 'accept'),
+     (r'\<return>', 'accept'),
+     (r'\C-k', 'kill-line'),
+     (r'\C-l', 'clear-screen'),
+     (r'\C-m', 'accept'),
+     (r'\C-q', 'quoted-insert'),
+     (r'\C-t', 'transpose-characters'),
+     (r'\C-u', 'unix-line-discard'),
+     (r'\C-v', 'quoted-insert'),
+     (r'\C-w', 'unix-word-rubout'),
+     (r'\C-x\C-u', 'upcase-region'),
+     (r'\C-y', 'yank'),
+     (r'\C-z', 'suspend'),
+     
+     (r'\M-b', 'backward-word'),
+     (r'\M-c', 'capitalize-word'),
+     (r'\M-d', 'kill-word'),
+     (r'\M-f', 'forward-word'),
+     (r'\M-l', 'downcase-word'),
+     (r'\M-t', 'transpose-words'),
+     (r'\M-u', 'upcase-word'),
+     (r'\M-y', 'yank-pop'),
+     (r'\M--', 'digit-arg'),
+     (r'\M-0', 'digit-arg'),
+     (r'\M-1', 'digit-arg'),
+     (r'\M-2', 'digit-arg'),
+     (r'\M-3', 'digit-arg'),
+     (r'\M-4', 'digit-arg'),
+     (r'\M-5', 'digit-arg'),
+     (r'\M-6', 'digit-arg'),
+     (r'\M-7', 'digit-arg'),
+     (r'\M-8', 'digit-arg'),
+     (r'\M-9', 'digit-arg'),
+     #(r'\M-\n', 'insert-nl'),
+     ('\\\\', 'self-insert')] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(32, 127)) if c <> '\\'] + \
+    [(c, 'self-insert')
+     for c in map(chr, range(128, 256)) if c.isalpha()] + \
+    [(r'\<up>', 'up'),
+     (r'\<down>', 'down'),
+     (r'\<left>', 'left'),
+     (r'\<right>', 'right'),
+     (r'\<insert>', 'quoted-insert'),
+     (r'\<delete>', 'delete'),
+     (r'\<backspace>', 'backspace'),
+     (r'\M-\<backspace>', 'backward-kill-word'),
+     (r'\<end>', 'end'),
+     (r'\<home>', 'home'),
+     (r'\<f1>', 'help'),
+     (r'\EOF', 'end'),  # the entries in the terminfo database for xterms
+     (r'\EOH', 'home'), # seem to be wrong.  this is a less than ideal
+                        # workaround
+     ])
+
+del c # from the listcomps
+
+class Reader(object):
+    """The Reader class implements the bare bones of a command reader,
+    handling such details as editing and cursor motion.  What it does
+    not support are such things as completion or history support -
+    these are implemented elsewhere.
+
+    Instance variables of note include:
+
+      * buffer:
+        A *list* (*not* a string at the moment :-) containing all the
+        characters that have been entered.
+      * console:
+        Hopefully encapsulates the OS dependent stuff.
+      * pos:
+        A 0-based index into `buffer' for where the insertion point
+        is.
+      * screeninfo:
+        Ahem.  This list contains some info needed to move the
+        insertion point around reasonably efficiently.  I'd like to
+        get rid of it, because its contents are obtuse (to put it
+        mildly) but I haven't worked out if that is possible yet.
+      * cxy, lxy:
+        the position of the insertion point in screen ... XXX
+      * syntax_table:
+        Dictionary mapping characters to `syntax class'; read the
+        emacs docs to see what this means :-)
+      * commands:
+        Dictionary mapping command names to command classes.
+      * arg:
+        The emacs-style prefix argument.  It will be None if no such
+        argument has been provided.
+      * dirty:
+        True if we need to refresh the display.
+      * kill_ring:
+        The emacs-style kill-ring; manipulated with yank & yank-pop
+      * ps1, ps2, ps3, ps4:
+        prompts.  ps1 is the prompt for a one-line input; for a
+        multiline input it looks like:
+            ps2> first line of input goes here
+            ps3> second and further
+            ps3> lines get ps3
+            ...
+            ps4> and the last one gets ps4
+        As with the usual top-level, you can set these to instances if
+        you like; str() will be called on them (once) at the beginning
+        of each command.  Don't put really long or newline containing
+        strings here, please!
+        This is just the default policy; you can change it freely by
+        overriding get_prompt() (and indeed some standard subclasses
+        do).
+      * finished:
+        handle1 will set this to a true value if a command signals
+        that we're done.
+    """
+
+    help_text = """\
+This is pyrepl.  Hear my roar.
+
+Helpful text may appear here at some point in the future when I'm
+feeling more loquacious than I am now."""
+
+    msg_at_bottom = True
+
+    def __init__(self, console):
+        self.buffer = []
+        self.ps1 = "->> "
+        self.ps2 = "/>> "
+        self.ps3 = "|.. "
+        self.ps4 = "\__ "
+        self.kill_ring = []
+        self.arg = None
+        self.finished = 0
+        self.console = console
+        self.commands = {}
+        self.msg = ''
+        for v in vars(commands).values():
+            if  ( isinstance(v, type)
+                  and issubclass(v, commands.Command)
+                  and v.__name__[0].islower() ):
+                self.commands[v.__name__] = v
+                self.commands[v.__name__.replace('_', '-')] = v
+        self.syntax_table = make_default_syntax_table()
+        self.input_trans_stack = []
+        self.keymap = self.collect_keymap()
+        self.input_trans = input.KeymapTranslator(
+            self.keymap,
+            invalid_cls='invalid-key',
+            character_cls='self-insert')
+
+    def collect_keymap(self):
+        return default_keymap
+
+    def calc_screen(self):
+        """The purpose of this method is to translate changes in
+        self.buffer into changes in self.screen.  Currently it rips
+        everything down and starts from scratch, which whilst not
+        especially efficient is certainly simple(r).
+        """
+        lines = self.get_unicode().split("\n")
+        screen = []
+        screeninfo = []
+        w = self.console.width - 1
+        p = self.pos
+        for ln, line in zip(range(len(lines)), lines):
+            ll = len(line)
+            if 0 <= p <= ll:
+                if self.msg and not self.msg_at_bottom:
+                    for mline in self.msg.split("\n"):
+                        screen.append(mline)
+                        screeninfo.append((0, []))
+                self.lxy = p, ln
+            prompt = self.get_prompt(ln, ll >= p >= 0)
+            while '\n' in prompt:
+                pre_prompt, _, prompt = prompt.partition('\n')
+                screen.append(pre_prompt)
+                screeninfo.append((0, []))
+            p -= ll + 1
+            prompt, lp = self.process_prompt(prompt)
+            l, l2 = disp_str(line)
+            wrapcount = (len(l) + lp) / w
+            if wrapcount == 0:
+                screen.append(prompt + l)
+                screeninfo.append((lp, l2+[1]))
+            else:
+                screen.append(prompt + l[:w-lp] + "\\")
+                screeninfo.append((lp, l2[:w-lp]))
+                for i in range(-lp + w, -lp + wrapcount*w, w):
+                    screen.append(l[i:i+w] +  "\\")
+                    screeninfo.append((0, l2[i:i + w]))
+                screen.append(l[wrapcount*w - lp:])
+                screeninfo.append((0, l2[wrapcount*w - lp:]+[1]))
+        self.screeninfo = screeninfo
+        self.cxy = self.pos2xy(self.pos)
+        if self.msg and self.msg_at_bottom:
+            for mline in self.msg.split("\n"):
+                screen.append(mline)
+                screeninfo.append((0, []))
+        return screen
+
+    def process_prompt(self, prompt):
+        """ Process the prompt.
+        
+        This means calculate the length of the prompt. The character \x01
+        and \x02 are used to bracket ANSI control sequences and need to be
+        excluded from the length calculation.  So also a copy of the prompt
+        is returned with these control characters removed.  """
+
+        out_prompt = ''
+        l = len(prompt)
+        pos = 0
+        while True:
+            s = prompt.find('\x01', pos)
+            if s == -1:
+                break
+            e = prompt.find('\x02', s)
+            if e == -1:
+                break
+            # Found start and end brackets, subtract from string length
+            l = l - (e-s+1)
+            out_prompt += prompt[pos:s] + prompt[s+1:e]
+            pos = e+1
+        out_prompt += prompt[pos:]
+        return out_prompt, l
+
+    def bow(self, p=None):
+        """Return the 0-based index of the word break preceding p most
+        immediately.
+
+        p defaults to self.pos; word boundaries are determined using
+        self.syntax_table."""
+        if p is None:
+            p = self.pos
+        st = self.syntax_table
+        b = self.buffer
+        p -= 1
+        while p >= 0 and st.get(b[p], SYNTAX_WORD) <> SYNTAX_WORD:
+            p -= 1
+        while p >= 0 and st.get(b[p], SYNTAX_WORD) == SYNTAX_WORD:
+            p -= 1
+        return p + 1
+
+    def eow(self, p=None):
+        """Return the 0-based index of the word break following p most
+        immediately.
+
+        p defaults to self.pos; word boundaries are determined using
+        self.syntax_table."""
+        if p is None:
+            p = self.pos
+        st = self.syntax_table
+        b = self.buffer
+        while p < len(b) and st.get(b[p], SYNTAX_WORD) <> SYNTAX_WORD:
+            p += 1
+        while p < len(b) and st.get(b[p], SYNTAX_WORD) == SYNTAX_WORD:
+            p += 1
+        return p
+
+    def bol(self, p=None):
+        """Return the 0-based index of the line break preceding p most
+        immediately.
+
+        p defaults to self.pos."""
+        # XXX there are problems here.
+        if p is None:
+            p = self.pos
+        b = self.buffer
+        p -= 1
+        while p >= 0 and b[p] <> '\n':
+            p -= 1
+        return p + 1
+    
+    def eol(self, p=None):
+        """Return the 0-based index of the line break following p most
+        immediately.
+
+        p defaults to self.pos."""
+        if p is None:
+            p = self.pos
+        b = self.buffer
+        while p < len(b) and b[p] <> '\n':
+            p += 1
+        return p
+
+    def get_arg(self, default=1):
+        """Return any prefix argument that the user has supplied,
+        returning `default' if there is None.  `default' defaults
+        (groan) to 1."""
+        if self.arg is None:
+            return default
+        else:
+            return self.arg
+
+    def get_prompt(self, lineno, cursor_on_line):
+        """Return what should be in the left-hand margin for line
+        `lineno'."""
+        if self.arg is not None and cursor_on_line:
+            return "(arg: %s) "%self.arg
+        if "\n" in self.buffer:
+            if lineno == 0:
+                return self._ps2
+            elif lineno == self.buffer.count("\n"):
+                return self._ps4
+            else:
+                return self._ps3
+        else:
+            return self._ps1
+
+    def push_input_trans(self, itrans):
+        self.input_trans_stack.append(self.input_trans)
+        self.input_trans = itrans
+
+    def pop_input_trans(self):
+        self.input_trans = self.input_trans_stack.pop()
+
+    def pos2xy(self, pos):
+        """Return the x, y coordinates of position 'pos'."""
+        # this *is* incomprehensible, yes.
+        y = 0
+        assert 0 <= pos <= len(self.buffer)
+        if pos == len(self.buffer):
+            y = len(self.screeninfo) - 1
+            p, l2 = self.screeninfo[y]
+            return p + len(l2) - 1, y
+        else:
+            for p, l2 in self.screeninfo:
+                l = l2.count(1)
+                if l > pos:
+                    break
+                else:
+                    pos -= l
+                    y += 1
+            c = 0
+            i = 0
+            while c < pos:
+                c += l2[i]
+                i += 1
+            while l2[i] == 0:
+                i += 1
+            return p + i, y
+
+    def insert(self, text):
+        """Insert 'text' at the insertion point."""
+        self.buffer[self.pos:self.pos] = list(text)
+        self.pos += len(text)
+        self.dirty = 1
+
+    def update_cursor(self):
+        """Move the cursor to reflect changes in self.pos"""
+        self.cxy = self.pos2xy(self.pos)
+        self.console.move_cursor(*self.cxy)
+
+    def after_command(self, cmd):
+        """This function is called to allow post command cleanup."""
+        if getattr(cmd, "kills_digit_arg", 1):
+            if self.arg is not None:
+                self.dirty = 1                
+            self.arg = None
+
+    def prepare(self):
+        """Get ready to run.  Call restore when finished.  You must not
+        write to the console in between the calls to prepare and
+        restore."""
+        try:
+            self.console.prepare()
+            self.arg = None
+            self.screeninfo = []
+            self.finished = 0
+            del self.buffer[:]
+            self.pos = 0
+            self.dirty = 1
+            self.last_command = None
+            self._ps1, self._ps2, self._ps3, self._ps4 = \
+                           map(str, [self.ps1, self.ps2, self.ps3, self.ps4])
+        except:
+            self.restore()
+            raise
+
+    def last_command_is(self, klass):
+        if not self.last_command:
+            return 0
+        return issubclass(klass, self.last_command)
+
+    def restore(self):
+        """Clean up after a run."""
+        self.console.restore()
+
+    def finish(self):
+        """Called when a command signals that we're finished."""
+        pass
+
+    def error(self, msg="none"):
+        self.msg = "! " + msg + " "
+        self.dirty = 1
+        self.console.beep()
+
+    def update_screen(self):
+        if self.dirty:
+            self.refresh()
+
+    def refresh(self):
+        """Recalculate and refresh the screen."""
+        # this call sets up self.cxy, so call it first.
+        screen = self.calc_screen()
+        self.console.refresh(screen, self.cxy)
+        self.dirty = 0 # forgot this for a while (blush)
+
+    def do_cmd(self, cmd):
+        #print cmd
+        if isinstance(cmd[0], str):
+            cmd = self.commands.get(cmd[0],
+                                    commands.invalid_command)(self, cmd)
+        elif isinstance(cmd[0], type):
+            cmd = cmd[0](self, cmd)
+
+        cmd.do()
+
+        self.after_command(cmd)
+
+        if self.dirty:
+            self.refresh()
+        else:
+            self.update_cursor()
+
+        if not isinstance(cmd, commands.digit_arg):
+            self.last_command = cmd.__class__
+
+        self.finished = cmd.finish
+        if self.finished:
+            self.console.finish()
+            self.finish()
+
+    def handle1(self, block=1):
+        """Handle a single event.  Wait as long as it takes if block
+        is true (the default), otherwise return None if no event is
+        pending."""
+
+        if self.msg:
+            self.msg = ''
+            self.dirty = 1
+
+        while 1:
+            event = self.console.get_event(block)
+            if not event: # can only happen if we're not blocking
+                return None
+
+            if event.evt == 'key':
+                self.input_trans.push(event)
+            elif event.evt == 'scroll':
+                self.refresh()
+            elif event.evt == 'resize':
+                self.refresh()
+            else:
+                pass
+
+            cmd = self.input_trans.get()
+
+            if cmd is None:
+                if block:
+                    continue
+                else:
+                    return None
+
+            self.do_cmd(cmd)
+            return 1
+
+    def push_char(self, char):
+        self.console.push_char(char)
+        self.handle1(0)
+    
+    def readline(self):
+        """Read a line.  The implementation of this method also shows
+        how to drive Reader if you want more control over the event
+        loop."""
+        self.prepare()
+        try:
+            self.refresh()
+            while not self.finished:
+                self.handle1()
+            return self.get_buffer()
+        finally:
+            self.restore()
+
+    def bind(self, spec, command):
+        self.keymap = self.keymap + ((spec, command),)
+        self.input_trans = input.KeymapTranslator(
+            self.keymap,
+            invalid_cls='invalid-key',
+            character_cls='self-insert')
+
+    def get_buffer(self, encoding=None):
+        if encoding is None:
+            encoding = self.console.encoding
+        return u''.join(self.buffer).encode(self.console.encoding)
+
+    def get_unicode(self):
+        """Return the current buffer as a unicode string."""
+        return u''.join(self.buffer)
+
+def test():
+    from pyrepl.unix_console import UnixConsole
+    reader = Reader(UnixConsole())
+    reader.ps1 = "**> "
+    reader.ps2 = "/*> "
+    reader.ps3 = "|*> "
+    reader.ps4 = "\*> "
+    while reader.readline():
+        pass
+
+if __name__=='__main__':
+    test()
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/readline.py
@@ -0,0 +1,408 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Alex Gaynor
+#                       Antonio Cuni
+#                       Armin Rigo
+#                       Holger Krekel
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""A compatibility wrapper reimplementing the 'readline' standard module
+on top of pyrepl.  Not all functionalities are supported.  Contains
+extensions for multiline input.
+"""
+
+import sys, os
+from pyrepl import commands
+from pyrepl.historical_reader import HistoricalReader
+from pyrepl.completing_reader import CompletingReader
+from pyrepl.unix_console import UnixConsole, _error
+
+
+ENCODING = 'latin1'     # XXX hard-coded
+
+__all__ = ['add_history',
+           'clear_history',
+           'get_begidx',
+           'get_completer',
+           'get_completer_delims',
+           'get_current_history_length',
+           'get_endidx',
+           'get_history_item',
+           'get_history_length',
+           'get_line_buffer',
+           'insert_text',
+           'parse_and_bind',
+           'read_history_file',
+           'read_init_file',
+           'redisplay',
+           'remove_history_item',
+           'replace_history_item',
+           'set_completer',
+           'set_completer_delims',
+           'set_history_length',
+           'set_pre_input_hook',
+           'set_startup_hook',
+           'write_history_file',
+           # ---- multiline extensions ----
+           'multiline_input',
+           ]
+
+# ____________________________________________________________
+
+class ReadlineConfig(object):
+    readline_completer = None
+    completer_delims = dict.fromkeys(' \t\n`~!@#$%^&*()-=+[{]}\\|;:\'",<>/?')
+
+class ReadlineAlikeReader(HistoricalReader, CompletingReader):
+
+    assume_immutable_completions = False
+    use_brackets = False
+    sort_in_column = True
+
+    def error(self, msg="none"):
+        pass    # don't show error messages by default
+
+    def get_stem(self):
+        b = self.buffer
+        p = self.pos - 1
+        completer_delims = self.config.completer_delims
+        while p >= 0 and b[p] not in completer_delims:
+            p -= 1
+        return ''.join(b[p+1:self.pos])
+
+    def get_completions(self, stem):
+        result = []
+        function = self.config.readline_completer
+        if function is not None:
+            try:
+                stem = str(stem)   # rlcompleter.py seems to not like unicode
+            except UnicodeEncodeError:
+                pass   # but feed unicode anyway if we have no choice
+            state = 0
+            while True:
+                try:
+                    next = function(stem, state)
+                except:
+                    break
+                if not isinstance(next, str):
+                    break
+                result.append(next)
+                state += 1
+            # emulate the behavior of the standard readline that sorts
+            # the completions before displaying them.
+            result.sort()
+        return result
+
+    def get_trimmed_history(self, maxlength):
+        if maxlength >= 0:
+            cut = len(self.history) - maxlength
+            if cut < 0:
+                cut = 0
+        else:
+            cut = 0
+        return self.history[cut:]
+
+    # --- simplified support for reading multiline Python statements ---
+
+    # This duplicates small parts of pyrepl.python_reader.  I'm not
+    # reusing the PythonicReader class directly for two reasons.  One is
+    # to try to keep as close as possible to CPython's prompt.  The
+    # other is that it is the readline module that we are ultimately
+    # implementing here, and I don't want the built-in raw_input() to
+    # start trying to read multiline inputs just because what the user
+    # typed look like valid but incomplete Python code.  So we get the
+    # multiline feature only when using the multiline_input() function
+    # directly (see _pypy_interact.py).
+
+    more_lines = None
+
+    def collect_keymap(self):
+        return super(ReadlineAlikeReader, self).collect_keymap() + (
+            (r'\n', 'maybe-accept'),)
+
+    def __init__(self, console):
+        super(ReadlineAlikeReader, self).__init__(console)
+        self.commands['maybe_accept'] = maybe_accept
+        self.commands['maybe-accept'] = maybe_accept
+
+    def after_command(self, cmd):
+        super(ReadlineAlikeReader, self).after_command(cmd)
+        if self.more_lines is None:
+            # Force single-line input if we are in raw_input() mode.
+            # Although there is no direct way to add a \n in this mode,
+            # multiline buffers can still show up using various
+            # commands, e.g. navigating the history.
+            try:
+                index = self.buffer.index("\n")
+            except ValueError:
+                pass
+            else:
+                self.buffer = self.buffer[:index]
+                if self.pos > len(self.buffer):
+                    self.pos = len(self.buffer)
+
+class maybe_accept(commands.Command):
+    def do(self):
+        r = self.reader
+        r.dirty = 1 # this is needed to hide the completion menu, if visible
+        #
+        # if there are already several lines and the cursor
+        # is not on the last one, always insert a new \n.
+        text = r.get_unicode()
+        if "\n" in r.buffer[r.pos:]:
+            r.insert("\n")
+        elif r.more_lines is not None and r.more_lines(text):
+            r.insert("\n")
+        else:
+            self.finish = 1
+
+# ____________________________________________________________
+
+class _ReadlineWrapper(object):
+    f_in = 0
+    f_out = 1
+    reader = None
+    saved_history_length = -1
+    startup_hook = None
+    config = ReadlineConfig()
+
+    def get_reader(self):
+        if self.reader is None:
+            console = UnixConsole(self.f_in, self.f_out, encoding=ENCODING)
+            self.reader = ReadlineAlikeReader(console)
+            self.reader.config = self.config
+        return self.reader
+
+    def raw_input(self, prompt=''):
+        try:
+            reader = self.get_reader()
+        except _error:
+            return _old_raw_input(prompt)
+        if self.startup_hook is not None:
+            self.startup_hook()
+        reader.ps1 = prompt
+        return reader.readline()
+
+    def multiline_input(self, more_lines, ps1, ps2):
+        """Read an input on possibly multiple lines, asking for more
+        lines as long as 'more_lines(unicodetext)' returns an object whose
+        boolean value is true.
+        """
+        reader = self.get_reader()
+        saved = reader.more_lines
+        try:
+            reader.more_lines = more_lines
+            reader.ps1 = reader.ps2 = ps1
+            reader.ps3 = reader.ps4 = ps2
+            return reader.readline()
+        finally:
+            reader.more_lines = saved
+
+    def parse_and_bind(self, string):
+        pass  # XXX we don't support parsing GNU-readline-style init files
+
+    def set_completer(self, function=None):
+        self.config.readline_completer = function
+
+    def get_completer(self):
+        return self.config.readline_completer
+
+    def set_completer_delims(self, string):
+        self.config.completer_delims = dict.fromkeys(string)
+
+    def get_completer_delims(self):
+        chars = self.config.completer_delims.keys()
+        chars.sort()
+        return ''.join(chars)
+
+    def _histline(self, line):
+        return unicode(line.rstrip('\n'), ENCODING)
+
+    def get_history_length(self):
+        return self.saved_history_length
+
+    def set_history_length(self, length):
+        self.saved_history_length = length
+
+    def get_current_history_length(self):
+        return len(self.get_reader().history)
+
+    def read_history_file(self, filename='~/.history'):
+        # multiline extension (really a hack) for the end of lines that
+        # are actually continuations inside a single multiline_input()
+        # history item: we use \r\n instead of just \n.  If the history
+        # file is passed to GNU readline, the extra \r are just ignored.
+        history = self.get_reader().history
+        f = open(os.path.expanduser(filename), 'r')
+        buffer = []
+        for line in f:
+            if line.endswith('\r\n'):
+                buffer.append(line)
+            else:
+                line = self._histline(line)
+                if buffer:
+                    line = ''.join(buffer).replace('\r', '') + line
+                    del buffer[:]
+                if line:
+                    history.append(line)
+        f.close()
+
+    def write_history_file(self, filename='~/.history'):
+        maxlength = self.saved_history_length
+        history = self.get_reader().get_trimmed_history(maxlength)
+        f = open(os.path.expanduser(filename), 'w')
+        for entry in history:
+            if isinstance(entry, unicode):
+                entry = entry.encode(ENCODING)
+            entry = entry.replace('\n', '\r\n')   # multiline history support
+            f.write(entry + '\n')
+        f.close()
+
+    def clear_history(self):
+        del self.get_reader().history[:]
+
+    def get_history_item(self, index):
+        history = self.get_reader().history
+        if 1 <= index <= len(history):
+            return history[index-1]
+        else:
+            return None        # blame readline.c for not raising
+
+    def remove_history_item(self, index):
+        history = self.get_reader().history
+        if 0 <= index < len(history):
+            del history[index]
+        else:
+            raise ValueError("No history item at position %d" % index)
+            # blame readline.c for raising ValueError
+
+    def replace_history_item(self, index, line):
+        history = self.get_reader().history
+        if 0 <= index < len(history):
+            history[index] = self._histline(line)
+        else:
+            raise ValueError("No history item at position %d" % index)
+            # blame readline.c for raising ValueError
+
+    def add_history(self, line):
+        self.get_reader().history.append(self._histline(line))
+
+    def set_startup_hook(self, function=None):
+        self.startup_hook = function
+
+    def get_line_buffer(self):
+        return self.get_reader().get_buffer()
+
+    def _get_idxs(self):
+        start = cursor = self.get_reader().pos
+        buf = self.get_line_buffer()
+        for i in xrange(cursor - 1, -1, -1):
+            if buf[i] in self.get_completer_delims():
+                break
+            start = i
+        return start, cursor
+
+    def get_begidx(self):
+        return self._get_idxs()[0]
+
+    def get_endidx(self):
+        return self._get_idxs()[1]
+
+    def insert_text(self, text):
+        return self.get_reader().insert(text)
+
+
+_wrapper = _ReadlineWrapper()
+
+# ____________________________________________________________
+# Public API
+
+parse_and_bind = _wrapper.parse_and_bind
+set_completer = _wrapper.set_completer
+get_completer = _wrapper.get_completer
+set_completer_delims = _wrapper.set_completer_delims
+get_completer_delims = _wrapper.get_completer_delims
+get_history_length = _wrapper.get_history_length
+set_history_length = _wrapper.set_history_length
+get_current_history_length = _wrapper.get_current_history_length
+read_history_file = _wrapper.read_history_file
+write_history_file = _wrapper.write_history_file
+clear_history = _wrapper.clear_history
+get_history_item = _wrapper.get_history_item
+remove_history_item = _wrapper.remove_history_item
+replace_history_item = _wrapper.replace_history_item
+add_history = _wrapper.add_history
+set_startup_hook = _wrapper.set_startup_hook
+get_line_buffer = _wrapper.get_line_buffer
+get_begidx = _wrapper.get_begidx
+get_endidx = _wrapper.get_endidx
+insert_text = _wrapper.insert_text
+
+# Extension
+multiline_input = _wrapper.multiline_input
+
+# Internal hook
+_get_reader = _wrapper.get_reader
+
+# ____________________________________________________________
+# Stubs
+
+def _make_stub(_name, _ret):
+    def stub(*args, **kwds):
+        import warnings
+        warnings.warn("readline.%s() not implemented" % _name, stacklevel=2)
+    stub.func_name = _name
+    globals()[_name] = stub
+
+for _name, _ret in [
+    ('read_init_file', None),
+    ('redisplay', None),
+    ('set_pre_input_hook', None),
+    ]:
+    assert _name not in globals(), _name
+    _make_stub(_name, _ret)
+
+# ____________________________________________________________
+
+def _setup():
+    global _old_raw_input
+    if _old_raw_input is not None:
+        return # don't run _setup twice
+    
+    try:
+        f_in = sys.stdin.fileno()
+        f_out = sys.stdout.fileno()
+    except (AttributeError, ValueError):
+        return
+    if not os.isatty(f_in) or not os.isatty(f_out):
+        return
+
+    _wrapper.f_in = f_in
+    _wrapper.f_out = f_out
+
+    if hasattr(sys, '__raw_input__'):    # PyPy
+        _old_raw_input = sys.__raw_input__
+        sys.__raw_input__ = _wrapper.raw_input
+    else:
+        # this is not really what readline.c does.  Better than nothing I guess
+        import __builtin__
+        _old_raw_input = __builtin__.raw_input
+        __builtin__.raw_input = _wrapper.raw_input
+
+_old_raw_input = None
+_setup()
diff --git a/lib_pypy/pyrepl/simple_interact.py b/lib_pypy/pyrepl/simple_interact.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -0,0 +1,64 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""This is an alternative to python_reader which tries to emulate
+the CPython prompt as closely as possible, with the exception of
+allowing multiline input and multiline history entries.
+"""
+
+import sys
+from pyrepl.readline import multiline_input, _error, _get_reader
+
+def check():     # returns False if there is a problem initializing the state
+    try:
+        _get_reader()
+    except _error:
+        return False
+    return True
+
+def run_multiline_interactive_console(mainmodule=None):
+    import code
+    if mainmodule is None:
+        import __main__ as mainmodule
+    console = code.InteractiveConsole(mainmodule.__dict__)
+
+    def more_lines(unicodetext):
+        # ooh, look at the hack:
+        src = "#coding:utf-8\n"+unicodetext.encode('utf-8')
+        try:
+            code = console.compile(src, '<input>', 'single')
+        except (OverflowError, SyntaxError, ValueError):
+            return False
+        else:
+            return code is None
+
+    while 1:
+        try:
+            ps1 = getattr(sys, 'ps1', '>>> ')
+            ps2 = getattr(sys, 'ps2', '... ')
+            try:
+                statement = multiline_input(more_lines, ps1, ps2)
+            except EOFError:
+                break
+            more = console.push(statement)
+            assert not more
+        except KeyboardInterrupt:
+            console.write("\nKeyboardInterrupt\n")
+            console.resetbuffer()
diff --git a/lib_pypy/pyrepl/test/test_functional.py b/lib_pypy/pyrepl/test/test_functional.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/test/test_functional.py
@@ -0,0 +1,50 @@
+#   Copyright 2000-2007 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Maciek Fijalkowski
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# some functional tests, to see if this is really working
+
+import py
+import sys
+
+class TestTerminal(object):
+    def _spawn(self, *args, **kwds):
+        try:
+            import pexpect
+        except ImportError, e:
+            py.test.skip(str(e))
+        kwds.setdefault('timeout', 10)
+        child = pexpect.spawn(*args, **kwds)
+        child.logfile = sys.stdout
+        return child
+
+    def spawn(self, argv=[]):
+        # avoid running start.py, cause it might contain
+        # things like readline or rlcompleter(2) included
+        child = self._spawn(sys.executable, ['-S'] + argv)
+        child.sendline('from pyrepl.python_reader import main')
+        child.sendline('main()')
+        return child
+
+    def test_basic(self):
+        child = self.spawn()
+        child.sendline('a = 3')
+        child.sendline('a')
+        child.expect('3')
+        
diff --git a/lib_pypy/pyrepl/tests/__init__.py b/lib_pypy/pyrepl/tests/__init__.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/__init__.py
@@ -0,0 +1,20 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# moo
diff --git a/lib_pypy/pyrepl/tests/basic.py b/lib_pypy/pyrepl/tests/basic.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/basic.py
@@ -0,0 +1,115 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.console import Event
+from pyrepl.tests.infrastructure import ReaderTestCase, EA, run_testcase
+
+class SimpleTestCase(ReaderTestCase):
+
+    def test_basic(self):
+        self.run_test([(('self-insert', 'a'), ['a']),
+                       ( 'accept',            ['a'])])
+
+    def test_repeat(self):
+        self.run_test([(('digit-arg', '3'),   ['']),
+                       (('self-insert', 'a'), ['aaa']),
+                       ( 'accept',            ['aaa'])])
+
+    def test_kill_line(self):
+        self.run_test([(('self-insert', 'abc'), ['abc']),
+                       ( 'left',                None),
+                       ( 'kill-line',           ['ab']),
+                       ( 'accept',              ['ab'])])
+
+    def test_unix_line_discard(self):
+        self.run_test([(('self-insert', 'abc'), ['abc']),
+                       ( 'left',                None),
+                       ( 'unix-word-rubout',    ['c']),
+                       ( 'accept',              ['c'])])
+
+    def test_kill_word(self):
+        self.run_test([(('self-insert', 'ab cd'), ['ab cd']),
+                       ( 'beginning-of-line',     ['ab cd']),
+                       ( 'kill-word',             [' cd']),
+                       ( 'accept',                [' cd'])])
+
+    def test_backward_kill_word(self):
+        self.run_test([(('self-insert', 'ab cd'), ['ab cd']),
+                       ( 'backward-kill-word',    ['ab ']),
+                       ( 'accept',                ['ab '])])
+
+    def test_yank(self):
+        self.run_test([(('self-insert', 'ab cd'), ['ab cd']),
+                       ( 'backward-kill-word',    ['ab ']),
+                       ( 'beginning-of-line',     ['ab ']),
+                       ( 'yank',                  ['cdab ']),
+                       ( 'accept',                ['cdab '])])
+        
+    def test_yank_pop(self):
+        self.run_test([(('self-insert', 'ab cd'), ['ab cd']),
+                       ( 'backward-kill-word',    ['ab ']),
+                       ( 'left',                  ['ab ']),
+                       ( 'backward-kill-word',    [' ']),
+                       ( 'yank',                  ['ab ']),
+                       ( 'yank-pop',              ['cd ']),
+                       ( 'accept',                ['cd '])])
+
+    def test_interrupt(self):
+        try:
+            self.run_test([( 'interrupt',  [''])])
+        except KeyboardInterrupt:
+            pass
+        else:
+            self.fail('KeyboardInterrupt got lost')
+
+    # test_suspend -- hah
+
+    def test_up(self):
+        self.run_test([(('self-insert', 'ab\ncd'), ['ab', 'cd']),
+                       ( 'up',                     ['ab', 'cd']),
+                       (('self-insert', 'e'),      ['abe', 'cd']),
+                       ( 'accept',                 ['abe', 'cd'])])
+
+    def test_down(self):
+        self.run_test([(('self-insert', 'ab\ncd'), ['ab', 'cd']),
+                       ( 'up',                     ['ab', 'cd']),
+                       (('self-insert', 'e'),      ['abe', 'cd']),
+                       ( 'down',                   ['abe', 'cd']),
+                       (('self-insert', 'f'),      ['abe', 'cdf']),
+                       ( 'accept',                 ['abe', 'cdf'])])
+
+    def test_left(self):
+        self.run_test([(('self-insert', 'ab'), ['ab']),
+                       ( 'left',               ['ab']),
+                       (('self-insert', 'c'),  ['acb']),
+                       ( 'accept',             ['acb'])])
+
+    def test_right(self):
+        self.run_test([(('self-insert', 'ab'), ['ab']),
+                       ( 'left',               ['ab']),
+                       (('self-insert', 'c'),  ['acb']),
+                       ( 'right',              ['acb']),
+                       (('self-insert', 'd'),  ['acbd']),
+                       ( 'accept',             ['acbd'])])
+        
+def test():
+    run_testcase(SimpleTestCase)
+
+if __name__ == '__main__':
+    test()
diff --git a/lib_pypy/pyrepl/tests/bugs.py b/lib_pypy/pyrepl/tests/bugs.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/bugs.py
@@ -0,0 +1,36 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.console import Event
+from pyrepl.tests.infrastructure import ReaderTestCase, EA, run_testcase
+
+# this test case should contain as-verbatim-as-possible versions of
+# (applicable) bug reports
+
+class BugsTestCase(ReaderTestCase):
+
+    def test_transpose_at_start(self):
+        self.run_test([( 'transpose', [EA, '']),
+                       ( 'accept',    [''])])
+
+def test():
+    run_testcase(BugsTestCase)
+
+if __name__ == '__main__':
+    test()
diff --git a/lib_pypy/pyrepl/tests/infrastructure.py b/lib_pypy/pyrepl/tests/infrastructure.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/infrastructure.py
@@ -0,0 +1,82 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.reader import Reader
+from pyrepl.console import Console, Event
+import unittest
+import sys
+
+class EqualsAnything(object):
+    def __eq__(self, other):
+        return True
+EA = EqualsAnything()
+
+class TestConsole(Console):
+    height = 24
+    width = 80
+    encoding = 'utf-8'
+
+    def __init__(self, events, testcase, verbose=False):
+        self.events = events
+        self.next_screen = None
+        self.verbose = verbose
+        self.testcase = testcase
+
+    def refresh(self, screen, xy):
+        if self.next_screen is not None:
+            self.testcase.assertEqual(
+                screen, self.next_screen,
+                "[ %s != %s after %r ]"%(screen, self.next_screen,
+                                         self.last_event_name))
+
+    def get_event(self, block=1):
+        ev, sc = self.events.pop(0)
+        self.next_screen = sc
+        if not isinstance(ev, tuple):
+            ev = (ev,)
+        self.last_event_name = ev[0]
+        if self.verbose:
+            print "event", ev
+        return Event(*ev)
+
+class TestReader(Reader):
+    def get_prompt(self, lineno, cursor_on_line):
+        return ''
+    def refresh(self):
+        Reader.refresh(self)
+        self.dirty = True
+
+class ReaderTestCase(unittest.TestCase):
+    def run_test(self, test_spec, reader_class=TestReader):
+        # remember to finish your test_spec with 'accept' or similar!
+        con = TestConsole(test_spec, self)
+        reader = reader_class(con)
+        reader.readline()
+
+class BasicTestRunner:
+    def run(self, test):
+        result = unittest.TestResult()
+        test(result)
+        return result
+
+def run_testcase(testclass):
+    suite = unittest.makeSuite(testclass)
+    runner = unittest.TextTestRunner(sys.stdout, verbosity=1)
+    result = runner.run(suite)
+    
diff --git a/lib_pypy/pyrepl/tests/wishes.py b/lib_pypy/pyrepl/tests/wishes.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/tests/wishes.py
@@ -0,0 +1,38 @@
+#   Copyright 2000-2004 Michael Hudson-Doyle <micahel at gmail.com>
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from pyrepl.console import Event
+from pyrepl.tests.infrastructure import ReaderTestCase, EA, run_testcase
+
+# this test case should contain as-verbatim-as-possible versions of
+# (applicable) feature requests
+
+class WishesTestCase(ReaderTestCase):
+
+    def test_quoted_insert_repeat(self):
+        self.run_test([(('digit-arg', '3'),      ['']),
+                       ( 'quoted-insert',        ['']),
+                       (('self-insert', '\033'), ['^[^[^[']),
+                       ( 'accept',               None)])
+
+def test():
+    run_testcase(WishesTestCase)
+
+if __name__ == '__main__':
+    test()
diff --git a/lib_pypy/pyrepl/unicodedata_.py b/lib_pypy/pyrepl/unicodedata_.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/unicodedata_.py
@@ -0,0 +1,59 @@
+try:
+    from unicodedata import *
+except ImportError:
+
+    def category(ch):
+        """
+        ASCII only implementation
+        """
+        if type(ch) is not unicode:
+            raise TypeError
+        if len(ch) != 1:
+            raise TypeError
+        return _categories.get(ord(ch), 'Co') # "Other, private use"
+
+    _categories = {
+        0: 'Cc', 1: 'Cc', 2: 'Cc', 3: 'Cc', 4: 'Cc', 5: 'Cc',
+        6: 'Cc', 7: 'Cc', 8: 'Cc', 9: 'Cc', 10: 'Cc', 11: 'Cc',
+        12: 'Cc', 13: 'Cc', 14: 'Cc', 15: 'Cc', 16: 'Cc', 17: 'Cc',
+        18: 'Cc', 19: 'Cc', 20: 'Cc', 21: 'Cc', 22: 'Cc', 23: 'Cc',
+        24: 'Cc', 25: 'Cc', 26: 'Cc', 27: 'Cc', 28: 'Cc', 29: 'Cc',
+        30: 'Cc', 31: 'Cc', 32: 'Zs', 33: 'Po', 34: 'Po', 35: 'Po',
+        36: 'Sc', 37: 'Po', 38: 'Po', 39: 'Po', 40: 'Ps', 41: 'Pe',
+        42: 'Po', 43: 'Sm', 44: 'Po', 45: 'Pd', 46: 'Po', 47: 'Po',
+        48: 'Nd', 49: 'Nd', 50: 'Nd', 51: 'Nd', 52: 'Nd', 53: 'Nd',
+        54: 'Nd', 55: 'Nd', 56: 'Nd', 57: 'Nd', 58: 'Po', 59: 'Po',
+        60: 'Sm', 61: 'Sm', 62: 'Sm', 63: 'Po', 64: 'Po', 65: 'Lu',
+        66: 'Lu', 67: 'Lu', 68: 'Lu', 69: 'Lu', 70: 'Lu', 71: 'Lu',
+        72: 'Lu', 73: 'Lu', 74: 'Lu', 75: 'Lu', 76: 'Lu', 77: 'Lu',
+        78: 'Lu', 79: 'Lu', 80: 'Lu', 81: 'Lu', 82: 'Lu', 83: 'Lu',
+        84: 'Lu', 85: 'Lu', 86: 'Lu', 87: 'Lu', 88: 'Lu', 89: 'Lu',
+        90: 'Lu', 91: 'Ps', 92: 'Po', 93: 'Pe', 94: 'Sk', 95: 'Pc',
+        96: 'Sk', 97: 'Ll', 98: 'Ll', 99: 'Ll', 100: 'Ll', 101: 'Ll',
+        102: 'Ll', 103: 'Ll', 104: 'Ll', 105: 'Ll', 106: 'Ll', 107: 'Ll',
+        108: 'Ll', 109: 'Ll', 110: 'Ll', 111: 'Ll', 112: 'Ll', 113: 'Ll',
+        114: 'Ll', 115: 'Ll', 116: 'Ll', 117: 'Ll', 118: 'Ll', 119: 'Ll',
+        120: 'Ll', 121: 'Ll', 122: 'Ll', 123: 'Ps', 124: 'Sm', 125: 'Pe',
+        126: 'Sm', 127: 'Cc', 128: 'Cc', 129: 'Cc', 130: 'Cc', 131: 'Cc',
+        132: 'Cc', 133: 'Cc', 134: 'Cc', 135: 'Cc', 136: 'Cc', 137: 'Cc',
+        138: 'Cc', 139: 'Cc', 140: 'Cc', 141: 'Cc', 142: 'Cc', 143: 'Cc',
+        144: 'Cc', 145: 'Cc', 146: 'Cc', 147: 'Cc', 148: 'Cc', 149: 'Cc',
+        150: 'Cc', 151: 'Cc', 152: 'Cc', 153: 'Cc', 154: 'Cc', 155: 'Cc',
+        156: 'Cc', 157: 'Cc', 158: 'Cc', 159: 'Cc', 160: 'Zs', 161: 'Po',
+        162: 'Sc', 163: 'Sc', 164: 'Sc', 165: 'Sc', 166: 'So', 167: 'So',
+        168: 'Sk', 169: 'So', 170: 'Ll', 171: 'Pi', 172: 'Sm', 173: 'Cf',
+        174: 'So', 175: 'Sk', 176: 'So', 177: 'Sm', 178: 'No', 179: 'No',
+        180: 'Sk', 181: 'Ll', 182: 'So', 183: 'Po', 184: 'Sk', 185: 'No',
+        186: 'Ll', 187: 'Pf', 188: 'No', 189: 'No', 190: 'No', 191: 'Po',
+        192: 'Lu', 193: 'Lu', 194: 'Lu', 195: 'Lu', 196: 'Lu', 197: 'Lu',
+        198: 'Lu', 199: 'Lu', 200: 'Lu', 201: 'Lu', 202: 'Lu', 203: 'Lu',
+        204: 'Lu', 205: 'Lu', 206: 'Lu', 207: 'Lu', 208: 'Lu', 209: 'Lu',
+        210: 'Lu', 211: 'Lu', 212: 'Lu', 213: 'Lu', 214: 'Lu', 215: 'Sm',
+        216: 'Lu', 217: 'Lu', 218: 'Lu', 219: 'Lu', 220: 'Lu', 221: 'Lu',
+        222: 'Lu', 223: 'Ll', 224: 'Ll', 225: 'Ll', 226: 'Ll', 227: 'Ll',
+        228: 'Ll', 229: 'Ll', 230: 'Ll', 231: 'Ll', 232: 'Ll', 233: 'Ll',
+        234: 'Ll', 235: 'Ll', 236: 'Ll', 237: 'Ll', 238: 'Ll', 239: 'Ll',
+        240: 'Ll', 241: 'Ll', 242: 'Ll', 243: 'Ll', 244: 'Ll', 245: 'Ll',
+        246: 'Ll', 247: 'Sm', 248: 'Ll', 249: 'Ll', 250: 'Ll', 251: 'Ll',
+        252: 'Ll', 253: 'Ll', 254: 'Ll'
+        }
diff --git a/lib_pypy/pyrepl/unix_console.py b/lib_pypy/pyrepl/unix_console.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/unix_console.py
@@ -0,0 +1,567 @@
+#   Copyright 2000-2010 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Antonio Cuni
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import termios, select, os, struct, errno
+import signal, re, time, sys
+from fcntl import ioctl
+from pyrepl import curses
+from pyrepl.fancy_termios import tcgetattr, tcsetattr
+from pyrepl.console import Console, Event
+from pyrepl import unix_eventqueue
+
+class InvalidTerminal(RuntimeError):
+    pass
+
+_error = (termios.error, curses.error, InvalidTerminal)
+
+# there are arguments for changing this to "refresh"
+SIGWINCH_EVENT = 'repaint'
+
+FIONREAD = getattr(termios, "FIONREAD", None)
+TIOCGWINSZ = getattr(termios, "TIOCGWINSZ", None)
+
+def _my_getstr(cap, optional=0):
+    r = curses.tigetstr(cap)
+    if not optional and r is None:
+        raise InvalidTerminal, \
+              "terminal doesn't have the required '%s' capability"%cap
+    return r
+
+# at this point, can we say: AAAAAAAAAAAAAAAAAAAAAARGH!
+def maybe_add_baudrate(dict, rate):
+    name = 'B%d'%rate
+    if hasattr(termios, name):
+        dict[getattr(termios, name)] = rate
+
+ratedict = {}
+for r in [0, 110, 115200, 1200, 134, 150, 1800, 19200, 200, 230400,
+          2400, 300, 38400, 460800, 4800, 50, 57600, 600, 75, 9600]:
+    maybe_add_baudrate(ratedict, r)
+
+del r, maybe_add_baudrate
+
+delayprog = re.compile("\\$<([0-9]+)((?:/|\\*){0,2})>")
+
+try:
+    poll = select.poll
+except AttributeError:
+    # this is exactly the minumum necessary to support what we
+    # do with poll objects
+    class poll:
+        def __init__(self):
+            pass
+        def register(self, fd, flag):
+            self.fd = fd
+        def poll(self, timeout=None):
+            r,w,e = select.select([self.fd],[],[],timeout)
+            return r
+
+POLLIN = getattr(select, "POLLIN", None)
+
+class UnixConsole(Console):
+    def __init__(self, f_in=0, f_out=1, term=None, encoding=None):
+        if encoding is None:
+            encoding = sys.getdefaultencoding()
+            
+        self.encoding = encoding
+
+        if isinstance(f_in, int):
+            self.input_fd = f_in
+        else:
+            self.input_fd = f_in.fileno()
+
+        if isinstance(f_out, int):
+            self.output_fd = f_out
+        else:
+            self.output_fd = f_out.fileno()
+        
+        self.pollob = poll()
+        self.pollob.register(self.input_fd, POLLIN)
+        curses.setupterm(term, self.output_fd)
+        self.term = term
+        
+        self._bel   = _my_getstr("bel")
+        self._civis = _my_getstr("civis", optional=1)
+        self._clear = _my_getstr("clear")
+        self._cnorm = _my_getstr("cnorm", optional=1)
+        self._cub   = _my_getstr("cub",   optional=1)
+        self._cub1  = _my_getstr("cub1",  1)
+        self._cud   = _my_getstr("cud",   1)
+        self._cud1  = _my_getstr("cud1",  1)
+        self._cuf   = _my_getstr("cuf",   1)
+        self._cuf1  = _my_getstr("cuf1",  1)
+        self._cup   = _my_getstr("cup")
+        self._cuu   = _my_getstr("cuu",   1)
+        self._cuu1  = _my_getstr("cuu1",  1)
+        self._dch1  = _my_getstr("dch1",  1)
+        self._dch   = _my_getstr("dch",   1)
+        self._el    = _my_getstr("el")
+        self._hpa   = _my_getstr("hpa",   1)
+        self._ich   = _my_getstr("ich",   1)
+        self._ich1  = _my_getstr("ich1",  1)
+        self._ind   = _my_getstr("ind",   1)
+        self._pad   = _my_getstr("pad",   1)
+        self._ri    = _my_getstr("ri",    1)
+        self._rmkx  = _my_getstr("rmkx",  1)
+        self._smkx  = _my_getstr("smkx",  1)
+        
+        ## work out how we're going to sling the cursor around
+        if 0 and self._hpa: # hpa don't work in windows telnet :-(
+            self.__move_x = self.__move_x_hpa
+        elif self._cub and self._cuf:
+            self.__move_x = self.__move_x_cub_cuf
+        elif self._cub1 and self._cuf1:
+            self.__move_x = self.__move_x_cub1_cuf1
+        else:
+            raise RuntimeError, "insufficient terminal (horizontal)"
+
+        if self._cuu and self._cud:
+            self.__move_y = self.__move_y_cuu_cud
+        elif self._cuu1 and self._cud1:
+            self.__move_y = self.__move_y_cuu1_cud1
+        else:
+            raise RuntimeError, "insufficient terminal (vertical)"
+
+        if self._dch1:
+            self.dch1 = self._dch1
+        elif self._dch:
+            self.dch1 = curses.tparm(self._dch, 1)
+        else:
+            self.dch1 = None
+
+        if self._ich1:
+            self.ich1 = self._ich1
+        elif self._ich:
+            self.ich1 = curses.tparm(self._ich, 1)
+        else:
+            self.ich1 = None
+
+        self.__move = self.__move_short
+
+        self.event_queue = unix_eventqueue.EventQueue(self.input_fd)
+        self.partial_char = ''
+        self.cursor_visible = 1
+
+    def change_encoding(self, encoding):
+        self.encoding = encoding
+    
+    def refresh(self, screen, (cx, cy)):
+        # this function is still too long (over 90 lines)
+
+        if not self.__gone_tall:
+            while len(self.screen) < min(len(screen), self.height):
+                self.__hide_cursor()
+                self.__move(0, len(self.screen) - 1)
+                self.__write("\n")
+                self.__posxy = 0, len(self.screen)
+                self.screen.append("")
+        else:
+            while len(self.screen) < len(screen):
+                self.screen.append("")            
+
+        if len(screen) > self.height:
+            self.__gone_tall = 1
+            self.__move = self.__move_tall
+
+        px, py = self.__posxy
+        old_offset = offset = self.__offset
+        height = self.height
+
+        if 0:
+            global counter
+            try:
+                counter
+            except NameError:
+                counter = 0
+            self.__write_code(curses.tigetstr("setaf"), counter)
+            counter += 1
+            if counter > 8:
+                counter = 0
+
+        # we make sure the cursor is on the screen, and that we're
+        # using all of the screen if we can
+        if cy < offset:
+            offset = cy
+        elif cy >= offset + height:
+            offset = cy - height + 1
+        elif offset > 0 and len(screen) < offset + height:
+            offset = max(len(screen) - height, 0)
+            screen.append("")
+
+        oldscr = self.screen[old_offset:old_offset + height]
+        newscr = screen[offset:offset + height]
+
+        # use hardware scrolling if we have it.
+        if old_offset > offset and self._ri:
+            self.__hide_cursor()
+            self.__write_code(self._cup, 0, 0)
+            self.__posxy = 0, old_offset
+            for i in range(old_offset - offset):
+                self.__write_code(self._ri)
+                oldscr.pop(-1)
+                oldscr.insert(0, "")
+        elif old_offset < offset and self._ind:
+            self.__hide_cursor()
+            self.__write_code(self._cup, self.height - 1, 0)
+            self.__posxy = 0, old_offset + self.height - 1
+            for i in range(offset - old_offset):
+                self.__write_code(self._ind)
+                oldscr.pop(0)
+                oldscr.append("")
+
+        self.__offset = offset
+
+        for y, oldline, newline, in zip(range(offset, offset + height),
+                                        oldscr,
+                                        newscr):
+            if oldline != newline:
+                self.__write_changed_line(y, oldline, newline, px)
+                
+        y = len(newscr)
+        while y < len(oldscr):
+            self.__hide_cursor()
+            self.__move(0, y)
+            self.__posxy = 0, y
+            self.__write_code(self._el)
+            y += 1
+
+        self.__show_cursor()
+        
+        self.screen = screen
+        self.move_cursor(cx, cy)
+        self.flushoutput()
+
+    def __write_changed_line(self, y, oldline, newline, px):
+        # this is frustrating; there's no reason to test (say)
+        # self.dch1 inside the loop -- but alternative ways of
+        # structuring this function are equally painful (I'm trying to
+        # avoid writing code generators these days...)
+        x = 0
+        minlen = min(len(oldline), len(newline))
+        #
+        # reuse the oldline as much as possible, but stop as soon as we
+        # encounter an ESCAPE, because it might be the start of an escape
+        # sequene
+        while x < minlen and oldline[x] == newline[x] and newline[x] != '\x1b':
+            x += 1
+        if oldline[x:] == newline[x+1:] and self.ich1:
+            if ( y == self.__posxy[1] and x > self.__posxy[0]
+                 and oldline[px:x] == newline[px+1:x+1] ):
+                x = px
+            self.__move(x, y)
+            self.__write_code(self.ich1)
+            self.__write(newline[x])
+            self.__posxy = x + 1, y
+        elif x < minlen and oldline[x + 1:] == newline[x + 1:]:
+            self.__move(x, y)
+            self.__write(newline[x])
+            self.__posxy = x + 1, y
+        elif (self.dch1 and self.ich1 and len(newline) == self.width
+              and x < len(newline) - 2
+              and newline[x+1:-1] == oldline[x:-2]):
+            self.__hide_cursor()
+            self.__move(self.width - 2, y)
+            self.__posxy = self.width - 2, y
+            self.__write_code(self.dch1)
+            self.__move(x, y)
+            self.__write_code(self.ich1)
+            self.__write(newline[x])
+            self.__posxy = x + 1, y
+        else:
+            self.__hide_cursor()
+            self.__move(x, y)
+            if len(oldline) > len(newline):
+                self.__write_code(self._el)
+            self.__write(newline[x:])
+            self.__posxy = len(newline), y
+        
+        if '\x1b' in newline:
+            # ANSI escape characters are present, so we can't assume
+            # anything about the position of the cursor.  Moving the cursor
+            # to the left margin should work to get to a known position.
+            self.move_cursor(0, y)
+
+    def __write(self, text):
+        self.__buffer.append((text, 0))
+
+    def __write_code(self, fmt, *args):
+        self.__buffer.append((curses.tparm(fmt, *args), 1))
+
+    def __maybe_write_code(self, fmt, *args):
+        if fmt:
+            self.__write_code(fmt, *args)
+
+    def __move_y_cuu1_cud1(self, y):
+        dy = y - self.__posxy[1]
+        if dy > 0:
+            self.__write_code(dy*self._cud1)
+        elif dy < 0:
+            self.__write_code((-dy)*self._cuu1)
+
+    def __move_y_cuu_cud(self, y):
+        dy = y - self.__posxy[1]
+        if dy > 0:
+            self.__write_code(self._cud, dy)
+        elif dy < 0:
+            self.__write_code(self._cuu, -dy)
+
+    def __move_x_hpa(self, x):
+        if x != self.__posxy[0]:
+            self.__write_code(self._hpa, x)
+
+    def __move_x_cub1_cuf1(self, x):
+        dx = x - self.__posxy[0]
+        if dx > 0:
+            self.__write_code(self._cuf1*dx)
+        elif dx < 0:
+            self.__write_code(self._cub1*(-dx))
+
+    def __move_x_cub_cuf(self, x):
+        dx = x - self.__posxy[0]
+        if dx > 0:
+            self.__write_code(self._cuf, dx)
+        elif dx < 0:
+            self.__write_code(self._cub, -dx)
+
+    def __move_short(self, x, y):
+        self.__move_x(x)
+        self.__move_y(y)
+
+    def __move_tall(self, x, y):
+        assert 0 <= y - self.__offset < self.height, y - self.__offset
+        self.__write_code(self._cup, y - self.__offset, x)
+
+    def move_cursor(self, x, y):
+        if y < self.__offset or y >= self.__offset + self.height:
+            self.event_queue.insert(Event('scroll', None))
+        else:
+            self.__move(x, y)
+            self.__posxy = x, y
+            self.flushoutput()
+
+    def prepare(self):
+        # per-readline preparations:
+        self.__svtermstate = tcgetattr(self.input_fd)
+        raw = self.__svtermstate.copy()
+        raw.iflag &=~ (termios.BRKINT | termios.INPCK |
+                       termios.ISTRIP | termios.IXON)
+        raw.oflag &=~ (termios.OPOST)
+        raw.cflag &=~ (termios.CSIZE|termios.PARENB)
+        raw.cflag |=  (termios.CS8)
+        raw.lflag &=~ (termios.ICANON|termios.ECHO|
+                       termios.IEXTEN|(termios.ISIG*1))
+        raw.cc[termios.VMIN] = 1
+        raw.cc[termios.VTIME] = 0
+        tcsetattr(self.input_fd, termios.TCSADRAIN, raw)
+
+        self.screen = []
+        self.height, self.width = self.getheightwidth()
+
+        self.__buffer = []
+        
+        self.__posxy = 0, 0
+        self.__gone_tall = 0
+        self.__move = self.__move_short
+        self.__offset = 0
+
+        self.__maybe_write_code(self._smkx)
+
+        self.old_sigwinch = signal.signal(
+            signal.SIGWINCH, self.__sigwinch)
+
+    def restore(self):
+        self.__maybe_write_code(self._rmkx)
+        self.flushoutput()
+        tcsetattr(self.input_fd, termios.TCSADRAIN, self.__svtermstate)
+
+        signal.signal(signal.SIGWINCH, self.old_sigwinch)
+
+    def __sigwinch(self, signum, frame):
+        self.height, self.width = self.getheightwidth()
+        self.event_queue.insert(Event('resize', None))
+
+    def push_char(self, char):
+        self.partial_char += char
+        try:
+            c = unicode(self.partial_char, self.encoding)
+        except UnicodeError, e:
+            if len(e.args) > 4 and \
+                   e.args[4] == 'unexpected end of data':
+                pass
+            else:
+                raise
+        else:
+            self.partial_char = ''
+            self.event_queue.push(c)
+        
+    def get_event(self, block=1):
+        while self.event_queue.empty():
+            while 1: # All hail Unix!
+                try:
+                    self.push_char(os.read(self.input_fd, 1))
+                except (IOError, OSError), err:
+                    if err.errno == errno.EINTR:
+                        if not self.event_queue.empty():
+                            return self.event_queue.get()
+                        else:
+                            continue
+                    else:
+                        raise
+                else:
+                    break
+            if not block:
+                break
+        return self.event_queue.get()
+
+    def wait(self):
+        self.pollob.poll()
+
+    def set_cursor_vis(self, vis):
+        if vis:
+            self.__show_cursor()
+        else:
+            self.__hide_cursor()
+
+    def __hide_cursor(self):
+        if self.cursor_visible:
+            self.__maybe_write_code(self._civis)
+            self.cursor_visible = 0
+
+    def __show_cursor(self):
+        if not self.cursor_visible:
+            self.__maybe_write_code(self._cnorm)
+            self.cursor_visible = 1
+
+    def repaint_prep(self):
+        if not self.__gone_tall:
+            self.__posxy = 0, self.__posxy[1]
+            self.__write("\r")
+            ns = len(self.screen)*['\000'*self.width]
+            self.screen = ns
+        else:
+            self.__posxy = 0, self.__offset
+            self.__move(0, self.__offset)
+            ns = self.height*['\000'*self.width]
+            self.screen = ns
+
+    if TIOCGWINSZ:
+        def getheightwidth(self):
+            try:
+                return int(os.environ["LINES"]), int(os.environ["COLUMNS"])
+            except KeyError:
+                height, width = struct.unpack(
+                    "hhhh", ioctl(self.input_fd, TIOCGWINSZ, "\000"*8))[0:2]
+                if not height: return 25, 80
+                return height, width
+    else:
+        def getheightwidth(self):
+            try:
+                return int(os.environ["LINES"]), int(os.environ["COLUMNS"])
+            except KeyError:
+                return 25, 80
+
+    def forgetinput(self):
+        termios.tcflush(self.input_fd, termios.TCIFLUSH)
+
+    def flushoutput(self):
+        for text, iscode in self.__buffer:
+            if iscode:
+                self.__tputs(text)
+            else:
+                os.write(self.output_fd, text.encode(self.encoding))
+        del self.__buffer[:]
+
+    def __tputs(self, fmt, prog=delayprog):
+        """A Python implementation of the curses tputs function; the
+        curses one can't really be wrapped in a sane manner.
+
+        I have the strong suspicion that this is complexity that
+        will never do anyone any good."""
+        # using .get() means that things will blow up
+        # only if the bps is actually needed (which I'm
+        # betting is pretty unlkely)
+        bps = ratedict.get(self.__svtermstate.ospeed)
+        while 1:
+            m = prog.search(fmt)
+            if not m:
+                os.write(self.output_fd, fmt)
+                break
+            x, y = m.span()
+            os.write(self.output_fd, fmt[:x])
+            fmt = fmt[y:]
+            delay = int(m.group(1))
+            if '*' in m.group(2):
+                delay *= self.height
+            if self._pad:
+                nchars = (bps*delay)/1000
+                os.write(self.output_fd, self._pad*nchars)
+            else:
+                time.sleep(float(delay)/1000.0)
+
+    def finish(self):
+        y = len(self.screen) - 1
+        while y >= 0 and not self.screen[y]:
+            y -= 1
+        self.__move(0, min(y, self.height + self.__offset - 1))
+        self.__write("\n\r")
+        self.flushoutput()
+
+    def beep(self):
+        self.__maybe_write_code(self._bel)
+        self.flushoutput()
+
+    if FIONREAD:
+        def getpending(self):
+            e = Event('key', '', '')
+
+            while not self.event_queue.empty():
+                e2 = self.event_queue.get()
+                e.data += e2.data
+                e.raw += e.raw
+                
+            amount = struct.unpack(
+                "i", ioctl(self.input_fd, FIONREAD, "\0\0\0\0"))[0]
+            raw = unicode(os.read(self.input_fd, amount), self.encoding, 'replace')
+            e.data += raw
+            e.raw += raw
+            return e
+    else:
+        def getpending(self):
+            e = Event('key', '', '')
+
+            while not self.event_queue.empty():
+                e2 = self.event_queue.get()
+                e.data += e2.data
+                e.raw += e.raw
+                
+            amount = 10000
+            raw = unicode(os.read(self.input_fd, amount), self.encoding, 'replace')
+            e.data += raw
+            e.raw += raw
+            return e
+
+    def clear(self):
+        self.__write_code(self._clear)
+        self.__gone_tall = 1
+        self.__move = self.__move_tall
+        self.__posxy = 0, 0
+        self.screen = []
+
diff --git a/lib_pypy/pyrepl/unix_eventqueue.py b/lib_pypy/pyrepl/unix_eventqueue.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pyrepl/unix_eventqueue.py
@@ -0,0 +1,86 @@
+#   Copyright 2000-2008 Michael Hudson-Doyle <micahel at gmail.com>
+#                       Armin Rigo
+#
+#                        All Rights Reserved
+#
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose is hereby granted without fee,
+# provided that the above copyright notice appear in all copies and
+# that both that copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
+# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# Bah, this would be easier to test if curses/terminfo didn't have so
+# much non-introspectable global state.
+
+from pyrepl import keymap
+from pyrepl.console import Event
+from pyrepl import curses
+from termios import tcgetattr, VERASE
+import os
+
+_keynames = {
+    "delete" : "kdch1",
+    "down" : "kcud1",
+    "end" : "kend",
+    "enter" : "kent",
+    "f1"  : "kf1",    "f2"  : "kf2",    "f3"  : "kf3",    "f4"  : "kf4",
+    "f5"  : "kf5",    "f6"  : "kf6",    "f7"  : "kf7",    "f8"  : "kf8",
+    "f9"  : "kf9",    "f10" : "kf10",   "f11" : "kf11",   "f12" : "kf12",
+    "f13" : "kf13",   "f14" : "kf14",   "f15" : "kf15",   "f16" : "kf16",
+    "f17" : "kf17",   "f18" : "kf18",   "f19" : "kf19",   "f20" : "kf20",
+    "home" : "khome",
+    "insert" : "kich1",
+    "left" : "kcub1",
+    "page down" : "knp",
+    "page up"   : "kpp",
+    "right" : "kcuf1",
+    "up" : "kcuu1",
+    }
+
+class EventQueue(object):
+    def __init__(self, fd):
+        our_keycodes = {}
+        for key, tiname in _keynames.items():
+            keycode = curses.tigetstr(tiname)
+            if keycode:
+                our_keycodes[keycode] = unicode(key)
+        if os.isatty(fd):
+            our_keycodes[tcgetattr(fd)[6][VERASE]] = u'backspace'
+        self.k = self.ck = keymap.compile_keymap(our_keycodes)
+        self.events = []
+        self.buf = []
+    def get(self):
+        if self.events:
+            return self.events.pop(0)
+        else:
+            return None
+    def empty(self):
+        return not self.events
+    def insert(self, event):
+        self.events.append(event)
+    def push(self, char):
+        if char in self.k:
+            k = self.k[char]
+            if isinstance(k, dict):
+                self.buf.append(char)
+                self.k = k
+            else:
+                self.events.append(Event('key', k, ''.join(self.buf) + char))
+                self.buf = []
+                self.k = self.ck
+        elif self.buf:
+            self.events.extend([Event('key', c, c) for c in self.buf])
+            self.buf = []
+            self.k = self.ck
+            self.push(char)
+        else:
+            self.events.append(Event('key', char, char))
diff --git a/py/_io/terminalwriter.py b/py/_io/terminalwriter.py
--- a/py/_io/terminalwriter.py
+++ b/py/_io/terminalwriter.py
@@ -81,6 +81,9 @@
         oldcolors = GetConsoleInfo(handle).wAttributes
         attr |= (oldcolors & 0x0f0)
         SetConsoleTextAttribute(handle, attr)
+        while len(text) > 32768:
+            file.write(text[:32768])
+            text = text[32768:]
         file.write(text)
         SetConsoleTextAttribute(handle, oldcolors)
     else:
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -3,6 +3,7 @@
 from pypy.interpreter.pycode import cpython_code_signature
 from pypy.interpreter.argument import rawshape
 from pypy.interpreter.argument import ArgErr
+from pypy.interpreter.function import Defaults
 from pypy.tool.sourcetools import valid_identifier
 from pypy.tool.pairtype import extendabletype
 
@@ -15,7 +16,7 @@
     overridden = False
     normalized = False
     modified   = True
-    
+
     def __init__(self, desc):
         self.descs = { desc: True }
         self.calltables = {}  # see calltable_lookup_row()
@@ -172,7 +173,7 @@
 class FunctionDesc(Desc):
     knowntype = types.FunctionType
     overridden = False
-    
+
     def __init__(self, bookkeeper, pyobj=None,
                  name=None, signature=None, defaults=None,
                  specializer=None):
@@ -230,7 +231,7 @@
                     return '_'.join(map(nameof, thing))
                 else:
                     return str(thing)[:30]
-                
+
             if key is not None and alt_name is None:
                 postfix = valid_identifier(nameof(key))
                 alt_name = "%s__%s"%(self.name, postfix)
@@ -250,7 +251,7 @@
             for x in defaults:
                 defs_s.append(self.bookkeeper.immutablevalue(x))
         try:
-            inputcells = args.match_signature(signature, defs_s)
+            inputcells = args.match_signature(signature, Defaults(defs_s))
         except ArgErr, e:
             raise TypeError, "signature mismatch: %s" % e.getmsg(self.name)
         return inputcells
@@ -291,7 +292,7 @@
 
     def bind_under(self, classdef, name):
         # XXX static methods
-        return self.bookkeeper.getmethoddesc(self, 
+        return self.bookkeeper.getmethoddesc(self,
                                              classdef,   # originclassdef,
                                              None,       # selfclassdef
                                              name)
@@ -574,7 +575,7 @@
         while name not in cdesc.classdict:
             cdesc = cdesc.basedesc
             if cdesc is None:
-                return None 
+                return None
         else:
             return cdesc
 
@@ -750,7 +751,7 @@
 class MethodDesc(Desc):
     knowntype = types.MethodType
 
-    def __init__(self, bookkeeper, funcdesc, originclassdef, 
+    def __init__(self, bookkeeper, funcdesc, originclassdef,
                  selfclassdef, name, flags={}):
         super(MethodDesc, self).__init__(bookkeeper)
         self.funcdesc = funcdesc
@@ -803,7 +804,7 @@
         # FunctionDescs, not MethodDescs.  The present method returns the
         # FunctionDesc to use as a key in that family.
         return self.funcdesc
-    
+
     def simplify_desc_set(descs):
         # Some hacking needed to make contains() happy on SomePBC: if the
         # set of MethodDescs contains some "redundant" ones, i.e. ones that
@@ -894,7 +895,7 @@
             return s_ImpossibleValue
         else:
             return self.bookkeeper.immutablevalue(value)
-    
+
     def create_new_attribute(self, name, value):
         try:
             self.read_attribute(name)
@@ -946,7 +947,7 @@
         s_self = SomePBC([self.frozendesc])
         args = args.prepend(s_self)
         return self.funcdesc.pycall(schedule, args, s_previous_result)
-    
+
     def consider_call_site(bookkeeper, family, descs, args, s_result):
         shape = rawshape(args, nextra=1)    # account for the extra 'self'
         funcdescs = [mofdesc.funcdesc for mofdesc in descs]
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -499,10 +499,14 @@
     def getanyitem(str):
         return str.basecharclass()
 
-    def method_split(str, patt): # XXX
+    def method_split(str, patt, max=-1):
         getbookkeeper().count("str_split", str, patt)
         return getbookkeeper().newlist(str.basestringclass())
 
+    def method_rsplit(str, patt, max=-1):
+        getbookkeeper().count("str_rsplit", str, patt)
+        return getbookkeeper().newlist(str.basestringclass())
+
     def method_replace(str, s1, s2):
         return str.basestringclass()
 
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -159,6 +159,11 @@
                cmdline="--allworkingmodules",
                negation=True),
 
+    StrOption("extmodules",
+              "Comma-separated list of third-party builtin modules",
+              cmdline="--ext",
+              default=None),
+
     BoolOption("translationmodules",
           "use only those modules that are needed to run translate.py on pypy",
                default=False,
@@ -356,8 +361,8 @@
         config.objspace.std.suggest(optimized_list_getitem=True)
         config.objspace.std.suggest(getattributeshortcut=True)
         config.objspace.std.suggest(newshortcut=True)
-        if not IS_64_BITS:
-            config.objspace.std.suggest(withsmalllong=True)
+        #if not IS_64_BITS:
+        #    config.objspace.std.suggest(withsmalllong=True)
 
     # extra costly optimizations only go in level 3
     if level == '3':
diff --git a/pypy/config/test/test_pypyoption.py b/pypy/config/test/test_pypyoption.py
--- a/pypy/config/test/test_pypyoption.py
+++ b/pypy/config/test/test_pypyoption.py
@@ -70,6 +70,6 @@
         prefix = descr._name
         c = Config(descr)
         for path in c.getpaths(include_groups=True):
-            fn = prefix + "." + path + ".txt"
+            fn = prefix + "." + path + ".rst"
             yield check_file_exists, fn
 
diff --git a/pypy/doc/Makefile b/pypy/doc/Makefile
new file mode 100644
--- /dev/null
+++ b/pypy/doc/Makefile
@@ -0,0 +1,89 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  dirhtml   to make HTML files named index.html in directories"
+	@echo "  pickle    to make pickle files"
+	@echo "  json      to make JSON files"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  qthelp    to make HTML files and a qthelp project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+	@echo "  doctest   to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyPy.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyPy.qhc"
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/pypy/doc/__pypy__-module.txt b/pypy/doc/__pypy__-module.rst
rename from pypy/doc/__pypy__-module.txt
rename to pypy/doc/__pypy__-module.rst
diff --git a/pypy/doc/_ref.txt b/pypy/doc/_ref.rst
rename from pypy/doc/_ref.txt
rename to pypy/doc/_ref.rst
--- a/pypy/doc/_ref.txt
+++ b/pypy/doc/_ref.rst
@@ -3,48 +3,48 @@
 .. _`lib-python/`: ../../lib-python
 .. _`lib-python/2.5.2/dis.py`: ../../lib-python/2.5.2/dis.py
 .. _`annotation/`:
-.. _`pypy/annotation`: ../../pypy/annotation
-.. _`pypy/annotation/annrpython.py`: ../../pypy/annotation/annrpython.py
-.. _`annotation/binaryop.py`: ../../pypy/annotation/binaryop.py
-.. _`pypy/annotation/builtin.py`: ../../pypy/annotation/builtin.py
-.. _`pypy/annotation/model.py`: ../../pypy/annotation/model.py
-.. _`bin/`: ../../pypy/bin
-.. _`config/`: ../../pypy/config
-.. _`pypy/config/pypyoption.py`: ../../pypy/config/pypyoption.py
-.. _`doc/`: ../../pypy/doc
-.. _`doc/config/`: ../../pypy/doc/config
-.. _`doc/discussion/`: ../../pypy/doc/discussion
+.. _`pypy/annotation`: ../../../../pypy/annotation
+.. _`pypy/annotation/annrpython.py`: ../../../../pypy/annotation/annrpython.py
+.. _`annotation/binaryop.py`: ../../../../pypy/annotation/binaryop.py
+.. _`pypy/annotation/builtin.py`: ../../../../pypy/annotation/builtin.py
+.. _`pypy/annotation/model.py`: ../../../../pypy/annotation/model.py
+.. _`bin/`: ../../../../pypy/bin
+.. _`config/`: ../../../../pypy/config
+.. _`pypy/config/pypyoption.py`: ../../../../pypy/config/pypyoption.py
+.. _`doc/`: ../../../../pypy/doc
+.. _`doc/config/`: ../../../../pypy/doc/config
+.. _`doc/discussion/`: ../../../../pypy/doc/discussion
 .. _`interpreter/`:
-.. _`pypy/interpreter`: ../../pypy/interpreter
-.. _`pypy/interpreter/argument.py`: ../../pypy/interpreter/argument.py
+.. _`pypy/interpreter`: ../../../../pypy/interpreter
+.. _`pypy/interpreter/argument.py`: ../../../../pypy/interpreter/argument.py
 .. _`interpreter/astcompiler/`:
-.. _`pypy/interpreter/astcompiler`: ../../pypy/interpreter/astcompiler
-.. _`pypy/interpreter/executioncontext.py`: ../../pypy/interpreter/executioncontext.py
-.. _`pypy/interpreter/function.py`: ../../pypy/interpreter/function.py
+.. _`pypy/interpreter/astcompiler`: ../../../../pypy/interpreter/astcompiler
+.. _`pypy/interpreter/executioncontext.py`: ../../../../pypy/interpreter/executioncontext.py
+.. _`pypy/interpreter/function.py`: ../../../../pypy/interpreter/function.py
 .. _`interpreter/gateway.py`:
-.. _`pypy/interpreter/gateway.py`: ../../pypy/interpreter/gateway.py
-.. _`pypy/interpreter/generator.py`: ../../pypy/interpreter/generator.py
-.. _`pypy/interpreter/mixedmodule.py`: ../../pypy/interpreter/mixedmodule.py
-.. _`pypy/interpreter/module.py`: ../../pypy/interpreter/module.py
-.. _`pypy/interpreter/nestedscope.py`: ../../pypy/interpreter/nestedscope.py
-.. _`pypy/interpreter/pyopcode.py`: ../../pypy/interpreter/pyopcode.py
+.. _`pypy/interpreter/gateway.py`: ../../../../pypy/interpreter/gateway.py
+.. _`pypy/interpreter/generator.py`: ../../../../pypy/interpreter/generator.py
+.. _`pypy/interpreter/mixedmodule.py`: ../../../../pypy/interpreter/mixedmodule.py
+.. _`pypy/interpreter/module.py`: ../../../../pypy/interpreter/module.py
+.. _`pypy/interpreter/nestedscope.py`: ../../../../pypy/interpreter/nestedscope.py
+.. _`pypy/interpreter/pyopcode.py`: ../../../../pypy/interpreter/pyopcode.py
 .. _`interpreter/pyparser/`:
-.. _`pypy/interpreter/pyparser`: ../../pypy/interpreter/pyparser
-.. _`pypy/interpreter/pyparser/pytokenizer.py`: ../../pypy/interpreter/pyparser/pytokenizer.py
-.. _`pypy/interpreter/pyparser/parser.py`: ../../pypy/interpreter/pyparser/parser.py
-.. _`pypy/interpreter/pyparser/pyparse.py`: ../../pypy/interpreter/pyparser/pyparse.py
-.. _`pypy/interpreter/pyparser/future.py`: ../../pypy/interpreter/pyparser/future.py
-.. _`pypy/interpreter/pyparser/metaparser.py`: ../../pypy/interpreter/pyparser/metaparser.py
-.. _`pypy/interpreter/astcompiler/astbuilder.py`: ../../pypy/interpreter/astcompiler/astbuilder.py
-.. _`pypy/interpreter/astcompiler/optimize.py`: ../../pypy/interpreter/astcompiler/optimize.py
-.. _`pypy/interpreter/astcompiler/codegen.py`: ../../pypy/interpreter/astcompiler/codegen.py
-.. _`pypy/interpreter/astcompiler/tools/asdl_py.py`: ../../pypy/interpreter/astcompiler/tools/asdl_py.py
-.. _`pypy/interpreter/astcompiler/tools/Python.asdl`: ../../pypy/interpreter/astcompiler/tools/Python.asdl
-.. _`pypy/interpreter/astcompiler/assemble.py`: ../../pypy/interpreter/astcompiler/assemble.py
-.. _`pypy/interpreter/astcompiler/symtable.py`: ../../pypy/interpreter/astcompiler/symtable.py
-.. _`pypy/interpreter/astcompiler/asthelpers.py`: ../../pypy/interpreter/astcompiler/asthelpers.py
-.. _`pypy/interpreter/astcompiler/ast.py`: ../../pypy/interpreter/astcompiler/ast.py
-.. _`pypy/interpreter/typedef.py`: ../../pypy/interpreter/typedef.py
+.. _`pypy/interpreter/pyparser`: ../../../../pypy/interpreter/pyparser
+.. _`pypy/interpreter/pyparser/pytokenizer.py`: ../../../../pypy/interpreter/pyparser/pytokenizer.py
+.. _`pypy/interpreter/pyparser/parser.py`: ../../../../pypy/interpreter/pyparser/parser.py
+.. _`pypy/interpreter/pyparser/pyparse.py`: ../../../../pypy/interpreter/pyparser/pyparse.py
+.. _`pypy/interpreter/pyparser/future.py`: ../../../../pypy/interpreter/pyparser/future.py
+.. _`pypy/interpreter/pyparser/metaparser.py`: ../../../../pypy/interpreter/pyparser/metaparser.py
+.. _`pypy/interpreter/astcompiler/astbuilder.py`: ../../../../pypy/interpreter/astcompiler/astbuilder.py
+.. _`pypy/interpreter/astcompiler/optimize.py`: ../../../../pypy/interpreter/astcompiler/optimize.py
+.. _`pypy/interpreter/astcompiler/codegen.py`: ../../../../pypy/interpreter/astcompiler/codegen.py
+.. _`pypy/interpreter/astcompiler/tools/asdl_py.py`: ../../../../pypy/interpreter/astcompiler/tools/asdl_py.py
+.. _`pypy/interpreter/astcompiler/tools/Python.asdl`: ../../../../pypy/interpreter/astcompiler/tools/Python.asdl
+.. _`pypy/interpreter/astcompiler/assemble.py`: ../../../../pypy/interpreter/astcompiler/assemble.py
+.. _`pypy/interpreter/astcompiler/symtable.py`: ../../../../pypy/interpreter/astcompiler/symtable.py
+.. _`pypy/interpreter/astcompiler/asthelpers.py`: ../../../../pypy/interpreter/astcompiler/asthelpers.py
+.. _`pypy/interpreter/astcompiler/ast.py`: ../../../../pypy/interpreter/astcompiler/ast.py
+.. _`pypy/interpreter/typedef.py`: ../../../../pypy/interpreter/typedef.py
 .. _`lib/`:
 .. _`lib_pypy/`: ../../lib_pypy
 .. _`lib/distributed/`: ../../lib_pypy/distributed
@@ -52,56 +52,56 @@
 .. _`lib_pypy/pypy_test/`: ../../lib_pypy/pypy_test
 .. _`module/`:
 .. _`pypy/module`:
-.. _`pypy/module/`: ../../pypy/module
-.. _`pypy/module/__builtin__/__init__.py`: ../../pypy/module/__builtin__/__init__.py
-.. _`pypy/module/_stackless/test/test_clonable.py`: ../../pypy/module/_stackless/test/test_clonable.py
-.. _`pypy/module/_stackless/test/test_composable_coroutine.py`: ../../pypy/module/_stackless/test/test_composable_coroutine.py
+.. _`pypy/module/`: ../../../../pypy/module
+.. _`pypy/module/__builtin__/__init__.py`: ../../../../pypy/module/__builtin__/__init__.py
+.. _`pypy/module/_stackless/test/test_clonable.py`: ../../../../pypy/module/_stackless/test/test_clonable.py
+.. _`pypy/module/_stackless/test/test_composable_coroutine.py`: ../../../../pypy/module/_stackless/test/test_composable_coroutine.py
 .. _`objspace/`:
-.. _`pypy/objspace`: ../../pypy/objspace
-.. _`objspace/dump.py`: ../../pypy/objspace/dump.py
-.. _`objspace/flow/`: ../../pypy/objspace/flow
+.. _`pypy/objspace`: ../../../../pypy/objspace
+.. _`objspace/dump.py`: ../../../../pypy/objspace/dump.py
+.. _`objspace/flow/`: ../../../../pypy/objspace/flow
 .. _`objspace/std/`:
-.. _`pypy/objspace/std`: ../../pypy/objspace/std
-.. _`objspace/taint.py`: ../../pypy/objspace/taint.py
+.. _`pypy/objspace/std`: ../../../../pypy/objspace/std
+.. _`objspace/taint.py`: ../../../../pypy/objspace/taint.py
 .. _`objspace/thunk.py`:
-.. _`pypy/objspace/thunk.py`: ../../pypy/objspace/thunk.py
+.. _`pypy/objspace/thunk.py`: ../../../../pypy/objspace/thunk.py
 .. _`objspace/trace.py`:
-.. _`pypy/objspace/trace.py`: ../../pypy/objspace/trace.py
+.. _`pypy/objspace/trace.py`: ../../../../pypy/objspace/trace.py
 .. _`pypy/rlib`:
-.. _`rlib/`: ../../pypy/rlib
-.. _`pypy/rlib/rarithmetic.py`: ../../pypy/rlib/rarithmetic.py
-.. _`pypy/rlib/test`: ../../pypy/rlib/test
+.. _`rlib/`: ../../../../pypy/rlib
+.. _`pypy/rlib/rarithmetic.py`: ../../../../pypy/rlib/rarithmetic.py
+.. _`pypy/rlib/test`: ../../../../pypy/rlib/test
 .. _`pypy/rpython`:
 .. _`pypy/rpython/`:
-.. _`rpython/`: ../../pypy/rpython
-.. _`rpython/lltypesystem/`: ../../pypy/rpython/lltypesystem
+.. _`rpython/`: ../../../../pypy/rpython
+.. _`rpython/lltypesystem/`: ../../../../pypy/rpython/lltypesystem
 .. _`pypy/rpython/lltypesystem/lltype.py`:
-.. _`rpython/lltypesystem/lltype.py`: ../../pypy/rpython/lltypesystem/lltype.py
-.. _`rpython/memory/`: ../../pypy/rpython/memory
-.. _`rpython/memory/gc/generation.py`: ../../pypy/rpython/memory/gc/generation.py
-.. _`rpython/memory/gc/hybrid.py`: ../../pypy/rpython/memory/gc/hybrid.py
-.. _`rpython/memory/gc/markcompact.py`: ../../pypy/rpython/memory/gc/markcompact.py
-.. _`rpython/memory/gc/marksweep.py`: ../../pypy/rpython/memory/gc/marksweep.py
-.. _`rpython/memory/gc/semispace.py`: ../../pypy/rpython/memory/gc/semispace.py
-.. _`rpython/ootypesystem/`: ../../pypy/rpython/ootypesystem
-.. _`rpython/ootypesystem/ootype.py`: ../../pypy/rpython/ootypesystem/ootype.py
-.. _`rpython/rint.py`: ../../pypy/rpython/rint.py
-.. _`rpython/rlist.py`: ../../pypy/rpython/rlist.py
-.. _`rpython/rmodel.py`: ../../pypy/rpython/rmodel.py
-.. _`pypy/rpython/rtyper.py`: ../../pypy/rpython/rtyper.py
-.. _`pypy/rpython/test/test_llinterp.py`: ../../pypy/rpython/test/test_llinterp.py
-.. _`pypy/test_all.py`: ../../pypy/test_all.py
-.. _`tool/`: ../../pypy/tool
-.. _`tool/algo/`: ../../pypy/tool/algo
-.. _`tool/pytest/`: ../../pypy/tool/pytest
+.. _`rpython/lltypesystem/lltype.py`: ../../../../pypy/rpython/lltypesystem/lltype.py
+.. _`rpython/memory/`: ../../../../pypy/rpython/memory
+.. _`rpython/memory/gc/generation.py`: ../../../../pypy/rpython/memory/gc/generation.py
+.. _`rpython/memory/gc/hybrid.py`: ../../../../pypy/rpython/memory/gc/hybrid.py
+.. _`rpython/memory/gc/markcompact.py`: ../../../../pypy/rpython/memory/gc/markcompact.py
+.. _`rpython/memory/gc/marksweep.py`: ../../../../pypy/rpython/memory/gc/marksweep.py
+.. _`rpython/memory/gc/semispace.py`: ../../../../pypy/rpython/memory/gc/semispace.py
+.. _`rpython/ootypesystem/`: ../../../../pypy/rpython/ootypesystem
+.. _`rpython/ootypesystem/ootype.py`: ../../../../pypy/rpython/ootypesystem/ootype.py
+.. _`rpython/rint.py`: ../../../../pypy/rpython/rint.py
+.. _`rpython/rlist.py`: ../../../../pypy/rpython/rlist.py
+.. _`rpython/rmodel.py`: ../../../../pypy/rpython/rmodel.py
+.. _`pypy/rpython/rtyper.py`: ../../../../pypy/rpython/rtyper.py
+.. _`pypy/rpython/test/test_llinterp.py`: ../../../../pypy/rpython/test/test_llinterp.py
+.. _`pypy/test_all.py`: ../../../../pypy/test_all.py
+.. _`tool/`: ../../../../pypy/tool
+.. _`tool/algo/`: ../../../../pypy/tool/algo
+.. _`tool/pytest/`: ../../../../pypy/tool/pytest
 .. _`pypy/translator`:
-.. _`translator/`: ../../pypy/translator
-.. _`translator/backendopt/`: ../../pypy/translator/backendopt
-.. _`translator/c/`: ../../pypy/translator/c
-.. _`translator/cli/`: ../../pypy/translator/cli
-.. _`translator/goal/`: ../../pypy/translator/goal
-.. _`pypy/translator/goal/targetnopstandalone.py`: ../../pypy/translator/goal/targetnopstandalone.py
-.. _`translator/jvm/`: ../../pypy/translator/jvm
-.. _`translator/stackless/`: ../../pypy/translator/stackless
-.. _`translator/tool/`: ../../pypy/translator/tool
+.. _`translator/`: ../../../../pypy/translator
+.. _`translator/backendopt/`: ../../../../pypy/translator/backendopt
+.. _`translator/c/`: ../../../../pypy/translator/c
+.. _`translator/cli/`: ../../../../pypy/translator/cli
+.. _`translator/goal/`: ../../../../pypy/translator/goal
+.. _`pypy/translator/goal/targetnopstandalone.py`: ../../../../pypy/translator/goal/targetnopstandalone.py
+.. _`translator/jvm/`: ../../../../pypy/translator/jvm
+.. _`translator/stackless/`: ../../../../pypy/translator/stackless
+.. _`translator/tool/`: ../../../../pypy/translator/tool
 .. _`translator/js/`: http://codespeak.net/svn/pypy/branch/oo-jit/pypy/translator/js/
diff --git a/pypy/doc/architecture.txt b/pypy/doc/architecture.rst
rename from pypy/doc/architecture.txt
rename to pypy/doc/architecture.rst
--- a/pypy/doc/architecture.txt
+++ b/pypy/doc/architecture.rst
@@ -1,9 +1,9 @@
 ==================================================
-PyPy - Goals and Architecture Overview 
+Goals and Architecture Overview 
 ==================================================
 
 .. contents::
-.. sectnum::
+
 
 This document gives an overview of the goals and architecture of PyPy.
 See `getting started`_ for a practical introduction and starting points. 
@@ -260,5 +260,5 @@
 .. _`generate Just-In-Time Compilers`: jit/index.html
 .. _`JIT Generation in PyPy`: jit/index.html
 
-.. include:: _ref.txt
+.. include:: _ref.rst
 
diff --git a/pypy/doc/buildtool.txt b/pypy/doc/buildtool.rst
rename from pypy/doc/buildtool.txt
rename to pypy/doc/buildtool.rst
--- a/pypy/doc/buildtool.txt
+++ b/pypy/doc/buildtool.rst
@@ -2,6 +2,8 @@
 PyPyBuilder
 ============
 
+.. include:: crufty.rst
+
 What is this?
 =============
 
diff --git a/pypy/doc/carbonpython.txt b/pypy/doc/carbonpython.rst
rename from pypy/doc/carbonpython.txt
rename to pypy/doc/carbonpython.rst
diff --git a/pypy/doc/cleanup-todo.txt b/pypy/doc/cleanup-todo.rst
rename from pypy/doc/cleanup-todo.txt
rename to pypy/doc/cleanup-todo.rst
diff --git a/pypy/doc/cleanup.rst b/pypy/doc/cleanup.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/cleanup.rst
@@ -0,0 +1,46 @@
+Old documentation that needs review
+-----------------------------------
+
+.. The following stuff is old (and crufty?), and needs further investigation:
+
+.. doc-index: This needs merging somehow
+
+.. svn-help.rst: Needs merging/replacing with hg stuff:
+
+
+.. toctree::
+
+   buildtool.rst
+   distribution.rst
+
+   externaltools.rst
+
+   geninterp.rst
+
+   objspace-proxies.rst
+
+   old_news.rst
+
+   project-ideas.rst
+
+   rffi.rst
+
+   sandbox.rst
+
+   statistic/index.rst
+
+   theory.rst
+
+   translation-aspects.rst
+
+   docindex.rst
+
+   svn-help.rst
+
+   dot-net.rst
+
+   maemo.rst
+
+
+
+
diff --git a/pypy/doc/cli-backend.txt b/pypy/doc/cli-backend.rst
rename from pypy/doc/cli-backend.txt
rename to pypy/doc/cli-backend.rst
diff --git a/pypy/doc/clr-module.txt b/pypy/doc/clr-module.rst
rename from pypy/doc/clr-module.txt
rename to pypy/doc/clr-module.rst
diff --git a/pypy/doc/coding-guide.txt b/pypy/doc/coding-guide.rst
rename from pypy/doc/coding-guide.txt
rename to pypy/doc/coding-guide.rst
--- a/pypy/doc/coding-guide.txt
+++ b/pypy/doc/coding-guide.rst
@@ -1,9 +1,9 @@
 =====================================
-PyPy - Coding Guide
+Coding Guide
 =====================================
 
 .. contents::
-.. sectnum::
+
 
 
 This document describes coding requirements and conventions for
@@ -354,7 +354,7 @@
 silent wrap-around.  Whenever we need more control, we use the following
 helpers (which live the `pypy/rlib/rarithmetic.py`_):
 
-.. _`pypy/rlib/rarithmetic.py`: ../../pypy/rlib/rarithmetic.py
+.. _`pypy/rlib/rarithmetic.py`: ../../../../pypy/rlib/rarithmetic.py
 
 
 **ovfcheck()**
@@ -1085,4 +1085,4 @@
 which will check that remote URLs are reachable.
 
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
new file mode 100644
--- /dev/null
+++ b/pypy/doc/conf.py
@@ -0,0 +1,198 @@
+# -*- coding: utf-8 -*-
+#
+# PyPy documentation build configuration file, created by
+# sphinx-quickstart on Mon Mar 14 10:44:41 2011.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.ifconfig']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'PyPy'
+copyright = u'2011, The PyPy Project'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.5'
+# The full version, including alpha/beta/rc tags.
+release = '1.5-alpha'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'PyPydoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('temp_index', 'PyPy.tex', u'PyPy Documentation',
+   u'The PyPy Project', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}
diff --git a/pypy/doc/config/commandline.txt b/pypy/doc/config/commandline.rst
rename from pypy/doc/config/commandline.txt
rename to pypy/doc/config/commandline.rst
diff --git a/pypy/doc/config/confrest.py b/pypy/doc/config/confrest.py
--- a/pypy/doc/config/confrest.py
+++ b/pypy/doc/config/confrest.py
@@ -7,7 +7,6 @@
 all_optiondescrs = [pypyoption.pypy_optiondescription,
                     translationoption.translation_optiondescription,
                    ]
-
 start_to_descr = dict([(descr._name, descr) for descr in all_optiondescrs])
 
 class PyPyPage(PyPyPage): 
@@ -29,7 +28,7 @@
     Page = PyPyPage 
 
     def get_content(self, txtpath, encoding):
-        if txtpath.basename == "commandline.txt":
+        if txtpath.basename == "commandline.rst":
             result = []
             for line in txtpath.read().splitlines():
                 if line.startswith('.. GENERATE:'):
diff --git a/pypy/doc/config/generate.py b/pypy/doc/config/generate.py
--- a/pypy/doc/config/generate.py
+++ b/pypy/doc/config/generate.py
@@ -8,8 +8,8 @@
 for descr in all_optiondescrs:
     prefix = descr._name
     c = config.Config(descr)
-    thisdir.join(prefix + ".txt").ensure()
+    thisdir.join(prefix + ".rst").ensure()
     for p in c.getpaths(include_groups=True):
-        basename = prefix + "." + p + ".txt"
+        basename = prefix + "." + p + ".rst"
         f = thisdir.join(basename)
         f.ensure()
diff --git a/pypy/doc/config/index.txt b/pypy/doc/config/index.rst
rename from pypy/doc/config/index.txt
rename to pypy/doc/config/index.rst
diff --git a/pypy/doc/config/objspace.allworkingmodules.txt b/pypy/doc/config/objspace.allworkingmodules.rst
rename from pypy/doc/config/objspace.allworkingmodules.txt
rename to pypy/doc/config/objspace.allworkingmodules.rst
diff --git a/pypy/doc/config/objspace.disable_call_speedhacks.txt b/pypy/doc/config/objspace.disable_call_speedhacks.rst
rename from pypy/doc/config/objspace.disable_call_speedhacks.txt
rename to pypy/doc/config/objspace.disable_call_speedhacks.rst
diff --git a/pypy/doc/config/objspace.extmodules.rst b/pypy/doc/config/objspace.extmodules.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.extmodules.rst
@@ -0,0 +1,12 @@
+You can pass a comma-separated list of third-party builtin modules
+which should be translated along with the standard modules within
+``pypy.module``.
+
+The module names need to be fully qualified (i.e. have a ``.`` in them),
+be on the ``$PYTHONPATH`` and not conflict with any existing ones, e.g.
+``mypkg.somemod``.
+
+Once translated, the module will be accessible with a simple::
+
+    import somemod
+
diff --git a/pypy/doc/config/objspace.geninterp.txt b/pypy/doc/config/objspace.geninterp.rst
rename from pypy/doc/config/objspace.geninterp.txt
rename to pypy/doc/config/objspace.geninterp.rst
diff --git a/pypy/doc/config/objspace.honor__builtins__.txt b/pypy/doc/config/objspace.honor__builtins__.rst
rename from pypy/doc/config/objspace.honor__builtins__.txt
rename to pypy/doc/config/objspace.honor__builtins__.rst
diff --git a/pypy/doc/config/objspace.logbytecodes.txt b/pypy/doc/config/objspace.logbytecodes.rst
rename from pypy/doc/config/objspace.logbytecodes.txt
rename to pypy/doc/config/objspace.logbytecodes.rst
diff --git a/pypy/doc/config/objspace.lonepycfiles.txt b/pypy/doc/config/objspace.lonepycfiles.rst
rename from pypy/doc/config/objspace.lonepycfiles.txt
rename to pypy/doc/config/objspace.lonepycfiles.rst
diff --git a/pypy/doc/config/objspace.name.txt b/pypy/doc/config/objspace.name.rst
rename from pypy/doc/config/objspace.name.txt
rename to pypy/doc/config/objspace.name.rst
diff --git a/pypy/doc/config/objspace.nofaking.txt b/pypy/doc/config/objspace.nofaking.rst
rename from pypy/doc/config/objspace.nofaking.txt
rename to pypy/doc/config/objspace.nofaking.rst
diff --git a/pypy/doc/config/objspace.opcodes.CALL_LIKELY_BUILTIN.txt b/pypy/doc/config/objspace.opcodes.CALL_LIKELY_BUILTIN.rst
rename from pypy/doc/config/objspace.opcodes.CALL_LIKELY_BUILTIN.txt
rename to pypy/doc/config/objspace.opcodes.CALL_LIKELY_BUILTIN.rst
diff --git a/pypy/doc/config/objspace.opcodes.CALL_METHOD.txt b/pypy/doc/config/objspace.opcodes.CALL_METHOD.rst
rename from pypy/doc/config/objspace.opcodes.CALL_METHOD.txt
rename to pypy/doc/config/objspace.opcodes.CALL_METHOD.rst
diff --git a/pypy/doc/config/objspace.opcodes.txt b/pypy/doc/config/objspace.opcodes.rst
rename from pypy/doc/config/objspace.opcodes.txt
rename to pypy/doc/config/objspace.opcodes.rst
diff --git a/pypy/doc/config/objspace.txt b/pypy/doc/config/objspace.rst
rename from pypy/doc/config/objspace.txt
rename to pypy/doc/config/objspace.rst
diff --git a/pypy/doc/config/objspace.soabi.txt b/pypy/doc/config/objspace.soabi.rst
rename from pypy/doc/config/objspace.soabi.txt
rename to pypy/doc/config/objspace.soabi.rst
diff --git a/pypy/doc/config/objspace.std.builtinshortcut.txt b/pypy/doc/config/objspace.std.builtinshortcut.rst
rename from pypy/doc/config/objspace.std.builtinshortcut.txt
rename to pypy/doc/config/objspace.std.builtinshortcut.rst
diff --git a/pypy/doc/config/objspace.std.getattributeshortcut.txt b/pypy/doc/config/objspace.std.getattributeshortcut.rst
rename from pypy/doc/config/objspace.std.getattributeshortcut.txt
rename to pypy/doc/config/objspace.std.getattributeshortcut.rst
diff --git a/pypy/doc/config/objspace.std.logspaceoptypes.txt b/pypy/doc/config/objspace.std.logspaceoptypes.rst
rename from pypy/doc/config/objspace.std.logspaceoptypes.txt
rename to pypy/doc/config/objspace.std.logspaceoptypes.rst
diff --git a/pypy/doc/config/objspace.std.methodcachesizeexp.txt b/pypy/doc/config/objspace.std.methodcachesizeexp.rst
rename from pypy/doc/config/objspace.std.methodcachesizeexp.txt
rename to pypy/doc/config/objspace.std.methodcachesizeexp.rst
diff --git a/pypy/doc/config/objspace.std.multimethods.txt b/pypy/doc/config/objspace.std.multimethods.rst
rename from pypy/doc/config/objspace.std.multimethods.txt
rename to pypy/doc/config/objspace.std.multimethods.rst
diff --git a/pypy/doc/config/objspace.std.mutable_builtintypes.txt b/pypy/doc/config/objspace.std.mutable_builtintypes.rst
rename from pypy/doc/config/objspace.std.mutable_builtintypes.txt
rename to pypy/doc/config/objspace.std.mutable_builtintypes.rst
diff --git a/pypy/doc/config/objspace.std.newshortcut.txt b/pypy/doc/config/objspace.std.newshortcut.rst
rename from pypy/doc/config/objspace.std.newshortcut.txt
rename to pypy/doc/config/objspace.std.newshortcut.rst
diff --git a/pypy/doc/config/objspace.std.optimized_comparison_op.txt b/pypy/doc/config/objspace.std.optimized_comparison_op.rst
rename from pypy/doc/config/objspace.std.optimized_comparison_op.txt
rename to pypy/doc/config/objspace.std.optimized_comparison_op.rst
diff --git a/pypy/doc/config/objspace.std.optimized_int_add.txt b/pypy/doc/config/objspace.std.optimized_int_add.rst
rename from pypy/doc/config/objspace.std.optimized_int_add.txt
rename to pypy/doc/config/objspace.std.optimized_int_add.rst
diff --git a/pypy/doc/config/objspace.std.optimized_list_getitem.txt b/pypy/doc/config/objspace.std.optimized_list_getitem.rst
rename from pypy/doc/config/objspace.std.optimized_list_getitem.txt
rename to pypy/doc/config/objspace.std.optimized_list_getitem.rst
diff --git a/pypy/doc/config/objspace.std.prebuiltintfrom.txt b/pypy/doc/config/objspace.std.prebuiltintfrom.rst
rename from pypy/doc/config/objspace.std.prebuiltintfrom.txt
rename to pypy/doc/config/objspace.std.prebuiltintfrom.rst
diff --git a/pypy/doc/config/objspace.std.prebuiltintto.txt b/pypy/doc/config/objspace.std.prebuiltintto.rst
rename from pypy/doc/config/objspace.std.prebuiltintto.txt
rename to pypy/doc/config/objspace.std.prebuiltintto.rst
diff --git a/pypy/doc/config/objspace.std.txt b/pypy/doc/config/objspace.std.rst
rename from pypy/doc/config/objspace.std.txt
rename to pypy/doc/config/objspace.std.rst
diff --git a/pypy/doc/config/objspace.std.sharesmallstr.txt b/pypy/doc/config/objspace.std.sharesmallstr.rst
rename from pypy/doc/config/objspace.std.sharesmallstr.txt
rename to pypy/doc/config/objspace.std.sharesmallstr.rst
diff --git a/pypy/doc/config/objspace.std.withcelldict.txt b/pypy/doc/config/objspace.std.withcelldict.rst
rename from pypy/doc/config/objspace.std.withcelldict.txt
rename to pypy/doc/config/objspace.std.withcelldict.rst
diff --git a/pypy/doc/config/objspace.std.withdictmeasurement.txt b/pypy/doc/config/objspace.std.withdictmeasurement.rst
rename from pypy/doc/config/objspace.std.withdictmeasurement.txt
rename to pypy/doc/config/objspace.std.withdictmeasurement.rst
diff --git a/pypy/doc/config/objspace.std.withmapdict.txt b/pypy/doc/config/objspace.std.withmapdict.rst
rename from pypy/doc/config/objspace.std.withmapdict.txt
rename to pypy/doc/config/objspace.std.withmapdict.rst
diff --git a/pypy/doc/config/objspace.std.withmethodcache.txt b/pypy/doc/config/objspace.std.withmethodcache.rst
rename from pypy/doc/config/objspace.std.withmethodcache.txt
rename to pypy/doc/config/objspace.std.withmethodcache.rst
diff --git a/pypy/doc/config/objspace.std.withmethodcachecounter.txt b/pypy/doc/config/objspace.std.withmethodcachecounter.rst
rename from pypy/doc/config/objspace.std.withmethodcachecounter.txt
rename to pypy/doc/config/objspace.std.withmethodcachecounter.rst
diff --git a/pypy/doc/config/objspace.std.withprebuiltchar.txt b/pypy/doc/config/objspace.std.withprebuiltchar.rst
rename from pypy/doc/config/objspace.std.withprebuiltchar.txt
rename to pypy/doc/config/objspace.std.withprebuiltchar.rst
diff --git a/pypy/doc/config/objspace.std.withprebuiltint.txt b/pypy/doc/config/objspace.std.withprebuiltint.rst
rename from pypy/doc/config/objspace.std.withprebuiltint.txt
rename to pypy/doc/config/objspace.std.withprebuiltint.rst
diff --git a/pypy/doc/config/objspace.std.withrangelist.txt b/pypy/doc/config/objspace.std.withrangelist.rst
rename from pypy/doc/config/objspace.std.withrangelist.txt
rename to pypy/doc/config/objspace.std.withrangelist.rst
diff --git a/pypy/doc/config/objspace.std.withrope.txt b/pypy/doc/config/objspace.std.withrope.rst
rename from pypy/doc/config/objspace.std.withrope.txt
rename to pypy/doc/config/objspace.std.withrope.rst
diff --git a/pypy/doc/config/objspace.std.withropeunicode.txt b/pypy/doc/config/objspace.std.withropeunicode.rst
rename from pypy/doc/config/objspace.std.withropeunicode.txt
rename to pypy/doc/config/objspace.std.withropeunicode.rst
diff --git a/pypy/doc/config/objspace.std.withsmallint.txt b/pypy/doc/config/objspace.std.withsmallint.rst
rename from pypy/doc/config/objspace.std.withsmallint.txt
rename to pypy/doc/config/objspace.std.withsmallint.rst
diff --git a/pypy/doc/config/objspace.std.withsmalllong.txt b/pypy/doc/config/objspace.std.withsmalllong.rst
rename from pypy/doc/config/objspace.std.withsmalllong.txt
rename to pypy/doc/config/objspace.std.withsmalllong.rst
diff --git a/pypy/doc/config/objspace.std.withstrbuf.txt b/pypy/doc/config/objspace.std.withstrbuf.rst
rename from pypy/doc/config/objspace.std.withstrbuf.txt
rename to pypy/doc/config/objspace.std.withstrbuf.rst
diff --git a/pypy/doc/config/objspace.std.withstrjoin.txt b/pypy/doc/config/objspace.std.withstrjoin.rst
rename from pypy/doc/config/objspace.std.withstrjoin.txt
rename to pypy/doc/config/objspace.std.withstrjoin.rst
diff --git a/pypy/doc/config/objspace.std.withstrslice.txt b/pypy/doc/config/objspace.std.withstrslice.rst
rename from pypy/doc/config/objspace.std.withstrslice.txt
rename to pypy/doc/config/objspace.std.withstrslice.rst
diff --git a/pypy/doc/config/objspace.std.withtproxy.txt b/pypy/doc/config/objspace.std.withtproxy.rst
rename from pypy/doc/config/objspace.std.withtproxy.txt
rename to pypy/doc/config/objspace.std.withtproxy.rst
diff --git a/pypy/doc/config/objspace.std.withtypeversion.txt b/pypy/doc/config/objspace.std.withtypeversion.rst
rename from pypy/doc/config/objspace.std.withtypeversion.txt
rename to pypy/doc/config/objspace.std.withtypeversion.rst
diff --git a/pypy/doc/config/objspace.timing.txt b/pypy/doc/config/objspace.timing.rst
rename from pypy/doc/config/objspace.timing.txt
rename to pypy/doc/config/objspace.timing.rst
diff --git a/pypy/doc/config/objspace.translationmodules.txt b/pypy/doc/config/objspace.translationmodules.rst
rename from pypy/doc/config/objspace.translationmodules.txt
rename to pypy/doc/config/objspace.translationmodules.rst
diff --git a/pypy/doc/config/objspace.usemodules.__builtin__.txt b/pypy/doc/config/objspace.usemodules.__builtin__.rst
rename from pypy/doc/config/objspace.usemodules.__builtin__.txt
rename to pypy/doc/config/objspace.usemodules.__builtin__.rst
diff --git a/pypy/doc/config/objspace.usemodules.__pypy__.txt b/pypy/doc/config/objspace.usemodules.__pypy__.rst
rename from pypy/doc/config/objspace.usemodules.__pypy__.txt
rename to pypy/doc/config/objspace.usemodules.__pypy__.rst
diff --git a/pypy/doc/config/objspace.usemodules._ast.txt b/pypy/doc/config/objspace.usemodules._ast.rst
rename from pypy/doc/config/objspace.usemodules._ast.txt
rename to pypy/doc/config/objspace.usemodules._ast.rst
diff --git a/pypy/doc/config/objspace.usemodules._bisect.txt b/pypy/doc/config/objspace.usemodules._bisect.rst
rename from pypy/doc/config/objspace.usemodules._bisect.txt
rename to pypy/doc/config/objspace.usemodules._bisect.rst
diff --git a/pypy/doc/config/objspace.usemodules._codecs.txt b/pypy/doc/config/objspace.usemodules._codecs.rst
rename from pypy/doc/config/objspace.usemodules._codecs.txt
rename to pypy/doc/config/objspace.usemodules._codecs.rst
diff --git a/pypy/doc/config/objspace.usemodules._collections.txt b/pypy/doc/config/objspace.usemodules._collections.rst
rename from pypy/doc/config/objspace.usemodules._collections.txt
rename to pypy/doc/config/objspace.usemodules._collections.rst
diff --git a/pypy/doc/config/objspace.usemodules._demo.txt b/pypy/doc/config/objspace.usemodules._demo.rst
rename from pypy/doc/config/objspace.usemodules._demo.txt
rename to pypy/doc/config/objspace.usemodules._demo.rst
diff --git a/pypy/doc/config/objspace.usemodules._ffi.txt b/pypy/doc/config/objspace.usemodules._ffi.rst
rename from pypy/doc/config/objspace.usemodules._ffi.txt
rename to pypy/doc/config/objspace.usemodules._ffi.rst
diff --git a/pypy/doc/config/objspace.usemodules._file.txt b/pypy/doc/config/objspace.usemodules._file.rst
rename from pypy/doc/config/objspace.usemodules._file.txt
rename to pypy/doc/config/objspace.usemodules._file.rst
diff --git a/pypy/doc/config/objspace.usemodules._hashlib.txt b/pypy/doc/config/objspace.usemodules._hashlib.rst
rename from pypy/doc/config/objspace.usemodules._hashlib.txt
rename to pypy/doc/config/objspace.usemodules._hashlib.rst
diff --git a/pypy/doc/config/objspace.usemodules._io.txt b/pypy/doc/config/objspace.usemodules._io.rst
rename from pypy/doc/config/objspace.usemodules._io.txt
rename to pypy/doc/config/objspace.usemodules._io.rst
diff --git a/pypy/doc/config/objspace.usemodules._locale.txt b/pypy/doc/config/objspace.usemodules._locale.rst
rename from pypy/doc/config/objspace.usemodules._locale.txt
rename to pypy/doc/config/objspace.usemodules._locale.rst
diff --git a/pypy/doc/config/objspace.usemodules._lsprof.txt b/pypy/doc/config/objspace.usemodules._lsprof.rst
rename from pypy/doc/config/objspace.usemodules._lsprof.txt
rename to pypy/doc/config/objspace.usemodules._lsprof.rst
diff --git a/pypy/doc/config/objspace.usemodules._md5.txt b/pypy/doc/config/objspace.usemodules._md5.rst
rename from pypy/doc/config/objspace.usemodules._md5.txt
rename to pypy/doc/config/objspace.usemodules._md5.rst
diff --git a/pypy/doc/config/objspace.usemodules._minimal_curses.txt b/pypy/doc/config/objspace.usemodules._minimal_curses.rst
rename from pypy/doc/config/objspace.usemodules._minimal_curses.txt
rename to pypy/doc/config/objspace.usemodules._minimal_curses.rst
diff --git a/pypy/doc/config/objspace.usemodules._multiprocessing.txt b/pypy/doc/config/objspace.usemodules._multiprocessing.rst
rename from pypy/doc/config/objspace.usemodules._multiprocessing.txt
rename to pypy/doc/config/objspace.usemodules._multiprocessing.rst
diff --git a/pypy/doc/config/objspace.usemodules._pickle_support.txt b/pypy/doc/config/objspace.usemodules._pickle_support.rst
rename from pypy/doc/config/objspace.usemodules._pickle_support.txt
rename to pypy/doc/config/objspace.usemodules._pickle_support.rst
diff --git a/pypy/doc/config/objspace.usemodules._random.txt b/pypy/doc/config/objspace.usemodules._random.rst
rename from pypy/doc/config/objspace.usemodules._random.txt
rename to pypy/doc/config/objspace.usemodules._random.rst
diff --git a/pypy/doc/config/objspace.usemodules._rawffi.txt b/pypy/doc/config/objspace.usemodules._rawffi.rst
rename from pypy/doc/config/objspace.usemodules._rawffi.txt
rename to pypy/doc/config/objspace.usemodules._rawffi.rst
diff --git a/pypy/doc/config/objspace.usemodules._sha.txt b/pypy/doc/config/objspace.usemodules._sha.rst
rename from pypy/doc/config/objspace.usemodules._sha.txt
rename to pypy/doc/config/objspace.usemodules._sha.rst
diff --git a/pypy/doc/config/objspace.usemodules._socket.txt b/pypy/doc/config/objspace.usemodules._socket.rst
rename from pypy/doc/config/objspace.usemodules._socket.txt
rename to pypy/doc/config/objspace.usemodules._socket.rst
diff --git a/pypy/doc/config/objspace.usemodules._sre.txt b/pypy/doc/config/objspace.usemodules._sre.rst
rename from pypy/doc/config/objspace.usemodules._sre.txt
rename to pypy/doc/config/objspace.usemodules._sre.rst
diff --git a/pypy/doc/config/objspace.usemodules._ssl.txt b/pypy/doc/config/objspace.usemodules._ssl.rst
rename from pypy/doc/config/objspace.usemodules._ssl.txt
rename to pypy/doc/config/objspace.usemodules._ssl.rst
diff --git a/pypy/doc/config/objspace.usemodules._stackless.txt b/pypy/doc/config/objspace.usemodules._stackless.rst
rename from pypy/doc/config/objspace.usemodules._stackless.txt
rename to pypy/doc/config/objspace.usemodules._stackless.rst
diff --git a/pypy/doc/config/objspace.usemodules._testing.txt b/pypy/doc/config/objspace.usemodules._testing.rst
rename from pypy/doc/config/objspace.usemodules._testing.txt
rename to pypy/doc/config/objspace.usemodules._testing.rst
diff --git a/pypy/doc/config/objspace.usemodules._warnings.txt b/pypy/doc/config/objspace.usemodules._warnings.rst
rename from pypy/doc/config/objspace.usemodules._warnings.txt
rename to pypy/doc/config/objspace.usemodules._warnings.rst
diff --git a/pypy/doc/config/objspace.usemodules._weakref.txt b/pypy/doc/config/objspace.usemodules._weakref.rst
rename from pypy/doc/config/objspace.usemodules._weakref.txt
rename to pypy/doc/config/objspace.usemodules._weakref.rst
diff --git a/pypy/doc/config/objspace.usemodules._winreg.txt b/pypy/doc/config/objspace.usemodules._winreg.rst
rename from pypy/doc/config/objspace.usemodules._winreg.txt
rename to pypy/doc/config/objspace.usemodules._winreg.rst
diff --git a/pypy/doc/config/objspace.usemodules.array.txt b/pypy/doc/config/objspace.usemodules.array.rst
rename from pypy/doc/config/objspace.usemodules.array.txt
rename to pypy/doc/config/objspace.usemodules.array.rst
diff --git a/pypy/doc/config/objspace.usemodules.binascii.txt b/pypy/doc/config/objspace.usemodules.binascii.rst
rename from pypy/doc/config/objspace.usemodules.binascii.txt
rename to pypy/doc/config/objspace.usemodules.binascii.rst
diff --git a/pypy/doc/config/objspace.usemodules.bz2.txt b/pypy/doc/config/objspace.usemodules.bz2.rst
rename from pypy/doc/config/objspace.usemodules.bz2.txt
rename to pypy/doc/config/objspace.usemodules.bz2.rst
diff --git a/pypy/doc/config/objspace.usemodules.cStringIO.txt b/pypy/doc/config/objspace.usemodules.cStringIO.rst
rename from pypy/doc/config/objspace.usemodules.cStringIO.txt
rename to pypy/doc/config/objspace.usemodules.cStringIO.rst
diff --git a/pypy/doc/config/objspace.usemodules.clr.txt b/pypy/doc/config/objspace.usemodules.clr.rst
rename from pypy/doc/config/objspace.usemodules.clr.txt
rename to pypy/doc/config/objspace.usemodules.clr.rst
diff --git a/pypy/doc/config/objspace.usemodules.cmath.txt b/pypy/doc/config/objspace.usemodules.cmath.rst
rename from pypy/doc/config/objspace.usemodules.cmath.txt
rename to pypy/doc/config/objspace.usemodules.cmath.rst
diff --git a/pypy/doc/config/objspace.usemodules.cpyext.txt b/pypy/doc/config/objspace.usemodules.cpyext.rst
rename from pypy/doc/config/objspace.usemodules.cpyext.txt
rename to pypy/doc/config/objspace.usemodules.cpyext.rst
diff --git a/pypy/doc/config/objspace.usemodules.crypt.txt b/pypy/doc/config/objspace.usemodules.crypt.rst
rename from pypy/doc/config/objspace.usemodules.crypt.txt
rename to pypy/doc/config/objspace.usemodules.crypt.rst
diff --git a/pypy/doc/config/objspace.usemodules.errno.txt b/pypy/doc/config/objspace.usemodules.errno.rst
rename from pypy/doc/config/objspace.usemodules.errno.txt
rename to pypy/doc/config/objspace.usemodules.errno.rst
diff --git a/pypy/doc/config/objspace.usemodules.exceptions.txt b/pypy/doc/config/objspace.usemodules.exceptions.rst
rename from pypy/doc/config/objspace.usemodules.exceptions.txt
rename to pypy/doc/config/objspace.usemodules.exceptions.rst
diff --git a/pypy/doc/config/objspace.usemodules.fcntl.txt b/pypy/doc/config/objspace.usemodules.fcntl.rst
rename from pypy/doc/config/objspace.usemodules.fcntl.txt
rename to pypy/doc/config/objspace.usemodules.fcntl.rst
diff --git a/pypy/doc/config/objspace.usemodules.gc.txt b/pypy/doc/config/objspace.usemodules.gc.rst
rename from pypy/doc/config/objspace.usemodules.gc.txt
rename to pypy/doc/config/objspace.usemodules.gc.rst
diff --git a/pypy/doc/config/objspace.usemodules.imp.txt b/pypy/doc/config/objspace.usemodules.imp.rst
rename from pypy/doc/config/objspace.usemodules.imp.txt
rename to pypy/doc/config/objspace.usemodules.imp.rst
diff --git a/pypy/doc/config/objspace.usemodules.itertools.txt b/pypy/doc/config/objspace.usemodules.itertools.rst
rename from pypy/doc/config/objspace.usemodules.itertools.txt
rename to pypy/doc/config/objspace.usemodules.itertools.rst
diff --git a/pypy/doc/config/objspace.usemodules.marshal.txt b/pypy/doc/config/objspace.usemodules.marshal.rst
rename from pypy/doc/config/objspace.usemodules.marshal.txt
rename to pypy/doc/config/objspace.usemodules.marshal.rst
diff --git a/pypy/doc/config/objspace.usemodules.math.txt b/pypy/doc/config/objspace.usemodules.math.rst
rename from pypy/doc/config/objspace.usemodules.math.txt
rename to pypy/doc/config/objspace.usemodules.math.rst
diff --git a/pypy/doc/config/objspace.usemodules.micronumpy.txt b/pypy/doc/config/objspace.usemodules.micronumpy.rst
rename from pypy/doc/config/objspace.usemodules.micronumpy.txt
rename to pypy/doc/config/objspace.usemodules.micronumpy.rst
diff --git a/pypy/doc/config/objspace.usemodules.mmap.txt b/pypy/doc/config/objspace.usemodules.mmap.rst
rename from pypy/doc/config/objspace.usemodules.mmap.txt
rename to pypy/doc/config/objspace.usemodules.mmap.rst
diff --git a/pypy/doc/config/objspace.usemodules.operator.txt b/pypy/doc/config/objspace.usemodules.operator.rst
rename from pypy/doc/config/objspace.usemodules.operator.txt
rename to pypy/doc/config/objspace.usemodules.operator.rst
diff --git a/pypy/doc/config/objspace.usemodules.oracle.txt b/pypy/doc/config/objspace.usemodules.oracle.rst
rename from pypy/doc/config/objspace.usemodules.oracle.txt
rename to pypy/doc/config/objspace.usemodules.oracle.rst
diff --git a/pypy/doc/config/objspace.usemodules.parser.txt b/pypy/doc/config/objspace.usemodules.parser.rst
rename from pypy/doc/config/objspace.usemodules.parser.txt
rename to pypy/doc/config/objspace.usemodules.parser.rst
diff --git a/pypy/doc/config/objspace.usemodules.posix.txt b/pypy/doc/config/objspace.usemodules.posix.rst
rename from pypy/doc/config/objspace.usemodules.posix.txt
rename to pypy/doc/config/objspace.usemodules.posix.rst
diff --git a/pypy/doc/config/objspace.usemodules.pyexpat.txt b/pypy/doc/config/objspace.usemodules.pyexpat.rst
rename from pypy/doc/config/objspace.usemodules.pyexpat.txt
rename to pypy/doc/config/objspace.usemodules.pyexpat.rst
diff --git a/pypy/doc/config/objspace.usemodules.pypyjit.txt b/pypy/doc/config/objspace.usemodules.pypyjit.rst
rename from pypy/doc/config/objspace.usemodules.pypyjit.txt
rename to pypy/doc/config/objspace.usemodules.pypyjit.rst
diff --git a/pypy/doc/config/objspace.usemodules.rbench.txt b/pypy/doc/config/objspace.usemodules.rbench.rst
rename from pypy/doc/config/objspace.usemodules.rbench.txt
rename to pypy/doc/config/objspace.usemodules.rbench.rst
diff --git a/pypy/doc/config/objspace.usemodules.rctime.txt b/pypy/doc/config/objspace.usemodules.rctime.rst
rename from pypy/doc/config/objspace.usemodules.rctime.txt
rename to pypy/doc/config/objspace.usemodules.rctime.rst
diff --git a/pypy/doc/config/objspace.usemodules.txt b/pypy/doc/config/objspace.usemodules.rst
rename from pypy/doc/config/objspace.usemodules.txt
rename to pypy/doc/config/objspace.usemodules.rst
diff --git a/pypy/doc/config/objspace.usemodules.select.txt b/pypy/doc/config/objspace.usemodules.select.rst
rename from pypy/doc/config/objspace.usemodules.select.txt
rename to pypy/doc/config/objspace.usemodules.select.rst
diff --git a/pypy/doc/config/objspace.usemodules.signal.txt b/pypy/doc/config/objspace.usemodules.signal.rst
rename from pypy/doc/config/objspace.usemodules.signal.txt
rename to pypy/doc/config/objspace.usemodules.signal.rst
diff --git a/pypy/doc/config/objspace.usemodules.struct.txt b/pypy/doc/config/objspace.usemodules.struct.rst
rename from pypy/doc/config/objspace.usemodules.struct.txt
rename to pypy/doc/config/objspace.usemodules.struct.rst
diff --git a/pypy/doc/config/objspace.usemodules.symbol.txt b/pypy/doc/config/objspace.usemodules.symbol.rst
rename from pypy/doc/config/objspace.usemodules.symbol.txt
rename to pypy/doc/config/objspace.usemodules.symbol.rst
diff --git a/pypy/doc/config/objspace.usemodules.sys.txt b/pypy/doc/config/objspace.usemodules.sys.rst
rename from pypy/doc/config/objspace.usemodules.sys.txt
rename to pypy/doc/config/objspace.usemodules.sys.rst
diff --git a/pypy/doc/config/objspace.usemodules.termios.txt b/pypy/doc/config/objspace.usemodules.termios.rst
rename from pypy/doc/config/objspace.usemodules.termios.txt
rename to pypy/doc/config/objspace.usemodules.termios.rst
diff --git a/pypy/doc/config/objspace.usemodules.thread.txt b/pypy/doc/config/objspace.usemodules.thread.rst
rename from pypy/doc/config/objspace.usemodules.thread.txt
rename to pypy/doc/config/objspace.usemodules.thread.rst
diff --git a/pypy/doc/config/objspace.usemodules.time.txt b/pypy/doc/config/objspace.usemodules.time.rst
rename from pypy/doc/config/objspace.usemodules.time.txt
rename to pypy/doc/config/objspace.usemodules.time.rst
diff --git a/pypy/doc/config/objspace.usemodules.token.txt b/pypy/doc/config/objspace.usemodules.token.rst
rename from pypy/doc/config/objspace.usemodules.token.txt
rename to pypy/doc/config/objspace.usemodules.token.rst
diff --git a/pypy/doc/config/objspace.usemodules.unicodedata.txt b/pypy/doc/config/objspace.usemodules.unicodedata.rst
rename from pypy/doc/config/objspace.usemodules.unicodedata.txt
rename to pypy/doc/config/objspace.usemodules.unicodedata.rst
diff --git a/pypy/doc/config/objspace.usemodules.zipimport.txt b/pypy/doc/config/objspace.usemodules.zipimport.rst
rename from pypy/doc/config/objspace.usemodules.zipimport.txt
rename to pypy/doc/config/objspace.usemodules.zipimport.rst
diff --git a/pypy/doc/config/objspace.usemodules.zlib.txt b/pypy/doc/config/objspace.usemodules.zlib.rst
rename from pypy/doc/config/objspace.usemodules.zlib.txt
rename to pypy/doc/config/objspace.usemodules.zlib.rst
diff --git a/pypy/doc/config/objspace.usepycfiles.txt b/pypy/doc/config/objspace.usepycfiles.rst
rename from pypy/doc/config/objspace.usepycfiles.txt
rename to pypy/doc/config/objspace.usepycfiles.rst
diff --git a/pypy/doc/config/opt.txt b/pypy/doc/config/opt.rst
rename from pypy/doc/config/opt.txt
rename to pypy/doc/config/opt.rst
diff --git a/pypy/doc/config/translation.backend.txt b/pypy/doc/config/translation.backend.rst
rename from pypy/doc/config/translation.backend.txt
rename to pypy/doc/config/translation.backend.rst
diff --git a/pypy/doc/config/translation.backendopt.clever_malloc_removal.txt b/pypy/doc/config/translation.backendopt.clever_malloc_removal.rst
rename from pypy/doc/config/translation.backendopt.clever_malloc_removal.txt
rename to pypy/doc/config/translation.backendopt.clever_malloc_removal.rst
diff --git a/pypy/doc/config/translation.backendopt.clever_malloc_removal_heuristic.txt b/pypy/doc/config/translation.backendopt.clever_malloc_removal_heuristic.rst
rename from pypy/doc/config/translation.backendopt.clever_malloc_removal_heuristic.txt
rename to pypy/doc/config/translation.backendopt.clever_malloc_removal_heuristic.rst
diff --git a/pypy/doc/config/translation.backendopt.clever_malloc_removal_threshold.txt b/pypy/doc/config/translation.backendopt.clever_malloc_removal_threshold.rst
rename from pypy/doc/config/translation.backendopt.clever_malloc_removal_threshold.txt
rename to pypy/doc/config/translation.backendopt.clever_malloc_removal_threshold.rst
diff --git a/pypy/doc/config/translation.backendopt.constfold.txt b/pypy/doc/config/translation.backendopt.constfold.rst
rename from pypy/doc/config/translation.backendopt.constfold.txt
rename to pypy/doc/config/translation.backendopt.constfold.rst
diff --git a/pypy/doc/config/translation.backendopt.inline.txt b/pypy/doc/config/translation.backendopt.inline.rst
rename from pypy/doc/config/translation.backendopt.inline.txt
rename to pypy/doc/config/translation.backendopt.inline.rst
diff --git a/pypy/doc/config/translation.backendopt.inline_heuristic.txt b/pypy/doc/config/translation.backendopt.inline_heuristic.rst
rename from pypy/doc/config/translation.backendopt.inline_heuristic.txt
rename to pypy/doc/config/translation.backendopt.inline_heuristic.rst
diff --git a/pypy/doc/config/translation.backendopt.inline_threshold.txt b/pypy/doc/config/translation.backendopt.inline_threshold.rst
rename from pypy/doc/config/translation.backendopt.inline_threshold.txt
rename to pypy/doc/config/translation.backendopt.inline_threshold.rst
diff --git a/pypy/doc/config/translation.backendopt.mallocs.txt b/pypy/doc/config/translation.backendopt.mallocs.rst
rename from pypy/doc/config/translation.backendopt.mallocs.txt
rename to pypy/doc/config/translation.backendopt.mallocs.rst
diff --git a/pypy/doc/config/translation.backendopt.merge_if_blocks.txt b/pypy/doc/config/translation.backendopt.merge_if_blocks.rst
rename from pypy/doc/config/translation.backendopt.merge_if_blocks.txt
rename to pypy/doc/config/translation.backendopt.merge_if_blocks.rst
diff --git a/pypy/doc/config/translation.backendopt.none.txt b/pypy/doc/config/translation.backendopt.none.rst
rename from pypy/doc/config/translation.backendopt.none.txt
rename to pypy/doc/config/translation.backendopt.none.rst
diff --git a/pypy/doc/config/translation.backendopt.print_statistics.txt b/pypy/doc/config/translation.backendopt.print_statistics.rst
rename from pypy/doc/config/translation.backendopt.print_statistics.txt
rename to pypy/doc/config/translation.backendopt.print_statistics.rst
diff --git a/pypy/doc/config/translation.backendopt.profile_based_inline.txt b/pypy/doc/config/translation.backendopt.profile_based_inline.rst
rename from pypy/doc/config/translation.backendopt.profile_based_inline.txt
rename to pypy/doc/config/translation.backendopt.profile_based_inline.rst
diff --git a/pypy/doc/config/translation.backendopt.profile_based_inline_heuristic.txt b/pypy/doc/config/translation.backendopt.profile_based_inline_heuristic.rst
rename from pypy/doc/config/translation.backendopt.profile_based_inline_heuristic.txt
rename to pypy/doc/config/translation.backendopt.profile_based_inline_heuristic.rst
diff --git a/pypy/doc/config/translation.backendopt.profile_based_inline_threshold.txt b/pypy/doc/config/translation.backendopt.profile_based_inline_threshold.rst
rename from pypy/doc/config/translation.backendopt.profile_based_inline_threshold.txt
rename to pypy/doc/config/translation.backendopt.profile_based_inline_threshold.rst
diff --git a/pypy/doc/config/translation.backendopt.raisingop2direct_call.txt b/pypy/doc/config/translation.backendopt.raisingop2direct_call.rst
rename from pypy/doc/config/translation.backendopt.raisingop2direct_call.txt
rename to pypy/doc/config/translation.backendopt.raisingop2direct_call.rst
diff --git a/pypy/doc/config/translation.backendopt.really_remove_asserts.txt b/pypy/doc/config/translation.backendopt.really_remove_asserts.rst
rename from pypy/doc/config/translation.backendopt.really_remove_asserts.txt
rename to pypy/doc/config/translation.backendopt.really_remove_asserts.rst
diff --git a/pypy/doc/config/translation.backendopt.remove_asserts.txt b/pypy/doc/config/translation.backendopt.remove_asserts.rst
rename from pypy/doc/config/translation.backendopt.remove_asserts.txt
rename to pypy/doc/config/translation.backendopt.remove_asserts.rst
diff --git a/pypy/doc/config/translation.backendopt.txt b/pypy/doc/config/translation.backendopt.rst
rename from pypy/doc/config/translation.backendopt.txt
rename to pypy/doc/config/translation.backendopt.rst
diff --git a/pypy/doc/config/translation.backendopt.stack_optimization.txt b/pypy/doc/config/translation.backendopt.stack_optimization.rst
rename from pypy/doc/config/translation.backendopt.stack_optimization.txt
rename to pypy/doc/config/translation.backendopt.stack_optimization.rst
diff --git a/pypy/doc/config/translation.backendopt.storesink.txt b/pypy/doc/config/translation.backendopt.storesink.rst
rename from pypy/doc/config/translation.backendopt.storesink.txt
rename to pypy/doc/config/translation.backendopt.storesink.rst
diff --git a/pypy/doc/config/translation.builtins_can_raise_exceptions.txt b/pypy/doc/config/translation.builtins_can_raise_exceptions.rst
rename from pypy/doc/config/translation.builtins_can_raise_exceptions.txt
rename to pypy/doc/config/translation.builtins_can_raise_exceptions.rst
diff --git a/pypy/doc/config/translation.cc.txt b/pypy/doc/config/translation.cc.rst
rename from pypy/doc/config/translation.cc.txt
rename to pypy/doc/config/translation.cc.rst
diff --git a/pypy/doc/config/translation.cli.exception_transformer.txt b/pypy/doc/config/translation.cli.exception_transformer.rst
rename from pypy/doc/config/translation.cli.exception_transformer.txt
rename to pypy/doc/config/translation.cli.exception_transformer.rst
diff --git a/pypy/doc/config/translation.cli.txt b/pypy/doc/config/translation.cli.rst
rename from pypy/doc/config/translation.cli.txt
rename to pypy/doc/config/translation.cli.rst
diff --git a/pypy/doc/config/translation.cli.trace_calls.txt b/pypy/doc/config/translation.cli.trace_calls.rst
rename from pypy/doc/config/translation.cli.trace_calls.txt
rename to pypy/doc/config/translation.cli.trace_calls.rst
diff --git a/pypy/doc/config/translation.compilerflags.txt b/pypy/doc/config/translation.compilerflags.rst
rename from pypy/doc/config/translation.compilerflags.txt
rename to pypy/doc/config/translation.compilerflags.rst
diff --git a/pypy/doc/config/translation.countmallocs.txt b/pypy/doc/config/translation.countmallocs.rst
rename from pypy/doc/config/translation.countmallocs.txt
rename to pypy/doc/config/translation.countmallocs.rst
diff --git a/pypy/doc/config/translation.debug.txt b/pypy/doc/config/translation.debug.rst
rename from pypy/doc/config/translation.debug.txt
rename to pypy/doc/config/translation.debug.rst
diff --git a/pypy/doc/config/translation.dump_static_data_info.txt b/pypy/doc/config/translation.dump_static_data_info.rst
rename from pypy/doc/config/translation.dump_static_data_info.txt
rename to pypy/doc/config/translation.dump_static_data_info.rst
diff --git a/pypy/doc/config/translation.force_make.txt b/pypy/doc/config/translation.force_make.rst
rename from pypy/doc/config/translation.force_make.txt
rename to pypy/doc/config/translation.force_make.rst
diff --git a/pypy/doc/config/translation.fork_before.txt b/pypy/doc/config/translation.fork_before.rst
rename from pypy/doc/config/translation.fork_before.txt
rename to pypy/doc/config/translation.fork_before.rst
diff --git a/pypy/doc/config/translation.gc.txt b/pypy/doc/config/translation.gc.rst
rename from pypy/doc/config/translation.gc.txt
rename to pypy/doc/config/translation.gc.rst
diff --git a/pypy/doc/config/translation.gcremovetypeptr.txt b/pypy/doc/config/translation.gcremovetypeptr.rst
rename from pypy/doc/config/translation.gcremovetypeptr.txt
rename to pypy/doc/config/translation.gcremovetypeptr.rst
diff --git a/pypy/doc/config/translation.gcrootfinder.txt b/pypy/doc/config/translation.gcrootfinder.rst
rename from pypy/doc/config/translation.gcrootfinder.txt
rename to pypy/doc/config/translation.gcrootfinder.rst
diff --git a/pypy/doc/config/translation.gctransformer.txt b/pypy/doc/config/translation.gctransformer.rst
rename from pypy/doc/config/translation.gctransformer.txt
rename to pypy/doc/config/translation.gctransformer.rst
diff --git a/pypy/doc/config/translation.insist.txt b/pypy/doc/config/translation.insist.rst
rename from pypy/doc/config/translation.insist.txt
rename to pypy/doc/config/translation.insist.rst
diff --git a/pypy/doc/config/translation.instrument.txt b/pypy/doc/config/translation.instrument.rst
rename from pypy/doc/config/translation.instrument.txt
rename to pypy/doc/config/translation.instrument.rst
diff --git a/pypy/doc/config/translation.instrumentctl.txt b/pypy/doc/config/translation.instrumentctl.rst
rename from pypy/doc/config/translation.instrumentctl.txt
rename to pypy/doc/config/translation.instrumentctl.rst
diff --git a/pypy/doc/config/translation.jit.txt b/pypy/doc/config/translation.jit.rst
rename from pypy/doc/config/translation.jit.txt
rename to pypy/doc/config/translation.jit.rst
diff --git a/pypy/doc/config/translation.jit_backend.txt b/pypy/doc/config/translation.jit_backend.rst
rename from pypy/doc/config/translation.jit_backend.txt
rename to pypy/doc/config/translation.jit_backend.rst
diff --git a/pypy/doc/config/translation.jit_ffi.txt b/pypy/doc/config/translation.jit_ffi.rst
rename from pypy/doc/config/translation.jit_ffi.txt
rename to pypy/doc/config/translation.jit_ffi.rst
diff --git a/pypy/doc/config/translation.jit_profiler.txt b/pypy/doc/config/translation.jit_profiler.rst
rename from pypy/doc/config/translation.jit_profiler.txt
rename to pypy/doc/config/translation.jit_profiler.rst
diff --git a/pypy/doc/config/translation.linkerflags.txt b/pypy/doc/config/translation.linkerflags.rst
rename from pypy/doc/config/translation.linkerflags.txt
rename to pypy/doc/config/translation.linkerflags.rst
diff --git a/pypy/doc/config/translation.list_comprehension_operations.txt b/pypy/doc/config/translation.list_comprehension_operations.rst
rename from pypy/doc/config/translation.list_comprehension_operations.txt
rename to pypy/doc/config/translation.list_comprehension_operations.rst
diff --git a/pypy/doc/config/translation.log.txt b/pypy/doc/config/translation.log.rst
rename from pypy/doc/config/translation.log.txt
rename to pypy/doc/config/translation.log.rst
diff --git a/pypy/doc/config/translation.make_jobs.txt b/pypy/doc/config/translation.make_jobs.rst
rename from pypy/doc/config/translation.make_jobs.txt
rename to pypy/doc/config/translation.make_jobs.rst
diff --git a/pypy/doc/config/translation.no__thread.txt b/pypy/doc/config/translation.no__thread.rst
rename from pypy/doc/config/translation.no__thread.txt
rename to pypy/doc/config/translation.no__thread.rst
diff --git a/pypy/doc/config/translation.noprofopt.txt b/pypy/doc/config/translation.noprofopt.rst
rename from pypy/doc/config/translation.noprofopt.txt
rename to pypy/doc/config/translation.noprofopt.rst
diff --git a/pypy/doc/config/translation.ootype.mangle.txt b/pypy/doc/config/translation.ootype.mangle.rst
rename from pypy/doc/config/translation.ootype.mangle.txt
rename to pypy/doc/config/translation.ootype.mangle.rst
diff --git a/pypy/doc/config/translation.ootype.txt b/pypy/doc/config/translation.ootype.rst
rename from pypy/doc/config/translation.ootype.txt
rename to pypy/doc/config/translation.ootype.rst
diff --git a/pypy/doc/config/translation.output.txt b/pypy/doc/config/translation.output.rst
rename from pypy/doc/config/translation.output.txt
rename to pypy/doc/config/translation.output.rst
diff --git a/pypy/doc/config/translation.platform.txt b/pypy/doc/config/translation.platform.rst
rename from pypy/doc/config/translation.platform.txt
rename to pypy/doc/config/translation.platform.rst
diff --git a/pypy/doc/config/translation.profopt.txt b/pypy/doc/config/translation.profopt.rst
rename from pypy/doc/config/translation.profopt.txt
rename to pypy/doc/config/translation.profopt.rst
diff --git a/pypy/doc/config/translation.txt b/pypy/doc/config/translation.rst
rename from pypy/doc/config/translation.txt
rename to pypy/doc/config/translation.rst
diff --git a/pypy/doc/config/translation.rweakref.txt b/pypy/doc/config/translation.rweakref.rst
rename from pypy/doc/config/translation.rweakref.txt
rename to pypy/doc/config/translation.rweakref.rst
diff --git a/pypy/doc/config/translation.sandbox.txt b/pypy/doc/config/translation.sandbox.rst
rename from pypy/doc/config/translation.sandbox.txt
rename to pypy/doc/config/translation.sandbox.rst
diff --git a/pypy/doc/config/translation.secondaryentrypoints.txt b/pypy/doc/config/translation.secondaryentrypoints.rst
rename from pypy/doc/config/translation.secondaryentrypoints.txt
rename to pypy/doc/config/translation.secondaryentrypoints.rst
diff --git a/pypy/doc/config/translation.shared.txt b/pypy/doc/config/translation.shared.rst
rename from pypy/doc/config/translation.shared.txt
rename to pypy/doc/config/translation.shared.rst
diff --git a/pypy/doc/config/translation.simplifying.txt b/pypy/doc/config/translation.simplifying.rst
rename from pypy/doc/config/translation.simplifying.txt
rename to pypy/doc/config/translation.simplifying.rst
diff --git a/pypy/doc/config/translation.stackless.txt b/pypy/doc/config/translation.stackless.rst
rename from pypy/doc/config/translation.stackless.txt
rename to pypy/doc/config/translation.stackless.rst
diff --git a/pypy/doc/config/translation.taggedpointers.txt b/pypy/doc/config/translation.taggedpointers.rst
rename from pypy/doc/config/translation.taggedpointers.txt
rename to pypy/doc/config/translation.taggedpointers.rst
diff --git a/pypy/doc/config/translation.thread.txt b/pypy/doc/config/translation.thread.rst
rename from pypy/doc/config/translation.thread.txt
rename to pypy/doc/config/translation.thread.rst
diff --git a/pypy/doc/config/translation.type_system.txt b/pypy/doc/config/translation.type_system.rst
rename from pypy/doc/config/translation.type_system.txt
rename to pypy/doc/config/translation.type_system.rst
diff --git a/pypy/doc/config/translation.vanilla.txt b/pypy/doc/config/translation.vanilla.rst
rename from pypy/doc/config/translation.vanilla.txt
rename to pypy/doc/config/translation.vanilla.rst
diff --git a/pypy/doc/config/translation.verbose.txt b/pypy/doc/config/translation.verbose.rst
rename from pypy/doc/config/translation.verbose.txt
rename to pypy/doc/config/translation.verbose.rst
diff --git a/pypy/doc/config/translation.withsmallfuncsets.txt b/pypy/doc/config/translation.withsmallfuncsets.rst
rename from pypy/doc/config/translation.withsmallfuncsets.txt
rename to pypy/doc/config/translation.withsmallfuncsets.rst
diff --git a/pypy/doc/configuration.txt b/pypy/doc/configuration.rst
rename from pypy/doc/configuration.txt
rename to pypy/doc/configuration.rst
diff --git a/pypy/doc/conftest.py b/pypy/doc/conftest.py
deleted file mode 100644
--- a/pypy/doc/conftest.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import py
-
-from pypy.config.makerestdoc import register_config_role 
-docdir = py.path.local(__file__).dirpath()
-
-pytest_plugins = "pypy.doc.pytest_restdoc"
-
-def pytest_addoption(parser):
-    group = parser.getgroup("pypy-doc options")
-    group.addoption('--pypy-doctests', action="store_true",
-           dest="pypy_doctests", default=False, 
-           help="enable doctests in .txt files")
-    group.addoption('--generate-redirections',
-        action="store_true", dest="generateredirections",
-        default=True, help="Generate redirecting HTML files")
-
-def pytest_configure(config):
-    register_config_role(docdir)
-
-def pytest_doctest_prepare_content(content):
-    if not py.test.config.getvalue("pypy_doctests"):
-        py.test.skip("specify --pypy-doctests to run doctests")
-    l = []
-    for line in content.split("\n"):
-        if line.find('>>>>') != -1: 
-            line = "" 
-        l.append(line) 
-    return "\n".join(l) 
-
diff --git a/pypy/doc/contributor.txt b/pypy/doc/contributor.rst
rename from pypy/doc/contributor.txt
rename to pypy/doc/contributor.rst
diff --git a/pypy/doc/cpython_differences.txt b/pypy/doc/cpython_differences.rst
rename from pypy/doc/cpython_differences.txt
rename to pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.txt
+++ b/pypy/doc/cpython_differences.rst
@@ -222,4 +222,4 @@
   *more* case on PyPy than on CPython 2.6/2.7.)
 
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/crufty.rst b/pypy/doc/crufty.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/crufty.rst
@@ -0,0 +1,3 @@
+.. warning::
+
+   This documentation may be out-of-date or obsolete (identified on 2011-03-14 at the PyCon US sprint)
diff --git a/pypy/doc/ctypes-implementation.txt b/pypy/doc/ctypes-implementation.rst
rename from pypy/doc/ctypes-implementation.txt
rename to pypy/doc/ctypes-implementation.rst
--- a/pypy/doc/ctypes-implementation.txt
+++ b/pypy/doc/ctypes-implementation.rst
@@ -1,3 +1,4 @@
+.. include:: crufty.rst
 
 =============================
 PyPy's ctypes implementation 
diff --git a/pypy/doc/dev_method.txt b/pypy/doc/dev_method.rst
rename from pypy/doc/dev_method.txt
rename to pypy/doc/dev_method.rst
diff --git a/pypy/doc/discussion/GC-performance.txt b/pypy/doc/discussion/GC-performance.rst
rename from pypy/doc/discussion/GC-performance.txt
rename to pypy/doc/discussion/GC-performance.rst
diff --git a/pypy/doc/discussion/VM-integration.txt b/pypy/doc/discussion/VM-integration.rst
rename from pypy/doc/discussion/VM-integration.txt
rename to pypy/doc/discussion/VM-integration.rst
diff --git a/pypy/doc/discussion/chained_getattr.txt b/pypy/doc/discussion/chained_getattr.rst
rename from pypy/doc/discussion/chained_getattr.txt
rename to pypy/doc/discussion/chained_getattr.rst
diff --git a/pypy/doc/discussion/cli-optimizations.txt b/pypy/doc/discussion/cli-optimizations.rst
rename from pypy/doc/discussion/cli-optimizations.txt
rename to pypy/doc/discussion/cli-optimizations.rst
diff --git a/pypy/doc/discussion/cmd-prompt-translation.txt b/pypy/doc/discussion/cmd-prompt-translation.rst
rename from pypy/doc/discussion/cmd-prompt-translation.txt
rename to pypy/doc/discussion/cmd-prompt-translation.rst
diff --git a/pypy/doc/discussion/compiled-swamp.txt b/pypy/doc/discussion/compiled-swamp.rst
rename from pypy/doc/discussion/compiled-swamp.txt
rename to pypy/doc/discussion/compiled-swamp.rst
diff --git a/pypy/doc/discussion/ctypes_modules.txt b/pypy/doc/discussion/ctypes_modules.rst
rename from pypy/doc/discussion/ctypes_modules.txt
rename to pypy/doc/discussion/ctypes_modules.rst
diff --git a/pypy/doc/discussion/ctypes_todo.txt b/pypy/doc/discussion/ctypes_todo.rst
rename from pypy/doc/discussion/ctypes_todo.txt
rename to pypy/doc/discussion/ctypes_todo.rst
diff --git a/pypy/doc/discussion/distribution-implementation.txt b/pypy/doc/discussion/distribution-implementation.rst
rename from pypy/doc/discussion/distribution-implementation.txt
rename to pypy/doc/discussion/distribution-implementation.rst
diff --git a/pypy/doc/discussion/distribution-newattempt.txt b/pypy/doc/discussion/distribution-newattempt.rst
rename from pypy/doc/discussion/distribution-newattempt.txt
rename to pypy/doc/discussion/distribution-newattempt.rst
diff --git a/pypy/doc/discussion/distribution-roadmap.txt b/pypy/doc/discussion/distribution-roadmap.rst
rename from pypy/doc/discussion/distribution-roadmap.txt
rename to pypy/doc/discussion/distribution-roadmap.rst
diff --git a/pypy/doc/discussion/distribution.txt b/pypy/doc/discussion/distribution.rst
rename from pypy/doc/discussion/distribution.txt
rename to pypy/doc/discussion/distribution.rst
diff --git a/pypy/doc/discussion/emptying-the-malloc-zoo.txt b/pypy/doc/discussion/emptying-the-malloc-zoo.rst
rename from pypy/doc/discussion/emptying-the-malloc-zoo.txt
rename to pypy/doc/discussion/emptying-the-malloc-zoo.rst
diff --git a/pypy/doc/discussion/finalizer-order.txt b/pypy/doc/discussion/finalizer-order.rst
rename from pypy/doc/discussion/finalizer-order.txt
rename to pypy/doc/discussion/finalizer-order.rst
diff --git a/pypy/doc/discussion/gc.txt b/pypy/doc/discussion/gc.rst
rename from pypy/doc/discussion/gc.txt
rename to pypy/doc/discussion/gc.rst
diff --git a/pypy/doc/discussion/howtoimplementpickling.txt b/pypy/doc/discussion/howtoimplementpickling.rst
rename from pypy/doc/discussion/howtoimplementpickling.txt
rename to pypy/doc/discussion/howtoimplementpickling.rst
diff --git a/pypy/doc/discussion/improve-rpython.txt b/pypy/doc/discussion/improve-rpython.rst
rename from pypy/doc/discussion/improve-rpython.txt
rename to pypy/doc/discussion/improve-rpython.rst
diff --git a/pypy/doc/discussion/outline-external-ootype.txt b/pypy/doc/discussion/outline-external-ootype.rst
rename from pypy/doc/discussion/outline-external-ootype.txt
rename to pypy/doc/discussion/outline-external-ootype.rst
diff --git a/pypy/doc/discussion/oz-thread-api.txt b/pypy/doc/discussion/oz-thread-api.rst
rename from pypy/doc/discussion/oz-thread-api.txt
rename to pypy/doc/discussion/oz-thread-api.rst
diff --git a/pypy/doc/discussion/paper-wishlist.txt b/pypy/doc/discussion/paper-wishlist.rst
rename from pypy/doc/discussion/paper-wishlist.txt
rename to pypy/doc/discussion/paper-wishlist.rst
diff --git a/pypy/doc/discussion/parsing-ideas.txt b/pypy/doc/discussion/parsing-ideas.rst
rename from pypy/doc/discussion/parsing-ideas.txt
rename to pypy/doc/discussion/parsing-ideas.rst
diff --git a/pypy/doc/discussion/pypy_metaclasses_in_cl.txt b/pypy/doc/discussion/pypy_metaclasses_in_cl.rst
rename from pypy/doc/discussion/pypy_metaclasses_in_cl.txt
rename to pypy/doc/discussion/pypy_metaclasses_in_cl.rst
diff --git a/pypy/doc/discussion/removing-stable-compiler.txt b/pypy/doc/discussion/removing-stable-compiler.rst
rename from pypy/doc/discussion/removing-stable-compiler.txt
rename to pypy/doc/discussion/removing-stable-compiler.rst
diff --git a/pypy/doc/discussion/security-ideas.txt b/pypy/doc/discussion/security-ideas.rst
rename from pypy/doc/discussion/security-ideas.txt
rename to pypy/doc/discussion/security-ideas.rst
diff --git a/pypy/doc/discussion/somepbc-refactoring-plan.txt b/pypy/doc/discussion/somepbc-refactoring-plan.rst
rename from pypy/doc/discussion/somepbc-refactoring-plan.txt
rename to pypy/doc/discussion/somepbc-refactoring-plan.rst
diff --git a/pypy/doc/discussion/summer-of-pypy-pytest.txt b/pypy/doc/discussion/summer-of-pypy-pytest.rst
rename from pypy/doc/discussion/summer-of-pypy-pytest.txt
rename to pypy/doc/discussion/summer-of-pypy-pytest.rst
diff --git a/pypy/doc/discussion/testing-zope.txt b/pypy/doc/discussion/testing-zope.rst
rename from pypy/doc/discussion/testing-zope.txt
rename to pypy/doc/discussion/testing-zope.rst
diff --git a/pypy/doc/discussion/thoughts_string_interning.txt b/pypy/doc/discussion/thoughts_string_interning.rst
rename from pypy/doc/discussion/thoughts_string_interning.txt
rename to pypy/doc/discussion/thoughts_string_interning.rst
diff --git a/pypy/doc/discussion/translation-swamp.txt b/pypy/doc/discussion/translation-swamp.rst
rename from pypy/doc/discussion/translation-swamp.txt
rename to pypy/doc/discussion/translation-swamp.rst
diff --git a/pypy/doc/discussion/use_case_of_logic.txt b/pypy/doc/discussion/use_case_of_logic.rst
rename from pypy/doc/discussion/use_case_of_logic.txt
rename to pypy/doc/discussion/use_case_of_logic.rst
diff --git a/pypy/doc/discussions.rst b/pypy/doc/discussions.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/discussions.rst
@@ -0,0 +1,41 @@
+Old discussion notes needing categorization
+-------------------------------------------
+
+The following are old discussion notes which may or may not reflect the current reality.
+
+Help from domain experts would be welcome, since some of these documents probably ought to be moved to a more prominent location, some should be deleted, and some left here.
+
+
+.. toctree::
+
+   discussion/GC-performance.rst
+   discussion/VM-integration.rst
+   discussion/chained_getattr.rst
+   discussion/cli-optimizations.rst
+   discussion/cmd-prompt-translation.rst
+   discussion/compiled-swamp.rst
+   discussion/ctypes_modules.rst
+   discussion/ctypes_todo.rst
+   discussion/distribution.rst
+   discussion/distribution-implementation.rst
+   discussion/distribution-newattempt.rst
+   discussion/distribution-roadmap.rst
+   discussion/emptying-the-malloc-zoo.rst
+   discussion/finalizer-order.rst
+   discussion/gc.rst
+   discussion/howtoimplementpickling.rst
+   discussion/improve-rpython.rst
+   discussion/outline-external-ootype.rst
+   discussion/oz-thread-api.rst
+   discussion/paper-wishlist.rst
+   discussion/parsing-ideas.rst
+   discussion/pypy_metaclasses_in_cl.rst
+   discussion/removing-stable-compiler.rst
+   discussion/security-ideas.rst
+   discussion/somepbc-refactoring-plan.rst
+   discussion/summer-of-pypy-pytest.rst
+   discussion/testing-zope.rst
+   discussion/thoughts_string_interning.rst
+   discussion/translation-swamp.rst
+   discussion/use_case_of_logic.rst
+
diff --git a/pypy/doc/distribution.txt b/pypy/doc/distribution.rst
rename from pypy/doc/distribution.txt
rename to pypy/doc/distribution.rst
--- a/pypy/doc/distribution.txt
+++ b/pypy/doc/distribution.rst
@@ -1,3 +1,6 @@
+.. include:: crufty.rst
+
+     .. ^^ Incomplete,  superceded elsewhere
 
 ========================
 lib/distributed features
diff --git a/pypy/doc/docindex.txt b/pypy/doc/docindex.rst
rename from pypy/doc/docindex.txt
rename to pypy/doc/docindex.rst
--- a/pypy/doc/docindex.txt
+++ b/pypy/doc/docindex.rst
@@ -4,7 +4,7 @@
 
 .. _Python: http://www.python.org/doc/2.5.2/
 
-.. sectnum::
+
 .. contents:: :depth: 1
 
 
@@ -310,5 +310,5 @@
 .. _`graph viewer`: getting-started-dev.html#try-out-the-translator
 .. _`compatibility matrix`: image/compat-matrix.png
 
-.. include:: _ref.txt
+.. include:: _ref.rst
 
diff --git a/pypy/doc/dot-net.rst b/pypy/doc/dot-net.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/dot-net.rst
@@ -0,0 +1,12 @@
+.NET support
+============
+
+   .. warning::
+   
+      The .NET backend within PyPy is unmaintained.  This documentation may be out-of-date.  We welcome contributors who are interested in doing the work to get this into shape.
+
+.. toctree::
+
+   cli-backend.rst
+   clr-module.rst
+   carbonpython.rst
diff --git a/pypy/doc/download.txt b/pypy/doc/download.txt
deleted file mode 100644
--- a/pypy/doc/download.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-Download one of the following release files: 
-=============================================
-
-Download page has moved to `pypy.org`_.
-
-.. _`pypy.org`: http://pypy.org/download.html
diff --git a/pypy/doc/eventhistory.txt b/pypy/doc/eventhistory.rst
rename from pypy/doc/eventhistory.txt
rename to pypy/doc/eventhistory.rst
--- a/pypy/doc/eventhistory.txt
+++ b/pypy/doc/eventhistory.rst
@@ -1,4 +1,6 @@
-
+------------
+More sprints
+------------
 
     The PyPy project is a worldwide collaborative effort and its
     members are organizing sprints and presenting results at conferences
diff --git a/pypy/doc/extending.txt b/pypy/doc/extending.rst
rename from pypy/doc/extending.txt
rename to pypy/doc/extending.rst
diff --git a/pypy/doc/externaltools.txt b/pypy/doc/externaltools.rst
rename from pypy/doc/externaltools.txt
rename to pypy/doc/externaltools.rst
--- a/pypy/doc/externaltools.txt
+++ b/pypy/doc/externaltools.rst
@@ -1,3 +1,7 @@
+.. include:: crufty.rst
+
+     .. ^^ Incomplete and wrong,  superceded elsewhere
+
 External tools&programs needed by PyPy
 ======================================
 
@@ -16,6 +20,8 @@
 
   - gcc
 
+  - make
+
   - Some libraries (these are Debian package names, adapt as needed):
 
     * ``python-dev``
diff --git a/pypy/doc/extradoc.txt b/pypy/doc/extradoc.rst
rename from pypy/doc/extradoc.txt
rename to pypy/doc/extradoc.rst
--- a/pypy/doc/extradoc.txt
+++ b/pypy/doc/extradoc.rst
@@ -1,5 +1,5 @@
 =================================================
-PyPy - papers, talks and related projects 
+Papers, talks and related projects 
 =================================================
 
 Papers
diff --git a/pypy/doc/faq.txt b/pypy/doc/faq.rst
rename from pypy/doc/faq.txt
rename to pypy/doc/faq.rst
--- a/pypy/doc/faq.txt
+++ b/pypy/doc/faq.rst
@@ -416,7 +416,7 @@
 .. _`RPython`: coding-guide.html#rpython
 .. _`getting-started`: getting-started.html
 
-.. include:: _ref.txt
+.. include:: _ref.rst
 
 ----------------------------------------------------------
 Why does PyPy draw a Mandelbrot fractal while translating?
diff --git a/pypy/doc/garbage_collection.txt b/pypy/doc/garbage_collection.rst
rename from pypy/doc/garbage_collection.txt
rename to pypy/doc/garbage_collection.rst
--- a/pypy/doc/garbage_collection.txt
+++ b/pypy/doc/garbage_collection.rst
@@ -3,7 +3,7 @@
 ==========================
 
 .. contents::
-.. sectnum::
+
 
 Introduction
 ============
@@ -124,4 +124,4 @@
 More details are available as comments at the start of the source
 in `rpython/memory/gc/markcompact.py`_.
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/geninterp.txt b/pypy/doc/geninterp.rst
rename from pypy/doc/geninterp.txt
rename to pypy/doc/geninterp.rst
--- a/pypy/doc/geninterp.txt
+++ b/pypy/doc/geninterp.rst
@@ -1,3 +1,7 @@
+.. include:: crufty.rst
+
+     .. ^^ apparently dead
+
 The Interpreter-Level backend
 -----------------------------
 
@@ -42,7 +46,7 @@
 Example
 +++++++
 
-.. _implementation: ../../pypy/translator/geninterplevel.py
+.. _implementation: ../../../../pypy/translator/geninterplevel.py
 
 Let's try a little example. You might want to look at the flowgraph that it
 produces. Here, we directly run the Python translation and look at the
diff --git a/pypy/doc/getting-started-dev.txt b/pypy/doc/getting-started-dev.rst
rename from pypy/doc/getting-started-dev.txt
rename to pypy/doc/getting-started-dev.rst
--- a/pypy/doc/getting-started-dev.txt
+++ b/pypy/doc/getting-started-dev.rst
@@ -1,9 +1,8 @@
 ===============================================================================
-PyPy - Getting Started with the Translation Toolchain and Development Process
+Getting Started with the Translation Toolchain and Development Process
 ===============================================================================
 
 .. contents::
-.. sectnum::
 
 .. _`try out the translator`:
 
@@ -18,9 +17,7 @@
 
   * Download and install Pygame_.
 
-  * Download and install `Dot Graphviz`_ (optional if you have an internet
-    connection: the flowgraph viewer then connects to
-    codespeak.net and lets it convert the flowgraph by a graphviz server).
+  * Download and install `Dot Graphviz`_ 
 
 To start the interactive translator shell do::
 
@@ -410,16 +407,16 @@
 .. _mixedmodule.py:          http://codespeak.net/svn/pypy/trunk/pypy/interpreter/mixedmodule.py
 .. _typedef.py:             http://codespeak.net/svn/pypy/trunk/pypy/interpreter/typedef.py
 .. _Standard object space:  objspace.html#the-standard-object-space
-.. _objspace.py:            ../../pypy/objspace/std/objspace.py
-.. _thunk:                  ../../pypy/objspace/thunk.py
-.. _trace:                  ../../pypy/objspace/trace.py
-.. _flow:                   ../../pypy/objspace/flow/
-.. _translator.py:          ../../pypy/translator/translator.py
+.. _objspace.py:            ../../../../pypy/objspace/std/objspace.py
+.. _thunk:                  ../../../../pypy/objspace/thunk.py
+.. _trace:                  ../../../../pypy/objspace/trace.py
+.. _flow:                   ../../../../pypy/objspace/flow/
+.. _translator.py:          ../../../../pypy/translator/translator.py
 .. _mailing lists:          index.html
 .. _documentation:          docindex.html 
 .. _unit tests:             coding-guide.html#test-design
 
 .. _`directory reference`: docindex.html#directory-reference
 
-.. include:: _ref.txt
+.. include:: _ref.rst
 
diff --git a/pypy/doc/getting-started-python.txt b/pypy/doc/getting-started-python.rst
rename from pypy/doc/getting-started-python.txt
rename to pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.txt
+++ b/pypy/doc/getting-started-python.rst
@@ -3,7 +3,7 @@
 ==============================================
 
 .. contents::
-.. sectnum::
+
 
 PyPy's Python interpreter is a very compliant Python
 interpreter implemented in Python.  When translated to C, it passes most of 
@@ -35,20 +35,31 @@
 You can translate the whole of PyPy's Python interpreter to low level C code,
 `CLI code`_, or `JVM code`_.
 
-1. Install dependencies.  You need (these are Debian package names,
-   adapt as needed):
+1. Install build-time dependencies.  On a Debian box these are::
 
-   * ``gcc``
-   * ``python-dev``
-   * ``python-ctypes`` if you are still using Python2.4
-   * ``libffi-dev``
+     [user at debian-box ~]$ sudo apt-get install \
+     gcc make python-dev libffi-dev pkg-config \
+     libz-dev libbz2-dev libncurses-dev libexpat1-dev \
+     libssl-dev libgc-dev python-sphinx python-greenlet
+
+   On a Fedora box these are::
+
+     [user at fedora-or-rh-box ~]$ sudo yum install \
+     gcc make python-devel libffi-devel pkg-config \
+     zlib-devel bzip2-devel ncurses-devel expat-devel \
+     openssl-devel gc-devel python-sphinx python-greenlet
+
+   The above command lines are split with continuation characters, giving the necessary dependencies first, then the optional ones.
+
    * ``pkg-config`` (to help us locate libffi files)
    * ``libz-dev`` (for the optional ``zlib`` module)
    * ``libbz2-dev`` (for the optional ``bz2`` module)
    * ``libncurses-dev`` (for the optional ``_minimal_curses`` module)
    * ``libexpat1-dev`` (for the optional ``pyexpat`` module)
    * ``libssl-dev`` (for the optional ``_ssl`` module)
-   * ``libgc-dev`` (Boehm: only when translating with `--opt=0, 1` or `size`)
+   * ``libgc-dev`` (for the Boehm garbage collector: only needed when translating with `--opt=0, 1` or `size`)
+   * ``python-sphinx`` (for the optional documentation build)
+   * ``python-greenlet`` (for the optional stackless support in interpreted mode/testing)
 
 2. Translation is somewhat time-consuming (30 min to
    over one hour) and RAM-hungry.  If you have less than 1.5 GB of
@@ -68,8 +79,8 @@
 
    possibly replacing ``--opt=jit`` with another `optimization level`_
    of your choice like ``--opt=2`` if you do not want the included JIT
-   compiler.  (As of March 2010, the default level is ``--opt=2``, and
-   ``--opt=jit`` requires an Intel **32-bit** environment.)
+   compiler.  As of March 2011, Intel 32-bit environment needs **at
+   least** 2GB, and 64-bit needs 4GB.
 
 .. _`optimization level`: config/opt.html
 
@@ -222,6 +233,12 @@
     ../../..
     etc.
 
+If the executable fails to find suitable libraries, it will report
+``debug: WARNING: library path not found, using compiled-in sys.path``
+and then attempt to continue normally.  If the default path is usable,
+most code will be fine.  However, the ``sys.prefix`` will be unset
+and some existing libraries assume that this is never the case.
+
 In order to use ``distutils`` or ``setuptools`` a directory ``PREFIX/site-packages`` needs to be created. Here's an example session setting up and using ``easy_install``::
 
     $ cd PREFIX
@@ -299,4 +316,4 @@
 .. _clr: clr-module.html
 .. _`CPythons core language regression tests`: http://codespeak.net:8099/summary?category=applevel&branch=%3Ctrunk%3E
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/getting-started.txt b/pypy/doc/getting-started.rst
rename from pypy/doc/getting-started.txt
rename to pypy/doc/getting-started.rst
--- a/pypy/doc/getting-started.txt
+++ b/pypy/doc/getting-started.rst
@@ -1,9 +1,8 @@
 ==================================
-PyPy - Getting Started 
+Getting Started 
 ==================================
 
 .. contents::
-.. sectnum::
 
 .. _howtopypy: 
 
@@ -34,9 +33,11 @@
 repository using mercurial.  We suggest using mercurial if one
 wants to access the current development.
 
-.. _`downloading them from the download page`: download.html
+.. _`downloading them from the download page`: http://pypy.org/download.html
 
-If you choose to use mercurial, you must issue the following command on your
+If you choose to use mercurial,
+first make sure you have ``subversion`` installed.
+You must issue the following command on your
 command line, DOS box, or terminal::
 
     hg clone http://bitbucket.org/pypy/pypy pypy
@@ -120,4 +121,4 @@
 .. _bug reports:            https://codespeak.net/issue/pypy-dev/
 
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/glossary.txt b/pypy/doc/glossary.rst
rename from pypy/doc/glossary.txt
rename to pypy/doc/glossary.rst
--- a/pypy/doc/glossary.txt
+++ b/pypy/doc/glossary.rst
@@ -1,7 +1,17 @@
+.. _glossary:
+
+********
+Glossary
+********
+
 PyPy, like any large project, has developed a jargon of its own.  This
 document gives brief definition of some of these terms and provides
 links to more information.
 
+.. if you add new entries, keep the alphabetical sorting!
+
+.. glossary::
+
 **abstract interpretation**
     The technique of interpreting the bytecode of a user program with
     an interpreter that handles abstract objects instead of concrete ones.
@@ -234,4 +244,4 @@
 .. _`subsystem implementing the Python language`: architecture.html#standard-interpreter
 .. _Theory: theory.html
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/how-to-release.txt b/pypy/doc/how-to-release.rst
rename from pypy/doc/how-to-release.txt
rename to pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.txt
+++ b/pypy/doc/how-to-release.rst
@@ -1,3 +1,5 @@
+.. include:: crufty.rst
+
 Making a PyPy Release
 =======================
 
diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/index-of-release-notes.rst
@@ -0,0 +1,17 @@
+Historical release notes
+------------------------
+
+.. toctree::
+
+   release-0.6
+   release-0.7.0.rst
+   release-0.8.0.rst
+   release-0.9.0.rst
+   release-0.99.0.rst
+   release-1.0.0.rst
+   release-1.1.0.rst
+   release-1.2.0.rst
+   release-1.3.0.rst
+   release-1.4.0.rst
+   release-1.4.0beta.rst
+   release-1.4.1.rst
diff --git a/pypy/doc/index-report.txt b/pypy/doc/index-report.rst
rename from pypy/doc/index-report.txt
rename to pypy/doc/index-report.rst
--- a/pypy/doc/index-report.txt
+++ b/pypy/doc/index-report.rst
@@ -1,3 +1,5 @@
+.. include:: crufty.rst
+
 ============================================
 PyPy - Overview over the EU-reports
 ============================================
diff --git a/pypy/doc/index.txt b/pypy/doc/index.rst
rename from pypy/doc/index.txt
rename to pypy/doc/index.rst
--- a/pypy/doc/index.txt
+++ b/pypy/doc/index.rst
@@ -1,3 +1,6 @@
+
+Welcome to PyPy Development
+=============================================
 
 The PyPy project aims at producing a flexible and fast Python_
 implementation.  The guiding idea is to translate a Python-level
@@ -12,10 +15,17 @@
 
 * `PyPy Blog`_: news and status info about PyPy 
 
-* `Documentation`_: extensive documentation and papers_ about PyPy.  
+* `Documentation`_: extensive documentation about PyPy.  
 
 * `Getting Started`_: Getting started and playing with PyPy. 
 
+* `Papers`_: Academic papers, talks, and related projects
+
+* `Videos`_: Videos of PyPy talks and presentations
+
+* `speed.pypy.org`_: Daily benchmarks of how fast PyPy is
+
+
 Mailing lists, bug tracker, IRC channel
 =============================================
 
@@ -55,5 +65,79 @@
 .. _`FAQ`: faq.html
 .. _`Documentation`: docindex.html 
 .. _`Getting Started`: getting-started.html
-.. _papers: extradoc.html
+.. _`Papers`: extradoc.html
+.. _`Videos`: video-index.html
 .. _`Release 1.4`: http://pypy.org/download.html
+.. _`speed.pypy.org`: http://speed.pypy.org
+
+Detailed Documentation
+======================
+
+.. The following documentation is important and reasonably up-to-date:
+
+.. extradoc: should this be integrated one level up: dcolish?
+
+
+.. toctree::
+   :maxdepth: 1
+
+   getting-started.rst
+   getting-started-python.rst
+   getting-started-dev.rst
+   windows.rst
+   faq.rst
+   architecture.rst
+   coding-guide.rst
+   cpython_differences.rst
+   cleanup-todo.rst
+   garbage_collection.rst
+   interpreter.rst
+   objspace.rst
+
+   dev_method.rst
+   extending.rst
+
+   extradoc.rst
+
+   glossary.rst
+
+   contributor.rst
+
+   interpreter-optimizations.rst
+   configuration.rst
+   low-level-encapsulation.rst
+   parser.rst
+   rlib.rst
+   rtyper.rst
+   translation.rst
+   jit/_ref.rst
+   jit/index.rst
+   jit/overview.rst
+   jit/pyjitpl5.rst
+
+   index-of-release-notes.rst
+
+   ctypes-implementation.rst
+
+   how-to-release.rst
+
+   index-report.rst
+
+   stackless.rst
+
+   discussions.rst
+
+   cleanup.rst
+
+   sprint-reports.rst
+
+   eventhistory.rst
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+* :ref:`glossary`
+
diff --git a/pypy/doc/interpreter-optimizations.txt b/pypy/doc/interpreter-optimizations.rst
rename from pypy/doc/interpreter-optimizations.txt
rename to pypy/doc/interpreter-optimizations.rst
diff --git a/pypy/doc/interpreter.txt b/pypy/doc/interpreter.rst
rename from pypy/doc/interpreter.txt
rename to pypy/doc/interpreter.rst
--- a/pypy/doc/interpreter.txt
+++ b/pypy/doc/interpreter.rst
@@ -1,9 +1,9 @@
 ===================================
-PyPy - Bytecode Interpreter 
+Bytecode Interpreter 
 ===================================
 
 .. contents::
-.. sectnum::
+
 
 
 Introduction and Overview
@@ -407,4 +407,4 @@
 as a reference for the exact attributes of interpreter classes visible 
 at application level. 
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/jit/_ref.txt b/pypy/doc/jit/_ref.rst
rename from pypy/doc/jit/_ref.txt
rename to pypy/doc/jit/_ref.rst
diff --git a/pypy/doc/jit/index.txt b/pypy/doc/jit/index.rst
rename from pypy/doc/jit/index.txt
rename to pypy/doc/jit/index.rst
diff --git a/pypy/doc/jit/overview.txt b/pypy/doc/jit/overview.rst
rename from pypy/doc/jit/overview.txt
rename to pypy/doc/jit/overview.rst
--- a/pypy/doc/jit/overview.txt
+++ b/pypy/doc/jit/overview.rst
@@ -3,7 +3,6 @@
 ------------------------------------------------------------------------
 
 .. contents::
-.. sectnum::
 
 This is a non-technical introduction and motivation for PyPy's approach
 to Just-In-Time compiler generation.
diff --git a/pypy/doc/jit/pyjitpl5.txt b/pypy/doc/jit/pyjitpl5.rst
rename from pypy/doc/jit/pyjitpl5.txt
rename to pypy/doc/jit/pyjitpl5.rst
diff --git a/pypy/doc/low-level-encapsulation.txt b/pypy/doc/low-level-encapsulation.rst
rename from pypy/doc/low-level-encapsulation.txt
rename to pypy/doc/low-level-encapsulation.rst
--- a/pypy/doc/low-level-encapsulation.txt
+++ b/pypy/doc/low-level-encapsulation.rst
@@ -3,7 +3,7 @@
 ============================================================
 
 .. contents::
-.. sectnum::
+
 
 
 Abstract
diff --git a/pypy/doc/maemo.txt b/pypy/doc/maemo.rst
rename from pypy/doc/maemo.txt
rename to pypy/doc/maemo.rst
diff --git a/pypy/doc/make.bat b/pypy/doc/make.bat
new file mode 100644
--- /dev/null
+++ b/pypy/doc/make.bat
@@ -0,0 +1,113 @@
+ at ECHO OFF
+
+REM Command file for Sphinx documentation
+
+set SPHINXBUILD=sphinx-build
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html      to make standalone HTML files
+	echo.  dirhtml   to make HTML files named index.html in directories
+	echo.  pickle    to make pickle files
+	echo.  json      to make JSON files
+	echo.  htmlhelp  to make HTML files and a HTML help project
+	echo.  qthelp    to make HTML files and a qthelp project
+	echo.  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  changes   to make an overview over all changed/added/deprecated items
+	echo.  linkcheck to check all external links for integrity
+	echo.  doctest   to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PyPy.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PyPy.ghc
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end
diff --git a/pypy/doc/objspace-proxies.txt b/pypy/doc/objspace-proxies.rst
rename from pypy/doc/objspace-proxies.txt
rename to pypy/doc/objspace-proxies.rst
--- a/pypy/doc/objspace-proxies.txt
+++ b/pypy/doc/objspace-proxies.rst
@@ -3,7 +3,7 @@
 =================================
 
 .. contents::
-.. sectnum::
+
 
 
 Thanks to the `Object Space`_ architecture, any feature that is
@@ -607,12 +607,12 @@
 lists, dicts, exceptions, tracebacks and frames.
 
 .. _`standard object space`: objspace.html#the-standard-object-space
-.. _`proxy_helpers.py`: ../../pypy/objspace/std/proxy_helpers.py
-.. _`proxyobject.py`: ../../pypy/objspace/std/proxyobject.py
-.. _`transparent.py`: ../../pypy/objspace/std/transparent.py
+.. _`proxy_helpers.py`: ../../../../pypy/objspace/std/proxy_helpers.py
+.. _`proxyobject.py`: ../../../../pypy/objspace/std/proxyobject.py
+.. _`transparent.py`: ../../../../pypy/objspace/std/transparent.py
 .. _`tputil.py`: ../../lib_pypy/tputil.py
 
 .. [D12.1] `High-Level Backends and Interpreter Feature Prototypes`, PyPy
            EU-Report, 2007, http://codespeak.net/pypy/extradoc/eu-report/D12.1_H-L-Backends_and_Feature_Prototypes-2007-03-22.pdf
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/objspace.txt b/pypy/doc/objspace.rst
rename from pypy/doc/objspace.txt
rename to pypy/doc/objspace.rst
--- a/pypy/doc/objspace.txt
+++ b/pypy/doc/objspace.rst
@@ -1,9 +1,9 @@
 ======================
-PyPy - Object Spaces
+Object Spaces
 ======================
 
 .. contents::
-.. sectnum::
+
 
 .. _`objectspace`: 
 .. _`Object Space`: 
@@ -341,7 +341,7 @@
 using plain integers instead is the complex path, not the other way
 around.
 
-.. _StdObjSpace: ../objspace/std/
+.. _StdObjSpace: ../../../../pypy/objspace/std/
 
 
 Object types
@@ -394,10 +394,10 @@
 For other examples of multiple implementations of the same Python type,
 see `Standard Interpreter Optimizations`_.
 
-.. _`listtype.py`: ../objspace/std/listtype.py
-.. _`stringtype.py`: ../objspace/std/stringtype.py
-.. _`tupletype.py`: ../objspace/std/tupletype.py
-.. _`tupleobject.py`: ../objspace/std/tupleobject.py
+.. _`listtype.py`: ../../../../pypy/objspace/std/listtype.py
+.. _`stringtype.py`: ../../../../pypy/objspace/std/stringtype.py
+.. _`tupletype.py`: ../../../../pypy/objspace/std/tupletype.py
+.. _`tupleobject.py`: ../../../../pypy/objspace/std/tupleobject.py
 
 .. _`Standard Interpreter Optimizations`: interpreter-optimizations.html
 
@@ -412,7 +412,7 @@
 alone are not enough for the Standard Object Space: the complete picture
 spans several levels in order to emulate the exact Python semantics.
 
-.. __: ../objspace/std/multimethod.py
+.. __: ../../../../pypy/objspace/std/multimethod.py
 
 Consider the example of the ``space.getitem(w_a, w_b)`` operation,
 corresponding to the application-level syntax ``a[b]``.  The Standard
@@ -600,7 +600,7 @@
     v3 = add(v2, Constant(2))
 
 
-.. _FlowObjSpace: ../objspace/flow/
+.. _FlowObjSpace: ../../../../pypy/objspace/flow/
 
 
 The Flow model
@@ -650,4 +650,4 @@
 
 .. _`What PyPy can do for your objects`: objspace-proxies.html
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/old_news.txt b/pypy/doc/old_news.rst
rename from pypy/doc/old_news.txt
rename to pypy/doc/old_news.rst
diff --git a/pypy/doc/parser.txt b/pypy/doc/parser.rst
rename from pypy/doc/parser.txt
rename to pypy/doc/parser.rst
--- a/pypy/doc/parser.txt
+++ b/pypy/doc/parser.rst
@@ -100,4 +100,4 @@
 information like the line number table and stack depth are computed.  Finally,
 everything is passed to a brand new ``PyCode`` object.
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/project-ideas.txt b/pypy/doc/project-ideas.rst
rename from pypy/doc/project-ideas.txt
rename to pypy/doc/project-ideas.rst
diff --git a/pypy/doc/pytest_restdoc.py b/pypy/doc/pytest_restdoc.py
deleted file mode 100644
--- a/pypy/doc/pytest_restdoc.py
+++ /dev/null
@@ -1,434 +0,0 @@
-"""
-perform ReST syntax, local and remote reference tests on .rst/.txt files. 
-"""
-import py
-import sys, os, re
-
-def pytest_addoption(parser):
-    group = parser.getgroup("ReST", "ReST documentation check options")
-    group.addoption('-R', '--urlcheck',
-           action="store_true", dest="urlcheck", default=False, 
-           help="urlopen() remote links found in ReST text files.") 
-    group.addoption('--urltimeout', action="store", metavar="secs",
-        type="int", dest="urlcheck_timeout", default=5,
-        help="timeout in seconds for remote urlchecks")
-    group.addoption('--forcegen',
-           action="store_true", dest="forcegen", default=False,
-           help="force generation of html files.")
-
-def pytest_collect_file(path, parent):
-    if path.ext in (".txt", ".rst"):
-        project = getproject(path)
-        if project is not None:
-            return ReSTFile(path, parent=parent, project=project)
-
-def getproject(path):
-    for parent in path.parts(reverse=True):
-        confrest = parent.join("confrest.py")
-        if confrest.check():
-            Project = confrest.pyimport().Project
-            return Project(parent)
-
-class ReSTFile(py.test.collect.File):
-    def __init__(self, fspath, parent, project):
-        super(ReSTFile, self).__init__(fspath=fspath, parent=parent)
-        self.project = project
-
-    def collect(self):
-        return [
-            ReSTSyntaxTest("ReSTSyntax", parent=self, project=self.project),
-            LinkCheckerMaker("checklinks", parent=self),
-            DoctestText("doctest", parent=self),
-        ]
-
-def deindent(s, sep='\n'):
-    leastspaces = -1
-    lines = s.split(sep)
-    for line in lines:
-        if not line.strip():
-            continue
-        spaces = len(line) - len(line.lstrip())
-        if leastspaces == -1 or spaces < leastspaces:
-            leastspaces = spaces
-    if leastspaces == -1:
-        return s
-    for i, line in enumerate(lines):
-        if not line.strip():
-            lines[i] = ''
-        else:
-            lines[i] = line[leastspaces:]
-    return sep.join(lines)
-
-class ReSTSyntaxTest(py.test.collect.Item): 
-    def __init__(self, name, parent, project):
-        super(ReSTSyntaxTest, self).__init__(name=name, parent=parent)
-        self.project = project
-
-    def reportinfo(self):
-        return self.fspath, None, "syntax check"
-
-    def runtest(self):
-        self.restcheck(py.path.svnwc(self.fspath))
-
-    def restcheck(self, path):
-        py.test.importorskip("docutils")
-        self.register_linkrole()
-        from docutils.utils import SystemMessage
-        try:
-            self._checkskip(path, self.project.get_htmloutputpath(path))
-            self.project.process(path)
-        except KeyboardInterrupt:
-            raise
-        except SystemExit, error:
-            if error.message == "ERROR: dot not found":
-                py.test.skip("system doesn't have graphviz installed")
-                return
-            raise
-        except SystemMessage:
-            # we assume docutils printed info on stdout
-            py.test.fail("docutils processing failed, see captured stderr")
-
-    def register_linkrole(self):
-        #directive.register_linkrole('api', self.resolve_linkrole)
-        #directive.register_linkrole('source', self.resolve_linkrole)
-#
-#        # XXX fake sphinx' "toctree" and refs
-#        directive.register_linkrole('ref', self.resolve_linkrole)
-        
-        from docutils.parsers.rst import directives
-        def toctree_directive(name, arguments, options, content, lineno,
-                      content_offset, block_text, state, state_machine):
-            return []
-        toctree_directive.content = 1
-        toctree_directive.options = {'maxdepth': int, 'glob': directives.flag,
-                             'hidden': directives.flag}
-        directives.register_directive('toctree', toctree_directive)
-        self.register_pygments()
-
-    def register_pygments(self):
-        # taken from pygments-main/external/rst-directive.py 
-        from docutils.parsers.rst import directives
-        try:
-            from pygments.formatters import HtmlFormatter
-        except ImportError:
-            def pygments_directive(name, arguments, options, content, lineno,
-                                   content_offset, block_text, state, state_machine):
-                return []
-            pygments_directive.options = {}
-        else:
-            # The default formatter
-            DEFAULT = HtmlFormatter(noclasses=True)
-            # Add name -> formatter pairs for every variant you want to use
-            VARIANTS = {
-                # 'linenos': HtmlFormatter(noclasses=INLINESTYLES, linenos=True),
-            }
-
-            from docutils import nodes
-
-            from pygments import highlight
-            from pygments.lexers import get_lexer_by_name, TextLexer
-
-            def pygments_directive(name, arguments, options, content, lineno,
-                                   content_offset, block_text, state, state_machine):
-                try:
-                    lexer = get_lexer_by_name(arguments[0])
-                except ValueError:
-                    # no lexer found - use the text one instead of an exception
-                    lexer = TextLexer()
-                # take an arbitrary option if more than one is given
-                formatter = options and VARIANTS[options.keys()[0]] or DEFAULT
-                parsed = highlight('\n'.join(content), lexer, formatter)
-                return [nodes.raw('', parsed, format='html')]
-
-            pygments_directive.options = dict([(key, directives.flag) for key in VARIANTS])
-
-        pygments_directive.arguments = (1, 0, 1)
-        pygments_directive.content = 1
-        directives.register_directive('sourcecode', pygments_directive)
-
-    def resolve_linkrole(self, name, text, check=True):
-        apigen_relpath = self.project.apigen_relpath
-    
-        if name == 'api':
-            if text == 'py':
-                return ('py', apigen_relpath + 'api/index.html')
-            else:
-                assert text.startswith('py.'), (
-                    'api link "%s" does not point to the py package') % (text,)
-                dotted_name = text
-                if dotted_name.find('(') > -1:
-                    dotted_name = dotted_name[:text.find('(')]
-                # remove pkg root
-                path = dotted_name.split('.')[1:]
-                dotted_name = '.'.join(path)
-                obj = py
-                if check:
-                    for chunk in path:
-                        try:
-                            obj = getattr(obj, chunk)
-                        except AttributeError:
-                            raise AssertionError(
-                                'problem with linkrole :api:`%s`: can not resolve '
-                                'dotted name %s' % (text, dotted_name,))
-                return (text, apigen_relpath + 'api/%s.html' % (dotted_name,))
-        elif name == 'source':
-            assert text.startswith('py/'), ('source link "%s" does not point '
-                                            'to the py package') % (text,)
-            relpath = '/'.join(text.split('/')[1:])
-            if check:
-                pkgroot = py._pydir
-                abspath = pkgroot.join(relpath)
-                assert pkgroot.join(relpath).check(), (
-                        'problem with linkrole :source:`%s`: '
-                        'path %s does not exist' % (text, relpath))
-            if relpath.endswith('/') or not relpath:
-                relpath += 'index.html'
-            else:
-                relpath += '.html'
-            return (text, apigen_relpath + 'source/%s' % (relpath,))
-        elif name == 'ref':
-            return ("", "") 
-
-    def _checkskip(self, lpath, htmlpath=None):
-        if not self.config.getvalue("forcegen"):
-            lpath = py.path.local(lpath)
-            if htmlpath is not None:
-                htmlpath = py.path.local(htmlpath)
-            if lpath.ext == '.txt': 
-                htmlpath = htmlpath or lpath.new(ext='.html')
-                if htmlpath.check(file=1) and htmlpath.mtime() >= lpath.mtime(): 
-                    py.test.skip("html file is up to date, use --forcegen to regenerate")
-                    #return [] # no need to rebuild 
-
-class DoctestText(py.test.collect.Item): 
-    def reportinfo(self):
-        return self.fspath, None, "doctest"
-
-    def runtest(self): 
-        content = self._normalize_linesep()
-        newcontent = self.config.hook.pytest_doctest_prepare_content(content=content)
-        if newcontent is not None:
-            content = newcontent 
-        s = content 
-        l = []
-        prefix = '.. >>> '
-        mod = py.std.types.ModuleType(self.fspath.purebasename) 
-        skipchunk = False
-        for line in deindent(s).split('\n'):
-            stripped = line.strip()
-            if skipchunk and line.startswith(skipchunk):
-                py.builtin.print_("skipping", line)
-                continue
-            skipchunk = False 
-            if stripped.startswith(prefix):
-                try:
-                    py.builtin.exec_(py.code.Source(
-                            stripped[len(prefix):]).compile(),  mod.__dict__)
-                except ValueError:
-                    e = sys.exc_info()[1]
-                    if e.args and e.args[0] == "skipchunk":
-                        skipchunk = " " * (len(line) - len(line.lstrip()))
-                    else:
-                        raise
-            else:
-                l.append(line)
-        docstring = "\n".join(l)
-        mod.__doc__ = docstring 
-        failed, tot = py.std.doctest.testmod(mod, verbose=1)
-        if failed: 
-            py.test.fail("doctest %s: %s failed out of %s" %(
-                         self.fspath, failed, tot))
-
-    def _normalize_linesep(self):
-        # XXX quite nasty... but it works (fixes win32 issues)
-        s = self.fspath.read()
-        linesep = '\n'
-        if '\r' in s:
-            if '\n' not in s:
-                linesep = '\r'
-            else:
-                linesep = '\r\n'
-        s = s.replace(linesep, '\n')
-        return s
-        
-class LinkCheckerMaker(py.test.collect.Collector): 
-    def collect(self):
-        return list(self.genlinkchecks())
-
-    def genlinkchecks(self):
-        path = self.fspath
-        # generating functions + args as single tests 
-        timeout = self.config.getvalue("urlcheck_timeout")
-        for lineno, line in enumerate(path.readlines()): 
-            line = line.strip()
-            if line.startswith('.. _'): 
-                if line.startswith('.. _`'):
-                    delim = '`:'
-                else:
-                    delim = ':'
-                l = line.split(delim, 1)
-                if len(l) != 2: 
-                    continue
-                tryfn = l[1].strip() 
-                name = "%s:%d" %(tryfn, lineno)
-                if tryfn.startswith('http:') or tryfn.startswith('https'): 
-                    if self.config.getvalue("urlcheck"):
-                        yield CheckLink(name, parent=self, 
-                            args=(tryfn, path, lineno, timeout), checkfunc=urlcheck)
-                elif tryfn.startswith('webcal:'):
-                    continue
-                else: 
-                    i = tryfn.find('#') 
-                    if i != -1: 
-                        checkfn = tryfn[:i]
-                    else: 
-                        checkfn = tryfn 
-                    if checkfn.strip() and (1 or checkfn.endswith('.html')): 
-                        yield CheckLink(name, parent=self, 
-                            args=(tryfn, path, lineno), checkfunc=localrefcheck)
-        
-class CheckLink(py.test.collect.Item):
-    def __init__(self, name, parent, args, checkfunc):
-        super(CheckLink, self).__init__(name, parent)
-        self.args = args
-        self.checkfunc = checkfunc
-
-    def runtest(self):
-        return self.checkfunc(*self.args)
-
-    def reportinfo(self, basedir=None):
-        return (self.fspath, self.args[2], "checklink: %s" % self.args[0])
-
-def urlcheck(tryfn, path, lineno, TIMEOUT_URLOPEN): 
-    old = py.std.socket.getdefaulttimeout()
-    py.std.socket.setdefaulttimeout(TIMEOUT_URLOPEN)
-    try:
-        try: 
-            py.builtin.print_("trying remote", tryfn)
-            py.std.urllib2.urlopen(tryfn)
-        finally:
-            py.std.socket.setdefaulttimeout(old)
-    except (py.std.urllib2.URLError, py.std.urllib2.HTTPError): 
-        e = sys.exc_info()[1]
-        if getattr(e, 'code', None) in (401, 403): # authorization required, forbidden
-            py.test.skip("%s: %s" %(tryfn, str(e)))
-        else:
-            py.test.fail("remote reference error %r in %s:%d\n%s" %(
-                         tryfn, path.basename, lineno+1, e))
-
-def localrefcheck(tryfn, path, lineno): 
-    # assume it should be a file 
-    i = tryfn.find('#')
-    if tryfn.startswith('javascript:'):
-        return # don't check JS refs
-    if i != -1: 
-        anchor = tryfn[i+1:]
-        tryfn = tryfn[:i]
-    else: 
-        anchor = ''
-    fn = path.dirpath(tryfn) 
-    ishtml = fn.ext == '.html' 
-    fn = ishtml and fn.new(ext='.txt') or fn
-    py.builtin.print_("filename is", fn)
-    if not fn.check(): # not ishtml or not fn.check(): 
-        if not py.path.local(tryfn).check(): # the html could be there 
-            py.test.fail("reference error %r in %s:%d" %(
-                          tryfn, path.basename, lineno+1))
-    if anchor: 
-        source = unicode(fn.read(), 'latin1')
-        source = source.lower().replace('-', ' ') # aehem
-
-        anchor = anchor.replace('-', ' ') 
-        match2 = ".. _`%s`:" % anchor 
-        match3 = ".. _%s:" % anchor 
-        candidates = (anchor, match2, match3)
-        py.builtin.print_("candidates", repr(candidates))
-        for line in source.split('\n'): 
-            line = line.strip()
-            if line in candidates: 
-                break 
-        else: 
-            py.test.fail("anchor reference error %s#%s in %s:%d" %(
-                tryfn, anchor, path.basename, lineno+1))
-
-if hasattr(sys.stdout, 'fileno') and os.isatty(sys.stdout.fileno()):
-    def log(msg):
-        print(msg)
-else:
-    def log(msg):
-        pass
-
-def convert_rest_html(source, source_path, stylesheet=None, encoding='latin1'):
-    """ return html latin1-encoded document for the given input. 
-        source  a ReST-string
-        sourcepath where to look for includes (basically)
-        stylesheet path (to be used if any)
-    """
-    from docutils.core import publish_string
-    kwargs = {
-        'stylesheet' : stylesheet, 
-        'stylesheet_path': None,
-        'traceback' : 1, 
-        'embed_stylesheet': 0,
-        'output_encoding' : encoding, 
-        #'halt' : 0, # 'info',
-        'halt_level' : 2, 
-    }
-    # docutils uses os.getcwd() :-(
-    source_path = os.path.abspath(str(source_path))
-    prevdir = os.getcwd()
-    try:
-        #os.chdir(os.path.dirname(source_path))
-        return publish_string(source, source_path, writer_name='html',
-                              settings_overrides=kwargs)
-    finally:
-        os.chdir(prevdir)
-
-def process(txtpath, encoding='latin1'):
-    """ process a textfile """
-    log("processing %s" % txtpath)
-    assert txtpath.check(ext='.txt')
-    if isinstance(txtpath, py.path.svnwc):
-        txtpath = txtpath.localpath
-    htmlpath = txtpath.new(ext='.html')
-    #svninfopath = txtpath.localpath.new(ext='.svninfo')
-
-    style = txtpath.dirpath('style.css')
-    if style.check():
-        stylesheet = style.basename
-    else:
-        stylesheet = None
-    content = unicode(txtpath.read(), encoding)
-    doc = convert_rest_html(content, txtpath, stylesheet=stylesheet, encoding=encoding)
-    htmlpath.open('wb').write(doc)
-    #log("wrote %r" % htmlpath)
-    #if txtpath.check(svnwc=1, versioned=1): 
-    #    info = txtpath.info()
-    #    svninfopath.dump(info) 
-
-if sys.version_info > (3, 0):
-    def _uni(s): return s
-else:
-    def _uni(s):
-        return unicode(s)
-
-rex1 = re.compile(r'.*<body>(.*)</body>.*', re.MULTILINE | re.DOTALL)
-rex2 = re.compile(r'.*<div class="document">(.*)</div>.*', re.MULTILINE | re.DOTALL)
-
-def strip_html_header(string, encoding='utf8'):
-    """ return the content of the body-tag """ 
-    uni = unicode(string, encoding)
-    for rex in rex1,rex2: 
-        match = rex.search(uni) 
-        if not match: 
-            break 
-        uni = match.group(1) 
-    return uni 
-
-class Project: # used for confrest.py files 
-    def __init__(self, sourcepath):
-        self.sourcepath = sourcepath
-    def process(self, path):
-        return process(path)
-    def get_htmloutputpath(self, path):
-        return path.new(ext='html')
diff --git a/pypy/doc/redirections b/pypy/doc/redirections
deleted file mode 100644
--- a/pypy/doc/redirections
+++ /dev/null
@@ -1,10 +0,0 @@
-# please make sure this is evaluable 
-{
-    'proxy.html': 'objspace-proxies.html#tproxy',
-    'news.html': 'index.html',
-    'contact.html': 'index.html',
-    'home.html': 'index.html',
-    'jit.html': 'jit/index.html',
-    'standalone-howto.html': 'faq.html#pypy-translation-tool-chain',
-    'dynamic-language-translation.html': 'http://codespeak.net/svn/pypy/extradoc/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf',
-}
diff --git a/pypy/doc/release-0.6.txt b/pypy/doc/release-0.6.rst
rename from pypy/doc/release-0.6.txt
rename to pypy/doc/release-0.6.rst
diff --git a/pypy/doc/release-0.7.0.txt b/pypy/doc/release-0.7.0.rst
rename from pypy/doc/release-0.7.0.txt
rename to pypy/doc/release-0.7.0.rst
diff --git a/pypy/doc/release-0.8.0.txt b/pypy/doc/release-0.8.0.rst
rename from pypy/doc/release-0.8.0.txt
rename to pypy/doc/release-0.8.0.rst
diff --git a/pypy/doc/release-0.9.0.txt b/pypy/doc/release-0.9.0.rst
rename from pypy/doc/release-0.9.0.txt
rename to pypy/doc/release-0.9.0.rst
diff --git a/pypy/doc/release-0.99.0.txt b/pypy/doc/release-0.99.0.rst
rename from pypy/doc/release-0.99.0.txt
rename to pypy/doc/release-0.99.0.rst
diff --git a/pypy/doc/release-1.0.0.txt b/pypy/doc/release-1.0.0.rst
rename from pypy/doc/release-1.0.0.txt
rename to pypy/doc/release-1.0.0.rst
diff --git a/pypy/doc/release-1.1.0.txt b/pypy/doc/release-1.1.0.rst
rename from pypy/doc/release-1.1.0.txt
rename to pypy/doc/release-1.1.0.rst
diff --git a/pypy/doc/release-1.2.0.txt b/pypy/doc/release-1.2.0.rst
rename from pypy/doc/release-1.2.0.txt
rename to pypy/doc/release-1.2.0.rst
diff --git a/pypy/doc/release-1.3.0.txt b/pypy/doc/release-1.3.0.rst
rename from pypy/doc/release-1.3.0.txt
rename to pypy/doc/release-1.3.0.rst
diff --git a/pypy/doc/release-1.4.0.txt b/pypy/doc/release-1.4.0.rst
rename from pypy/doc/release-1.4.0.txt
rename to pypy/doc/release-1.4.0.rst
diff --git a/pypy/doc/release-1.4.0beta.txt b/pypy/doc/release-1.4.0beta.rst
rename from pypy/doc/release-1.4.0beta.txt
rename to pypy/doc/release-1.4.0beta.rst
diff --git a/pypy/doc/release-1.4.1.txt b/pypy/doc/release-1.4.1.rst
rename from pypy/doc/release-1.4.1.txt
rename to pypy/doc/release-1.4.1.rst
diff --git a/pypy/doc/rffi.txt b/pypy/doc/rffi.rst
rename from pypy/doc/rffi.txt
rename to pypy/doc/rffi.rst
diff --git a/pypy/doc/rlib.txt b/pypy/doc/rlib.rst
rename from pypy/doc/rlib.txt
rename to pypy/doc/rlib.rst
--- a/pypy/doc/rlib.txt
+++ b/pypy/doc/rlib.rst
@@ -14,8 +14,8 @@
 to change at some point.  Usually it is useful to look at the tests in
 `pypy/rlib/test`_ to get an impression of how to use a module.
 
-.. _`pypy/rlib`: ../../pypy/rlib
-.. _`pypy/rlib/test`: ../../pypy/rlib/test
+.. _`pypy/rlib`: ../../../../pypy/rlib
+.. _`pypy/rlib/test`: ../../../../pypy/rlib/test
 
 ``listsort``
 ============
@@ -29,7 +29,7 @@
 be sorted using the ``listsort`` module in one program, otherwise the annotator
 will be confused.
 
-.. _listsort: ../../pypy/rlib/listsort.py
+.. _listsort: ../../../../pypy/rlib/listsort.py
 
 ``nonconst``
 ============
@@ -41,7 +41,7 @@
 ``NonConst`` will behave during annotation like that value, but no constant
 folding will happen.
 
-.. _nonconst: ../../pypy/rlib/nonconst.py
+.. _nonconst: ../../../../pypy/rlib/nonconst.py
 .. _`flow object space`: objspace.html#the-flow-object-space
 .. _`annotator`: translation.html#the-annotation-pass
 
@@ -95,7 +95,7 @@
     won't be allocated but represented by *tagged pointers**, that is pointers
     that have the lowest bit set.
 
-.. _objectmodel: ../../pypy/rlib/objectmodel.py
+.. _objectmodel: ../../../../pypy/rlib/objectmodel.py
 
 
 ``rarithmetic``
@@ -105,7 +105,7 @@
 in the behaviour of arithmetic code in regular Python and RPython code. Most of
 them are already described in the `coding guide`_
 
-.. _rarithmetic: ../../pypy/rlib/rarithmetic.py
+.. _rarithmetic: ../../../../pypy/rlib/rarithmetic.py
 .. _`coding guide`: coding-guide.html
 
 
@@ -122,7 +122,7 @@
 these underscores left out for better readability (so ``a.add(b)`` can be used
 to add two rbigint instances).
 
-.. _rbigint: ../../pypy/rlib/rbigint.py
+.. _rbigint: ../../../../pypy/rlib/rbigint.py
 
 
 ``rrandom``
@@ -133,7 +133,7 @@
 ``random`` method which returns a pseudo-random floating point number between
 0.0 and 1.0.
 
-.. _rrandom: ../../pypy/rlib/rrandom.py
+.. _rrandom: ../../../../pypy/rlib/rrandom.py
 
 ``rsocket``
 ===========
@@ -145,7 +145,7 @@
 so on, which is not suitable for RPython.  Instead, ``rsocket`` contains
 a hierarchy of Address classes, in a typical static-OO-programming style.
 
-.. _rsocket: ../../pypy/rlib/rsocket.py
+.. _rsocket: ../../../../pypy/rlib/rsocket.py
 
 
 ``rstack``
@@ -210,7 +210,7 @@
 
     f()
 
-.. _rstack: ../../pypy/rlib/rstack.py
+.. _rstack: ../../../../pypy/rlib/rstack.py
 
 
 ``streamio``
@@ -220,7 +220,7 @@
 by Guido van Rossum as `sio.py`_ in the CPython sandbox as a prototype for the
 upcoming new file implementation in Python 3000).
 
-.. _streamio: ../../pypy/rlib/streamio.py
+.. _streamio: ../../../../pypy/rlib/streamio.py
 .. _`sio.py`: http://svn.python.org/view/sandbox/trunk/sio/sio.py
 
 ``unroll``
@@ -230,7 +230,7 @@
 which wraps an iterator. Looping over the iterator in RPython code will not
 produce a loop in the resulting flow graph but will unroll the loop instead.
 
-.. _unroll: ../../pypy/rlib/unroll.py
+.. _unroll: ../../../../pypy/rlib/unroll.py
 
 ``parsing``
 ===========
@@ -359,7 +359,7 @@
 of the nonterminal and ``children`` which is a list of the children attributes.
 
 
-.. _`pypy.rlib.parsing.tree`: ../../pypy/rlib/parsing/tree.py
+.. _`pypy.rlib.parsing.tree`: ../../../../pypy/rlib/parsing/tree.py
 
 Visitors
 ++++++++
@@ -531,5 +531,5 @@
 
 
 .. _`Prolog interpreter`: http://codespeak.net/svn/pypy/lang/prolog/
-.. _parsing: ../../pypy/rlib/parsing/
+.. _parsing: ../../../../pypy/rlib/parsing/
 .. _`json format`: http://www.json.org
diff --git a/pypy/doc/rtyper.txt b/pypy/doc/rtyper.rst
rename from pypy/doc/rtyper.txt
rename to pypy/doc/rtyper.rst
--- a/pypy/doc/rtyper.txt
+++ b/pypy/doc/rtyper.rst
@@ -2,7 +2,7 @@
 =================
 
 .. contents::
-.. sectnum::
+
 
 The RPython Typer lives in the directory `pypy/rpython/`_.
 
@@ -791,4 +791,4 @@
         assert res == ~3
 
 .. _annotator: translation.html#the-annotation-pass
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/sandbox.txt b/pypy/doc/sandbox.rst
rename from pypy/doc/sandbox.txt
rename to pypy/doc/sandbox.rst
--- a/pypy/doc/sandbox.txt
+++ b/pypy/doc/sandbox.rst
@@ -1,3 +1,7 @@
+.. include:: crufty.rst
+
+     .. ^^ it continues to work, but is unmaintained
+
 PyPy's sandboxing features
 ==========================
 
diff --git a/pypy/doc/sprint-reports.txt b/pypy/doc/sprint-reports.rst
rename from pypy/doc/sprint-reports.txt
rename to pypy/doc/sprint-reports.rst
--- a/pypy/doc/sprint-reports.txt
+++ b/pypy/doc/sprint-reports.rst
@@ -78,3 +78,6 @@
     .. _`CERN (July 2010)`: http://morepypy.blogspot.com/2010/07/cern-sprint-report-wrapping-c-libraries.html
     .. _`D&#252;sseldorf (October 2010)`: http://morepypy.blogspot.com/2010/10/dusseldorf-sprint-report-2010.html
 
+Further event notes:
+
+* :ref:`eventhistory.rst`
diff --git a/pypy/doc/stackless.txt b/pypy/doc/stackless.rst
rename from pypy/doc/stackless.txt
rename to pypy/doc/stackless.rst
--- a/pypy/doc/stackless.txt
+++ b/pypy/doc/stackless.rst
@@ -2,9 +2,15 @@
          Application-level Stackless features
 ==========================================================
 
+
+
 Introduction
 ================
 
+.. include:: crufty.rst
+
+   .. apparently this still works; needs JIT integration; hasn't been maintained for years
+
 PyPy can expose to its user language features similar to the ones
 present in `Stackless Python`_: **no recursion depth limit**, and the
 ability to write code in a **massively concurrent style**.  It actually
@@ -619,4 +625,4 @@
 .. _`documentation of the greenlets`: http://codespeak.net/svn/greenlet/trunk/doc/greenlet.txt
 .. _`Stackless Transform`: translation.html#the-stackless-transform
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/statistic/index.txt b/pypy/doc/statistic/index.rst
rename from pypy/doc/statistic/index.txt
rename to pypy/doc/statistic/index.rst
diff --git a/pypy/doc/svn-help.txt b/pypy/doc/svn-help.rst
rename from pypy/doc/svn-help.txt
rename to pypy/doc/svn-help.rst
diff --git a/pypy/doc/test_redirections.py b/pypy/doc/test_redirections.py
deleted file mode 100644
--- a/pypy/doc/test_redirections.py
+++ /dev/null
@@ -1,54 +0,0 @@
-
-import py 
-redir = py.path.local(__file__).dirpath('redirections') 
-
-def checkexist(path):
-    print "checking", path
-    assert path.ext == '.html'
-    assert path.new(ext='.txt').check(file=1) 
-
-def checkredirection(oldname, newname):
-    print "checking", newname
-    if not newname.startswith('http://'):
-        newpath = redir.dirpath(newname.split('#')[0])
-        checkexist(newpath)
-    # HACK: create the redirecting HTML file here...
-    # XXX obscure fishing
-    if py.test.config.option.generateredirections and '#' not in oldname:
-        generate_redirection(oldname, newname)
-
-def test_eval(): 
-    d = eval(redir.read(mode='r')) 
-    return d
-
-def test_redirections(): 
-    d = test_eval() 
-    for oldname, newname in d.items():
-        yield checkredirection, oldname, newname
-
-def test_navlist(): 
-    navlist = eval(redir.dirpath('navlist').read())
-    for entry in navlist:
-        yield checkexist, redir.dirpath(entry)
-
-# ____________________________________________________________
-
-def generate_redirection(oldname, newname):
-    print "redirecting from", oldname
-    oldpath = redir.dirpath(oldname)
-    url = newname    # relative URL
-    oldpath.write("""<html>
-    <head>
-        <meta http-equiv="refresh"
-              content="0 ; URL=%s" />
-        <META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
-        <META HTTP-EQUIV="expires" CONTENT="0">
-    </head>
-    <body>
-        <p>
-            you should be automatically redirected to
-            <a href="%s">%s</a>
-        </p>
-    </body>
-</html>
-""" % (url, url, url))
diff --git a/pypy/doc/theory.txt b/pypy/doc/theory.rst
rename from pypy/doc/theory.txt
rename to pypy/doc/theory.rst
--- a/pypy/doc/theory.txt
+++ b/pypy/doc/theory.rst
@@ -1,9 +1,13 @@
+.. include:: crufty.rst
+
+     .. ^^ old ideas; we're not doing it this way any more
+
 ===================================
 Techniques used in PyPy
 ===================================
 
 .. contents::
-.. sectnum::
+
 
 .. _`abstract interpretation`: 
     
diff --git a/pypy/doc/translation-aspects.txt b/pypy/doc/translation-aspects.rst
rename from pypy/doc/translation-aspects.txt
rename to pypy/doc/translation-aspects.rst
--- a/pypy/doc/translation-aspects.txt
+++ b/pypy/doc/translation-aspects.rst
@@ -1,9 +1,12 @@
+.. include:: crufty.rst
+.. ^^ old and needs updating
+
 ==========================================================================================
 Memory management and threading models as translation aspects -- solutions and challenges
 ==========================================================================================
 
 .. contents::
-.. sectnum::
+
 
 Introduction
 =============
diff --git a/pypy/doc/translation.txt b/pypy/doc/translation.rst
rename from pypy/doc/translation.txt
rename to pypy/doc/translation.rst
--- a/pypy/doc/translation.txt
+++ b/pypy/doc/translation.rst
@@ -3,7 +3,7 @@
 =====================
 
 .. contents::
-.. sectnum::
+
 
 This document describes the tool chain that we have developed to analyze
 and "compile" RPython_ programs (like PyPy itself) to various target
@@ -107,7 +107,7 @@
 .. _`abstract interpretation`: theory.html#abstract-interpretation
 .. _`Flow Object Space`: objspace.html#the-flow-object-space
 .. _`interactive interface`: getting-started-dev.html#try-out-the-translator
-.. _`translatorshell.py`: ../../pypy/bin/translatorshell.py
+.. _`translatorshell.py`: ../../../../pypy/bin/translatorshell.py
 
 .. _`flow model`:
 .. _`control flow graphs`: 
@@ -274,7 +274,7 @@
     should not attempt to actually mutate such Constants.
 
 .. _`document describing object spaces`: objspace.html
-.. _`pypy.objspace.flow.model`: ../objspace/flow/model.py
+.. _`pypy.objspace.flow.model`: ../../../../pypy/objspace/flow/model.py
 
 
 .. _Annotator:
@@ -768,4 +768,4 @@
 collection of functions (which may refer to each other in a mutually
 recursive fashion) and annotate and rtype them all at once.
 
-.. include:: _ref.txt
+.. include:: _ref.rst
diff --git a/pypy/doc/video-index.txt b/pypy/doc/video-index.rst
rename from pypy/doc/video-index.txt
rename to pypy/doc/video-index.rst
diff --git a/pypy/doc/windows.txt b/pypy/doc/windows.rst
rename from pypy/doc/windows.txt
rename to pypy/doc/windows.rst
--- a/pypy/doc/windows.txt
+++ b/pypy/doc/windows.rst
@@ -1,6 +1,6 @@
-=============
-Windows Hints
-=============
+===============
+PyPy on Windows
+===============
 
 Pypy is supported on Windows platforms, starting with Windows 2000.
 The following text gives some hints about how to translate the PyPy
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -77,13 +77,13 @@
         if i == 2:
             return self.kwargname
         raise IndexError
-        
+
 
 
 class Arguments(object):
     """
     Collects the arguments of a function call.
-    
+
     Instances should be considered immutable.
     """
 
@@ -146,7 +146,7 @@
             self._combine_starstarargs_wrapped(w_starstararg)
 
     def _combine_starargs_wrapped(self, w_stararg):
-        # unpack the * arguments 
+        # unpack the * arguments
         space = self.space
         try:
             args_w = space.fixedview(w_stararg)
@@ -236,10 +236,10 @@
         if self.arguments_w:
             return self.arguments_w[0]
         return None
-        
+
     ###  Parsing for function calls  ###
 
-    def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=[],
+    def _match_signature(self, w_firstarg, scope_w, signature, defaults=None,
                          blindargs=0):
         """Parse args and kwargs according to the signature of a code object,
         or raise an ArgErr in case of failure.
@@ -247,19 +247,19 @@
         """
         if jit.we_are_jitted() and self._dont_jit:
             return self._match_signature_jit_opaque(w_firstarg, scope_w,
-                                                    signature, defaults_w,
+                                                    signature, defaults,
                                                     blindargs)
         return self._really_match_signature(w_firstarg, scope_w, signature,
-                                            defaults_w, blindargs)
+                                            defaults, blindargs)
 
     @jit.dont_look_inside
     def _match_signature_jit_opaque(self, w_firstarg, scope_w, signature,
-                                    defaults_w, blindargs):
+                                    defaults, blindargs):
         return self._really_match_signature(w_firstarg, scope_w, signature,
-                                            defaults_w, blindargs)
+                                            defaults, blindargs)
 
     @jit.unroll_safe
-    def _really_match_signature(self, w_firstarg, scope_w, signature, defaults_w=[],
+    def _really_match_signature(self, w_firstarg, scope_w, signature, defaults=None,
                                 blindargs=0):
         #
         #   args_w = list of the normal actual parameters, wrapped
@@ -283,10 +283,10 @@
                 scope_w[0] = w_firstarg
                 input_argcount = 1
             else:
-                extravarargs = [ w_firstarg ]
+                extravarargs = [w_firstarg]
         else:
             upfront = 0
-        
+
         args_w = self.arguments_w
         num_args = len(args_w)
 
@@ -327,7 +327,7 @@
         elif avail > co_argcount:
             raise ArgErrCount(avail, num_kwds,
                               co_argcount, has_vararg, has_kwarg,
-                              defaults_w, 0)
+                              defaults, 0)
 
         # the code assumes that keywords can potentially be large, but that
         # argnames is typically not too large
@@ -357,12 +357,12 @@
                     num_remainingkwds -= 1
         missing = 0
         if input_argcount < co_argcount:
-            def_first = co_argcount - len(defaults_w)
+            def_first = co_argcount - (0 if defaults is None else defaults.getlen())
             for i in range(input_argcount, co_argcount):
                 if scope_w[i] is not None:
                     pass
                 elif i >= def_first:
-                    scope_w[i] = defaults_w[i-def_first]
+                    scope_w[i] = defaults.getitem(i - def_first)
                 else:
                     # error: not enough arguments.  Don't signal it immediately
                     # because it might be related to a problem with */** or
@@ -382,20 +382,20 @@
             if co_argcount == 0:
                 raise ArgErrCount(avail, num_kwds,
                               co_argcount, has_vararg, has_kwarg,
-                              defaults_w, missing)
+                              defaults, missing)
             raise ArgErrUnknownKwds(num_remainingkwds, keywords, used_keywords)
 
         if missing:
             raise ArgErrCount(avail, num_kwds,
                               co_argcount, has_vararg, has_kwarg,
-                              defaults_w, missing)
+                              defaults, missing)
 
         return co_argcount + has_vararg + has_kwarg
-    
+
 
 
     def parse_into_scope(self, w_firstarg,
-                         scope_w, fnname, signature, defaults_w=[]):
+                         scope_w, fnname, signature, defaults=None):
         """Parse args and kwargs to initialize a frame
         according to the signature of code object.
         Store the argumentvalues into scope_w.
@@ -403,32 +403,32 @@
         """
         try:
             return self._match_signature(w_firstarg,
-                                         scope_w, signature, defaults_w, 0)
+                                         scope_w, signature, defaults, 0)
         except ArgErr, e:
             raise OperationError(self.space.w_TypeError,
                                  self.space.wrap(e.getmsg(fnname)))
 
-    def _parse(self, w_firstarg, signature, defaults_w, blindargs=0):
+    def _parse(self, w_firstarg, signature, defaults, blindargs=0):
         """Parse args and kwargs according to the signature of a code object,
         or raise an ArgErr in case of failure.
         """
         scopelen = signature.scope_length()
         scope_w = [None] * scopelen
-        self._match_signature(w_firstarg, scope_w, signature, defaults_w,
+        self._match_signature(w_firstarg, scope_w, signature, defaults,
                               blindargs)
-        return scope_w    
+        return scope_w
 
 
     def parse_obj(self, w_firstarg,
-                  fnname, signature, defaults_w=[], blindargs=0):
+                  fnname, signature, defaults=None, blindargs=0):
         """Parse args and kwargs to initialize a frame
         according to the signature of code object.
         """
         try:
-            return self._parse(w_firstarg, signature, defaults_w, blindargs)
+            return self._parse(w_firstarg, signature, defaults, blindargs)
         except ArgErr, e:
             raise OperationError(self.space.w_TypeError,
-                                 self.space.wrap(e.getmsg(fnname)))        
+                                 self.space.wrap(e.getmsg(fnname)))
 
     @staticmethod
     def frompacked(space, w_args=None, w_kwds=None):
@@ -473,24 +473,24 @@
                                        self.w_starstararg)
 
 
-            
-    def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=[],
+
+    def _match_signature(self, w_firstarg, scope_w, signature, defaults=None,
                          blindargs=0):
         self.combine_if_necessary()
         # _match_signature is destructive
         return Arguments._match_signature(
                self, w_firstarg, scope_w, signature,
-               defaults_w, blindargs)
+               defaults, blindargs)
 
     def unpack(self):
         self.combine_if_necessary()
         return Arguments.unpack(self)
 
-    def match_signature(self, signature, defaults_w):
+    def match_signature(self, signature, defaults):
         """Parse args and kwargs according to the signature of a code object,
         or raise an ArgErr in case of failure.
         """
-        return self._parse(None, signature, defaults_w)
+        return self._parse(None, signature, defaults)
 
     def unmatch_signature(self, signature, data_w):
         """kind of inverse of match_signature"""
@@ -513,10 +513,10 @@
             for w_key in space.unpackiterable(data_w_starargarg):
                 key = space.str_w(w_key)
                 w_value = space.getitem(data_w_starargarg, w_key)
-                unfiltered_kwds_w[key] = w_value            
+                unfiltered_kwds_w[key] = w_value
             cnt += 1
         assert len(data_w) == cnt
-        
+
         ndata_args_w = len(data_args_w)
         if ndata_args_w >= need_cnt:
             args_w = data_args_w[:need_cnt]
@@ -532,19 +532,19 @@
             for i in range(0, len(stararg_w)):
                 args_w[i + datalen] = stararg_w[i]
             assert len(args_w) == need_cnt
-            
+
         keywords = []
         keywords_w = []
         for key in need_kwds:
             keywords.append(key)
             keywords_w.append(unfiltered_kwds_w[key])
-                    
+
         return ArgumentsForTranslation(self.space, args_w, keywords, keywords_w)
 
     @staticmethod
     def frompacked(space, w_args=None, w_kwds=None):
         raise NotImplementedError("go away")
-    
+
     @staticmethod
     def fromshape(space, (shape_cnt,shape_keys,shape_star,shape_stst), data_w):
         args_w = data_w[:shape_cnt]
@@ -596,23 +596,23 @@
 #
 
 class ArgErr(Exception):
-    
+
     def getmsg(self, fnname):
         raise NotImplementedError
 
 class ArgErrCount(ArgErr):
 
     def __init__(self, got_nargs, nkwds, expected_nargs, has_vararg, has_kwarg,
-                 defaults_w, missing_args):
+                 defaults, missing_args):
         self.expected_nargs = expected_nargs
         self.has_vararg = has_vararg
         self.has_kwarg = has_kwarg
-        
-        self.num_defaults = len(defaults_w)
+
+        self.num_defaults = 0 if defaults is None else defaults.getlen()
         self.missing_args = missing_args
         self.num_args = got_nargs
         self.num_kwds = nkwds
-        
+
     def getmsg(self, fnname):
         args = None
         #args_w, kwds_w = args.unpack()
@@ -620,7 +620,7 @@
         n = self.expected_nargs
         if n == 0:
             msg = "%s() takes no argument (%d given)" % (
-                fnname, 
+                fnname,
                 nargs)
         else:
             defcount = self.num_defaults
diff --git a/pypy/interpreter/astcompiler/ast.py b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -3590,6 +3590,8 @@
     try:
         obj = space.interp_w(operator, w_new_value)
         w_self.op = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'op', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
@@ -4824,6 +4826,8 @@
     try:
         obj = space.interp_w(boolop, w_new_value)
         w_self.op = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'op', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
@@ -4911,6 +4915,8 @@
     try:
         obj = space.interp_w(operator, w_new_value)
         w_self.op = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'op', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
@@ -4980,6 +4986,8 @@
     try:
         obj = space.interp_w(unaryop, w_new_value)
         w_self.op = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'op', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
@@ -6028,6 +6036,8 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
@@ -6118,6 +6128,8 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
@@ -6187,6 +6199,8 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
@@ -6252,6 +6266,8 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
@@ -6318,6 +6334,8 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
+        # need to save the original object too
+        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -454,6 +454,9 @@
                                   (field.type,), 2)
                     self.emit("w_self.%s = obj.to_simple_int(space)" %
                               (field.name,), 2)
+                    self.emit("# need to save the original object too", 2)
+                    self.emit("w_self.setdictvalue(space, '%s', w_new_value)"
+                              % (field.name,), 2)
                 else:
                     config = (field.name, field.type, repr(field.opt))
                     self.emit("w_self.%s = space.interp_w(%s, w_new_value, %s)" %
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -365,7 +365,11 @@
 
     def setbuiltinmodule(self, importname):
         """NOT_RPYTHON. load a lazy pypy/module and put it into sys.modules"""
-        fullname = "pypy.module.%s" % importname
+        if '.' in importname:
+            fullname = importname
+            importname = fullname.rsplit('.', 1)[1]
+        else:
+            fullname = "pypy.module.%s" % importname
 
         Module = __import__(fullname,
                             None, None, ["Module"]).Module
@@ -428,6 +432,11 @@
             if value and name not in modules:
                 modules.append(name)
 
+        if self.config.objspace.extmodules:
+            for name in self.config.objspace.extmodules.split(','):
+                if name not in modules:
+                    modules.append(name)
+
         # a bit of custom logic: time2 or rctime take precedence over time
         # XXX this could probably be done as a "requires" in the config
         if ('time2' in modules or 'rctime' in modules) and 'time' in modules:
@@ -745,7 +754,12 @@
         """Unpack an iterable object into a real (interpreter-level) list.
         Raise an OperationError(w_ValueError) if the length is wrong."""
         w_iterator = self.iter(w_iterable)
-        items = []
+        # If we know the expected length we can preallocate.
+        if expected_length == -1:
+            items = []
+        else:
+            items = [None] * expected_length
+        idx = 0
         while True:
             try:
                 w_item = self.next(w_iterator)
@@ -753,19 +767,22 @@
                 if not e.match(self, self.w_StopIteration):
                     raise
                 break  # done
-            if expected_length != -1 and len(items) == expected_length:
+            if expected_length != -1 and idx == expected_length:
                 raise OperationError(self.w_ValueError,
                                      self.wrap("too many values to unpack"))
-            items.append(w_item)
-        if expected_length != -1 and len(items) < expected_length:
-            i = len(items)
-            if i == 1:
+            if expected_length == -1:
+                items.append(w_item)
+            else:
+                items[idx] = w_item
+            idx += 1
+        if expected_length != -1 and idx < expected_length:
+            if idx == 1:
                 plural = ""
             else:
                 plural = "s"
             raise OperationError(self.w_ValueError,
                       self.wrap("need more than %d value%s to unpack" %
-                                (i, plural)))
+                                (idx, plural)))
         return items
 
     unpackiterable_unroll = jit.unroll_safe(func_with_new_name(unpackiterable,
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -21,6 +21,21 @@
     assert not func.can_change_code
     return func.code
 
+class Defaults(object):
+    _immutable_fields_ = ["items[*]"]
+
+    def __init__(self, items):
+        self.items = items
+
+    def getitems(self):
+        return jit.hint(self, promote=True).items
+
+    def getitem(self, idx):
+        return self.getitems()[idx]
+
+    def getlen(self):
+        return len(self.getitems())
+
 class Function(Wrappable):
     """A function is a code object captured with some environment:
     an object space, a dictionary of globals, default arguments,
@@ -36,8 +51,7 @@
         self.code = code       # Code instance
         self.w_func_globals = w_globals  # the globals dictionary
         self.closure   = closure    # normally, list of Cell instances or None
-        self.defs_w    = defs_w     # list of w_default's
-        make_sure_not_resized(self.defs_w)
+        self.defs = Defaults(defs_w)     # wrapper around list of w_default's
         self.w_func_dict = None # filled out below if needed
         self.w_module = None
 
@@ -87,7 +101,7 @@
                 assert isinstance(code, gateway.BuiltinCode4)
                 return code.fastcall_4(self.space, self, args_w[0],
                                        args_w[1], args_w[2], args_w[3])
-        elif (nargs|PyCode.FLATPYCALL) == fast_natural_arity:
+        elif (nargs | PyCode.FLATPYCALL) == fast_natural_arity:
             assert isinstance(code, PyCode)
             if nargs < 5:
                 new_frame = self.space.createframe(code, self.w_func_globals,
@@ -129,15 +143,15 @@
                 return code.fastcall_4(self.space, self, frame.peekvalue(3),
                                        frame.peekvalue(2), frame.peekvalue(1),
                                         frame.peekvalue(0))
-        elif (nargs|Code.FLATPYCALL) == fast_natural_arity:
+        elif (nargs | Code.FLATPYCALL) == fast_natural_arity:
             assert isinstance(code, PyCode)
             return self._flat_pycall(code, nargs, frame)
-        elif fast_natural_arity&Code.FLATPYCALL:
-            natural_arity = fast_natural_arity&0xff
-            if natural_arity > nargs >= natural_arity-len(self.defs_w):
+        elif fast_natural_arity & Code.FLATPYCALL:
+            natural_arity = fast_natural_arity & 0xff
+            if natural_arity > nargs >= natural_arity - self.defs.getlen():
                 assert isinstance(code, PyCode)
                 return self._flat_pycall_defaults(code, nargs, frame,
-                                                  natural_arity-nargs)
+                                                  natural_arity - nargs)
         elif fast_natural_arity == Code.PASSTHROUGHARGS1 and nargs >= 1:
             assert isinstance(code, gateway.BuiltinCodePassThroughArguments1)
             w_obj = frame.peekvalue(nargs-1)
@@ -167,12 +181,12 @@
             w_arg = frame.peekvalue(nargs-1-i)
             new_frame.fastlocals_w[i] = w_arg
 
-        defs_w = self.defs_w
-        ndefs = len(defs_w)
-        start = ndefs-defs_to_load
+        defs = self.defs
+        ndefs = defs.getlen()
+        start = ndefs - defs_to_load
         i = nargs
         for j in xrange(start, ndefs):
-            new_frame.fastlocals_w[i] = defs_w[j]
+            new_frame.fastlocals_w[i] = defs.getitem(j)
             i += 1
         return new_frame.run()
 
@@ -182,8 +196,10 @@
         return self.w_func_dict
 
     def setdict(self, space, w_dict):
-        if not space.is_true(space.isinstance( w_dict, space.w_dict )):
-            raise OperationError( space.w_TypeError, space.wrap("setting function's dictionary to a non-dict") )
+        if not space.isinstance_w(w_dict, space.w_dict):
+            raise OperationError(space.w_TypeError,
+                space.wrap("setting function's dictionary to a non-dict")
+            )
         self.w_func_dict = w_dict
 
     def descr_function__new__(space, w_subtype, w_code, w_globals,
@@ -286,7 +302,7 @@
             w(self.code),
             w_func_globals,
             w_closure,
-            nt(self.defs_w),
+            nt(self.defs.getitems()),
             w_func_dict,
             self.w_module,
         ]
@@ -296,7 +312,7 @@
         from pypy.interpreter.pycode import PyCode
         args_w = space.unpackiterable(w_args)
         try:
-            (w_name, w_doc, w_code, w_func_globals, w_closure, w_defs_w,
+            (w_name, w_doc, w_code, w_func_globals, w_closure, w_defs,
              w_func_dict, w_module) = args_w
         except ValueError:
             # wrong args
@@ -321,25 +337,28 @@
         if space.is_w(w_func_dict, space.w_None):
             w_func_dict = None
         self.w_func_dict = w_func_dict
-        self.defs_w    = space.fixedview(w_defs_w)
+        self.defs = Defaults(space.fixedview(w_defs))
         self.w_module = w_module
 
     def fget_func_defaults(self, space):
-        values_w = self.defs_w
+        values_w = self.defs.getitems()
+        # the `None in values_w` check here is to ensure that interp-level
+        # functions with a default of NoneNotWrapped do not get their defaults
+        # exposed at applevel
         if not values_w or None in values_w:
             return space.w_None
         return space.newtuple(values_w)
 
     def fset_func_defaults(self, space, w_defaults):
         if space.is_w(w_defaults, space.w_None):
-            self.defs_w = []
+            self.defs = Defaults([])
             return
         if not space.is_true(space.isinstance(w_defaults, space.w_tuple)):
             raise OperationError( space.w_TypeError, space.wrap("func_defaults must be set to a tuple object or None") )
-        self.defs_w = space.fixedview(w_defaults)
+        self.defs = Defaults(space.fixedview(w_defaults))
 
     def fdel_func_defaults(self, space):
-        self.defs_w = []
+        self.defs = Defaults([])
 
     def fget_func_doc(self, space):
         if self.w_doc is None:
@@ -369,7 +388,7 @@
     def fget___module__(self, space):
         if self.w_module is None:
             if self.w_func_globals is not None and not space.is_w(self.w_func_globals, space.w_None):
-                self.w_module = space.call_method( self.w_func_globals, "get", space.wrap("__name__") )
+                self.w_module = space.call_method(self.w_func_globals, "get", space.wrap("__name__"))
             else:
                 self.w_module = space.w_None
         return self.w_module
@@ -601,7 +620,7 @@
     def __init__(self, func):
         assert isinstance(func, Function)
         Function.__init__(self, func.space, func.code, func.w_func_globals,
-                          func.defs_w, func.closure, func.name)
+                          func.defs.getitems(), func.closure, func.name)
         self.w_doc = func.w_doc
         self.w_func_dict = func.w_func_dict
         self.w_module = func.w_module
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -13,7 +13,7 @@
 NoneNotWrapped = object()
 
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.interpreter.error import OperationError 
+from pypy.interpreter.error import OperationError
 from pypy.interpreter import eval
 from pypy.interpreter.function import Function, Method, ClassMethod
 from pypy.interpreter.function import FunctionWithFixedCode
@@ -25,7 +25,7 @@
 from pypy.rlib import rstackovf
 from pypy.rlib.objectmodel import we_are_translated
 
-# internal non-translatable parts: 
+# internal non-translatable parts:
 import py
 
 class SignatureBuilder(object):
@@ -78,13 +78,13 @@
         dispatch = self.dispatch
         for el in unwrap_spec:
             dispatch(el, *extra)
-            
+
 class UnwrapSpecEmit(UnwrapSpecRecipe):
 
     def __init__(self):
         self.n = 0
         self.miniglobals = {}
-        
+
     def succ(self):
         n = self.n
         self.n += 1
@@ -94,7 +94,7 @@
         name = obj.__name__
         self.miniglobals[name] = obj
         return name
-    
+
 #________________________________________________________________
 
 class UnwrapSpec_Check(UnwrapSpecRecipe):
@@ -147,7 +147,7 @@
             "unwrapped %s argument %s of built-in function %r should "
             "not start with 'w_'" % (name, argname, self.func))
         app_sig.append(argname)
-        
+
     def visit__ObjSpace(self, el, app_sig):
         self.orig_arg()
 
@@ -173,7 +173,7 @@
             (argname, self.func))
         assert app_sig.varargname is None,(
             "built-in function %r has conflicting rest args specs" % self.func)
-        app_sig.varargname = argname[:-2]    
+        app_sig.varargname = argname[:-2]
 
     def visit_w_args(self, el, app_sig):
         argname = self.orig_arg()
@@ -199,7 +199,7 @@
 
     def scopenext(self):
         return "scope_w[%d]" % self.succ()
-    
+
     def visit_function(self, (func, cls)):
         self.run_args.append("%s(%s)" % (self.use(func),
                                          self.scopenext()))
@@ -207,7 +207,7 @@
     def visit_self(self, typ):
         self.run_args.append("space.descr_self_interp_w(%s, %s)" %
                              (self.use(typ), self.scopenext()))
-        
+
     def visit__Wrappable(self, typ):
         self.run_args.append("space.interp_w(%s, %s)" % (self.use(typ),
                                                          self.scopenext()))
@@ -265,7 +265,7 @@
                 "unexpected: same spec, different run_args")
             return activation_factory_cls
         except KeyError:
-            parts = []          
+            parts = []
             for el in unwrap_spec:
                 if isinstance(el, tuple):
                     parts.append(''.join([getattr(subel, '__name__', subel)
@@ -276,7 +276,7 @@
             #print label
 
             d = {}
-            source = """if 1: 
+            source = """if 1:
                 def _run(self, space, scope_w):
                     return self.behavior(%s)
                 \n""" % (', '.join(self.run_args),)
@@ -326,7 +326,7 @@
         self.finger += 1
         if self.n > 4:
             raise FastFuncNotSupported
-        
+
     def nextarg(self):
         arg = "w%d" % self.succ()
         self.args.append(arg)
@@ -405,7 +405,7 @@
                     raise FastFuncNotSupported
             d = {}
             unwrap_info.miniglobals['func'] = func
-            source = """if 1: 
+            source = """if 1:
                 def fastfunc_%s_%d(%s):
                     return func(%s)
                 \n""" % (func.__name__, narg,
@@ -511,7 +511,7 @@
         # 'w_args' for rest arguments passed as wrapped tuple
         # str,int,float: unwrap argument as such type
         # (function, cls) use function to check/unwrap argument of type cls
-        
+
         # First extract the signature from the (CPython-level) code object
         from pypy.interpreter import pycode
         argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code)
@@ -532,7 +532,7 @@
         else:
             assert descrmismatch is None, (
                 "descrmismatch without a self-type specified")
- 
+
 
         orig_sig = SignatureBuilder(func, argnames, varargname, kwargname)
         app_sig = SignatureBuilder(func)
@@ -594,7 +594,7 @@
         space = func.space
         activation = self.activation
         scope_w = args.parse_obj(w_obj, func.name, self.sig,
-                                 func.defs_w, self.minargs)
+                                 func.defs, self.minargs)
         try:
             w_result = activation._run(space, scope_w)
         except DescrMismatch:
@@ -615,10 +615,10 @@
             if not we_are_translated():
                 raise
             raise e
-        except KeyboardInterrupt: 
+        except KeyboardInterrupt:
             raise OperationError(space.w_KeyboardInterrupt,
-                                 space.w_None) 
-        except MemoryError: 
+                                 space.w_None)
+        except MemoryError:
             raise OperationError(space.w_MemoryError, space.w_None)
         except rstackovf.StackOverflow, e:
             rstackovf.check_stack_overflow()
@@ -668,7 +668,7 @@
 class BuiltinCode0(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 0
-    
+
     def fastcall_0(self, space, w_func):
         try:
             w_result = self.fastfunc_0(space)
@@ -684,7 +684,7 @@
 class BuiltinCode1(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 1
-    
+
     def fastcall_1(self, space, w_func, w1):
         try:
             w_result = self.fastfunc_1(space, w1)
@@ -702,7 +702,7 @@
 class BuiltinCode2(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 2
-    
+
     def fastcall_2(self, space, w_func, w1, w2):
         try:
             w_result = self.fastfunc_2(space, w1, w2)
@@ -720,7 +720,7 @@
 class BuiltinCode3(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 3
-    
+
     def fastcall_3(self, space, func, w1, w2, w3):
         try:
             w_result = self.fastfunc_3(space, w1, w2, w3)
@@ -738,7 +738,7 @@
 class BuiltinCode4(BuiltinCode):
     _immutable_ = True
     fast_natural_arity = 4
-    
+
     def fastcall_4(self, space, func, w1, w2, w3, w4):
         try:
             w_result = self.fastfunc_4(space, w1, w2, w3, w4)
@@ -770,7 +770,7 @@
     NOT_RPYTHON_ATTRIBUTES = ['_staticdefs']
 
     instancecache = {}
-    
+
     def __new__(cls, f, app_name=None, unwrap_spec = None,
                 descrmismatch=None, as_classmethod=False):
 
@@ -846,17 +846,17 @@
         return fn
 
 
-# 
-# the next gateways are to be used only for 
-# temporary/initialization purposes 
-     
-class interp2app_temp(interp2app): 
+#
+# the next gateways are to be used only for
+# temporary/initialization purposes
+
+class interp2app_temp(interp2app):
     "NOT_RPYTHON"
-    def getcache(self, space): 
+    def getcache(self, space):
         return self.__dict__.setdefault(space, GatewayCache(space))
 
 
-# and now for something completely different ... 
+# and now for something completely different ...
 #
 
 class ApplevelClass:
@@ -896,14 +896,14 @@
         from pypy.interpreter.module import Module
         return Module(space, space.wrap(name), self.getwdict(space))
 
-    def wget(self, space, name): 
-        w_globals = self.getwdict(space) 
+    def wget(self, space, name):
+        w_globals = self.getwdict(space)
         return space.getitem(w_globals, space.wrap(name))
 
     def interphook(self, name):
         "NOT_RPYTHON"
         def appcaller(space, *args_w):
-            if not isinstance(space, ObjSpace): 
+            if not isinstance(space, ObjSpace):
                 raise TypeError("first argument must be a space instance.")
             # redirect if the space handles this specially
             # XXX can this be factored a bit less flow space dependently?
@@ -932,7 +932,7 @@
                                                       args.arguments_w)
             return space.call_args(w_func, args)
         def get_function(space):
-            w_func = self.wget(space, name) 
+            w_func = self.wget(space, name)
             return space.unwrap(w_func)
         appcaller = func_with_new_name(appcaller, name)
         appcaller.get_function = get_function
@@ -1123,15 +1123,15 @@
     myfunc = appdef('''myfunc(x, y):
                            return x+y
                     ''')
-    """ 
-    if not isinstance(source, str): 
+    """
+    if not isinstance(source, str):
         source = py.std.inspect.getsource(source).lstrip()
-        while source.startswith('@py.test.mark.'):
+        while source.startswith(('@py.test.mark.', '@pytest.mark.')):
             # these decorators are known to return the same function
             # object, we may ignore them
             assert '\n' in source
             source = source[source.find('\n') + 1:].lstrip()
-        assert source.startswith("def "), "can only transform functions" 
+        assert source.startswith("def "), "can only transform functions"
         source = source[4:]
     p = source.find('(')
     assert p >= 0
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -86,7 +86,7 @@
         self._init_flags()
         # Precompute what arguments need to be copied into cellvars
         self._args_as_cellvars = []
-        
+
         if self.co_cellvars:
             argcount = self.co_argcount
             assert argcount >= 0     # annotator hint
@@ -146,7 +146,7 @@
 
     def signature(self):
         return self._signature
-    
+
     @classmethod
     def _from_code(cls, space, code, hidden_applevel=False, code_hook=None):
         """ Initialize the code object from a real (CPython) one.
@@ -182,7 +182,7 @@
                       list(code.co_cellvars),
                       hidden_applevel, cpython_magic)
 
-    
+
     def _compute_flatcall(self):
         # Speed hack!
         self.fast_natural_arity = eval.Code.HOPELESS
@@ -192,7 +192,7 @@
             return
         if self.co_argcount > 0xff:
             return
-        
+
         self.fast_natural_arity = eval.Code.FLATPYCALL | self.co_argcount
 
     def funcrun(self, func, args):
@@ -204,7 +204,7 @@
                                       fresh_virtualizable=True)
         args_matched = args.parse_into_scope(None, fresh_frame.fastlocals_w,
                                              func.name,
-                                             sig, func.defs_w)
+                                             sig, func.defs)
         fresh_frame.init_cells()
         return frame.run()
 
@@ -214,10 +214,10 @@
         sig = self._signature
         # speed hack
         fresh_frame = jit.hint(frame, access_directly=True,
-                                      fresh_virtualizable=True)        
+                                      fresh_virtualizable=True)
         args_matched = args.parse_into_scope(w_obj, fresh_frame.fastlocals_w,
                                              func.name,
-                                             sig, func.defs_w)
+                                             sig, func.defs)
         fresh_frame.init_cells()
         return frame.run()
 
@@ -269,7 +269,7 @@
 
     def fget_co_consts(self, space):
         return space.newtuple(self.co_consts_w)
-    
+
     def fget_co_names(self, space):
         return space.newtuple(self.co_names_w)
 
@@ -280,7 +280,7 @@
         return space.newtuple([space.wrap(name) for name in self.co_cellvars])
 


More information about the pypy-commit mailing list