[Python-ideas] Remove tty module

random832 at fastmail.us random832 at fastmail.us
Fri Aug 2 22:39:16 CEST 2013


I forgot to hit "reply all".

Omitted some of this that was in reply to something off-list, just in
case that wasn't an oversight (it was boring stuff about having multiple
consoles open anyway)

On Fri, Aug 2, 2013, at 16:05, random832 at fastmail.us wrote:
> 
> 
> On Fri, Aug 2, 2013, at 12:57, Andrew Barnert wrote:
> > Sure there is. It's harder to implement, and will be less portable. Even
> > just getting the screen width is tricky without curses.
> 
> Why would it be less portable? Right now, we have curses, which only
> works on unix. Implementing a simple set of functions for both unix and
> windows is more portable.
> 
> I am thinking in terms of "implement core functionality for multiple
> platforms, then implement anything more complex on top of that in pure
> python" - this necessarily means duplicating some of the work that
> curses does now for unix systems. What's wrong with this approach?
> 
> > And more importantly, a gotoxy function can only work after you've taken
> > over the whole terminal in the same way curses does.
> 
> Uh, all you have to do for that is clear the screen... and clrscr() was
> going to be the next function I was going to propose
> 
>  There are a lot of
> > things you may want to do--from getwch to setting colors--that don't
> > require that. So, a module that didn't let you getwch unless you enter a
> > curses-like mode would be less useful.
> > 
> > I think a simple consoleio module that just does nonblocking I/O is a
> > useful thing. A separate module that does non-full-screen formatting (and
> > there are dozens of these on PyPI) makes a nice complement. (Especially
> > since there are good use cases for using that _without_ a terminal--e.g.,
> > creating ANSI art text files--but also of course many good use cases for
> > doing both together.) A curses/conio wrapper for full-screen GUIs seems
> > like an almost entirely separate thing, except for the fact that both
> > would happen to use some of the same msvcrt calls on Windows.
> > > As for kbhit, you could probably implement it on unix with a call to
> > > select. If the tty file descriptor is ready for reading, then return
> > > true. The one possible wrinkle is that getwch could block if an
> > > incomplete multibyte character is read - something that cannot happen on
> > > windows.
> > 
> > There are other wrinkles. For example, on some posix platforms you also
> > need to fcntl the fd into nonblocking mode.
> 
> What platforms are those? I thought the whole POINT of select was that
> the file descriptor doesn't have to be in nonblocking mode, since
> otherwise you could just attempt to read and have it return
> EWOULDBLOCK/EAGAIN.
> 
> > Meanwhile, multibyte characters are not actually a problem. At an actual
> > console, if you type one, all of the bytes become ready at the same time,
> > so you can getwch.
> 
> Yes, the problem is if you type a single character in a non-UTF8
> character set that python _thinks_ is the first byte of a UTF8
> character. This is really more of an issue for escape sequences than
> multibyte characters, since in the multibyte case you could just say
> it's a misconfiguration so it's only natural that it leads to bad
> behavior.
> 
> > On a serial line, that isn't true, but it isn't true
> > on Windows either,
> 
> How is it not true on windows? The physical input on windows is unicode
> characters; any translation to multibyte characters happens within
> getch, getwch will never even _see_ anything that's not a whole unicode
> codepoint. The only reason you get multiple values for arrow keys is
> because getwch translates it _into_ multiple values from a lower-level
> source that generates a single event (see my other post where I propose
> bypassing this)
> 
> > There are also problems that are Windows specific that already affect
> > msvcrt and fancier implementations that I haven't made any attempt to
> > deal with, like the fact that getwch can return half a surrogate pair.
> 
> Surrogate pair support on the console is terrible in general. You might
> get half a surrogate pair and never get the other half, because there is
> no part of the data path that actually deals with whole code points [so
> it's possible the pair never existed]
> 
> > See the caveats in my readme, and the todo file, for everything I've
> > discovered so far. And please experiment with the code and find all the
> > problems I haven't discovered, because I'm sure there are plenty.
> 
> The way I see it, there are five possible types of keyboard events:
> 
> A unicode character is typed (if multiple characters are typed, this can
> be multiple events, even if it came from one key) - you still might want
> additional info to differentiate ctrl-h from ctrl-shift-h or backspace.
> Obviously, this is a normal event that you should be able to read and
> kbhit should return true.
> 
> An "action" key is typed, e.g. arrows, home, end, etc. You almost always
> want to be able to read this and it should trigger kbhit.
> 
> A modifier key or dead key is pressed. Generally, you don't want to read
> this or trigger kbhit, and on unix systems it is impossible to do so.
> Escape sequence on unix.
> 
> A key is released. Same as above, you don't want this event, and it's
> not possible on unix, barring some seriously esoteric xterm feature I'm
> not aware of.
> 
> Mouse events. On either unix or windows, this is part of the same
> "stream" as keyboard events, and you only get it if you ask for it.
> 
> > What about cbreak mode? It's a useful thing, there's no obvious way to fit it into the conio-style paradigm, and tty wraps it up for you.
> 
> I'd think cbreak mode basically consists of calling getche() all the
> time. What's the difference, other than that?
> 
> Windows acts weird if you mix line buffering and getch, by the way,
> which we may have to simply tolerate: type a line that's 10 characters,
> read 5, call getch, then read 5 more, and the second read will actually
> get the next 5 characters from the first line, even with no userspace
> buffering [directly calling os.read; haven't tried kernel32.ReadFile or
> ReadConsole yet - it's _possible_ there's a buffer we can flush
> somewhere].
> 
> >As I said in my last email, that implies that we need either curses or a whole lot of code rather than just termios, and more importantly that nobody can use consoleio without going into a curses full-screen mode.
> >
> > We could of course have two different modes that you can enable (just raw I/O vs. curses full screen), where the functionality that's common to both has the same names both ways, which you suggest later. But I'm wary about that, because getwch, kbhit, etc. based on curses will have many subtle differences from implementations based on select and raw mode.
> 
> I still don't understand your objection. People would be able to use the
> rest of consoleio all the time, just without using those functions (one
> of which, clrscr, basically _is_ "going into a curses full-screen mode"
> - i'm not sure what else you think going into a full-screen mode
> consists of) Input and output are basically completely independent
> (other than echoing), anyway, why would they have to use an output
> function to be able to use an input function? Why would being in full
> screen output mode have any effect on getwch or kbhit? Unless you're
> proposing using the _actual_ curses input functions, which I never so
> much as breathed a word of.

-- 
Random832


More information about the Python-ideas mailing list