    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Functional Programming in Python: An Introduction by
Example</title>
        <link>https://members.accu.org/index.php/journals/671</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">CVu Journal Vol 16, #3 - Jun 2004 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c102/">163</a>
                    (11)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c102-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c102+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Functional Programming in Python: An Introduction by
Example</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 June 2004 13:16:05 +01:00 or Thu, 03 June 2004 13:16:05 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e20" id="d0e20"></a></h2>
</div>
<p>In a previous article [<a href="#Guest">Guest</a>] I described
the development of a simple Python script to relocate source files,
demonstrating how Python's built in objects and modules can make
light work of such tasks. The final script bore a superficial
resemblence to a C program: the code was structured into blocks,
with a main routine calling subroutines to get the job done;
objects were scoped; and control flow was handled by familiar
constructs - loops, if statements and return statements.</p>
<p>Python also allows the creation of more C++ like scripts,
complete with classes, encapsulation, inheritance, polymorphism,
exceptions etc. In this article, however, I want to show how Python
copes cleanly in a situation where C++ struggles, namely functional
programming.</p>
<p>This article, then, builds on the previous article by
introducing some of Python's functional programming capabilities by
means of example. It also shows some more advanced uses of Python's
regular expression module.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e31" id="d0e31"></a>Statement of
the Problem</h2>
</div>
<p>Let's suppose we want to convert some articles from plain text
format into web pages. Since these articles are about programming,
they embed fragments of C/C++ source code, and since the
presentation of source code matters, we want these fragments to
have their syntax highlighted according to the following rules:</p>
<pre class="programlisting">
builtin types   -&gt; blue
keywords        -&gt; bold, blue
comments        -&gt; italics, red
string literals -&gt; green
</pre>
<p>I should confess at this point - as will soon become obvious -
that I'm an html novice, and am aiming for the very simplest of
markup to achieve the scheme presented above: this article is about
Python, not web page development. Nonetheless, the finished script
could be adapted to produce output suitable for more sophisticated
web pages.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e40" id="d0e40"></a>Towards a
Solution</h2>
</div>
<p>Full tokenization of C/C++ is beyond the scope of this script.
Even hooking in to some third-party parser would be overkill.
Fortunately, we can get the job done using a simple pattern
matching algorithm.</p>
<p>In outline this algorithm:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>creates a pattern to match regions of interest in the code,</p>
</li>
<li>
<p>processes the code, marking up these matches.</p>
</li>
</ul>
</div>
<p>To get us started, the following script picks out some C++
keywords associated with control flow and emphasises them using
bold text:</p>
<pre class="programlisting">
&lt;python&gt;
import re
html_data = re.sub(r'(if|else|for|do|while)',
                   r'\1', src_data)
&lt;/python&gt;
</pre>
<p>Notice here the <tt class="literal">\1</tt>, which
backreferences the first (and in this case, only) group matched by
the input pattern. The <tt class="literal">r</tt> before the string
literal often appears in Python regular expressions. It stands for
<span class="type">rawstring</span> and ensures that backslashes
are not handled in any special way by Python - the string literals
are passed directly on to the regular expression module.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e69" id="d0e69"></a>Patching up the
Problems</h2>
</div>
<p>The simple script above is broken. The code fragment:</p>
<pre class="programlisting">
&lt;cpp&gt;
  cutlery = fork + knife; // do we need spoons?
&lt;/cpp&gt;
</pre>
<p>would be marked up:</p>
<pre class="programlisting">
&lt;html&gt;
cutlery = &lt;b&gt;for&lt;/b&gt;k + kn&lt;b&gt;if&lt;/b&gt;e;
               // &lt;b&gt;do&lt;/b&gt; we need spoons?
&lt;/html&gt;
</pre>
<p>There are three unwanted substitutions! Clearly, we should only
match keywords which are complete words, and keywords cease to be
keywords when they're in a comment. Both problems can be fixed by
using a more complex pattern:</p>
<pre class="programlisting">
&lt;python&gt;
def markup(match):
  &quot;&quot;&quot;Return an html-marked-up version of the
     input match object&quot;&quot;&quot;
  html = ''
  if (match.group(1)):
    html = bold(match.group(1))
  elif (match.group(2)):
    html = italics(match.group(2))
  return html

cpp_re = re.compile(
  r'(\bif\b|\belse\b|\bfor\b|\bdo\b|\bwhile\b)'
  r'|'
  r'(//.*?$|/\*.*?\*/)',
  re.DOTALL |
  re.MULTILINE)

