Currently, I have an application which uses the cmd.Cmd module for the command line interface, tab-completion works perfectly.
Now, I'd like to replace sys.stdout
, with another object (For example, in order to capture what's being written.)
Following snippet should be completely transparent in theory, as every get/set operation to the Std object is redirected to the actial sys.__stdout__
.
class Std(object):
def __getattribute__(self, name):
if name in ('__getattribute__', '__setattr__'):
return object.__getattribute__(self, name)
else:
return getattr(sys.__stdout__, name)
def __setattr__(self, name, value):
setattr(sys.__stdout__, name, value)
sys.stdout = Std()
For example, sys.stdout.fileno()
will still print 1.
However, the readline tab-completion of Cmd.cmd
does no longer work now...
Okay, let's inherit from file. (stdout is a file object.)
class Std(file):
def __init__(self):
pass
def __getattribute__(self, name):
if name in ('__getattribute__', '__setattr__'):
return object.__getattribute__(self, name)
else:
return getattr(sys.__stdout__, name)
def __setattr__(self, name, value):
setattr(sys.__stdout__, name, value)
sys.stdout = Std()
And now I get:
Traceback (most recent call last):
File "./shell.py", line 61, in <module>
print '#1'
ValueError: I/O operation on closed file
However, the following assertion does not fail:
assert not sys.stdout.closed
Somehow, I guess, Python is overoptimizing something, and bypassing Std.write.
What should I do to replace stdout, without loosing readline support...?
Jonathan
-edit-
I'm also trying to replace sys.stdin. Passing it to cmd.Cmd does not work, because raw_input is used for readline support and Python's raw_input does not accept a file descriptor. It falls back to whatever pty is assigned to sys.stdin.
When I create a new pty (through os.openpty()), and assign this pair to sys.stdin/out, readline autocompletion through that pty works perfectly, but again, when wrapped in a proxy object, it works, but without autocompletion.
Trying to understand the source of readline, but it isn't easy: http://svn.python.org/projects/python/branches/release25-maint/Modules/readline.c