Python Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesPython Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old June 11th, 2004, 01:07 PM
percivall percivall is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jul 2003
Posts: 133 percivall User rank is Just a Lowly Private (1 - 20 Reputation Level) 
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.

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesPython Programming > On rlcompleter and completing the import statement


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump


Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 





© 2003-2008 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway
Stay green...Green IT