html_data = cpp_re.sub(markup, src_data)
&lt;/python&gt;
</pre>
<p>Some notes on the regex pattern:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p><tt class="literal">\b</tt> matches (the empty string at) the
beginning or end of a word,</p>
</li>
<li>
<p>the flag parameter to <tt class="literal">re.compile, re.DOTALL
| re.MULTILINE</tt>, enables us to match C-style multi-line
comments (refer to the Python documentation [<a href=
"#python">python</a>] for details),</p>
</li>
<li>
<p>asterisks - such as the ones which appear in C-style comments -
are regex special characters, so they need to be escaped for a
literal match,</p>
</li>
<li>
<p><tt class="literal">.*?</tt> is a non-greedy match of any
character. Non-greedy means that the regex parser doesn't consume
all the text it can to match a part of a pattern before
backtracking to match the next part of the pattern. So, for
example, <tt class="literal">//.*?$</tt> matches from the start of
a C++ style-comment up to the next end-of-line character, but
<tt class="literal">//.*$</tt> would match from this start point up
to the final end-of-line in the data.</p>
</li>
</ul>
</div>
<p>And some notes our more advanced use of the re module:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>parentheses have been used to capture matching text into
groups,</p>
</li>
<li>
<p>the first argument to <tt class=
"literal">&lt;code&gt;re.sub&lt;/code&gt;</tt> is now a function
which accepts a <span class="type">MatchObject</span>. This
function applies markup according to the group which has been
matched.</p>
</li>
</ul>
</div>
<p>Finally, it's probably worth saying something about the
triple-quoted string literal which appears as the first line of the
function. This is the function's documentation string, or
<span class="type">docstring</span>. These strings are, by
convention, triple-quoted, since they often span more than one
line. Refer to the Python documentation, and in particular &quot;PEP:
257 Docstring Conventions&quot;, for details.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e135" id="d0e135"></a>Creating
Patterns Using List Comprehensions</h2>
</div>
<p>I'm not entirely happy with the revised script above. I don't
like the repetition of the regex special character, <tt class=
"literal">\b</tt>, and I don't like the way the C++ keywords have
been obscured by the presence of these characters. This situation
is only going to get worse when we extend the pattern to include
all the other C++ keywords.</p>
<p>We could build the pattern up using an explicit loop and the
built in <tt class="function">join</tt> function.</p>
<pre class="programlisting">
&lt;python&gt;
keywords = ('if', 'else', 'for', 'do', 'while')
kw_patterns = []
for kw in keywords:
  kw_patterns.append(r'\b%s\b' % kw)
kw_pattern = '|'.join(kw_patterns)
&lt;/python&gt;
</pre>
<p>Alternatively, we can use a list comprehension instead of the
loop:</p>
<pre class="programlisting">
&lt;python&gt;
kw_pattern = '|'.join([r'\b%s\b' % kw
                        for kw in keywords])
&lt;/python&gt;
</pre>
<p>This alternative is the Python idiom for building lists from
sequences.</p>
<p>There are downsides to using this idiom. What if a C/C++
programmer tries to understand/modify this script? What if I don't
use Python for a while (day to day, I use C++) - will I remember
what the syntax means? (Think of all those ultra-succinct Perl
programs, which default pretty much everything to apparently
conjure their results from thin air.)</p>
<p>In this case, the idiom is well worth adopting. List
comprehensions are too useful to be ignored.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e160" id="d0e160"></a>Lambda
Functions</h2>
</div>
<p>There's another thing I'm not happy about: the separation of the
patterns being matched and the markup applied to the matches.
Recalling our original statement of the problem:</p>
<pre class="programlisting">
builtin types   -&gt; blue
keywords        -&gt; bold, blue
comments        -&gt; italics, red
string literals -&gt; green
</pre>
<p>I'd like the script to somehow embody this mapping.</p>
<p>The right arrows suggest using a dictionary to map from lexical
elements to markup functions. Rather than use a dictionary, we'll
choose a sequence of 2-tuples. This is because the elements of a
dictionary are not ordered (perhaps dictionary was not the best
term for Python to adopt for such a collection!) and we want to
control the order in which pattern matches are tested. For example,
<span class="type">double</span> will appear as both a builtin type
and as a keyword, and we can indicate we want it to match as a
builtin by placing builtins before keywords in our markup
rules.</p>
<p>So, we want something like:</p>
<pre class="programlisting">
&lt;python&gt;
def italics(str):
  return '&lt;i&gt;' + str + '&lt;/i&gt;'
def bold(str):
  return '&lt;b&gt;' + str + '&lt;/b&gt;'
