[IPython-user] pyreadline, code.InteractiveConsole and tab completion on Windows

Thomas Heller theller@ctypes....
Wed Apr 8 14:38:17 CDT 2009


Jörgen Stenarson schrieb:
> Thomas Heller skrev:
>> Jörgen Stenarson schrieb:
>>> Thomas Heller skrev:
>> My Python console isn't started in the usual way because my application is
>> a Windows application.
>> When a certain button is pressed in the GUI, a win32 console is allocated,
>> sys.std[in|out|err] are initialized to readers/writers that read and write to
>> from/to the corresponding console handles, and so on.  Basically the code goes
>> like this:
>> 
>>     windll.kernel32.AllocConsole()
>>     windll.kernel32.SetConsoleTitleA(str(title))
>> 
>>     sys.stdout = writer(windll.kernel32.GetStdHandle(-11))
>>     sys.stderr = writer(windll.kernel32.GetStdHandle(-12))
>>     sys.stdin = reader(windll.kernel32.GetStdHandle(-10))
>> 
> out of curiosity what is reader and writer?
> 
>>     from code import InteractiveConsole
>> 
>>     console = InteractiveConsole(ns)
>>     console.interact(title)
>> 
>> reader(handle) and writer(handle) are instances that read and write from/to
>> the console handles with the windll.kernel32.WriteConsole[A|W]()
>> and windll.kernel32.ReadConsoleW() windows functions.
>> So, is it possible to plug pyreadline into this system somehow?
>> 

I have a running demo script now; it was easier than I thought first.
Basically the trick was to open the input/output streams as "CONIN$"
and "CONOUT$".

<snip ---interp.pyw--->
# Thomas Heller <theller@ctypes.org>, 2009/04/07
#
# This script demonstrated how to use tab-completion with pyreadline
# on Windows in an interactive interpreter implemented by the code
# module.  It also works when started from a GUI-program (as .pyw
# script, for example).
import code, ctypes, sys

def main():
    # Allocate a console if there isn't one
    ctypes.windll.kernel32.AllocConsole()

    # Create new standard streams
    sys.stdin = open("CONIN$", "r")
    # Buffering on the output streams must be switched off explicitely
    # (is this a bug in the code module not calling flush()?)
    sys.stdout = open("CONOUT$", "w", 0)
    sys.stderr = open("CONOUT$", "w", 0)
    
    import rlcompleter, readline

    # pyreadline.unicode_helper (v 1.5) has one buglet: sys.stdout, as
    # defined above, has sys.stdout.encoding == None.  pyreadline
    # doesn't like this, so we set it here.
    #
    # I've made several experiments with codecs.open(...) to create
    # sys.std[in|out|err] but it didn't work.
    import pyreadline.unicode_helper
    input_cp = ctypes.windll.kernel32.GetConsoleCP()
    pyreadline.unicode_helper.pyreadline_codepage = "cp%d" % input_cp
    
    # Create a namespace for the interactive interpreter, this must
    # also be passed to the completer because otherwise the completer
    # would use the __main__ namespace.
    namespace = {}

    readline.parse_and_bind("tab: complete")
    # Override the default completer.
    readline.set_completer(rlcompleter.Completer(namespace).complete)

    # Start the interpreter.
    code.interact(local=namespace)

if __name__ == "__main__":
    main()
<snip>

> If you have any ideas on how to change things to make it more useful for 
> you please let me know.

As you can see in the comments above, one change to pyreadline/unicode_helpers.py
would be nice, because the sys.stdin object that I create above has a .encoding
attribute which is None:

diff -u c:\python24\lib\site-packages\pyreadline\unicode_helper.py~ c:\python24\lib\site-packages\pyreadline\unicode_helper.py
--- c:\python24\lib\site-packages\pyreadline\unicode_helper.py~	Wed Apr 08 19:37:36 2009
+++ c:\python24\lib\site-packages\pyreadline\unicode_helper.py	Wed Apr 08 19:37:36 2009
@@ -13,6 +13,9 @@
                               #stdout with stdout collector
     pyreadline_codepage="ascii"   #assume ascii codepage
 
+if pyreadline_codepage is None:
+    pyreadline_codepage="ascii"
+
 def ensure_unicode(text):
     """helper to ensure that text passed to WriteConsoleW is unicode"""
     if isinstance(text, str):


> /Jörgen


-- 
Thanks,
Thomas



More information about the IPython-user mailing list