[Python-ideas] Remove tty module
Andrew Barnert
abarnert at yahoo.com
Fri Aug 2 06:47:24 CEST 2013
From: "random832 at fastmail.us" <random832 at fastmail.us>
Sent: Thursday, August 1, 2013 1:18 PM
> On Thu, Jul 25, 2013, at 11:58, Andrew Barnert wrote:
>> Faking termios on Windows (and presumably faking attributes for the
>> cmd.exe console window) would probably be almost as much work as faking
>> curses, and a lot less useful, so I'm not sure that would be worth
> doing.
>
> What about faking conio on Unix? There's no rule that says
> cross-platform python APIs have to be inspired by POSIX C APIs. It's a
> very simple API and is sufficient to build a pure-python windowing
> library on top of.
That's a great idea.
The quasi-standardized core of conio is definitely not enough to write a windowing library. Although some of the old DOS implementations had gotoxy, setfg, and setbg functions, the Win32 implementations don't have those; they just have… well, the same functions as MSVCRT's console APIs, which the stdlib already wraps (see http://docs.python.org/3/library/msvcrt.html#console-i-o for details). And really, all we were looking for was a way to do raw input and a few related things in a cross-platform way (and, on Unix, an easier way than tty/termios), and those APIs seem like a good match. And they'd be pretty easy to implement on Unix.
Something like this (for Unix; the Windows implementations would just call the msvcrt functions):
def _check_tty(f):
if not f.isatty():
raise RuntimeError('consoleio on non-tty')
@contextmanager
def _tty_context(f, raw=False, echo=True):
fd = f.fileno()
stash = termios.tcgetattr(fd)
tty.setraw(fd)
yield
termios.tcsetattr(fd, termios.TCSAFLUSH, stash)
_pushback = []
def kbhit():
# Not sure how to write this in a cross-platform way...
def getwch():
_check_tty(sys.stdin)
if _pushback:
return _pushback.pop(0)
with _tty_context(sys.stdin, raw=True, echo=False):
return sys.stdin.read(1)
def ungetwch(wch):
_check_tty(sys.stdin)
_pushback.append(wch)
def putwch(wch):
_check_tty(sys.stdout)
sys.stdout.write(wch)
sys.stdout.flush()
# For the non-"wide" versions… just use sys.stdout.buffer instead of sys.stdout?
If we can require the user to call enable(input_only=False) before using any consoleio functions, and disable() before using normal I/O (maybe "with consoleio.context(input_only=False):" to wrap it), it could be simpler (especially the kbhit part), and more efficient and reliable.
Of course it is possible to have a TTY that isn't on stdin/stdout, or even two TTYs, but I don't think there's any need for the extra complexity.
Anyway, if you're interested, I could clean this up, test it out, and put something up on PyPI, and then we could see if it gets enough traction to be worth considering stdlib-ifying.
More information about the Python-ideas
mailing list