[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