[Python-Dev] Idle, site.py, and the release candidates

Nick Coghlan ncoghlan at gmail.com
Sun Mar 31 08:39:49 CEST 2013


On Sun, Mar 31, 2013 at 12:34 PM, Terry Jan Reedy <tjreedy at udel.edu> wrote:

> While trying to test the patch for
> http://bugs.python.org/**issue5492 <http://bugs.python.org/issue5492>
> on Windows, I discovered that quit() and exit() in the Idle Shell are now
> disabled, it seems, for all versions on all systems rather than just
> sometimes on Linux.
>
> The problem is a change in idlelib that invalidated an assumption made in
> site.py. Revs 81718-81721 for
> http://bugs.python.org/**issue9290 <http://bugs.python.org/issue9290>
> changed idlelib.PyShell.PseudoFile (line 1277 in 3.3) to subclass
> io.TextIOBase, which subclasses IOBase. This gave PseudoFile and its
> subclasses a .fileno instance method attribute that raises
> io.UnsupportedOperation: fileno.
>
> This is not a bug since the doc for io.IOBase.fileno says:
> "Return the underlying file descriptor (an integer) of the stream if it
> exists. An OSError is raised if the IO object does not use a file
> descriptor."
> (the particular error raised is not an issue here).
>
> This is the code for Quitter.__call__ in site.py (line 368 in 3.3):
>
>         def __call__(self, code=None):
>             # Shells like IDLE catch the SystemExit, but listen when
>             # stdin wrapper is closed.
>             try:
>                 fd = -1
>                 if hasattr(sys.stdin, "fileno"):
>                     fd = sys.stdin.fileno()
>                 if fd != 0:
>                     # Don't close stdin if it wraps fd 0
>                     sys.stdin.close()
>             except:
>                 pass
>             raise SystemExit(code)
>
> The incorrect assumption is that if sys.stdin.fileno exits but raises, the
> call did not come from a shell that needs .close called.
>
> I do not know enough about other circumstances in which stdin.fileno would
> do something other than return 0 to be sure of what the proper fix would
> be.  (I increasingly dislike bare excepts as they hide the thinking and
> knowledge of the original programmer. What exception was expected that
> should be passed away?)
>

The other problem is that making *two* function calls inside a broad
try/except is almost always a terrible idea. It seems to me that the
intended logic is more like this:

    try:
        # Close stdin if it wraps any fd other than 0
        close_stdin = (sys.stdin.fileno() != 0)
    except (AttributeError, OSError, io.UnsupportedOperation):
        # Also close stdin if it doesn't expose a file descriptor
        close_stdin = True
    if close_stdin:
        try:
            sys.stdin.close()
        except Exception:
            pass
    raise SystemExit(code)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20130331/cfed23af/attachment-0001.html>


More information about the Python-Dev mailing list