ipython/ipython — pull request #2701 by rmcgibbo (2012-12-18 07:20:13+00:00)
Title: function specific tab completion via annotations

This is a new attempt at #2636. The feature enables custom tab completion for different arguments of a function, and also for the return value of a function (without calling it).

It's easier to show in action though. Check it out!

------

Here's tab completion on the return value of a function, without ever `eval`ing the function
```
In [1]: from IPython.extensions.completion import tab_complete, globs_to, literal

In [2]: @tab_complete
...: def baz(x) -> str:
...: pass
...:

In [3]: baz(notevaluated).
.capitalize .find .isspace .partition .rstrip .translate
.center .format .istitle .replace .split .upper
.count .index .isupper .rfind .splitlines .zfill
.decode .isalnum .join .rindex .startswith
.encode .isalpha .ljust .rjust .strip
.endswith .isdigit .lower .rpartition .swapcase
.expandtabs .islower .lstrip .rsplit .title
```
Note that sense this never calls the function, all the tab completion is based on methods defined on the `str` class. If you notate the return value as some class that dynamically defines its methods when it is
instantiated, the tab complete engine is not going to be able to find them. There's no way around this without actually invoking the code on the TAB keypress, which is not desired (and is already possible by configuring your ipython config file).

-------

Here, tab completion on the first argument only shows literal strings and directories that match a `glob` pattern. For the second argument, it shows some string literals.
```
In [4]: @tab_complete
...: def foo(x : globs_to('*.txt'), mode : literal('r', 'w')):
...: pass
...:

In [5]: foo(
'COPYING.txt' 'dist/' 'setupext/'
'IPython/' 'docs/' 'tools/'
'__pycache__/' 'ipython.egg-info/'
'build/' 'scripts/'

In[6]: foo('COPYING.txt',
'r', 'w'
```
-------

The default type of tab completion is based on `isinstance` matching. You could also be explicit about it:
```
In [7]: @tab_complete
...: def bar(x : str, x : instance_of(str)):
...: pass
...:

In [8]: string1 = string2 = 'some string'

In [9]: bar(
string1 string2

In [9]: bar('a',
string1 string2
```

All of this functionality is possible in python2 syntax (without [PEP3107](http://www.python.org/dev/peps/pep-3107/) annotations) by calling the `@tab_complete` decorator with keyword arguments.

The design here was influenced by Nick Coghlan's [emails](http://mail.python.org/pipermail/python-ideas/2012-December/018092.html) on python-ideas, and an annotation-based [typechecking library](http://code.activestate.com/recipes/572161-method-signature-type-checking-decorator-for-pytho/) on activestate.