On 9/20/2016 9:31 AM, Steven D'Aprano wrote:
On Mon, Sep 19, 2016 at 06:18:38AM -0400, Terry Reedy wrote:
On 9/19/2016 4:31 AM, Paul Moore wrote:

shutil.get_terminal_size() is available on all platforms.

On windows, it works with Command Prompt and PowerShell but fails in
IDLE, as it must.

Why "must" it fail?

Good question. When I wrote that, I had in mind the qualification 'in IDLE's default mode, as IDLE is currently structured'. In the default mode with user code executed in a separate no-window process, there is currently no way for the child process to know the current size of Shell's tk text window in the parent process. But this is not the real story. See below.

What is it about the IDLE terminal that prevents it from emulating an
actual terminal, like all(?) the other terminal emulation programs
people use?

IDLE's Shell is based on a tk Text and by design is not a terminal emulation. (Which terminal would it emulate?). Note that with proportional fonts, a text editor does not really have character columns, though it can be sized according to some 'average' character width. Also, IDLE is a development environment, not a run environment, and this impacts a few decisions.

I just opened my Konqueror file & web browser, gave the command "Show
Terminal Emulator", and ran Python:

py> import shutil
py> shutil.get_terminal_size()
os.terminal_size(columns=85, lines=10)

That's spot on perfectly correct. I then resized the window and tried it

py> shutil.get_terminal_size()
os.terminal_size(columns=108, lines=13)

This is what I did and equivalently got with Command Prompt.

I then quit Python, and ran idle3.3 from the Konqueror terminal.
Unfortunately, get_terminal_size() returned the size of the *Konqueror*
terminal, instead of the IDLE terminal. I think that's a bug. I don't
know if its a bug in IDLE or get_terminal_size() or both.

If I run IDLE from Command Prompt, without or with the currently deprecated -n option, to run user code in the original IDLE process instead of a separate subprocess, I get the same -- the current size of the parent Command Prompt.

The reason is that shutil.get_terminal_size first looks for int(os.environ['COLUMNS']) (or 'LINES') and if that fails, calls os.get_terminal_size(sys.__stdout__.fileno()). In both cases, the latter refer to the parent console.

The 'obvious' possible solution is for Shell to set the environment variables when created or modified. On creation would be easy. Unfortunately, there is not, AFAIK, an application-accessible Resize event. A feature of tk is that geometry managers handle resizing automatically once the user sets the parameters of which widgets can be resized, and if so, min sizes and relative weights. But maybe there is a workaround.

I am also not sure if modified environ is propagated to subprocesses. On Posix, subprocess.Popen uses os.execvp, so the parent environment is inherited by the new process. I don't know if this means that subsequent changes are inherited. On Windows, Popen used the system CreateProcess and I don't know what this does.

A workaround would be to monkeypatch the function. In the rarely used -n mode, this would be easy. In normal mode, this would require the execution server to send an rpc message to the Shell client asking for its dimensions so the server can format the string to send to the client. I do not know if the current rpc mechanism is set up for requests from server to client.

If not fixed soon, I should add the limitation to the IDLE doc.

Terry Jan Reedy

Python-ideas mailing list
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to