Code
BeipMU gadgets
Movable Type plugins
POT.py
Radio UserLand tools
TBPY
NB: 1.2's .manifest files are incompatible with 1.3. Run with -1 and delete your .manifest before upgrading, then run with --lie afterward to rebuild the .manifest file.
NB: 1.3 uses the Python 2.3 logging module. You'll need Vinay Sajip's compatible logging module to run POT.py with Python 2.2.
POT.py is an engine for publishing HTML files with embedded Python code by FTP. POT.py requires options to tell it what to publish; these are:
-h host-u user--pass pass-r remotedir-L localdirPOT.py will publish every file in and under the specified local root directory to the server, relative to the specified remote root directory.
As exception to the above, POT.py does not publish any file the name of which starts with a period. (UNIX uses the period to denote a hidden file.) If you don't want to specify these options on the command line, you can save them in an .ftpData file in the directory where you run POT.py. This file is run as Python code; here's an example:
# Publish my site to myisp.net/~markpasc/
user = 'markpasc'
host = 'ftp.myisp.net'
password = 'steak'
remoteDir = '/home/markpasc/public_html'
localDir = '.'
Since ".ftpData" starts with a period, the ftpData file is not published even if, as in the example, the local root directory is the current directory. POT.py employs two other special dot-files:
.manifest.include.include files down the directory tree from the root to the parsed file.POT.py discovers what needs publishing by looking in its manifest, saved in the .manifest file in the root directory. POT.py keeps track of all the files it publishes, by the "mtime," or last modified time, for normal files, and by the MD5 hash for HTML files. (Since Python code in those HTML files is executed, their uploadable results may change without their unparsed content changing.)
Here's a basic example:
<?inherit('.header.html')?>
<p>Hello, world! 2 + 2 = <?2+2?>!</p>
<p>The sum of 1 to 100 is <?
ret = 0
for i in range(1,101):
ret += i
print ret
?></p>
<?inherit('.footer.html')?>
POT.py parses text inside <? and ?>, as highlighted in the example, as Python code. The example shows the difference between expressions and embedded scripts: code that can be stuffed on one line and is, syntactically, a Python expression can be placed inline like <?2+2?>. Code that doesn't count as a Python expression, such as the long script with the for loop, should be written as shown and must use print (or otherwise output to stdout) to "return" a value.
The example also uses POT.py's inherit function. POT.py provides several variables for use in your templates:
dynamic1 if the file is being uploaded, or 0 if it's merely being tested for change. Test dynamic to see if you should include content that always changes; for example, a random quote, or a real timestamp (though you should probably use the file's mtime anyway). Returning a static value when POT.py tests for change will prevent the file from uploading every time.filenameos.path.abspath or os.getcwd to get the path part.include(filename)include is a very simple wrapper for str(Document(open(filename, 'r'))).)inherit(filename)include, inherit will look up the directory tree until it finds filename. Use this instead of include for, say, templates that you want to store in your web site's root directory.At the top of this document (in its unpublished form on my computer) is:
<?
title.append('POT.py')
style += "span.potcode { background-color: #0c9; }\n"
print inherit('.header.html')
?>
.header.html might contain:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">...
<html><head>
<title><?
fulltitle = ''
for segment in title: # which is a list
fulltitle = segment + ": " + fulltitle
if fulltitle: print re.sub(r'<[^>]*>', '', fulltitle) ?>markpasc.org</title>
<style type="text/css"><? style ?></style>
</head><body>
<h1><? fulltitle[:-2] ?></h1>
See how .header.html prints the contents of the style variable inside the <style/> tag, and collapses the title list to make the nice <title/> and leading header on this page. (Also note that the inherit needs printed, since it's part of an embedded script, not a single expression.)
Whither .include? For one, by Python's rules, those variables style and title have to be initialized; .include files are good for that. Also, say a subdirectory has several subpages in it, like this site's code/ section. The sidebar can be set in a sidebar variable in code/.include and referenced in .header.html so all the pages under code/ have the section's sidebar. The sidebar's HTML is only given once—or even, as is the case with this site, generated from a Python dictionary containing the names of subdirectories, project names, and descriptions.
Lastly, POT.py has three other command line options:
-1--lie-1. Useful if you are, say, converting a site over from plain HTML and have a lot of images and other content files that are already on the remote site, or if POT.py's manifest gets out of sync or encounters errors uploading.-qPOT.py is a replacement for publish, an HTML preprocessor I threw together in Perl, so its design is heavily informed by the shortcomings and annoyances I discovered with it, as well as some of the "upstreaming" architecture of Radio UserLand. I hope you find it as useful (or at least as thought-provoking) as I do.
1.3, 22 August 2003: Made SpyDict class a dict, not a UserDict (NB: this broke .manifest file compatibility). Use standard logging module. Internal stylistic improvements.
1.2, 29 April 2003: Added inherit function, to source.