"""
MoinMoin - LikePages action (a whole rewrite)
Copyright (c) 2002 by June Kim <juneaftn@hanmail.net>
All rights reserved, see COPYING for details.
$Id: LikePages.py,v 1.1 2005/08/25 04:31:57 no-smok Exp no-smok $
"""
import re, sys
from MoinMoin import config, user, util, wikiutil, webapi
from cStringIO import StringIO
from difflib import get_close_matches
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(user.current.text('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, "<b>%s</b>"%user.current.text("Pages sharing initial or final title words/letters...")
print >>anOutStream, "<table><tr><td valign=top><ol>"
for eachPageName in self.getSimilarPagesInitial():
print >>anOutStream, '<li><a href="%s">%s</a>'%(
wikiutil.quoteWikiname(eachPageName),eachPageName)
print >>anOutStream, "</ol></td><td valign=top><ol>"
for eachPageName in self.getSimilarPagesFinal():
print >>anOutStream, '<li><a href="%s">%s</a>'%(
wikiutil.quoteWikiname(eachPageName),eachPageName)
print >>anOutStream, "</ol></td></tr></table>"
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)<self.theirPivot:
self.similarPagesInitial=self.similarPagesFinal=[]
return
self.initial=self.pageName[:self.theirPivot].lower()
self.final=self.pageName[-self.theirPivot:].lower()
for eachPage in self.allPageList:
lowered=eachPage.lower()
if lowered.startswith(self.initial): # or lowered.endswith(self.final):
self.similarPagesInitial.append(eachPage)
if lowered.endswith(self.final):
self.similarPagesFinal.append(eachPage)
if isSorted:
self.similarPagesInitial.sort()
self.similarPagesFinal.sort()
class SameInitialOrFinalSearcher(TwoSidesSearcher):
theirPivot=PIVOT
def __init__(self,aPageName,anAllPageList):
#SimilarPageSearcher.__init__(self,aPageName,anAllPageList)
if wikiutil.isStrictWikiname(aPageName):
self._searcher=SameInitialOrFinalWordSearcher(aPageName,anAllPageList)
else:
self._searcher=SameInitialOrFinalBytesSearcher(aPageName,anAllPageList)
def searchPages(self,isSorted=0):
return self._searcher.searchPages(isSorted)
def getSimilarPages(self):
return self._searcher.getSimilarPages()
def getSimilarPagesInitial(self):
return self._searcher.getSimilarPagesInitial()
def getSimilarPagesFinal(self):
return self._searcher.getSimilarPagesFinal()
class SingleSideSearcher(SimilarPageSearcher):
def __init__(self,aPageName,anAllPageList):
SimilarPageSearcher.__init__(self,aPageName,anAllPageList)
def display(self,anOutStream,printHeading=1): #TODO: take out html tags and use formatter or something like HTMLgen
if printHeading:
print >>anOutStream, "<b>%s</b>"%user.current.text("Pages sharing a similar title...")
print >>anOutStream, "<table><tr><td valign=top><ol>"
for eachPageName in self.getSimilarPages():
print >>anOutStream, '<li><a href="%s">%s</a>'%(
wikiutil.quoteWikiname(eachPageName),eachPageName)
print >>anOutStream, "</ol></td></tr></table>"
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()