Nicks Wiki

(Note: Newer version on #Python Wiki, see below. ALSO, I need to remove all that experimental "tag" function stuff....)

Based on IckyWiki by DirckBlaskey, this wiki is comparable in size but I'm doing a little refactoring on it. See if you can find the differences:

  """ NicksWiki - (still concerned about file locking?) """ 
  ### DirckBlaskey 8/3/01 1:50PDT
  ### NickBensema 8/3/01 6:58MST

import os, sys, re, cgi, time, winsound

os.chdir("c:\\mydocu~1\\testpiki\\") # yes, it's My Documents. DWiki,Default = os.path.basename(sys.argv[0]), 'FrontPage' RLink = '[<a href="%s">d^:</a>]' % DWiki

def tag(t, *text): return "<%s>%s</%s>" % (t, "".join(text), t) def huh(w): return "<h2>%s ???huh???</h2>" % RLink def exists(w): return os.access(w, os.R_OK) def contents(w): return exists(w) and open(w).read()

def wlink(w, op="get", t=None): return '<a href="%s?op=%s&word=%s">%s</a>' % (DWiki, op, w, t or w) def flink(w, t): return wlink(w, t.split()[0].lower(), t.title())

wsearch = re.compile("(^|[^A-Za-z0-9\?=]+)(([A-Z][a-z]+){2,})").search

Env, Args = os.environ.get, {} # Env temporarily not-in-use for i in cgi.FieldStorage?().list: Args[] = i.value Words = {} for word in filter(wsearch, os.listdir(".")): Words[word] = os.path.getmtime(word)

print "Content-type: text/html\r\n\r\n",

class Main: def __init__(self): op,word = Args.get('op', "get"), Args.get('word', Default) if not word.isalpha(): op,word = "recent",Default # close hack door print getattr(self, op, huh)(word) # self.op(word) or ?huh?

def get(self, w): winsound.Beep(440,60) d = wikifi(contents(w) or "Please create this page.") return '''<html><head><title>%s</title><body><h2>%s%s</h2><hr><p> <pre>%s</pre><hr>%s %s %s</body></html>''' % (w, RLink, wlink(w,"search"), d, flink(w,"Edit Page"), flink(w,"Like Pages"), flink(w,"Recent Changes"))

def edit(self, w): winsound.Beep(2600,60) d = contents(w) or "Describe "+w return '''<html><head><title>%s</title></head><body> <form action="%s" method="POST"><h2>%s <input type="hidden" name="word" value="%s"> <input type="hidden" name="date" value="%d"> <input type="submit" name="op" value="save"></h2> <textarea name="Data" rows=20 cols=75>%s</textarea> </form></body></html>''' % (w, DWiki, w, w, time.time(), d)

def save(self, w): for x in xrange(1,5): winsound.Beep(440 * (2**x), 100) if int(Args["date"]) < Words[w]: winsound.Beep(120,1000) return "<H2>Couldn't save; file changed by someone else.</H2>" if "Data" in Args: open(w, "wb").write(Args["Data"]) return self.get(w)

def recent(self, w): datelist = [(date, word) for word, date in Words.items()] datelist.sort() lines = "\n<P>".join(["%s %s" % (wlink(w), time.ctime(d)) for d, w in datelist[-20:]]) return ('''<html><head><title>Recent Changes</title><body> <h2>%sRecent Changes</h2> <hr>%s<hr></body></html>''' % (RLink, lines))

def search(self, w): winsound.Beep(120,60) findmatches = re.compile(w).search pages = [x for x in Words.keys() if findmatches(contents(x))] lines = '<p>'.join(map(wlink, pages)) return ('''<html><head><title>Searched %s</title><body> <h2>%sSearch results for: %s</h2> <hr>%s<hr></body></html>''' % (w, RLink, wlink(w), lines))

def like(self, w): winsound.Beep(120,60); winsound.Beep(200,60); winsound.Beep(120,60) first, last = re.match("^([A-Z][a-z]+).*?([A-Z][a-z]+)$", w).groups() findFirst = re.compile("^%s[A-Z]" % first).search findLast = re.compile("[a-z]%s$" % last).search matchesFirst = "<li>".join(map(wlink, filter(findFirst,Words.keys()))) matchesLast = "<li>".join(map(wlink, filter(findLast,Words.keys()))) return ('''<html><head><title>Pages like %s</title><body> <h2>%sPages like: %s</h2><table><tr><td valign=top><ol><li>%s <td valign=top><ol><li>%s</ol></table></body></html>''' % (w, RLink, wlink(w), matchesFirst, matchesLast))

def wikifi(a): r = "" while True: match = wsearch(a) if not match: break s, e = match.start(2), match.end(2) w = a[s:e] if exists(w): w = wlink(w, "get") else: w += wlink(w, "edit", "?") r, a = r + a[:s] + w, a[e:] return r + a

if __name__=="__main__": try: Main() except: cgi.print_exception()

I'm trying to do things OnceAndOnlyOnce, and that's why I've added functions exists() and contents(). It added two lines of code, but allowed me to remove except: clauses which originally trapped file-not-found errors, which saved me... ahem... two lines. But still, it uses a read-access check to see if the file exists. I hardly need the Words dictionary at all. In fact, the only function that uses Words anymore is the search() function, which no longer uses popen(). And I'm well aware that Dirck's search() didn't need the Words dictionary. Soon mine won't either. :)

I have Python 2.1 and I love list comprehensions, so expect some of those in my code.

I also changed wlink() so that it accepted the wikiword first, so that I could default the operator to "get".

I removed the msvcrt code, throwing caution to the wind, since writing the data files in binary mode seems to work fine on my system.

I'll add LikePages real soon now; it was working in a previous version.


Update 8/6/01 4:33am: First, I got rid of the pickled Words file, made the program too fragile. I also made the program detect its own name as I had several versions of the file and I didn't want them pointing at each other. It'd be pretty easy to change that "Words[word] = 1" to grab the file's date, and thus pave the way for file locking! I'd like Recent Changes first, though....

Update 8/6/01 7:04am: File locking is working in the latest version. Find further notes and versions here: -- I figured I'd move it to #Python's wiki because those people might be more motivated to rip this code apart. I also added winsound.Beep() calls so that it makes noise when people call up my server.


EditText of this page (last edited February 26, 2010) or FindPage with title or text search