2009-10-29 20:55:45 +00:00
|
|
|
# Copyright (c) 2009 Fernando Perez, www.stani.be (GPL license)
|
|
|
|
|
2011-02-08 00:01:15 +00:00
|
|
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
2009-10-29 20:55:45 +00:00
|
|
|
#
|
2011-02-08 00:01:15 +00:00
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU General Public License
|
|
|
|
# as published by the Free Software Foundation; either version 2
|
|
|
|
# of the License, or (at your option) any later version.
|
2009-10-29 20:55:45 +00:00
|
|
|
#
|
2011-02-08 00:01:15 +00:00
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software Foundation,
|
|
|
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
#
|
|
|
|
# ##### END GPL LICENSE BLOCK #####
|
2009-10-29 20:55:45 +00:00
|
|
|
|
|
|
|
# Original copyright (see docstring):
|
|
|
|
#*****************************************************************************
|
|
|
|
# Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
|
|
|
|
#
|
|
|
|
# Distributed under the terms of the BSD License. The full license is in
|
|
|
|
# the file COPYING, distributed as part of this software.
|
|
|
|
#*****************************************************************************
|
|
|
|
|
2009-12-13 14:38:30 +00:00
|
|
|
# <pep8 compliant>
|
|
|
|
|
2009-10-29 20:55:45 +00:00
|
|
|
"""Completer for import statements
|
|
|
|
|
|
|
|
Original code was from IPython/Extensions/ipy_completers.py. The following
|
|
|
|
changes have been made:
|
|
|
|
- ported to python3
|
|
|
|
- pep8 polishing
|
|
|
|
- limit list of modules to prefix in case of "from w"
|
|
|
|
- sorted modules
|
|
|
|
- added sphinx documentation
|
2010-04-25 15:21:46 +00:00
|
|
|
- complete() returns a blank list of the module isnt found
|
2009-10-29 20:55:45 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
|
2012-02-08 04:37:37 +00:00
|
|
|
TIMEOUT_STORAGE = 3 # Time in secs after which the root-modules will be stored
|
2009-10-29 20:55:45 +00:00
|
|
|
TIMEOUT_GIVEUP = 20 # Time in secs after which we give up
|
|
|
|
|
|
|
|
ROOT_MODULES = None
|
|
|
|
|
|
|
|
|
|
|
|
def get_root_modules():
|
|
|
|
"""
|
|
|
|
Returns a list containing the names of all the modules available in the
|
2012-02-08 04:37:37 +00:00
|
|
|
folders of the python-path.
|
2009-10-29 20:55:45 +00:00
|
|
|
|
|
|
|
:returns: modules
|
|
|
|
:rtype: list
|
|
|
|
"""
|
|
|
|
global ROOT_MODULES
|
|
|
|
modules = []
|
|
|
|
if not(ROOT_MODULES is None):
|
|
|
|
return ROOT_MODULES
|
|
|
|
from time import time
|
|
|
|
t = time()
|
|
|
|
store = False
|
|
|
|
for path in sys.path:
|
|
|
|
modules += module_list(path)
|
|
|
|
if time() - t >= TIMEOUT_STORAGE and not store:
|
|
|
|
# Caching the list of root modules, please wait!
|
|
|
|
store = True
|
|
|
|
if time() - t > TIMEOUT_GIVEUP:
|
|
|
|
# This is taking too long, we give up.
|
|
|
|
ROOT_MODULES = []
|
|
|
|
return []
|
|
|
|
|
|
|
|
modules += sys.builtin_module_names
|
|
|
|
|
2009-12-07 14:09:53 +00:00
|
|
|
# needed for modules defined in C
|
|
|
|
modules += sys.modules.keys()
|
|
|
|
|
2009-10-29 20:55:45 +00:00
|
|
|
modules = list(set(modules))
|
|
|
|
if '__init__' in modules:
|
|
|
|
modules.remove('__init__')
|
2009-12-07 14:09:53 +00:00
|
|
|
modules = sorted(modules)
|
2009-10-29 20:55:45 +00:00
|
|
|
if store:
|
|
|
|
ROOT_MODULES = modules
|
|
|
|
return modules
|
|
|
|
|
|
|
|
|
|
|
|
def module_list(path):
|
|
|
|
"""
|
|
|
|
Return the list containing the names of the modules available in
|
|
|
|
the given folder.
|
|
|
|
|
|
|
|
:param path: folder path
|
|
|
|
:type path: str
|
|
|
|
:returns: modules
|
|
|
|
:rtype: list
|
|
|
|
"""
|
|
|
|
|
|
|
|
if os.path.isdir(path):
|
|
|
|
folder_list = os.listdir(path)
|
|
|
|
elif path.endswith('.egg'):
|
|
|
|
from zipimport import zipimporter
|
|
|
|
try:
|
|
|
|
folder_list = [f for f in zipimporter(path)._files]
|
|
|
|
except:
|
|
|
|
folder_list = []
|
|
|
|
else:
|
|
|
|
folder_list = []
|
|
|
|
#folder_list = glob.glob(os.path.join(path,'*'))
|
|
|
|
folder_list = [p for p in folder_list \
|
|
|
|
if os.path.exists(os.path.join(path, p, '__init__.py'))\
|
|
|
|
or p[-3:] in ('.py', '.so')\
|
|
|
|
or p[-4:] in ('.pyc', '.pyo', '.pyd')]
|
|
|
|
|
|
|
|
folder_list = [os.path.basename(p).split('.')[0] for p in folder_list]
|
|
|
|
return folder_list
|
|
|
|
|
|
|
|
|
|
|
|
def complete(line):
|
|
|
|
"""
|
|
|
|
Returns a list containing the completion possibilities for an import line.
|
|
|
|
|
|
|
|
:param line:
|
|
|
|
|
|
|
|
incomplete line which contains an import statement::
|
|
|
|
|
|
|
|
import xml.d
|
|
|
|
from xml.dom import
|
|
|
|
|
|
|
|
:type line: str
|
|
|
|
:returns: list of completion possibilities
|
|
|
|
:rtype: list
|
|
|
|
|
|
|
|
>>> complete('import weak')
|
|
|
|
['weakref']
|
2009-10-30 09:34:57 +00:00
|
|
|
>>> complete('from weakref import C')
|
|
|
|
['CallableProxyType']
|
2009-10-29 20:55:45 +00:00
|
|
|
"""
|
|
|
|
import inspect
|
|
|
|
|
|
|
|
def try_import(mod, only_modules=False):
|
|
|
|
|
|
|
|
def is_importable(module, attr):
|
|
|
|
if only_modules:
|
|
|
|
return inspect.ismodule(getattr(module, attr))
|
|
|
|
else:
|
|
|
|
return not(attr[:2] == '__' and attr[-2:] == '__')
|
|
|
|
|
|
|
|
try:
|
|
|
|
m = __import__(mod)
|
|
|
|
except:
|
|
|
|
return []
|
|
|
|
mods = mod.split('.')
|
|
|
|
for module in mods[1:]:
|
|
|
|
m = getattr(m, module)
|
|
|
|
if (not hasattr(m, '__file__')) or (not only_modules) or\
|
|
|
|
(hasattr(m, '__file__') and '__init__' in m.__file__):
|
|
|
|
completion_list = [attr for attr in dir(m)
|
|
|
|
if is_importable(m, attr)]
|
2009-10-30 09:34:57 +00:00
|
|
|
else:
|
|
|
|
completion_list = []
|
2009-10-29 20:55:45 +00:00
|
|
|
completion_list.extend(getattr(m, '__all__', []))
|
|
|
|
if hasattr(m, '__file__') and '__init__' in m.__file__:
|
|
|
|
completion_list.extend(module_list(os.path.dirname(m.__file__)))
|
|
|
|
completion_list = list(set(completion_list))
|
|
|
|
if '__init__' in completion_list:
|
|
|
|
completion_list.remove('__init__')
|
|
|
|
return completion_list
|
|
|
|
|
2009-10-30 09:34:57 +00:00
|
|
|
def filter_prefix(names, prefix):
|
|
|
|
return [name for name in names if name.startswith(prefix)]
|
|
|
|
|
2009-10-29 20:55:45 +00:00
|
|
|
words = line.split(' ')
|
|
|
|
if len(words) == 3 and words[0] == 'from':
|
|
|
|
return ['import ']
|
|
|
|
if len(words) < 3 and (words[0] in ['import', 'from']):
|
|
|
|
if len(words) == 1:
|
|
|
|
return get_root_modules()
|
|
|
|
mod = words[1].split('.')
|
|
|
|
if len(mod) < 2:
|
2009-10-30 09:34:57 +00:00
|
|
|
return filter_prefix(get_root_modules(), words[-1])
|
2009-10-29 20:55:45 +00:00
|
|
|
completion_list = try_import('.'.join(mod[:-1]), True)
|
|
|
|
completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list]
|
2009-10-30 09:34:57 +00:00
|
|
|
return filter_prefix(completion_list, words[-1])
|
2009-10-29 20:55:45 +00:00
|
|
|
if len(words) >= 3 and words[0] == 'from':
|
|
|
|
mod = words[1]
|
2009-10-30 09:34:57 +00:00
|
|
|
return filter_prefix(try_import(mod), words[-1])
|
2010-04-25 15:21:46 +00:00
|
|
|
|
|
|
|
# get here if the import is not found
|
|
|
|
# import invalidmodule
|
|
|
|
# ^, in this case return nothing
|
|
|
|
return []
|