#format python """ MoinMoin - FuzzyLikePages action Copyright (c) 2001 by Richard Jones Copyright (c) 2001 by Jürgen Hermann Modifications by June Kim All rights reserved, see COPYING for details. This action generates a list of pages that either start or end with the same word as the current pagename. If only one matching page is found, that page is displayed directly. $Id: LikePages.py,v 1.3 2002/01/29 04:48:18 june Exp $ """ import re, sys from MoinMoin import config, user, util, wikiutil, webapi #from MoinMoin.Page import Page from cStringIO import StringIO from MoinMoin.support.difflib import get_close_matches _ = lambda x: x FUZZY_CUT_OFF=0.5333 PIVOT=4 def displayLikePages(anOutStream,aPageName): pageList=wikiutil.getPageList(config.text_dir) singleSideSearcher=FuzzyAndIncludingNameSearcher(aPageName,pageList) twoSidesSearcher=SameInitialOrFinalSearcher(aPageName,pageList) singleSideSearcher.searchAndDisplayAll(sys.stdout) twoSidesSearcher.searchAndDisplayAll(sys.stdout) def execute(pagename, form): webapi.http_headers() wikiutil.send_title(_('Like %s'%pagename),\ pagename=pagename) displayLikePages(sys.stdout,pagename) wikiutil.send_footer(pagename) def getUnion(aList1,aList2): assert aList1 is not None and aList2 is not None temp=aList1[:] for eachElement in aList2: if eachElement not in temp: temp.append(eachElement) return temp class SimilarPageSearcher: def __init__(self,aPageName,anAllPageList): self.pageName=aPageName self.similarPages=[] self.allPageList=anAllPageList[:] if aPageName in self.allPageList: #the page might be non-existent at the moment self.allPageList.remove(aPageName) def getSimilarPages(self): return self.similarPages def searchAndDisplayAll(self,anOutStream): self.searchPages(isSorted=1) self.display(anOutStream) class TwoSidesSearcher(SimilarPageSearcher): def __init__(self,aPageName,anAllPageList): SimilarPageSearcher.__init__(self,aPageName,anAllPageList) self.similarPagesInitial=[];self.similarPagesFinal=[] def getSimilarPages(self): temp=[] temp=getUnion(self.similarPagesInitial,self.similarPagesFinal) temp.sort() return temp def getSimilarPagesInitial(self): return self.similarPagesInitial def getSimilarPagesFinal(self): return self.similarPagesFinal def display(self,anOutStream,printHeading=1): #TODO: take out html tags and use formatter or something like HTMLgen if printHeading: print >>anOutStream, "%s"%_("Pages sharing initial or final title words/letters...") print >>anOutStream, "
    " for eachPageName in self.getSimilarPagesInitial(): print >>anOutStream, '
  1. %s'%( wikiutil.quoteWikiname(eachPageName),eachPageName) print >>anOutStream, "
    " for eachPageName in self.getSimilarPagesFinal(): print >>anOutStream, '
  1. %s'%( wikiutil.quoteWikiname(eachPageName),eachPageName) print >>anOutStream, "
" class FuzzyNameSearcher(SimilarPageSearcher): def __init__(self,aPageName,anAllPageList): SimilarPageSearcher.__init__(self,aPageName,anAllPageList) def searchPages(self,isSorted=0,maxPages=9): self.similarPages=get_close_matches(self.pageName,self.allPageList,n=maxPages,cutoff=FUZZY_CUT_OFF) if isSorted: self.similarPages.sort() class IncludingNameSearcher(SimilarPageSearcher): def __init__(self,aPageName,anAllPageList): SimilarPageSearcher.__init__(self,aPageName,anAllPageList) def searchPages(self,isSorted=0): self.similarPages=filter(lambda eachPage,thisPage=self.pageName:\ eachPage.lower().find(thisPage.lower())>=0, self.allPageList) if isSorted: self.similarPages.sort() class SameInitialOrFinalWordSearcher(TwoSidesSearcher): def __init__(self,aPageName,anAllPageList): SimilarPageSearcher.__init__(self,aPageName,anAllPageList) self.s_re=re.compile('([%s][%s]+)' % (config.upperletters, config.lowerletters)) self.e_re=re.compile('([%s][%s]+)$' % (config.upperletters, config.lowerletters)) self.s_re2=re.compile('([^ ]+)' ) self.e_re2=re.compile('([^ ]+)$') def searchPages(self,isSorted=0): matches,t,t=self._getMatchesStartEnd() self.similarPagesInitial=[eachPage for eachPage in matches.keys() if matches[eachPage] in [1,3]] self.similarPagesFinal=[eachPage for eachPage in matches.keys() if matches[eachPage] in [2,3]] if isSorted: self.similarPagesInitial.sort() self.similarPagesFinal.sort() def _getMatchesStartEnd(self): # figure the start and end words try: match = self.s_re.match(self.pageName) start = match.group(1) s_len = len(start) match = self.e_re.search(self.pageName) end = match.group(1) e_len = len(end) except: match = self.s_re2.match(self.pageName) start = match.group(1) s_len = len(start) match = self.e_re2.search(self.pageName) end = match.group(1) e_len = len(end) # find any matching pages matches = {} for anypage in self.allPageList: if anypage == self.pageName: # skip current page continue p_len = len(anypage) if p_len > s_len and anypage[:s_len] == start: matches[anypage] = 1 if p_len > e_len and anypage[-e_len:] == end: matches[anypage] = matches.get(anypage, 0) + 2 return matches,start,end class SameInitialOrFinalBytesSearcher(TwoSidesSearcher): theirPivot=PIVOT def __init__(self,aPageName,anAllPageList): TwoSidesSearcher.__init__(self,aPageName,anAllPageList) def searchPages(self,isSorted=0): if len(self.pageName)>anOutStream, "%s"%_("Pages sharing a similar title...") print >>anOutStream, "
    " for eachPageName in self.getSimilarPages(): print >>anOutStream, '
  1. %s'%( wikiutil.quoteWikiname(eachPageName),eachPageName) print >>anOutStream, "
