
June 11th, 2004, 01:07 PM
|
|
Contributing User
|
|
Join Date: Jul 2003
Posts: 133
Time spent in forums: < 1 sec
Reputation Power: 6
|
|
|
On rlcompleter and completing the import statement
So ... I like rlcompleter. It really makes experimenting in the Python interpreter easier. But it won't complete import statements.
Now: I've looked around but I haven't found an alternative to rlcompleter that will also complete import statements. This is irritating! So I wrote my own.
It's very much a hack and there's probably something better that I just haven't found. But for those that (like me) haven't found anything better, here's an extension to rlcompleter that also completes import statements:
Code:
import re
import readline
from rlcompleter import Completer as _Completer
__all__ = ["Completer"]
class Completer(_Completer):
def __init__(self):
_Completer.__init__(self)
def complete(self, text, state):
buffer = readline.get_line_buffer()
if state == 0:
if re.search(r"(import|from) ([\w_.]+)?$", buffer):
self.matches = self.import_matches(buffer, text)
else:
_Completer.complete(self, text, state)
try:
return self.matches[state]
except IndexError:
return None
def import_matches(self, buffer, text):
mods = Modules()
if re.search(r"from [\w_.]+ import", buffer):
return
if '.' in text:
return self._subpkgs(mods, text)
return [mod for mod in mods.completions
if mod.startswith(text)]
def _subpkgs(self, mods, text):
from os import path
parts = text.split('.')
basepath = ''
for pth, pkg in mods.rawmods:
if parts[0] == pkg:
basepath = pth
break
if not basepath:
return
for part in parts[1:-1]:
basepath = path.join(basepath, part)
if not path.isdir(basepath):
return
basename = '.'.join(parts[:-1])
rawmods = mods.modscan.submodules((basepath, basename))
completions = get_package_members(rawmods)
return ['.'.join([basename, mod]) for mod in completions
if mod.startswith(parts[-1])]
class Modules(object):
def __new__(cls, *args, **kwds):
inst = cls.__dict__.get("__inst__")
if inst is not None:
return inst["instance"]
cls.__inst__ = {}
cls.__inst__['instance'] = inst = object.__new__(cls)
return inst
def __init__(self):
if self.__inst__.get("initialized"):
return
self.__inst__['initialized'] = True
from pydoc import ModuleScanner
self.completions = ["errno", "exceptions", "gc", "imp",
"marshal", "posix", "signal", "sys",
"thread", "xxsubtype", "zipimport"]
self.modscan = ModuleScanner()
self.roots = self.modscan.roots
self.rawmods = self.flattened([self.modscan.submodules(mod)
for mod in self.roots[1:]])
self.completions.extend(get_package_members(self.rawmods))
def flattened(self, seq):
"""Flattens a sequence with nested sequences.
flattened() is non-recursive and does not flatten nested
sequences.
"""
result = []
for item in seq:
if not isinstance(item, basestring) and \
(hasattr(item, '__getitem__') or hasattr(item, '__iter__')):
result.extend(item)
else:
result.append(item)
return result
def get_package_members(rawmods):
completions = []
for pth, pkg in rawmods:
pth = pth.split('/')[-1]
pkg = pkg.split('.')[-1]
if pth == pkg:
completions.append(pkg)
elif pth.endswith('.py') or pth.endswith('.so') \
and not pth.endswith('__init__.py'):
if not pth.startswith('_'):
completions.append(pth[:-3])
return completions
readline.set_completer(Completer().complete)
This code will only work if you use Python on a *nix computer.
Last edited by percivall : June 11th, 2004 at 01:12 PM.
|