'Find keyword matches for a keyword. If there\'s an exact match,
just return it, else return a list of fuzzy matches if avoid_fuzzy
isn\'t True.
Keywords searched are: first modules, then descrefs.
Returns: None if nothing found
(type, docname, anchorname) if exact match found
list of (quality, type, docname, anchorname, description)
if fuzzy'

def find_keyword(self, keyword, avoid_fuzzy=False, cutoff=0.6, n=20):

    if (keyword in self.modules):
        (docname, title, system, deprecated) = self.modules[keyword]
        return ('module', docname, ('module-' + keyword))
    if (keyword in self.descrefs):
        (docname, ref_type) = self.descrefs[keyword]
        return (ref_type, docname, keyword)
    if ('.' not in keyword):
        if (('exceptions.' + keyword) in self.descrefs):
            (docname, ref_type) = self.descrefs[('exceptions.' + keyword)]
            return (ref_type, docname, ('exceptions.' + keyword))
        if (('object.' + keyword) in self.descrefs):
            (docname, ref_type) = self.descrefs[('object.' + keyword)]
            return (ref_type, docname, ('object.' + keyword))
    if avoid_fuzzy:
        return
    s = difflib.SequenceMatcher()
    s.set_seq2(keyword.lower())
    def possibilities():
        for (title, (fn, desc, _, _)) in self.modules.iteritems():
            (yield ('module', fn, ('module-' + title), desc))
        for (title, (fn, desctype)) in self.descrefs.iteritems():
            (yield (desctype, fn, title, ''))
    def dotsearch(string):
        parts = string.lower().split('.')
        for idx in xrange(0, len(parts)):
            (yield '.'.join(parts[idx:]))
    result = []
    for (type, docname, title, desc) in possibilities():
        best_res = 0
        for part in dotsearch(title):
            s.set_seq1(part)
            if ((s.real_quick_ratio() >= cutoff) and (s.quick_ratio() >= cutoff) and (s.ratio() >= cutoff) and (s.ratio() > best_res)):
                best_res = s.ratio()
        if best_res:
            result.append((best_res, type, docname, title, desc))
    return heapq.nlargest(n, result)