" class FuzzyAndIncludingNameSearcher(SingleSideSearcher): def __init__(self,aPageName,anAllPageList): self._searcher1=FuzzyNameSearcher(aPageName,anAllPageList) self._searcher2=IncludingNameSearcher(aPageName,anAllPageList) def searchPages(self,isSorted=0): self._searcher1.searchPages(isSorted) self._searcher2.searchPages(isSorted) self.similarPages=getUnion(self._searcher1.getSimilarPages(),self._searcher2.getSimilarPages()) if isSorted: self.similarPages.sort() #class PagesSharingInitialOrFinalWord: # def __init__(self,aPageName): # self.pageName=aPageName # # def getMatchesStartEnd(self, s_re=re.compile('([%s][%s]+)' % (config.upperletters, config.lowerletters)), # e_re=re.compile('([%s][%s]+)$' % (config.upperletters, config.lowerletters)), # s_re2=re.compile('([^ ]+)' ), # e_re2=re.compile('([^ ]+)$')): # # figure the start and end words # try: # match = s_re.match(self.pageName) # start = match.group(1) # s_len = len(start) # match = e_re.search(self.pageName) # end = match.group(1) # e_len = len(end) # except: # match = s_re2.match(self.pageName) # start = match.group(1) # s_len = len(start) # match = e_re2.search(self.pageName) # end = match.group(1) # e_len = len(end) # # # find any matching pages # matches = {} # for anypage in wikiutil.getPageList(config.text_dir): # if anypage == self.pageName: # skip current page # continue # p_len = len(anypage) # if p_len > s_len and anypage[:s_len] == start: # matches[anypage] = 1 # if p_len > e_len and anypage[-e_len:] == end: # matches[anypage] = matches.get(anypage, 0) + 2 # return matches,start,end # # def getLikePagesOutput(self,aMatches,aStart,anEnd): # # more than one match, list 'em # st=StringIO() # temp=sys.stdout # sys.stdout=st # keys = aMatches.keys() # keys.sort() # self.showMatches(aMatches, keys, 3, "%s...%s" % (aStart, anEnd)) # self.showMatches(aMatches, keys, 1, "%s..." % (aStart,)) # self.showMatches(aMatches, keys, 2, "...%s" % (anEnd,)) # texts=st.getvalue() # sys.stdout=temp # return texts # # def showMatches(self,matches, keys, match, title): # matchcount = matches.values().count(match) # # if matchcount: # print '' + _('%(matchcount)d %(matches)s for "%(title)s"') % { # 'matchcount': matchcount, # 'matches': (_(' match'), _(' matches'))[matchcount != 1], # 'title': title} + '' # print "
    " # for key in keys: # if matches[key] == match: # page = Page(key) # print '
  • %s' % ( # wikiutil.quoteWikiname(page.page_name), # page.split_title()) # print "
" # #def executeOld(pagename, form): # pagesInitialFinal=PagesSharingInitialOrFinalWord(pagename) # matches,start,end=pagesInitialFinal.getMatchesStartEnd() # # # no matches :( # if not matches: # return Page(pagename).send_page(form, # msg='' + _('No pages match "%s"!') % (pagename,) + '') # # # one match - display it # if len(matches) == 1: # return Page(matches.keys()[0]).send_page(form, # msg='' + _('Exactly one matching page for "%s" found!') % (pagename,) + '') # # webapi.http_headers() # wikiutil.send_title(_('Multiple matches for "%s...%s"') % (start, end), # pagename=pagename) # # sys.stdout.write(pagesInitialFinal.getLikePagesOutput(matches,start,end)) # wikiutil.send_footer(pagename) #