Subject: Re: bug#76205: 31.0.50; 31.0.50; python.el completion broken for non-builtin objects in IPython 8.30.0 & Python 3.13.2

From: kobarity <[email-masked]>
Date: Sun, 16 Feb 2025 19:20:38 +0900

Visuwesh wrote:
> 
> [சனி பிப்ரவரி 15, 2025] kobarity wrote:
> 
> >> [...]
> >> So...what do we do from here?  Unfortunately, I know next to nothing
> >> about this area to file a sensible bug report myself.
> >
> > I'm not sure either.  As ipython --simple-prompt does not support
> > completion, I don't know if using rlcompleter with ipython
> > --simple-prompt is supported or not.
> >
> > The direct cause of this problem seems to be that rlcompleter.__main__
> > is not as expected.  So the following steps enable completion on
> > ipython --simple-prompt on Python 3.13.
> >
> > import readline
> > import rlcompleter
> > import __main__
> > rlcompleter.__main__ = __main__
> > readline.parse_and_bind("tab: complete")
> >
> > Attached is a test patch that does something similar to this.
> 
> I can confirm that completion works for non-builtin objects with this
> patch.

Thank you for testing the patch.

Here's what's happening.  ipython --simple-prompt on Python 3.13 is
indirectly importing rlcompleter, which sets its Completer().complete
as the completer.  Completer() without the namespace argument uses
__main__.__dict__ as the source of global symbols to complete.  The
__main__ here is the name in rlcompleter.py namespace, which is bound
at import time of rlcompleter.py.  However, __main__ used in the REPL
of ipython --simple-prompt is different from __main__ used at the
import time of rlcompleter.py.  Therefore, changes in globals()
(i.e. __main__.__dict__) are not reflected in
rlcompleter.__main__.__dict__ and the completion will fail.

Prior to Python 3.12, the problem does not occur because rlcompleter
was not imported indirectly.  When we import rlcompleter in the native
completion setup code, __main__ is already the same as the one used in
the REPL.

Since IPython does not use rlcompleter, it seems difficult to consider
this problem a bug in IPython.  It would be better if rlcompleter
reads sys.modules["__main__"] instead of __main__, but it would not be
easy to change a long standing specification.  So I think it would be
better for python.el to address this issue.

To set up a completer that works correctly, it is sufficient to
specify the namespace argument:

readline.set_completer(rlcompleter.Completer(globals()).complete)

However, we need to make sure that we do not override the customized
completer.  The problem is that it is difficult to distinguish between
the completer that is set up by importing rlcompleter and the
customized completer.

So it seems to me that it would be reasonable to override
rlcompleter.__main__ so that the default completer works properly.  I
think the attached revised patch is slightly better than my previous
patch, since it does not add "__main__" to globals.  This change
affects only IPython.  I added some comments and the commit message.

I would like to hear your opinions.