-
-
Notifications
You must be signed in to change notification settings - Fork 373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tab completion ignores __all__ #129
Comments
It's configurable, with the option The reason we do this is that we often want to use IPython to poke about and debug modules, so we like to see what's really there, not just what's whitelisted as public API. We should, however, do a better job of prioritising completions, so that things in |
Thanks for the documentation link. 👍
I guess the question here is, who is "we"? I suspect most users are just getting on with using existing modules and not poking about debugging modules. That's what I've seen in workshops, user drop-ins, etc. Also, the ability to change the configuration is probably something a "developer" will be more aware of & happier doing. So perhaps a change of the default is in order? |
(Perhaps a different key combination could be used to allow an "enhanced" tab completion that shows more attributes, e.g. Ctrl+TAB) |
I'm not sure we can detect Ctrl+tab as a separate key combo in the terminal, and it would require changes to the message protocol for the Jupyter frontends - which is possible, but makes it quite a significant change. I think resolving the priority is a sensible compromise, so that we show the names in |
So changing the default isn't an option? |
It's definitely an option, just not my preferred one. ;-) Let's see if anyone else wants to weigh in. |
I tend to agree with @rhattersley. For me tab completion is not just for poking about and debugging; it is my main point of entry for any module on the command line. I've tried to restrict my own packages to return only their main API during tab completion but it leads to ugly and brittle code like this: # Hide submodules in module namespace, to avoid confusion with corresponding class names
# If the module is reloaded, this will fail - ignore the resulting NameError
try:
_target, _antenna, _timestamp, _flux, _catalogue, _ephem_extra, \
_conversion, _projection, _pointing, _refraction, _delay = \
target, antenna, timestamp, flux, catalogue, ephem_extra, \
conversion, projection, pointing, refraction, delay
del target, antenna, timestamp, flux, catalogue, ephem_extra, \
conversion, projection, pointing, refraction, delay
except NameError:
pass (I have a class |
I noticed that Is there another supported way to do this? (For what it's worth, I have also found this to be a minor pain point. Often users explore APIs using IPython, and this adds significant noise.) |
I'm running into this issue as well. I'm creating some modules for our team to use, and we rely on IPython/Jupyter pretty heavily. I'm writing my modules in such a way that they're easily explored interactively, and having to 'hide' imported functions and variables with _ is a bit ugly (and annoying). |
One of our developers/scientists just ran into this issue as well, and has been hiding, among other things, With the current defaults it seems that designing for interactivity and usability at some level is promoting non standard coding practices, as others have noticed. Echoing @aiguofer's sentiment here. More discussion here: |
TensorFlow goes to some heroics to delete undocumented variables from modules to work around this same issue. |
sigh . I'll see what I can do to re-enable limit-to-all. The issue is that regardless of the default about 50% of our users will be unhappy The completer is currently getting (some) refactor – showing types, function signature... etc. Would a "This function/attribute is private" ui indicator, and sorting these further down in the completion list be an acceptable middle ground ? |
Here is a thought, could the auto completer recognize a triple tab? \t is complete if single completion |
If ipython finds packages through dir(), Python 3.7 will allow overriding dir for a module (https://www.python.org/dev/peps/pep-0562/), thus giving back power to developers to control what is visible through tab-completion. |
This looks like a great solution -- does IPython use |
We have some custom logic and also fallback on Jedi.... we really need to get function to push tab-completiosn. |
So there is the option |
👋 Just checking in here, are there any updates on what the preferred way to expose an API that facilitates code-exploration through tab-completion? P.S. I am happy to help with a pr if someone is willing to give me a few pointers :) |
Totally agree, |
I agree with the other comments that limiting to |
Closes #55 Note that ipython usually does not respect these options, so end-users will probably not notice much of a difference. ipython/ipykernel#129
We hid submodules at the top-level katpoint namespace to aid IPython tab completion, since it is confusing to see both the "target" submodule and the preferred "Target" class in the list. This was done by adding underscores to their names. The downside is that it becomes yucky to import submodules to access internals in the unit tests (and the module can't be reloaded FWIW). Don't rename the submodules but cull their names from __all__ and the output of __dir__() instead. IPython has a love/hate relationship with __all__ (see e.g. ipython/ipykernel#129) and it is currently completely ignored. The newer and shinier __dir__() in Python 3.7 (PEP 562) is respected though. Customise both for good measure. Instead of hiding submodules individually by name, cull all submodules as a group, as well as variables starting with an underscore (except __version__). It would have been nice to sort the output of __dir__() in groups (say classes followed by functions etc) but that is undermined by IPython, which simply sorts everything again at the end.
Over five years later and this is still an issue (aka - "bump"). |
@Carreau It seems to me that overriding # Inside __init__.py
import sys
__all__ = [x for x in dir(sys.modules[__name__]) if x not in ['deprecated_module1', 'deprecated_module2']]
def __dir__():
return sorted(__all__) |
The Python docs describe "public names" as being defined by
__all__
where it exists. It would be helpful if this rule was respected by the Python kernel to avoid module authors that want to provide helpful tab-completion having to obfuscate imports, etc. with leading underscores. NB. This use case is explicitly recognised in the Python docs:WIth the current kernel behaviour, code such as:
needs to become:
The text was updated successfully, but these errors were encountered: