##// END OF EJS Templates
Applied Olivier Lauzannes patch for cleaner import completer
vivainio -
Show More
@@ -11,9 +11,84 b" ip.set_hook('complete_command', svn_completer, str_key = 'svn')"
11 11
12 12 import IPython.ipapi
13 13 import glob,os,shlex,sys
14
14 import inspect
15 15 ip = IPython.ipapi.get()
16 16
17 def getRootModules():
18 """
19 Returns a list containing the names of all the modules available in the
20 folders of the pythonpath.
21 """
22 modules = []
23 for path in sys.path:
24 modules += moduleList(path)
25 modules += sys.builtin_module_names
26 modules = list(set(modules))
27 if '__init__' in modules:
28 modules.remove('__init__')
29 return list(set(modules))
30
31 def moduleList(path):
32 """
33 Return the list containing the names of the modules available in the given
34 folder.
35 """
36 folder_list = glob.glob(os.path.join(path,'*'))
37 folder_list = [path for path in folder_list \
38 if (os.path.isdir(path) and os.path.exists(os.path.join(path,'__init__.py')))\
39 or path[-3:] in ('.py','.so')\
40 or path[-4:] in ('.pyc','.pyo')]
41 folder_list += folder_list
42 folder_list = [os.path.basename(path).split('.')[0] for path in folder_list]
43 return folder_list
44
45 def moduleCompletion(line):
46 """
47 Returns a list containing the completion possibilities for an import line.
48 The line looks like this :
49 'import xml.d'
50 'from xml.dom import'
51 """
52 def tryImport(mod, only_modules=False):
53 def isImportable(module, attr):
54 if only_modules:
55 return inspect.ismodule(getattr(module, attr))
56 else:
57 return not(attr[:2] == '__' and attr[-2:] == '__')
58 try:
59 m = __import__(mod)
60 except:
61 return []
62 mods = mod.split('.')
63 for module in mods[1:]:
64 m = getattr(m,module)
65 if (not hasattr(m, '__file__')) or (not only_modules) or\
66 (hasattr(m, '__file__') and '__init__' in m.__file__):
67 completion_list = [attr for attr in dir(m) if isImportable(m, attr)]
68 completion_list.extend(getattr(m,'__all__',[]))
69 if hasattr(m, '__file__') and '__init__' in m.__file__:
70 completion_list.extend(moduleList(os.path.dirname(m.__file__)))
71 completion_list = list(set(completion_list))
72 if '__init__' in completion_list:
73 completion_list.remove('__init__')
74 return completion_list
75
76 words = line.split(' ')
77 if len(words) == 3 and words[0] == 'from':
78 return ['import ']
79 if len(words) < 3 and (words[0] in ['import','from']) :
80 if len(words) == 1:
81 return getRootModules()
82 mod = words[1].split('.')
83 if len(mod) < 2:
84 return getRootModules()
85 completion_list = tryImport('.'.join(mod[:-1]), True)
86 completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list]
87 return completion_list
88 if len(words) >= 3 and words[0] == 'from':
89 mod = words[1]
90 return tryImport(mod)
91
17 92 def vcs_completer(commands, event):
18 93 """ utility to make writing typical version control app completers easier
19 94
@@ -66,19 +141,15 b' def apt_completers(self, event):'
66 141 pkg_cache = None
67 142
68 143 def module_completer(self,event):
69 """ Give completions after user has typed 'import'.
70
71 Note that only possible completions in the local directory are returned."""
144 """ Give completions after user has typed 'import ...' or 'from ...'"""
72 145
73 146 # This works in all versions of python. While 2.5 has
74 147 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
75 148 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
76 # of possibly problematic side effects. At some point we may implement
77 # something that searches sys.path in a saner/safer way, but for now we'll
78 # restrict ourselves to local completions only.
79 for el in [f[:-3] for f in glob.glob("*.py")]:
80 yield el
81 return
149 # of possibly problematic side effects.
150 # This search the folders in the sys.path for available modules.
151
152 return moduleCompletion(event.line)
82 153
83 154
84 155 svn_commands = """\
@@ -144,12 +215,12 b' def bzr_completer(self,event):'
144 215
145 216 return bzr_commands.split()
146 217
147
218
148 219 def shlex_split(x):
149 220 """Helper function to split lines into segments."""
150 221 #shlex.split raise exception if syntax error in sh syntax
151 222 #for example if no closing " is found. This function keeps dropping
152 #the last character of the line until shlex.split does not raise
223 #the last character of the line until shlex.split does not raise
153 224 #exception. Adds end of the line to the result of shlex.split
154 225 #example: %run "c:/python -> ['%run','"c:/python']
155 226 endofline=[]
@@ -167,11 +238,11 b' def shlex_split(x):'
167 238 def runlistpy(self, event):
168 239 comps = shlex_split(event.line)
169 240 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
170
241
171 242 #print "\nev=",event # dbg
172 243 #print "rp=",relpath # dbg
173 244 #print 'comps=',comps # dbg
174
245
175 246 lglob = glob.glob
176 247 isdir = os.path.isdir
177 248 if relpath.startswith('~'):
General Comments 0
You need to be logged in to leave comments. Login now