def colour(str, col):
  return ('&lt;font color=&quot;' + col + '&quot;&gt;'
          + str + '&lt;/font&gt;')
def boldBlue(str):
  return bold(colour(str, 'blue'))
# ...similarly define blue, italicsRed etc ...
markup_rules = (
  (builtin_pattern, blue),
  (kw_pattern, boldBlue),
  (comment_pattern, italicsRed),
  (string_pattern, green)
)
&lt;/python&gt;
</pre>
<p>Here, the html markup helper functions <tt class=
"function">italics</tt>, <tt class="function">colour</tt>,
<tt class="function">bold</tt>, are good general purpose utility
functions. The markup utilities - <tt class="literal">blue</tt>,
<tt class="literal">boldBlue</tt>, <tt class=
"literal">italicsRed</tt>, <tt class="literal">green</tt> - do not
merit existence as named functions: they are simply the result of
composing our utilities and binding arguments to values. This is
where Python's lambda functions can help:</p>
<pre class="programlisting">
&lt;python&gt;
markup_rules = (
  (comment_pattern,
   lambda s: colour(italics(s), 'red')),
  (builtin_pattern,
   lambda s: colour(s, 'blue')),
  (keyword_pattern,
   lambda s: colour(bold(s), 'blue')),
  (string_pattern,
   lambda s: colour(s, 'green'))
)
&lt;/python&gt;
</pre>
<p>A lambda function is an anonymous function. Nonetheless, these
anonymous functions can be passed around as parameters - we'll be
passing them into our regex text substitution function, for
example, and we'll use another lambda function to do this.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e205" id="d0e205"></a>The Final
Script</h2>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e208" id="d0e208"></a>General
Points</h3>
</div>
<p>The final script appears at the end of this section. Most of its
interesting points have already been discussed. Note, though:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>The lambda function used for pattern substitution, which binds
its second argument to our markup rules enabling us to pass our
markup rules into the markup function; this works around the fact
that a function passed into <tt class=
"literal">&lt;code&gt;re.sub&lt;/code&gt;</tt> must only accept a
single match object argument.</p>
</li>
<li>
<p>The use of the built in <tt class="function">filter</tt>
function, applied to the groups present in our match object. This
function accepts a predicate function and a list, and returns a
filtered list containing only those elements for which the
predicate is true. If the predicate is <tt class=
"literal">None</tt>, the returned list has its zero or empty
elements removed.</p>
</li>
<li>
<p>The string literal match pattern, which introduces a negative
look behind assertion, <tt class="literal">(?&lt;!\\)</tt>. The
pattern itself &quot;<tt class="literal">.*?(?&lt;!\\)</tt>&quot; will match
an opening double quote followed by a non-greedy sequence of any
characters followed by a closing double quote, provided that the
closing double quote is not preceded by a backslash - is not
escaped in C terminology. This is necessary in case we encounter a
string literal of the form:</p>
<pre class="programlisting">
&lt;cpp&gt;
  char const * what_he_said = &quot;He said \&quot;Hi!\&quot;&quot;;
&lt;/cpp&gt;
</pre></li>
<li>
<p>The <tt class="function">cookForHtml</tt> function. The term
&quot;cook&quot;, in this context, comes from ([<a href=
"#Freidl">Freidl</a>]). Python's cgi module provides the required
function directly.</p>
</li>
</ul>
</div>
<pre class="programlisting">
cpp_keywords = (
  'and',
  'and_eq',
  'asm',
  'auto',
  'bitand',
  'bitor',
  'bool',
  'break',
  'case',
  'catch',
  'char',
  'class',
  'compl',
  'const',
  'const
  'auto',
  'bitand',
  'bitor',
  'bool',
  'break',
  'case',
  'catch',
  'char',
  'class',
  'compl',
  'const',
  'const_cast',
  'continue',
  'default',
  'delete',
  'do',
  'double',
  'dynamic_cast',
  'else',
  'enum',
  'explicit',
  'export',
  'extern',
  'false',
  'float',
  'for',
  'friend',
  'goto',
  'if',
  'inline',
  'int',
  'long',
  'mutable',
  'namespace',
  'new',
  'not',
  'not_eq',
  'operator',
  'or',
  'or_eq',
  'private',
  'protected',
  'public',
  'register',
  'reinterpret_cast',
  'return',
  'short',
  'sizeof',
  'static',
  'static_cast',
  'struct',
  'switch',
  'template',
  'this',
  'throw',
  'true',
  'try',
  'typedef',
  'typeid',
  'typename',
  'union',
  'using',
  'virtual',
  'void',
  'volatile',
  'wchar_t',
  'while',
  'xor',
  'xor_eq'
)

