##// END OF EJS Templates
fixes #8012
fixes #8012

File last commit:

r17700:7b6d94ef
r20676:2aff1ee8
Show More
completerlib.py
353 lines | 11.5 KiB | text/x-python | PythonLexer
Brian E. Granger
Initial messing around....
r17700 # encoding: utf-8
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 """Implementations for various useful completers.
These are all loaded by default by IPython.
"""
#-----------------------------------------------------------------------------
Matthias BUSSONNIER
update copyright to 2011/20xx-2011...
r5390 # Copyright (C) 2010-2011 The IPython Development Team.
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 #
# Distributed under the terms of the BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from __future__ import print_function
# Stdlib imports
import glob
import inspect
import os
import re
import sys
MinRK
use importlib.machinery when available...
r14914 try:
Thomas Kluyver
Tiny comment correction
r14925 # Python >= 3.3
MinRK
use importlib.machinery when available...
r14914 from importlib.machinery import all_suffixes
_suffixes = all_suffixes()
except ImportError:
from imp import get_suffixes
_suffixes = [ s[0] for s in get_suffixes() ]
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 # Third-party imports
from time import time
from zipimport import zipimporter
# Our own imports
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965 from IPython.core.completer import expand_user, compress_user
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 from IPython.core.error import TryNext
Jörgen Stenarson
Replaced shlex_split with arg_split from _process_common....
r5688 from IPython.utils._process_common import arg_split
Thomas Kluyver
Replace references to unicode and basestring
r13353 from IPython.utils.py3compat import string_types
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
# FIXME: this should be pulled in with the right call via the component system
MinRK
Don't rely on `get_ipython` in builtins in library code
r10580 from IPython import get_ipython
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
#-----------------------------------------------------------------------------
# Globals and constants
#-----------------------------------------------------------------------------
# Time in seconds after which the rootmodules will be stored permanently in the
# ipython ip.db database (kept in the user's .ipython dir).
TIMEOUT_STORAGE = 2
# Time in seconds after which we give up
TIMEOUT_GIVEUP = 20
# Regular expression for the python import statement
Bradley M. Froehle
Fix 'import '... completion for py3 & egg files....
r8892 import_re = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*?)'
r'(?P<package>[/\\]__init__)?'
r'(?P<suffix>%s)$' %
MinRK
use importlib.machinery when available...
r14914 r'|'.join(re.escape(s) for s in _suffixes))
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
# RE for the ipython %run command (python + ipython scripts)
Paul Ivanov
make %run magic complete on .ipynb files
r13645 magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
#-----------------------------------------------------------------------------
# Local utilities
#-----------------------------------------------------------------------------
def module_list(path):
"""
Return the list containing the names of the modules available in the given
folder.
"""
Thomas Kluyver
Fix completion when importing modules in the cwd.
r6163 # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
if path == '':
path = '.'
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
# A few local constants to be used in loops below
pjoin = os.path.join
Bernardo B. Marques
remove all trailling spaces
r4872
Bradley M. Froehle
Fix 'import '... completion for py3 & egg files....
r8892 if os.path.isdir(path):
# Build a list of all files in the directory and all files
# in its subdirectories. For performance reasons, do not
# recurse more than one level into subdirectories.
files = []
Xiuming Chen
Make tab completion for 'from' suggest symlinked folders/modules.
r17036 for root, dirs, nondirs in os.walk(path, followlinks=True):
Bradley M. Froehle
Fix 'import '... completion for py3 & egg files....
r8892 subdir = root[len(path)+1:]
if subdir:
files.extend(pjoin(subdir, f) for f in nondirs)
dirs[:] = [] # Do not recurse into additional subdirectories.
else:
files.extend(nondirs)
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
Bradley M. Froehle
Fix 'import '... completion for py3 & egg files....
r8892 else:
try:
files = list(zipimporter(path)._files.keys())
except:
files = []
# Build a list of modules which match the import_re regex.
modules = []
for f in files:
m = import_re.match(f)
if m:
modules.append(m.group('name'))
return list(set(modules))
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
Antony Lee
Key the root modules cache by sys.path entries....
r10125
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 def get_root_modules():
"""
Returns a list containing the names of all the modules available in the
folders of the pythonpath.
Antony Lee
Key the root modules cache by sys.path entries....
r10125
ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 """
ip = get_ipython()
Antony Lee
Key the root modules cache by sys.path entries....
r10125 rootmodules_cache = ip.db.get('rootmodules_cache', {})
rootmodules = list(sys.builtin_module_names)
start_time = time()
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 store = False
for path in sys.path:
Antony Lee
Key the root modules cache by sys.path entries....
r10125 try:
modules = rootmodules_cache[path]
except KeyError:
modules = module_list(path)
try:
modules.remove('__init__')
except ValueError:
pass
if path not in ('', '.'): # cwd modules should not be cached
rootmodules_cache[path] = modules
if time() - start_time > TIMEOUT_STORAGE and not store:
store = True
print("\nCaching the list of root modules, please wait!")
print("(This will only be done once - type '%rehashx' to "
"reset cache!)\n")
sys.stdout.flush()
if time() - start_time > TIMEOUT_GIVEUP:
print("This is taking too long, we give up.\n")
return []
rootmodules.extend(modules)
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 if store:
Antony Lee
Key the root modules cache by sys.path entries....
r10125 ip.db['rootmodules_cache'] = rootmodules_cache
rootmodules = list(set(rootmodules))
return rootmodules
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
def is_importable(module, attr, only_modules):
if only_modules:
return inspect.ismodule(getattr(module, attr))
else:
return not(attr[:2] == '__' and attr[-2:] == '__')
def try_import(mod, only_modules=False):
try:
m = __import__(mod)
except:
return []
mods = mod.split('.')
for module in mods[1:]:
m = getattr(m, module)
m_is_init = hasattr(m, '__file__') and '__init__' in m.__file__
completions = []
if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
completions.extend( [attr for attr in dir(m) if
is_importable(m, attr, only_modules)])
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 completions.extend(getattr(m, '__all__', []))
if m_is_init:
completions.extend(module_list(os.path.dirname(m.__file__)))
completions = set(completions)
if '__init__' in completions:
completions.remove('__init__')
return list(completions)
#-----------------------------------------------------------------------------
# Completion-related functions.
#-----------------------------------------------------------------------------
def quick_completer(cmd, completions):
""" Easily create a trivial completer for a command.
Takes either a list of completions, or all completions in string (that will
be split on whitespace).
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 Example::
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 [d:\ipython]|1> import ipy_completers
[d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
[d:\ipython]|3> foo b<TAB>
bar baz
[d:\ipython]|3> foo ba
"""
Bernardo B. Marques
remove all trailling spaces
r4872
Thomas Kluyver
Replace references to unicode and basestring
r13353 if isinstance(completions, string_types):
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 completions = completions.split()
def do_complete(self, event):
return completions
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
def module_completion(line):
"""
Returns a list containing the completion possibilities for an import line.
The line looks like this :
'import xml.d'
'from xml.dom import'
"""
words = line.split(' ')
nwords = len(words)
# from whatever <tab> -> 'import '
if nwords == 3 and words[0] == 'from':
return ['import ']
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 # 'from xy<tab>' or 'import xy<tab>'
if nwords < 3 and (words[0] in ['import','from']) :
if nwords == 1:
return get_root_modules()
mod = words[1].split('.')
if len(mod) < 2:
return get_root_modules()
completion_list = try_import('.'.join(mod[:-1]), True)
return ['.'.join(mod[:-1] + [el]) for el in completion_list]
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 # 'from xyz import abc<tab>'
if nwords >= 3 and words[0] == 'from':
mod = words[1]
return try_import(mod)
#-----------------------------------------------------------------------------
# Completers
#-----------------------------------------------------------------------------
# These all have the func(self, event) signature to be used as custom
# completers
def module_completer(self,event):
"""Give completions after user has typed 'import ...' or 'from ...'"""
# This works in all versions of python. While 2.5 has
# pkgutil.walk_packages(), that particular routine is fairly dangerous,
# since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
# of possibly problematic side effects.
# This search the folders in the sys.path for available modules.
return module_completion(event.line)
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965 # FIXME: there's a lot of logic common to the run, cd and builtin file
# completers, that is currently reimplemented in each.
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
def magic_run_completer(self, event):
Paul Ivanov
make %run magic complete on .ipynb files
r13645 """Complete files that end in .py or .ipy or .ipynb for the %run command.
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 """
Min RK
use arg_split(...strict=False) in module_completer
r5689 comps = arg_split(event.line, strict=False)
Thomas Kluyver
Improve matching files after script name for magic %run....
r14815 # relpath should be the current token that we need to complete.
if (len(comps) > 1) and (not event.line.endswith(' ')):
relpath = comps[-1].strip("'\"")
else:
relpath = ''
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965 #print("\nev=", event) # dbg
#print("rp=", relpath) # dbg
#print('comps=', comps) # dbg
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
lglob = glob.glob
isdir = os.path.isdir
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965 relpath, tilde_expand, tilde_val = expand_user(relpath)
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 # Find if the user has already typed the first filename, after which we
# should complete on all files, since after the first one other files may
# be arguments to the input script.
Thomas Kluyver
Fix tests for core
r13375 if any(magic_run_re.match(c) for c in comps):
Thomas Kluyver
Fix duplicate directories in %run tab completion
r14818 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
for f in lglob(relpath+'*')]
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 else:
Thomas Kluyver
Fix duplicate directories in %run tab completion
r14818 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 pys = [f.replace('\\','/')
for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
Paul Ivanov
make %run magic complete on .ipynb files
r13645 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
Thomas Kluyver
Fix duplicate directories in %run tab completion
r14818
matches = dirs + pys
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965 #print('run comp:', dirs+pys) # dbg
Thomas Kluyver
Fix duplicate directories in %run tab completion
r14818 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
def cd_completer(self, event):
"""Completer function for cd, which only returns directories."""
ip = get_ipython()
relpath = event.symbol
#print(event) # dbg
if event.line.endswith('-b') or ' -b ' in event.line:
# return only bookmark completions
bkms = self.db.get('bookmarks', None)
if bkms:
return bkms.keys()
else:
return []
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 if event.symbol == '-':
width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
# jump in directory history by number
fmt = '-%0' + width_dh +'d [%s]'
ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
if len(ents) > 1:
return ents
return []
if event.symbol.startswith('--'):
return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965
# Expand ~ in path and normalize directory separators.
relpath, tilde_expand, tilde_val = expand_user(relpath)
relpath = relpath.replace('\\','/')
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
found = []
for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
if os.path.isdir(f)]:
if ' ' in d:
# we don't want to deal with any of that, complex code
# for this is elsewhere
raise TryNext
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965 found.append(d)
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
if not found:
if os.path.isdir(relpath):
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965 return [compress_user(relpath, tilde_expand, tilde_val)]
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959
# if no completions so far, try bookmarks
Thomas Kluyver
Remove uses of iterkeys
r13360 bks = self.db.get('bookmarks',{})
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 bkmatches = [s for s in bks if s.startswith(event.symbol)]
if bkmatches:
return bkmatches
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Restored major default completer functionality (cd, import, run)....
r2959 raise TryNext
Fernando Perez
Fix bugs with completions of paths that have ~ in them....
r2965 return [compress_user(p, tilde_expand, tilde_val) for p in found]
Paul Ivanov
making %clear a native magic
r5961
Paul Ivanov
%reset now takes optional in/out/dhist/array args...
r5965 def reset_completer(self, event):
"A completer for %reset magic"
return '-f -s in out array dhist'.split()