Hi,
I'm ploughing through Chapter 21 on web applications. I found the Wiki core example a bit convoluted. Did anyone else find it somewhat confusing? Anyway, I've rewritten it on a whim and it seems much clearer to me (code below). Perhaps that's gonna bite me in the ass when I get to doing the web interface though? Anyway, the basic (object based) design is this:
You can create a wiki page, wiki page object has a name and some text. A wiki page object has a constructor too. That's it. With that you can create pages, set their text and get their text. The page doesn't need to know anything about Wikis (looser coupling).
You also have a wiki core object. This allows you to add a page to the Wiki, get a page and delete a page. It has a constructor too. Simple.
I would be interesting in getting your feedback on the code. I'm probably gonna have a go at the web interface over the weekend.
Code:
# wiki-core-2.py
import os
import re
class WikiCore:
base = '' # base directory for wiki
def __init__(self, base):
self.base = base
if not os.path.exists(self.base):
os.makedirs(self.base)
elif not os.path.isdir(self.base):
raise IOError('Wiki base "%s" is not a directory!'%self.base)
def addPage(self, page):
page.path = os.path.join (self.base, page.name)
out = open(page.path, 'w')
out.write(page.text)
out.close()
def getPage(self, name):
path = os.path.join (self.base, name)
if self.onDisk(path):
page = Page(name)
infile = open(path, 'r')
page.text = infile.read()
infile.close()
return page
else:
print '%s does not exist in Wiki!' % name
def deletePage(self, name):
path = os.path.join (self.base, name)
if self.onDisk(path):
os.remove(path)
else:
print '%s does not exist in Wiki!' % name
# utility function
def onDisk(self, path):
return os.path.isfile(path)
class Page:
WIKI_WORD_MATCH = "(([A-Z][a-z0-9]*){2,})"
WIKI_WORD = re.compile(WIKI_WORD_MATCH)
WIKI_WORD_ALONE = re.compile('^%s$' % WIKI_WORD_MATCH)
text = '' # this stores the page text
name = '' # the page name
def __init__(self, name, text=''):
if not self.WIKI_WORD_ALONE.match(name):
raise NotWikiWord, name
self.name = name
self.text = text
class NotWikiWord(Exception):
pass
# test code
if __name__=='__main__':
w = WikiCore('MyWiki') # create the wiki core object
# create some pages
p1 = Page('WikiOne', 'This is the contents of page 1')
p2 = Page('WikiTwo')
p3 = Page('WikiThree')
# page text is an attribute (touching public parts)
p2.text = 'This is the contents of page 2'
print p1.text
# we have some pages, let's add them to the Wiki
w.addPage(p1)
w.addPage(p2)
w.addPage(p3)
# we can get a page from the Wiki whenever we want
p = w.getPage('WikiOne')
print p.text
p = w.getPage('WikiTwo')
print p.text
# we had a page without text in the Wiki, that's OK, set it now
p3 = w.getPage('WikiThree')
p3.text = "I've set this after added to Wiki"
# delete 2 pages
w.deletePage('WikiTwo')
w.deletePage('WikiOne')
# p3 object still lives
print p3.text