cpp_builtins = (
  'bool',
  'signed',
  'unsigned',
  'char',
  'short',
  'long',
  'float',
  'double',
  'wchar_t'
)

def preformat(str):
  &quot;&quot;&quot;Return a preformatted version of the
     string.&quot;&quot;&quot;    
  return '&lt;pre&gt;' + str + '&lt;/pre&gt;'

def italics(str):
  &quot;&quot;&quot;Return an italicised version of the
     string.&quot;&quot;&quot;
  return '&lt;i&gt;' + str + '&lt;/i&gt;'

def bold(str):
  &quot;&quot;&quot;Return a bold version of the
     string.&quot;&quot;&quot;
  return '&lt;b&gt;' + str + '&lt;/b&gt;'

def colour(str, colour):
  &quot;&quot;&quot;Returstr):
  &quot;&quot;&quot;Return a bold version of the string.&quot;&quot;&quot;
  return '&lt;b&gt;' + str + '&lt;/b&gt;'
def colour(str, colour):
  &quot;&quot;&quot;Return a coloured version of the
     string.&quot;&quot;&quot;
  return ('&lt;font color=&quot;' + colour + '&quot;&gt;'
          + str +
          '&lt;/font&gt;')

def orPatterns(patterns):
  &quot;&quot;&quot;Return a pattern which matches any one of
     the input patterns.&quot;&quot;&quot;
  return '|'.join(patterns)

def cookForHtml(src):
  &quot;&quot;&quot;Return the input data cooked for html.&quot;&quot;&quot;
  import cgi
  return cgi.escape(src)

def markup(match, rules):
  &quot;&quot;&quot;Markup the text matched by the input
     match object.&quot;&quot;&quot;
  # p the text matched by the input
 match object.&quot;&quot;&quot;
  # Sanity check: the rules match the groups
  hits = filter(None, match.groups())
  assert(len(hits) == 1)
  assert(len(match.groups()) == len(rules))

  ix = match.lastindex # Last and only index,
                       # in fac # Last and only index, in fact.

  # Careful! - rules are indexed from 0 but
  # matchObject groups are indexed from 1.
  markup_fn = rules[ix - 1][1]
  return markup_fn(match.group(ix))

def cpp2html(cpp_src):
  &quot;&quot;&quot;Return C++ source code marked up using
  html.&quot;&quot;&quot;
  comment_pattern = def cpp2html(cpp_src):
  &quot;&quot;&quot;Return C++ source code marked up using
     html.&quot;&quot;&quot;
  comment_pattern = o markup_fn(match.group(ix))

