##// 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 import IPython.ipapi
12 import IPython.ipapi
13 import glob,os,shlex,sys
13 import glob,os,shlex,sys
14
14 import inspect
15 ip = IPython.ipapi.get()
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 def vcs_completer(commands, event):
92 def vcs_completer(commands, event):
18 """ utility to make writing typical version control app completers easier
93 """ utility to make writing typical version control app completers easier
19
94
@@ -66,19 +141,15 b' def apt_completers(self, event):'
66 pkg_cache = None
141 pkg_cache = None
67
142
68 def module_completer(self,event):
143 def module_completer(self,event):
69 """ Give completions after user has typed 'import'.
144 """ Give completions after user has typed 'import ...' or 'from ...'"""
70
71 Note that only possible completions in the local directory are returned."""
72
145
73 # This works in all versions of python. While 2.5 has
146 # This works in all versions of python. While 2.5 has
74 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
147 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
75 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
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
149 # of possibly problematic side effects.
77 # something that searches sys.path in a saner/safer way, but for now we'll
150 # This search the folders in the sys.path for available modules.
78 # restrict ourselves to local completions only.
151
79 for el in [f[:-3] for f in glob.glob("*.py")]:
152 return moduleCompletion(event.line)
80 yield el
81 return
82
153
83
154
84 svn_commands = """\
155 svn_commands = """\
@@ -144,12 +215,12 b' def bzr_completer(self,event):'
144
215
145 return bzr_commands.split()
216 return bzr_commands.split()
146
217
147
218
148 def shlex_split(x):
219 def shlex_split(x):
149 """Helper function to split lines into segments."""
220 """Helper function to split lines into segments."""
150 #shlex.split raise exception if syntax error in sh syntax
221 #shlex.split raise exception if syntax error in sh syntax
151 #for example if no closing " is found. This function keeps dropping
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 #exception. Adds end of the line to the result of shlex.split
224 #exception. Adds end of the line to the result of shlex.split
154 #example: %run "c:/python -> ['%run','"c:/python']
225 #example: %run "c:/python -> ['%run','"c:/python']
155 endofline=[]
226 endofline=[]
@@ -167,11 +238,11 b' def shlex_split(x):'
167 def runlistpy(self, event):
238 def runlistpy(self, event):
168 comps = shlex_split(event.line)
239 comps = shlex_split(event.line)
169 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
240 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
170
241
171 #print "\nev=",event # dbg
242 #print "\nev=",event # dbg
172 #print "rp=",relpath # dbg
243 #print "rp=",relpath # dbg
173 #print 'comps=',comps # dbg
244 #print 'comps=',comps # dbg
174
245
175 lglob = glob.glob
246 lglob = glob.glob
176 isdir = os.path.isdir
247 isdir = os.path.isdir
177 if relpath.startswith('~'):
248 if relpath.startswith('~'):
General Comments 0
You need to be logged in to leave comments. Login now