[pypy-svn] r53464 - in pypy/dist/pypy: lib translator/goal

arigo at codespeak.net arigo at codespeak.net
Sun Apr 6 17:41:53 CEST 2008


Author: arigo
Date: Sun Apr  6 17:41:52 2008
New Revision: 53464

Added:
   pypy/dist/pypy/lib/_pypy_interact.py   (contents, props changed)
Modified:
   pypy/dist/pypy/lib/readline.py
   pypy/dist/pypy/translator/goal/app_main.py
Log:
* Move interactive_console() to its own module for easier experimentation.
* Extend the pyrepl-based readline with a multiline_input() function.
* Use it for multiline inputs in the default pypy-c prompt.  Yay :-)


Added: pypy/dist/pypy/lib/_pypy_interact.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/_pypy_interact.py	Sun Apr  6 17:41:52 2008
@@ -0,0 +1,74 @@
+"""Imported by app_main.py when PyPy needs to fire up the interactive console.
+"""
+import sys
+
+
+def interactive_console(mainmodule=None):
+    import code
+    if mainmodule is None:
+        import __main__ as mainmodule
+    console = code.InteractiveConsole(mainmodule.__dict__)
+    try:
+        from readline import multiline_input
+    except ImportError:
+        run_simple_interactive_console(console)
+    else:
+        run_multiline_interactive_console(console)
+
+def run_simple_interactive_console(console):
+    # some parts of code.py are copied here because it seems to be impossible
+    # to start an interactive console without printing at least one line
+    # of banner
+    more = 0
+    while 1:
+        try:
+            if more:
+                prompt = getattr(sys, 'ps2', '... ')
+            else:
+                prompt = getattr(sys, 'ps1', '>>> ')
+            try:
+                line = raw_input(prompt)
+            except EOFError:
+                console.write("\n")
+                break
+            else:
+                more = console.push(line)
+        except KeyboardInterrupt:
+            console.write("\nKeyboardInterrupt\n")
+            console.resetbuffer()
+            more = 0
+
+def run_multiline_interactive_console(console):
+    from readline import multiline_input
+
+    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()
+
+# ____________________________________________________________
+
+if __name__ == '__main__':    # for testing
+    import os
+    if os.getenv('PYTHONSTARTUP'):
+        execfile(os.getenv('PYTHONSTARTUP'))
+    interactive_console()

Modified: pypy/dist/pypy/lib/readline.py
==============================================================================
--- pypy/dist/pypy/lib/readline.py	(original)
+++ pypy/dist/pypy/lib/readline.py	Sun Apr  6 17:41:52 2008
@@ -45,6 +45,38 @@
             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(_ReaderMixin, self).collect_keymap() + (
+            (r'\n', 'maybe-accept'),)
+
+    def __init__(self, console):
+        super(_ReaderMixin, self).__init__(console)
+        from pyrepl import commands
+        class maybe_accept(commands.Command):
+            def do(self):
+                r = self.reader
+                text = r.get_unicode()
+                if r.more_lines is not None and r.more_lines(text):
+                    r.insert("\n")
+                else:
+                    self.finish = 1
+        self.commands['maybe_accept'] = maybe_accept
+        self.commands['maybe-accept'] = maybe_accept
+
 # ____________________________________________________________
 
 class _ReadlineWrapper(object):
@@ -72,6 +104,27 @@
         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 compiler(self, textstring):
+        if self.pyconsole is None:
+            return True
+        else:
+            return self.pyconsole.compile(textstring, '<input>', 'single')
+
     def parse_and_bind(self, string):
         pass  # XXX we don't support parsing GNU-readline-style init files
 
@@ -172,6 +225,9 @@
 add_history = _wrapper.add_history
 set_startup_hook = _wrapper.set_startup_hook
 
+# Extension
+multiline_input = _wrapper.multiline_input
+
 # ____________________________________________________________
 # Stubs
 
@@ -225,11 +281,3 @@
         __builtin__.raw_input = _wrapper.raw_input
 
 _setup()
-
-if __name__ == '__main__':    # for testing
-    import __main__
-    sys.modules['readline'] = __main__
-    if os.getenv('PYTHONSTARTUP'):
-        execfile(os.getenv('PYTHONSTARTUP'))
-    import code
-    code.interact()

Modified: pypy/dist/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/dist/pypy/translator/goal/app_main.py	(original)
+++ pypy/dist/pypy/translator/goal/app_main.py	Sun Apr  6 17:41:52 2008
@@ -337,6 +337,7 @@
             success = run_toplevel(execfile, sys.argv[0], mainmodule.__dict__)
             
         if is_interactive():
+            from _pypy_interact import interactive_console
             success = run_toplevel(interactive_console, mainmodule)
     except SystemExit, e:
         return e.code
@@ -363,35 +364,6 @@
     print ('Type "help", "copyright", "credits" or '
            '"license" for more information.')
 
-def interactive_console(mainmodule):
-    # some parts of code.py are copied here because it seems to be impossible
-    # to start an interactive console without printing at least one line
-    # of banner
-    import code
-    console = code.InteractiveConsole(mainmodule.__dict__)
-    try:
-        import readline
-    except ImportError:
-        pass
-    more = 0
-    while 1:
-        try:
-            if more:
-                prompt = sys.ps2
-            else:
-                prompt = sys.ps1
-            try:
-                line = raw_input(prompt)
-            except EOFError:
-                console.write("\n")
-                break
-            else:
-                more = console.push(line)
-        except KeyboardInterrupt:
-            console.write("\nKeyboardInterrupt\n")
-            console.resetbuffer()
-            more = 0
-
 
 if __name__ == '__main__':
     import autopath



More information about the Pypy-commit mailing list