def cpp2html(cpp_src):
  &quot;&quot;&quot;Return C++ source code marked up using html.&quot;&quot;&quot;
  comment_pattern = orPatterns([
    r'//.*?$',   # C++ style comment
    r'/\*.*?\*/' # C style comment
  ])

  builtin_pattern = orPatterns([
    r'\b%s\b' % bt
    for bt in cpp_builtins
  ])

  keyword_pattern = orPatterns([
    r'\b%s\b' % kw
    for kw in cpp_keywords
  ])
        
  string_pattern = r'&quot;.*?(?&lt;!\\)&quot;'
    
  markup_rules = (
    (comment_pattern,
     lambda s: colour(italics(s), 'red')),
    # Need builtins before keywords - there's
    # an overlap, since some keywords are
    # also designated as builtins.
    (builtin_pattern,
     lambda s: colour(s, 'blue')),
    (keyword_pattern,
     lambda s: colour(bold(s), 'blue')),
    (string_pattern,
     lambda s: colour(s, 'green'))
  )

  # Create a regex group for each
  # pattern in the markup rules, and
  # combine these groups into a single
  # pattern.
  cpp_pattern = orPatterns(
    ['(%s)' % p for p, f in markup_rules]
  )

  cpp_re = re.compile(
    cpp_pattern,
    re.DOTALL |
    re.MULTILINE # C-style comments can
                 # span multiple lines
  )
    
  cpp_src = cookForHtml(cpp_src)
    
  cpp_src = cpp_re.sub(.sub(cookForHtml(cpp_src)
    
  cpp_src = cpp_re.sub(
    lambda m: markup(m, markup_rules),
    cpp_src)

  return preformat(cpp_src)


def python2html(srcdata):
  &quot;&quot;&quot;Return Python source code marked up
     using html.&quot;&quot;&quot;
  import keyword
  import token
  import tokenize
    
  lines = srcdata.split('\n')    
  def popLine():
    line = ''
    if len(lines) &gt; 0:
      line = lines.pop(0) + '\n'
    return line

  marked_up = ''
  row, col = 0, 0 # Location of the end of
                  # the previous token
    
  for tok in tokenize.generin tokenize.generate_tokens(popLine):
    # The tokenizer skips whitespace.
    # We must put it back.        
    srow, scol = tok[2]
    if (srow &gt; :
      col = 0
    if (scol &gt;= col):
      marked_up += ' ' * (scol - col)
        
    tok_name = token.tok_name[tok[0]]
    str = cookForHtml(tok[1])

    if (tok_name == 'STRING'):
      marked_up += colour(str, 'green')
    elif (tok_name == 'COMMENT'):
      marked_up += colour(italics(str), 'red')
    elif (tok_name == 'NAME' and
          keyword.iskeyword(tok[1])):
      marked_up += colour(bold(str), 'blue')
    else:
      marked_up += str
                              
    row, col = tok[3]

  return preformat(marked_up)

&lt;/python&gt;
</pre></div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e251" id="d0e251"></a>Marking Up
Python Code</h2>
</div>
<p>I think it's clear that this script could be extended to handle
other highlighting schemes or source data of other types. It's just
a matter of defining the markup rules and patterns.</p>
<p>The thought of creating a pattern to match Python's various
flavours of string literal is rather daunting. Fortunately, the
language itself provides a <tt class="literal">tokenize</tt> module
which does the job more easily and more accurately. The final
script also provides a Python to html conversion function
<tt class="function">python2html</tt> based on the <tt class=
"function">generate_tokens</tt> function available in this
module.</p>
<p>This function embeds a sub-function, <tt class=
"function">popLine()</tt>, which is used as the callable object
required as a parameter to <tt class=
"function">generate_tokens</tt>. This function can directly access
the list of lines in the enclosing function's scope. An alternative
would have been to create a functor object initialised with a
reference to (or a copy of) the required list. In this case, I
prefer to keep related code as close together as possible, and
choose the subfunction.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e275" id=
"d0e275"></a>Weaknesses</h2>
</div>
<p>The script, although powerful, is far from perfect. It bundles
data sets together with a number of unrelated utility functions to
get the job done. Properly, it should be partitioned into modules:
perhaps one for the C++ data tuples, one for the pattern creation
utilities, one for the general purpose html markup utilities and
one for our main functions. This partitioning is not hard to
achieve, but will have to remain a subject for a future
article.</p>
<p>To provide a more flexible markup tool, the functions <tt class=
"function">python2html</tt> and <tt class="function">cpp2html</tt>
should provide a mechanism for clients to supply their own markup
rules. The obvious solution here would be to allow these rules to
be supplied as optional function parameters.</p>
<p>Finally, despite Python's support for unit testing, this script
contains no unit tests.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e290" id=
"d0e290"></a>Conclusions</h2>
</div>
<p>Python's support for lambda functions and list comprehensions
have allowed us to create a deceptively simple script.</p>
<p>The script by no means demonstrates all of Python's functional
programming capabilities. A good reference book ([<a href=
"#Beazley">Beazley</a>], for example) describes these in more
depth.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e300" id="d0e300"></a>Credits</h2>
</div>
<p>Thanks again to Dan Tallis for his expert review of an earlier
draft of this article.</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e305" id="d0e305"></a>References</h2>
</div>
<div class="bibliomixed"><a name="Guest" id="Guest"></a>
<p class="bibliomixed">[Guest] Thomas Guest, &quot;A Python Script to
Relocate Source Trees&quot;, <span class="citetitle"><i class=
"citetitle">C Vu 16.2</i></span>.</p>
</div>
<div class="bibliomixed"><a name="python" id="python"></a>
<p class="bibliomixed">[python] <span class="bibliomisc"><a href=
"http://www.python.org" target=
"_top">http://www.python.org</a></span></p>
</div>
<div class="bibliomixed"><a name="Freidl" id="Freidl"></a>
<p class="bibliomixed">[Freidl] Jeffrey E. F. Freidl, <span class=
"citetitle"><i class="citetitle">Mastering Regular
Expressions</i></span>. The definitive reference on regular
expressions, though note that it focuses mainly on Perl's regex
support.</p>
</div>
<div class="bibliomixed"><a name="Beazley" id="Beazley"></a>
<p class="bibliomixed">[Beazley] David Beazley, <span class=
"citetitle"><i class="citetitle">Python Essential
Reference</i></span>.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
