The code starts with by setting up the Txny
object containing the reference taxonomy, and the root
ImageCatalog object containing the
descriptions of cataloged images.
# - - - - - m a i n - - - - -
def main():
'''Main program.
[ index page := taxonomy with links to form pages from
photo archive indices named on the command line
those form pages := their content from those indices ]
'''
#-- 1 --
# [ the current directory has a readable, valid aou.xml file ->
# txny := a Txny object representing that file ]
txny = txnyModule.Txny()
#-- 2 --
# [ the current directory has a readable, valid
# birdimages.xml file ->
# catalog := a birdimages.ImageCatalog object
# representing that file ]
catalog = birdimages.ImageCatalog.readFile ( 'birdimages.xml' )
We start building the tree of taxa by instantiating a TaxonPhotoSet object linked to the root taxon from
txny.
#-- 3 --
# [ rootTaxon := a TaxonPhotoSet for txny.root ]
rootTaxon = TaxonPhotoSet ( txny.root )
Now we are ready to process the names of the index files
from the command line. Each file describes the contents of
one archive; the entries for each file are added to rootTaxon.
#-- 4 --
# [ rootTaxon := rootTaxon with photos from archives named
# on the command line, placed into taxa from txny, using
# forms from catalog ]
for archFileName in sys.argv[1:]:
addArchive ( txny, catalog, rootTaxon, archFileName )
Everything we need to build the web pages comes from > the
rootTaxon object.
#-- 5 --
# [ index page := taxonomy with links to form pages from
# rootTaxon
# form pages from rootTaxon := content from rootTaxon ]
buildWeb ( rootTaxon )
This function reads the contents of one archive index
file, and adds all its catalog information to the rootTaxon object.
# - - - a d d A r c h i v e - - -
def addArchive ( txny, catalog, rootTaxon, archFileName ):
"""Add one archive's worth of catalog entries.
[ (txny is a taxonomy as a txnyModule.Txny) and
(catalog is a birdimages.ImageCatalog) and
(rootTaxon is a TaxonPhotoset) and
(archFileName is a string) ->
if archFileName names a readable file valid against
archx.rnc ->
rootTaxon := rootTaxon with photos from that
archive, placed into taxa from txny, using
forms from catalog ]
"""
The ArchiveIndex.readFile() static method
takes care of reading the file and building an ArchiveIndex object to represent it.
#-- 1 --
# [ if archFileName names a file that is readable and valid
# against archx.rnc ->
# archIndex := an ArchiveIndex instance representing
# that file, with cataloging from catalog
# else -> raise IOError ]
archIndex = ArchiveIndex.readFile ( catalog, archFileName )
We extract each catalog entry in turn and add it to rootTaxon.
#-- 2 --
# [ rootTaxon := rootTaxon with photos added from
# archIndex, placed into taxa from txny ]
for archImage in archIndex.genArchImages():
addArchImage ( txny, archImage, rootTaxon )
This function examines the catalog information in one
ArchImage instance, and for each form name
cataloged, adds that ArchImage to the tree
rooted in rootTaxon.
# - - - a d d A r c h I m a g e - - -
def addArchImage ( txny, archImage, rootTaxon ):
"""Catalog all forms in one image.
[ (txny is a txnyModule.Txny) and
(archImage is an archindex.ArchImage) and
(rootTaxon is a TaxonPhotoSet) ->
rootTaxon := rootTaxon with archImage added under
each form cataloged in archImage ]
"""
Inside the archImage instance, the .original attribute is a birdimages.Original catalog object. The Original.ab6 attribute is a space-separated list
of “bird ID” strings, generally a
six-letter code, but possibly a longer code giving
information about hybrids, species pairs, and whether the
ID was questionable.
We take this string and break it on spaces, converting
each one to a txnyModule.BirdId instance
that links that form to a specific taxon. Then, for each
form, we use the TaxonPhotoSet.addArchImage() method to catalog
that image under that taxon and form name.
#-- 1 --
# [ birdIdList := list of bird codes from
# archImage.original.ab6, split at spaces ]
birdIdList = archImage.original.ab6.split()
#-- 2 --
# [ rootTaxon := rootTaxon with archImage added under
# each form code from birdIdList ]
for rawBirdId in birdIdList:
#-- 2 body --
# [ if rawBirdId is defined in txny ->
# rootTaxon := rootTaxon with archImage added
# under rawBirdId ]
#-- 2.1 --
# [ if rawBirdId is defined in txny ->
# birdId := an abbrModule.BirdId instance representing
# rawBirdId
# else -> raise Exception ]
try:
birdId = abbrModule.BirdId.parse ( txny, rawBirdId )
except Exception, detail:
print >>sys.stderr, ( "*** Invalid bird ID '%s': %s" %
(rawBirdId, detail) )
continue
#-- 2.2 --
# [ rootTaxon := rootTaxon with archImage added under birdID ]
try:
rootTaxon.addArchImage ( birdId, archImage )
except KeyError, detail:
print >>sys.stderr, "***", detail
This method generates the index page and all form pages.
# - - - b u i l d W e b - - -
def buildWeb ( rootTaxon ):
"""Build all web pages.
[ rootTaxon is a TaxonPhotoSet ->
index page := taxonomy with links to form pages from
rootTaxon
form pages from rootTaxon := content from rootTaxon ]
"""
First we use the webPage() function to set
up what will become the index page.
#-- 1 --
# [ indexPage := a new XHTML page as an xc.Document ]
# body := the body element of that page ]
indexPage, body = webPage ( "Shipman's bird photo index",
CSS_STYLESHEET )
The content of the page is added by visiting each node in
the taxonomic tree made up of TaxonPhotoSet instances. The .walk() method on the
root TaxonPhotoSet instance takes care of
this visitation process. It yields each node of the tree
in sequence, using pre-order traversal (that is, the root
node comes first, followed recursively by its child subtrees).
At each node, we call the node's .buildPage() method to add the node's content to
the index page, including generation of all the form
pages for forms referred to that node's taxon.
#-- 2 --
# [ body := body with content added for all nodes in the
# tree of TaxonPhotoSet instances rooted at rootTaxon ]
for taxonSet in rootTaxon.walk():
#-- 2 body --
# [ taxonSet is a TaxonPhotoSet instance ->
# body := body with content added from node
# form pages for forms in node := content from
# forms in node ]
taxonSet.buildPage ( body )
Now that the index page has been built, write it out.
#-- 3 --
# [ if index page can be created anew ->
# index page := indexPage, serialized ]
indexFile = open ( INDEX_PAGE, "w" )
indexPage.write ( indexFile )
indexFile.close()
This function builds a generic page of XHTML, to which
other functions can add content later. It returns a
2-tuple (): doc,
body) is an docxc.Document instance containing the whole page,
and is
the bodybody element of that page as an xc.Element instance.
# - - - w e b P a g e - - -
def webPage ( titleText, stylesheet=None ):
"""Builds the skeleton of an XHTML page.
[ (titleText is the text for the title and h1 elements) and
(stylesheet is the href of a stylesheet, or None) ->
return (a new XHTML page with that title and stylesheet
as an xc.Document, the body element of that page as an
xc.Element) ]
"""
Document creation is described in the documentation for the xml4create module. We'll even put
in a DOCTYPE so the W3C validator
will approve.
#-- 1 --
# [ doc := a new XHTML 1.0 Strict page as an xc.Document ]
doctype = xc.DocumentType ( "html",
"-//W3C//DTD XHTML 1.0 Strict//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" )
doc = xc.Document ( "html", doctype )
The rest is very similar to the example given in the
xml4create documentation.
#-- 2 --
# [ doc := doc with a new 'head' child containing
# titleText as its text, and a 'body' child
# containing titleText as its heading
# head := that 'head' child
# body := that 'body' child ]
head = xc.Element ( doc.root, "head" )
title = xc.Element ( head, "title" )
xc.Text ( title, titleText )
body = xc.Element ( doc.root, "body" )
h1 = xc.Element ( body, "h1" )
xc.Text ( h1, titleText )
#-- 3 --
# [ if stylesheet is None -> I
# else ->
# head := head with a new 'link' child linking to
# the stylesheet named (styleshee) ]
if stylesheet is not None:
link = xc.Element ( head, 'link', href=stylesheet,
rel='stylesheet', type='text/css' )
#-- 4 --
return (doc, body)