diff options
Diffstat (limited to 'sandbox/fwiemann')
-rw-r--r-- | sandbox/fwiemann/.fsfsbackup | 4 | ||||
-rw-r--r-- | sandbox/fwiemann/commit-email/README.txt | 21 | ||||
-rw-r--r-- | sandbox/fwiemann/commit-email/commit-email.patch | 135 | ||||
-rwxr-xr-x | sandbox/fwiemann/fsfsbackup.sh | 90 | ||||
-rw-r--r-- | sandbox/fwiemann/plugins/interface.py | 256 | ||||
-rwxr-xr-x | sandbox/fwiemann/release.sh | 490 | ||||
-rw-r--r-- | sandbox/fwiemann/users.txt | 70 | ||||
-rw-r--r-- | sandbox/fwiemann/xhtml2rest/README.txt | 15 | ||||
-rwxr-xr-x | sandbox/fwiemann/xhtml2rest/xhtml2rest.py | 551 |
9 files changed, 0 insertions, 1632 deletions
diff --git a/sandbox/fwiemann/.fsfsbackup b/sandbox/fwiemann/.fsfsbackup deleted file mode 100644 index 89588ab02..000000000 --- a/sandbox/fwiemann/.fsfsbackup +++ /dev/null @@ -1,4 +0,0 @@ -BACKUPDIR=~/remote-backup/docutils -HOST=svn.berlios.de -REMOTEDIR=/svnroot/repos/docutils -do_backup diff --git a/sandbox/fwiemann/commit-email/README.txt b/sandbox/fwiemann/commit-email/README.txt deleted file mode 100644 index 428a569d0..000000000 --- a/sandbox/fwiemann/commit-email/README.txt +++ /dev/null @@ -1,21 +0,0 @@ -========================================= - File name patch for ``commit-email.pl`` -========================================= - -:Author: Felix Wiemann -:Contact: Felix.Wiemann@ososo.de -:Revision: $Revision$ -:Date: $Date$ -:Copyright: This document has been placed in the public domain. - - -`<commit-email.patch>`_ is a patch against ``commit-email.pl`` of -Subversion 1.1.3. Note that the patch cannot be applied to newer -versions of ``commit-email.pl``. - -It adds file names to the subject lines, which would otherwise only -list directories. The Docutils Subversion repository currently uses -this patched version of ``commit-email.pl`` to generate the check-in -messages sent to the Docutils-checkins mailing list. - -The patch has been placed in the public domain. diff --git a/sandbox/fwiemann/commit-email/commit-email.patch b/sandbox/fwiemann/commit-email/commit-email.patch deleted file mode 100644 index ebc9a1ae4..000000000 --- a/sandbox/fwiemann/commit-email/commit-email.patch +++ /dev/null @@ -1,135 +0,0 @@ ---- tools/hook-scripts/commit-email.pl 2004-06-14 22:29:22.000000000 +0200 -+++ tools/hook-scripts/commit-email.pl 2005-10-30 22:39:22.942246752 +0100 -@@ -222,32 +222,16 @@ - shift @svnlooklines; - my @log = map { "$_\n" } @svnlooklines; - --# Figure out what directories have changed using svnlook. --my @dirschanged = &read_from_process($svnlook, 'dirs-changed', $repos, -- '-r', $rev); -- --# Lose the trailing slash in the directory names if one exists, except --# in the case of '/'. --my $rootchanged = 0; --for (my $i=0; $i<@dirschanged; ++$i) -- { -- if ($dirschanged[$i] eq '/') -- { -- $rootchanged = 1; -- } -- else -- { -- $dirschanged[$i] =~ s#^(.+)[/\\]$#$1#; -- } -- } - - # Figure out what files have changed using svnlook. - @svnlooklines = &read_from_process($svnlook, 'changed', $repos, '-r', $rev); - - # Parse the changed nodes. -+my @fileschanged; - my @adds; - my @dels; - my @mods; -+my $rootchanged = 0; - foreach my $line (@svnlooklines) - { - my $path = ''; -@@ -261,6 +245,12 @@ - $path = $2; - } - -+ push(@fileschanged, $path); -+ if ($path eq '/') -+ { -+ $rootchanged = 1; -+ } -+ - if ($code eq 'A') - { - push(@adds, $path); -@@ -288,11 +278,11 @@ - # there's no point in collapsing the directories, and only if more - # than one directory was modified. - my $commondir = ''; --if (!$rootchanged and @dirschanged > 1) -+if (!$rootchanged and @fileschanged > 1) - { -- my $firstline = shift @dirschanged; -+ my $firstline = shift @fileschanged; - my @commonpieces = split('/', $firstline); -- foreach my $line (@dirschanged) -+ foreach my $line (@fileschanged) - { - my @pieces = split('/', $line); - my $i = 0; -@@ -306,28 +296,28 @@ - $i++; - } - } -- unshift(@dirschanged, $firstline); -+ unshift(@fileschanged, $firstline); - - if (@commonpieces) - { - $commondir = join('/', @commonpieces); -- my @new_dirschanged; -- foreach my $dir (@dirschanged) -+ my @new_fileschanged; -+ foreach my $file (@fileschanged) - { -- if ($dir eq $commondir) -+ if ($file eq "$commondir/") - { -- $dir = '.'; -+ $file = '.'; - } - else - { -- $dir =~ s#^$commondir/##; -+ $file =~ s#^$commondir/##; - } -- push(@new_dirschanged, $dir); -+ push(@new_fileschanged, $file); - } -- @dirschanged = @new_dirschanged; -+ @fileschanged = @new_fileschanged; - } - } --my $dirlist = join(' ', @dirschanged); -+my $filelist = join(' ', @fileschanged); - - ###################################################################### - # Assembly of log message. -@@ -367,7 +357,7 @@ - { - my $match_re = $project->{match_re}; - my $match = 0; -- foreach my $path (@dirschanged, @adds, @dels, @mods) -+ foreach my $path (@adds, @dels, @mods) - { - if ($path =~ $match_re) - { -@@ -390,16 +380,20 @@ - - if ($commondir ne '') - { -- $subject = "r$rev - in $commondir: $dirlist"; -+ $subject = "r$rev - in $commondir: $filelist"; - } - else - { -- $subject = "r$rev - $dirlist"; -+ $subject = "r$rev - $filelist"; - } - if ($subject_prefix =~ /\w/) - { - $subject = "$subject_prefix $subject"; - } -+ if(length($subject) > 900) -+ { -+ $subject = substr($subject, 0, 896) . " ..."; -+ } - my $mail_from = $author; - - if ($from_address =~ /\w/) diff --git a/sandbox/fwiemann/fsfsbackup.sh b/sandbox/fwiemann/fsfsbackup.sh deleted file mode 100755 index 32d472760..000000000 --- a/sandbox/fwiemann/fsfsbackup.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash - -# Author: Felix Wiemann -# Contact: Felix_Wiemann@ososo.de -# Revision: $Revision$ -# Date: $Date$ -# Copyright: This file has been placed in the public domain. - -# Options: -# -# -f Do not print feedback. - -set -e - -trap "echo; echo Exiting with error.; trap - 0; exit 1" 0 1 2 3 15 - -test "$1" == -f && printfeedback= || printfeedback=1 - -function feedback() { - test "$printfeedback" && echo "$@" || true -} - -function do_backup() { - # If any of the tests fails, the script terminates silently. - feedback "Checking that all necessary variables are set." - test -n "$BACKUPDIR" - test -n "$HOST" - test -n "$REMOTEDIR" - if test ! -d "$BACKUPDIR"; then - feedback "Creating backup directory $BACKUPDIR." - mkdir --parents --verbose "$BACKUPDIR" - fi - if test ! -f "$BACKUPDIR/db/fs-type"; then - feedback - echo "$BACKUPDIR/db/fs-type not found." - echo "Please fetch the first copy of the repository database yourself." - echo "I only assist in doing incremental backups of repository databases." - exit 1 - fi - feedback "Checking that repository format is FSFS." - test "`cat "$BACKUPDIR/db/fs-type"`" == fsfs - feedback "Changing to database directory $BACKUPDIR/db." - cd "$BACKUPDIR/db" - feedback "Getting local current revision number." - LOCALREVNUM="`cat current | sed 's/ .*//'`" - feedback "Checking that current.new doesn't exist." - if test -f current.new; then - feedback - echo "Make sure that no other instance of this script" - echo "is running and delete the following file:" - echo "$BACKUPDIR/db/current.new" - exit 2 - fi - feedback "Getting remote 'current' file." - ssh "$HOST" "cat '$REMOTEDIR/db/current'" > current.new - feedback "Getting remote current revision number." - REMOTEREVNUM="`cat current.new | sed 's/ .*//'`" - feedback "Checking that we got a response from the server." - test -n "$REMOTEREVNUM" - if ! test "$LOCALREVNUM" -le "$REMOTEREVNUM"; then - feedback - echo "ERROR: Local revision number ($LOCALREVNUM) greater" - echo " than remote revision number ($REMOTEREVNUM)." - echo "Wrong backup directory or changed repository?" - exit 2 - fi - if test "$LOCALREVNUM" -eq "$REMOTEREVNUM"; then - feedback "No backup needed; at revision $LOCALREVNUM." - feedback "Removing 'current.new'." - rm current.new - feedback "Done." - return - fi - LOCALREVNUM="$[$LOCALREVNUM+1]" - feedback "Backing up from revision $LOCALREVNUM to revision $REMOTEREVNUM." - test "$printfeedback" && verbose=-v || verbose= - ssh "$HOST" " - set -e; - cd $REMOTEDIR/db/; - nice -n 10 tar cf - \`seq -f revs/%g $LOCALREVNUM $REMOTEREVNUM\` \`seq -f revprops/%g $LOCALREVNUM $REMOTEREVNUM\` | nice -n 10 bzip2 -c" \ - | tar $verbose -xjf - - feedback "Renaming 'current.new' to 'current'." - mv current.new current - feedback "Done." -} - -feedback 'Reading ~/.fsfsbackup.' -source ~/.fsfsbackup -feedback 'Finished.' -trap - 0 1 2 3 15 diff --git a/sandbox/fwiemann/plugins/interface.py b/sandbox/fwiemann/plugins/interface.py deleted file mode 100644 index 17e5d0a71..000000000 --- a/sandbox/fwiemann/plugins/interface.py +++ /dev/null @@ -1,256 +0,0 @@ -""" -Designing the urgently-needed plugin support... - -This module doesn't work, it's just there for showing the design, from -a plugin's point of view. (Kind of test-first. The required -interfaces will be implemented in Docutils later.) - -Let's implement an extension for rendering keys: - -reST source: - :key:`Ctrl+C` -Node tree: - <KeyNode> - Ctrl - + - <KeyNode> - C -HTML rendering: - <html><body><span style="border: 1px solid black;">Ctrl</span>+<span style="border: 1px solid black;">C</span></body></html> - -That isn't a particularly challenging task, but it's probably best to -stick to something simple first. (Later we could try to make a plugin -out of a math patch, but that will to require more code.) - -Things not (yet) covered here: - -* Adding a Component (this may require a generic frontend). -* Adding a directive (will require more complicated code than for - roles, because of arguments and options). -* Extending the parser by modifying a parser instance. (Do we *want* - to support that? It's powerful, but a little bit hackish.) -* Adding a transform. (Do we need that?) -* Writing a test case for an extension. -""" - - -class KeyNode(nodes.Inline, nodes.TextElement): - - """ - This is the node which stores the key texts (like "Ctrl" or "C"). - """ - - def __init__(self, key): - self += nodes.Text(key, key) - - -def html_visit_keynode(visitor, node): - """ - This is a visit_ method which looks like any normal Visitor - method. - - It is referenced from the writer support class below. - """ - if visitor.settings['key_html_tt']: - # Now insert a string into the writer's data stream. There is - # visitor.body.append(...) for the HTML visitor, but why not - # just return the string? That's much easier. The visitor - # should know where to put it. - return visitor.starttag('tt', - style='border: 1px solid black', - CLASS='key') - else: - return visitor.starttag('span', - style='border: 1px solid black', - CLASS='key') - -def html_depart_keynode(visitor, node): - """ - Now this is the depart method. - """ - if visitor.settings['key_html_tt']: - return '</tt>' - else: - return '</span>' - - -class KeyNodeHTMLSupport(docutils.WriterExtension): - - """ - This class describes HTML writer handling for the KeyNode, i.e. it - provides visit_ and depart_ methods. (By the way, is there any - term for visit_/depart_ methods?) - """ - - extends = 'html4css1' - """The writer this extension extends.""" - - handlers = {'KeyNode': (html_visit_keynode, html_depart_keynode)} - """ - Dictionary mapping node names to pairs of visit and departure - functions. - """ - - name = 'DefaultKeyHTMLSupport' - """ - Name of this extension. - - This is needed when there are several extensions proving support - for the same node, because in this case the user would have to - specify the name of the preferred extension (probably using an - option). - - For convenience, maybe we shouldn't require setting a name - attribute and have a default name of 'default' (or - self.__class__?). - """ - - settings_spec = (('Render key buttons in <tt> tags in HTML.', - ['--key-html-tt'], - {'default': 0, 'action': 'store_true'}), - ('Render key buttons in <span> tags in HTML.', - ['--key-html-span'], - {'dest': 'key_html_tt', 'action': 'store_false'},)) - """ - Sequence of settings. - """ - - -class KeyNodeLaTeXSupport(docutils.WriterExtension): - - """Support for the LaTeX writer. See KeyNodeHTMLSupport.""" - - extends = 'latex2e' - - handlers = {'KeyNode': ('\\fbox{', '}')} - """ - Here we have strings instead of functions. They are simply - inserted into the data stream; the visitor should know how to do - this. - - This is shorter and simpler than using lambdas, e.g. ``(lambda: - '\\fbox{', lambda: '}')``. - """ - - name = 'DefaultKeyLaTeXSupport' - - -class KeyRole(docutils.ParserExtension): - - """ - This is the role implementation for the reST parser. - - It is only registered at the parser if the parser requests it. - - The reST parser, for example, issues a request when it encounters - ".. require:: something". The request procedure might look like - this: - - Let's say the reST parser encounters a ".. require:: key". Then - it calls docutils.register_extension_by_id(self, 'key'). The - register function determines that the first parameter (self) is a - component instance of type Parser (so it only considers - ParserExtensions) and that its name is 'restructuredtext' (so it - only considers extensions whose `extends` attribute is - 'restructuredtext'). - - For all matching extensions, the register function then looks at - the `id` attribute. If the second parameter ('key' in this - example) matches `id`, the extension is registered at the - component instance passed as first parameter. - """ - - extends = 'restructuredtext' - """The component this extension extends.""" - - id = 'key' - """ - The id under which this extension is known. - - In this case, it's used for ".. require:: key" in reST. - - The presence of an `id` attribute means that the extension isn't - loaded automatically but only on request. (Is that too much - magic?) - """ - - type = 'role' - """ - The type of this extension. - - Might also be 'directive', for example. This attribute is read by - the reST parser. - """ - - # The rest of this class definition is specific to reST roles: - - role_name = 'key' - """ - Name of this role. - - This means we can write :key:`Ctrl+C`. - - There is no i18n support yet, because using a dictionary like - {'en': 'key'} seems a little bit too complex (since translations - usually aren't necessary) and the current i18n system needs a - redesign anyway. - """ - - raw = 1 - """ - If we pass pre-parsed contents to the role as proposed in - <http://article.gmane.org/gmane.text.docutils.user/1727>, we need - this ``raw`` attribute for the following purpose: - - The run() method wants to get a raw string, so we set raw to 1. - (Backslashes aren't interpreted then, but that isn't important in - the case of our key role.) - - If ``raw`` were 0, the run() method would get a list with one - Text node. Backslashes would be interpreted, and if there - were nested-inline-markup support, the list might contain any - Inline elements. - - If the role handler processes the role contents itself as proposed - in <http://article.gmane.org/gmane.text.docutils.user/1729>, we - don't need the ``raw`` attribute. - """ - - def run(self, contents): - """ - For the source text ":key:`Ctrl+C`", this method is called as - keyrole_instance.run('Ctrl+C'). - - lineno, inliner etc. aren't passed as parameters but they can - be grabbed from instance variables if needed (like - self.lineno). This avoids long useless copy'n'paste parameter - lists. - - Return value is a tuple of a node list and a system-message - list. - """ - - if (not contents or - contents.startswith('+') or contents.endswith('+') - or ' ' in contents): - # Not a valid key combination. - # Now we want to throw an error, but that isn't easy. - # Theoretically, we could do: - #msg = self.inliner.reporter.error( - # 'Invalid key string: %s' % contents, lineno=self.lineno) - #prb = self.inliner.problematic(contents, contents, msg) - #return [prb], [msg] - # But this causes a lot of redundancy, given that it's - # such a common case. It would be better to have a - # shortcut like this instead: - raise self.parser.RoleError('Invalid key string') - # which does the same as the three lines above. - - # Now comes our highly sophisticated key combination parsing - # algorithm. - keys = contents.split('+') - nodes = [KeyNode(keys[0])] - for i in keys[1:]: - nodes.append(nodes.Text('+')) - nodes.append(KeyNode(i)) - return [nodes], [] diff --git a/sandbox/fwiemann/release.sh b/sandbox/fwiemann/release.sh deleted file mode 100755 index f24cbd5bd..000000000 --- a/sandbox/fwiemann/release.sh +++ /dev/null @@ -1,490 +0,0 @@ -#!/bin/bash - -# Author: Felix Wiemann -# Contact: Felix_Wiemann@ososo.de -# Revision: $Revision$ -# Date: $Date$ -# Copyright: This script has been placed in the public domain. - -set -e - -function print_command() -{ - # Print "$@", quoting parameters containing spaces. - echo -n $ - for param in "$@"; do - echo "$param" | grep -Fq ' ' && echo -n " '$param'" || echo -n " $param" - done -} - -function run() -{ - # Print and run "$@". - print_command "$@" - echo - "$@" -} - -function confirm() -{ - # Print, let the user confirm and run "$@". - echo 'Press enter to run (or enter anything to skip):' - print_command "$@" - read - test "$REPLY" && echo Skipped. || "$@" -} - -function svn_up() -{ - if test $svn == svk; then - confirm svk sync "$depot" - fi - confirm $svn up -} - -function checkin() -{ - # Parameters: log_message, file, file, file ... - log_message="$1" - shift - confirm $svn diff "$@" - confirm $svn ci -m "$log_prefix $log_message" "$@" -} - -function set_ver() -{ - # Parameters: old_version new_version - shopt -s extglob - echo Determining list of files to be changed... - files="docutils/__init__.py setup.py `$svn ls test/functional/expected/ | sed 's|^|test/functional/expected/|'`" - echo "Now I'll change the version number to $2 in the following files:" - echo $files - echo - echo 'Press enter to proceed (or enter anything to skip)...' - read - if [ ! "$REPLY" ]; then - echo 'Modifying files with ed...' - old_ver_regex="`echo "$1" | sed 's/\./\\\\./g'`" - # "ed" returns an error code if there has been no substitution, so - # we temporarily deactivate exit-on-error. - set +e - for F in $files; do - (echo ",s/$old_ver_regex/$2/g"; echo 'wq') | ed "$F" - done - set -e - fi - echo - checkin "set version number to $2" $files -} - -function usage() -{ - echo 'Usage:' - echo - echo ' release.sh new_version svn_version[:branch_version] [stage]' - echo - echo 'The following things will be done:' - echo - echo '* Change version number to new_version. (stage 1)' - echo '* SVN-export, test, and release Docutils version new_version. (stage 2)' - echo '* Change version number to svn_version. (stage 3)' - echo - echo 'If stage is supplied (1, 2 or 3), only the specified stage will' - echo 'be executed. Otherwise, it defaults to executing all stages.' - echo - echo 'Before doing dangerous things, you will be asked to press enter.' - echo - echo 'A maintenance branch called docutils-new_version will be created' - echo 'if branch_version is given. The version number inside the' - echo 'maintenance branch will be set to branch_version.' - exit 1 -} - -function initialize() -{ - if [ "$#" -lt 2 ]; then - usage - fi - echo 'Initializing...' - python_versions='2.1 2.2 2.3 2.4' - for py_ver in $python_versions; do - echo -n "Checking for Python $py_ver (python$py_ver)... " - if ! echo 'print "OK"' | python$py_ver; then - echo "Python $py_ver (python$py_ver) not found." - echo Aborting. - exit 1 - fi - done - echo -n 'Clearing $PYTHONPATH... ' - export PYTHONPATH= - echo 'done' - echo -n 'Checking whether we are in a working copy... ' - if [ -f HISTORY.txt ]; then - echo yes - else - echo "no (HISTORY.txt doesn't exist)" - echo 'Aborting.' - echo 'Please cd to a working copy before running this script.' - exit 1 - fi - echo -n 'Subversion binary to use: ' - if [ -d .svn ]; then - svn=svn - else - svn=svk - fi - echo $svn - working_copy="`pwd -P`" - echo "Working copy: $working_copy" - if test $svn = svk; then - depot_path="`svk info . | grep ^Depot\ Path: | sed 's/Depot Path: //'`" - depot="`echo "$depot_path" | sed 's|\(//[^/]\+/[^/]\+\).*|\1|'`" - echo "SVK depot: $depot" - mirrored_from="`svk info . | grep ^Mirrored\ From: | sed 's/Mirrored From: //;s/, Rev\. .*//'`" - svnurl="$mirrored_from`echo "$depot_path" | sed 's|//[^/]\+/[^/]\+||'`" - else - svnurl="`$svn info . | grep ^URL: | sed 's/URL: //'`" - fi - if test -z "$svnurl"; then - echo 'Unable to detect Subversion URL. Aborting.' - exit 1 - fi - echo "Subversion URL: $svnurl" - if ! echo "$svnurl" | grep -q 'branches\|trunk'; then - echo 'Subversion URL contains neither "branches" nor "trunk".' - echo 'Aborting.' - exit 1 - fi - svnroot="`echo "$svnurl" | sed 's/\/\(branches\|trunk\).*//'`" - echo "Subversion root URL: $svnroot" - if test "$svnurl" = "$svnroot"; then - echo 'Error: Subversion URL and Subversion root URL are the same.' - exit 1 - fi - echo -n 'Detecting current Docutils version... ' - old_ver="`python -c 'import docutils; print docutils.__version__'`" - echo "$old_ver" - new_ver="$1" - # log_prefix is for SVN logs. - log_prefix="Release $new_ver:" - echo "New version number (for releasing): $new_ver" - svn_ver="$2" - if echo "$svn_ver" | grep -q :; then - # Split at colon: svn_ver:branch_ver - branch_ver="${svn_ver#*:}" - svn_ver="${svn_ver%:*}" - else - branch_ver= - fi - echo "New Subversion version number (after releasing): $svn_ver" - echo -n 'Create maintenance branch: ' - if test "$branch_ver"; then - echo yes - echo "New version number on maintenance branch: $branch_ver" - else - echo no - fi - if test "$branch_ver"; then - echo -n 'Checking that we have a full checkout... ' - if echo "$working_copy" | grep -q 'branches\|trunk'; then - echo OK - else - echo 'no' - echo 'Working copy path contains neither "branches" nor "trunk".' - echo 'You need a full checkout in order to branch.' - echo 'Aborting.' - exit 1 - fi - wcroot="`echo "$working_copy" | sed 's/\/\(branches\|trunk\).*//'`" - echo "Working copy root: $wcroot" - fi - tarball=docutils-"$new_ver".tar.gz - echo "Tarball name: $tarball" - echo 'Initialization completed.' - echo -} - -function test_tarball() -{ - # Assume we have the tarball in the current directory. - # Pass test number as first parameter. - echo 'Testing the release tarball.' - run mkdir tarball_test/ - run cd tarball_test/ - confirm tar xzvf "../$tarball" - echo - run cd docutils-"$new_ver" - echo 'Installing the distribution.' - # Extra files, with leading comma. - extras="`cd extras; for extrafile in *.py; do echo -n ",$extrafile{,c,o}"; done`" - confirm su -c ' - for py_ver in '"$python_versions"'; do - echo "Deleting and installing Docutils and its test suite on Python $py_ver." - echo "Press enter." - read - site_packages="/usr/local/lib/python$py_ver/site-packages" - if test ! -d "$site_packages"; then - site_packages="/usr/lib/python$py_ver/site-packages" - fi - if test ! -d "$site_packages"; then - echo "Error: \"$site_packages\" does not exist." - exit 1 - fi - if -e "$site_packages/test"; then - echo "Error: \"$site_packages/test\" exists." - exit 1 - fi - rm -rfv /usr/{local,}lib/python$py_ver/site-packages/{docutils'"$extras"'} - python$py_ver setup.py install - echo - cp -rv test "$site_packages/" - echo "Press enter to continue." - read - done' - echo 'Running the test suite with all Python versions.' - echo 'Press enter (or enter anything to skip):' - read - if [ ! "$REPLY" ]; then - for py_ver in $python_versions; do - site_packages="/usr/local/lib/python$py_ver/site-packages" - if test ! -d "$site_packages"; then - site_packages="/usr/lib/python$py_ver/site-packages" - fi - if test ! -d "$site_packages"; then - echo "Error: \"$site_packages\" does not exist." - exit 1 - fi - run python$py_ver -u "$site_packages/test/alltests.py" - run find -name \*.pyc -exec rm {} \; - done - fi - run cd .. - echo "Cleaning up..." - run rm -rf tarball_test - confirm su -c ' - for py_ver in '"$python_versions"'; do - rm -rfv /usr{/local,}/lib/python$py_ver/site-packages/test - done' - echo -} - -function upload_tarball() -{ - # Assume we have the tarball in the working area. - run cd "$working_area" - # You may need to adjust the command line for clients other than tnftp. - (echo 'bin'; echo 'cd /incoming'; echo "put $tarball") | \ - ftp ftp://anonymous:none@upload.sourceforge.net/ - echo 'Upload completed.' -} - -function upload_htdocs() -{ - # Assume we have the tarball in the working area. - run cd "$working_area" - echo "Upload htdocs for $new_ver" - run mkdir htdocs - run cd htdocs - confirm tar xzvf "../$tarball" - run cd docutils-"$new_ver"/tools/ - confirm ./buildhtml.py .. - run cd .. - echo '$ find -name test -type d -prune -o -name \*.css -print0 \ - -o -name \*.html -print0 -o -name \*.txt -print0 \ - | tar -cjvf docutils-docs.tar.bz2 -T - --null' - find -name test -type d -prune -o -name \*.css -print0 \ - -o -name \*.html -print0 -o -name \*.txt -print0 \ - | tar -cjvf docutils-docs.tar.bz2 -T - --null - echo 'Upload the tarball to your home directory on SF.net...' - confirm scp docutils-docs.tar.bz2 shell.sourceforge.net: - echo - echo 'Unpack the tarball on SF.net...' - echo 'Press enter (or enter anything to skip).' - read - if [ ! "$REPLY" ]; then - ssh shell.sourceforge.net<<-EOF - set -x - umask 002 - cd /home/groups/d/do/docutils/htdocs/ - mkdir -m g+rwxs $new_ver - cd $new_ver - tar -xjvf ~/docutils-docs.tar.bz2 - rm ~/docutils-docs.tar.bz2 -EOF - fi -} - -function create_maintenance_branch() -{ - echo 'Creating maintenance branch.' - branch_name="docutils-$new_ver" - echo "Branch name: $branch_name" - branch_url="$svnroot/branches/$branch_name" - echo "Branch URL: $branch_url" - confirm svn cp "$svnurl" "$branch_url" -m \ - "$log_prefix creating maintenance branch for version $new_ver" - cd "$wcroot" - svn_up - cd branches/"$branch_name" - set_ver "$new_ver" "$branch_ver" -} - -function run_stage() -{ - if [ ! "$1" ]; then - run_stage 1 - echo - run_stage 2 - echo - run_stage 3 - else - echo "Press enter to run stage $1 (or enter anything to skip this stage)." - read - if [ ! "$REPLY" ]; then - cd "$working_copy" - if [ "$1" == 1 ]; then - stage_1 - elif [ "$1" == 2 ]; then - stage_2 - elif [ "$1" == 3 ]; then - stage_3 - else - echo 'Invalid stage.' - echo - usage - fi - echo - echo "Stage $1 completed." - else - echo "Skipped stage $1." - fi - fi -} - -function stage_1() -{ - svn_up - echo - # update __version_details__ string - (echo ",s/^__version_details__ = .*\$/__version_details__ = 'release'/"; - echo wq) | ed docutils/__init__.py 2> /dev/null - set_ver "$old_ver" "$new_ver" - echo - history_files='HISTORY.txt RELEASE-NOTES.txt' - echo "Now updating the following files: $history_files" - old_string="Changes Since [0-9.]+" - new_string="Release $new_ver (`date --utc --iso-8601`)" - echo 'Press enter to replace "'"$old_string"'" with "'"$new_string"\", - echo 'or enter anything to skip.' - read - test "$REPLY" || python -c "for filename in '$history_files'.split(): - import re - h = file(filename).read() - h = re.sub('$old_string\\n=+', '$new_string\\n' + '=' * len('$new_string'), h, count=1) - file(filename, 'w').write(h)" - checkin 'closed "Changes Since ..." section' $history_files -} - -function stage_2() -{ - echo 'Creating working area...' - working_area="`echo ~/tmp/docutils-release.$$`" - run mkdir -p "$working_area" - echo - echo 'Getting a fresh export.' - echo 'Press enter to proceed (or enter anything to skip)...' - read - if [ ! "$REPLY" ]; then - run cd "$working_area" - confirm svn export "$svnurl" - echo - echo 'Building the release tarball.' - run cd docutils - confirm ./setup.py sdist - run cd .. - echo 'Tarball built.' - run cp docutils/dist/"$tarball" . - confirm test_tarball - echo "Testing documentation and uploading htdocs of version $new_ver..." - confirm upload_htdocs - echo "Tagging current revision..." - confirm $svn cp "${svnurl%/trunk*}/trunk/" "${svnurl%/trunk*}/tags/docutils-$new_ver/" -m "$log_prefix tagging released revision" - echo "Uploading $tarball to SF.net." - confirm upload_tarball - echo 'Now go to https://sourceforge.net/project/admin/editpackages.php?group_id=38414' - echo 'and follow the instructions at' - echo 'http://docutils.sf.net/docs/dev/release.html#file-release-system' - echo - echo 'Then press enter.' - read - fi - run cd $working_area - echo 'Downloading the tarball to verify its integrity.' - while true; do - confirm wget http://osdn.dl.sourceforge.net/sourceforge/docutils/"$tarball" - echo 'Was the download successful?' - echo 'If yes, press enter to continue, otherwise enter anything to repeat' - echo '(it is possible that the file will show up in a few minutes).' - read - test "$REPLY" || break - done - confirm test_tarball - echo 'Registering at PyPI...' - echo 'Press enter to proceed (or enter anything to skip)...' - read - if [ ! "$REPLY" ]; then - echo "Unpacking tarball..." - ls -l - pwd - run tar xzvf "$tarball" - run cd docutils-"$new_ver" - confirm ./setup.py register - fi -} - -function stage_3() -{ - svn_up - echo - # update __version_details__ string - (echo ",s/^__version_details__ = .*\$/__version_details__ = 'repository'/"; - echo wq) | ed docutils/__init__.py 2> /dev/null - checkin 'set __version_details__ to "repository"' - echo - history_files='HISTORY.txt RELEASE-NOTES.txt' - echo "Now updating the following files: $history_files" - add_string="Changes Since $new_ver" - before="Release " - echo 'Press enter to add "'"$add_string"'" section,' - echo 'or enter anything to skip.' - read - test "$REPLY" || python -c "for filename in '$history_files'.split(): - import re - h = file(filename).read() - h = re.sub('$before', '$add_string\\n' + '=' * len('$add_string') + - '\\n\\n\\n$before', h, count=1) - file(filename, 'w').write(h)" - checkin "added empty \"Changes Since $new_ver\" section" $history_files - echo - if test "$branch_ver"; then - create_maintenance_branch - cd "$working_copy" - fi - set_ver "$new_ver" "$svn_ver" - echo - echo 'Please update the web page now (web/index.txt).' - echo "Press enter when you're done." - read - echo 'Running docutils-update on the server...' - echo 'This may take some time.' - confirm ssh shell.berlios.de docutils-update -} - -initialize "$@" -run_stage "$3" -echo -echo 'Finished.' - -# Local Variables: -# indent-tabs-mode: nil -# End: diff --git a/sandbox/fwiemann/users.txt b/sandbox/fwiemann/users.txt deleted file mode 100644 index d6daa8b13..000000000 --- a/sandbox/fwiemann/users.txt +++ /dev/null @@ -1,70 +0,0 @@ -# User names merged from SourceForge and BerliOS as of -# $Date$. -aahz -agurtovoy -aisaac0 -ajung -akuchling -ax- -axk -bbum -bjoernp -blais -cben -chodorowski -cliechti -daddygravity -david_abrahams -david_ascher -dkuhlman -docutilsupdate -dreamcatcher -ebellot -edloper -fdrake -felixwiemann -fermigier -fffish -goodger -grubert -gschwant -gtk -holdenweb -i_am_the_user -ianbicking -injektilo -jaffray -jensj -jfmeinel -jhsh2 -ksato -kvaml -lalo -lcreighton -lele -mezis -mly -mmgilbe -mnodine -mwh -orutherfurd -pefu -pobrien -reggie -richard -richieadler -rnd0110 -sconce -sdeibel -sfcben -smerten -smurf -sunib -syt -tav -tibs -tracyshaun -ueli -wilk -yole -zemiak diff --git a/sandbox/fwiemann/xhtml2rest/README.txt b/sandbox/fwiemann/xhtml2rest/README.txt deleted file mode 100644 index a5f66a89c..000000000 --- a/sandbox/fwiemann/xhtml2rest/README.txt +++ /dev/null @@ -1,15 +0,0 @@ -This is xhtml2rest. - -It's a stop-gap solution for converting XHTML documents to -reStructuredText. - -Please find the documentation inline at the beginning of the source -file. - -The author is Antonios Christofides. It's in my (Felix Wiemann's) -sandbox because he asked me to take care of it. So please direct any -patches to Felix.Wiemann@ososo.de. - -Have fun! - -Felix Wiemann <Felix.Wiemann@ososo.de> diff --git a/sandbox/fwiemann/xhtml2rest/xhtml2rest.py b/sandbox/fwiemann/xhtml2rest/xhtml2rest.py deleted file mode 100755 index 8c6b366db..000000000 --- a/sandbox/fwiemann/xhtml2rest/xhtml2rest.py +++ /dev/null @@ -1,551 +0,0 @@ -#!/usr/bin/python -""" -NAME -==== - -xhtml2rest - Convert xhtml to reStructuredText - -SYNOPSIS -======== - -xhtml2rest *xhtmlfile* > *restfile* - -DESCRIPTION -=========== - -``xhtml2rest``, which, far from being a decent and complete program, is -only something to begin with, hopefully processes the given UTF-8 -xhtml file and produces reStructuredText "source code" in the standard -output. If your input is html and/or not in UTF-8, you can convert it -to UTF-8 xhtml using ``iconv`` and ``tidy``: - - iconv -f *source_encoding* -t utf-8 *source_html* > *html_utf8* - - tidy -utf8 -asxml -o *xhtmlfile* *html_utf8* - - xhtml2rest *xhtmlfile* > *restfile* - -Interestingly, since reStructuredText is not simple markup, but has -very strict rules with the intention that the source is perfectly -readable, it turns out that converting html to reStructuredText is -actually *rendering*. ``xhtml2rest`` is a small rendering engine. Since -I had no time to study how existing rendering engines work, I had to -reinvent the wheel. So although the code is clean (I actually wrote it -twice), I doubt that the core logic is adequate for future extensions. -But it's better than nothing. There is some documentation in the code, -but feel free to email me if you need more explanations. - -LIMITATIONS -=========== - -I created ``xhtml2rest`` for a very specific job. It does that job -correctly, but for your web page it might not work. It should not be -very hard, however, either to improve the code, or to determine what -it is in your web page that confuses ``xhtml2rest`` and remove it. - -Other than that, there are the following limitations: - -* No indented tables - -* No multi-col or -row spans in tables - -* No support for \<br> - -* Not tested in nested tables (check http://www.w3m.org/story.html) - -* \<th> support is quick and dirty - -* If the same anchor text is met twice, the anchor is ignored - -* No indented \<pre> elements (but I'm not sure the HTML standard - allows them) - -* Images are ignored - -* The word HARDWIRED in the code indicates a hardwired hack which is - specific to the job I wanted ``xhtml2rest`` to do. - -META -==== - -``xhtml2rest`` was created by Antonios Christofides, -anthony@itia.ntua.gr, May-June 2005. - -Revision: $Revision$ - -The code and this text is hereby placed in the public domain. -""" - -import xml.dom.minidom -import re -import sys -import textwrap -import math -import UserList -import warnings -import codecs - -############################################################################### -# Global variables. I know. I'm terribly sorry. Please get rid of them. - -# 'unindent' is used by list items. A li list item is always indented, but its -# first line is "unindented" and contains the number or bullet. However, it was -# difficult for the li node to tell its #text contents (which may be deeply -# nested) to use that. So it just places the number or bullet, which must be 4 -# characters, like " 1. ", in "unindent". The first text to be rendered uses -# the unindent and then sets it to empty again. - -unindent = '' -hyperlinks = {} # text-target pairs found in "a href" elements -############################################################################### - -class Ditem: - """A document item; usually a node, but can be a block of text - resulting from processing adjacent inline items. If it is a node, - it is usually the BlockDitem subclass; if it is text, it is - normally a plain Ditem.""" - def __init__(self, text): - self.text = text # Contained text (empty for BlockDitem) - self.type = '' # tag for block node, empty for inline - self.indentlevel = 0 # 0 - unindented; 1 - indented; etc. - def __repr__(self): - return self.__class__.__name__+'("""'+self.text+'""")' - def propagate_indents(self): - "Propagates indent level recursively to children" - pass - def maxwidth(self): - "Width it will occupy if allowed to render on infinite width" - self.remove_white_space() - return len(self.text) + 4*self.indentlevel - def minwidth(self): - "Width it will occupy if wrapped as much as possible" - wordlens = [len(x) for x in self.text.split()] - if wordlens: return max(wordlens) + 4*self.indentlevel - else: return 0 - def format(self, width): - """Returns contents formatted so as not to exceed specified - width, if possible""" - global unindent - if(self.type=='pre'): raise Exception, "What are we doing here?" - self.remove_white_space() - # Quick hack to fix a problem. Do we begin with '* '? - while len(self.text)>=2 and self.text[1]==' ' and self.text[0] in '*-': - # It may be mistaken for a bullet list. Strip it. - self.text = self.text[2:] - if width < self.minwidth(): width = self.minwidth() - # The textwrap module has the nasty habit of breaking at hyphens. So - # we'll do a nasty hack: find a character that does not exist in the - # text, replace all hyphens with that character, ok, you get the point. - hyphensurrogate = '' - for c in '!@#$%^&*~': - if self.text.find(c)<0: - hyphensurrogate = c - break - if not hyphensurrogate: raise Exception, "Houston we have a problem" - text = self.text.replace('-', hyphensurrogate) - wrapper = textwrap.TextWrapper( - initial_indent=((4*self.indentlevel)-len(unindent))*' '+unindent, - subsequent_indent=4*self.indentlevel*' ', - width=width, break_long_words = False) - unindent = '' - text = wrapper.fill(text) - text = text.replace(hyphensurrogate, '-') - return text - def empty(self): - "Returns true if contains nothing" - return not self.text - def remove_white_space(self): - "Removes extra white space" - self.text = re.sub('\s+', ' ', self.text).strip() - def canmerge(self): - "Tells whether it's possible to merge this Ditem with adjacent ones" - return True - def merge(self, aditem): - """If possible, merges aditem, which should be an adjacent Ditem that - comes after this one.""" - if not self.canmerge() or not aditem.canmerge(): return False - if len(self.text)>0 and self.text[-1] == '_' and len(aditem.text)>0 \ - and aditem.text[0] not in """ \n\t:.,!=/|;"'?<>[]{}()""": - # Leave space after link if not followed by punctuation - self.text = self.text + ' ' + aditem.text - else: - self.text = self.text + aditem.text - return True - -class BlockDitem(Ditem): - "A Ditem which contains other Ditems" - def __init__(self, type): - Ditem.__init__(self, '') - self.type = type - self.children = [] # Contained Ditems - def __repr__(self): - return self.__class__.__name__+'("'+self.type+'"); children = '+repr(self.children) - def maxwidth(self): - childmaxwidths = [x.maxwidth() for x in self.children] - return childmaxwidths and max(childmaxwidths) or 0 - def minwidth(self): - childminwidths = [x.minwidth() for x in self.children] - return childminwidths and max(childminwidths) or 0 - def propagate_indents(self): - for x in self.children: - x.indentlevel = self.indentlevel - x.propagate_indents() - def format(self, width): - if width < self.minwidth(): width = self.minwidth() - results = [x.format(width) for x in self.children] - results = [x for x in results if x] - return "\n\n".join(results) - def empty(self): - return not (self.children) - def canmerge(self): - return False - -class PreDitem(Ditem): - "A Ditem representing a literal block" - def maxwidth(self): - return max([len(x) for x in self.text.split('\n')]) - def minwidth(self): - return self.maxwidth() # Literal block; width's given - def remove_white_space(self): - pass - def format(self, width): - result = '::\n\n' - for x in self.text.split('\n'): - result = result + ' ' + x + '\n' - result = result + '..\n\n' - return result - def canmerge(self): - return False - -class HeadingDitem(BlockDitem): - "A Ditem representing an h1, h2, ..., h9" - def __init__(self, type): - BlockDitem.__init__(self, type) - def minwidth(self): - return self.maxwidth() # Headings don't wrap - def format(self, width): - assert(len(self.children)==1) - text = self.children[0].format(32767) - level = eval(self.type[1]) - underliner = "=-`'.~*+^"[level-1] - return text + '\n' + len(text)*underliner - -class BlockQuoteDitem(BlockDitem): - "A Ditem representing a blockquote" - def __init__(self, type): - BlockDitem.__init__(self, type) - def propagate_indents(self): - self.indentlevel = self.indentlevel + 1 - BlockDitem.propagate_indents(self) - -class ListDitem(BlockDitem): - "A Ditem representing an ol, ul, or dl" - def __init__(self, type): - BlockDitem.__init__(self, type) - def format(self, width): - # First pass the list type and order to the children - order = 1 - for x in self.children: - if isinstance(x, ListItemDitem): - x.listtype = self.type - x.order = order - order = order+1 - # And then process normally - return BlockDitem.format(self, width) - -class ListItemDitem(BlockDitem): - "A Ditem representing a li, dt, or dd" - def __init__(self, type): - BlockDitem.__init__(self, type) - self.listtype = None - self.order = 0 - def minwidth(self): - if self.type == 'dt': return self.maxwidth() # Don't wrap dt - else: return BlockDitem.minwidth(self) - def propagate_indents(self): - if self.type in ('li', 'ol', 'dd'): - self.indentlevel = self.indentlevel + 1 - BlockDitem.propagate_indents(self) - def format(self, width): - global unindent - if self.type == 'li' and self.listtype == 'ol': - unindent = ('%d. ' % (self.order)).ljust(4) - elif self.type == 'li' and self.listtype == 'ul': - unindent = '* ' - return BlockDitem.format(self, width) - -class RenderedColumn: - "Width information about a column being rendered" - def __init__(self, minwidth, maxwidth): - self.minwidth = minwidth - self.maxwidth = maxwidth - self.curwidth = maxwidth - self.fixedwidth = 0 - def logwidth(self): - if self.maxwidth==0: return 0 - else: return math.log(self.maxwidth) - def update(self, minwidth, maxwidth): - "Replaces minwidth/maxwidth if greater" - self.minwidth = minwidth>self.minwidth and minwidth or self.minwidth - self.maxwidth = maxwidth>self.maxwidth and maxwidth or self.maxwidth - self.curwidth = self.maxwidth - -class RenderedColumns(UserList.UserList): - "A list of RenderedColumn" - def __init__(self, alist): - self.data = alist - def totalWidth(self): - "Returns total table width" - return reduce(lambda x,y: x+y, [z.curwidth for z in self.data]) \ - + len(self.data) + 1 - def sumLogWidth(self): - "Returns sum of logwidth for nonfixed columns" - return reduce(lambda x,y: x+y, - [x.logwidth()*(1-x.fixedwidth) for x in self.data]) - def distributeWidthDifference(self, width): - "Step 4 of w3m table rendering algorithm" - # Note: The use of math.ceil below is because I'd rather have a - # suboptimal width (a few characters less than requested width) rather - # than go find what to do with rounding. - w = self.totalWidth() - width - assert(w>0) - repeat_distribution = 1 - while repeat_distribution: - repeat_distribution = 0 - for x in self.data: - if x.fixedwidth: continue - if x.curwidth - math.ceil(w*x.logwidth()/self.sumLogWidth()) < \ - x.minwidth: - x.curwidth = x.minwidth - x.fixedwidth = 1 - w = self.totalWidth() - width - repeat_distribution=1 - break - # Now that the we finished finding which columns need to be fixed to - # their minimum width, perform the distribution once again, without - # checking, and actually change remaining column widths - for x in self.data: - if x.fixedwidth: continue - x.curwidth = x.curwidth - math.ceil(w*x.logwidth()/self.sumLogWidth()) - -def tablehrule(colwidths, rule='-'): - "Returns a horizontal table separator for given column widths" - result = '+' - for x in colwidths: - result = result + rule * x + '+' - return result - -class TableDitem(BlockDitem): - def __init__(self, type): - BlockDitem.__init__(self, type) - def format(self, width): - # Uses table rendering algorithm of w3m - # (http://www.w3m.org/story.html), but ignoring width attribute - # Step 1 - columns = RenderedColumns([RenderedColumn(x.minwidth(), - max(x.maxwidth(), 1) # A column can't be smaller than 1 character - ) for x in self.children[0].children]) - for x in self.children: - for i in range(len(columns)): - if (len(x.children)<=i): continue # Skip empty columns - columns[i].update(x.children[i].minwidth(), x.children[i].maxwidth()) - # Step 2 (width attribute) ignored - # Step 3 (already done - list was created with maxwidth) - # Step 4 - if columns.totalWidth() > width: columns.distributeWidthDifference(width) - # OK, column widths are now calculated - colwidths = [int(x.curwidth) for x in columns] - result = tablehrule(colwidths) + '\n' - usedheadbodysep = False - for tr in self.children: - result = result + tr.format(colwidths) - rule = '-' - if not usedheadbodysep and tr.children[0].type == 'th' \ - and tr!=self.children[-1]: - rule = '=' - usedheadbodysep = True - result = result + tablehrule(colwidths, rule) + '\n' - return result - -class TrDitem(BlockDitem): - def __init__(self, type): - BlockDitem.__init__(self, type) - def maxwidth(self): - return reduce(lambda x,y: x+y, - [x.maxwidth() for x in self.children]) + len(self.children) + 1 - def minwidth(self): - return reduce(lambda x,y: x+y, - [x.minwidth() for x in self.children]) + len(self.children) + 1 - def format(self, colwidths): - columns = [] # List of lists of lines - maxlinecount = 0 # Num of lines in vertically largest column - for i in range(len(colwidths)): - if len(self.children)<=i: lines = [ '' ] - else: lines = self.children[i].format(colwidths[i]).split('\n') - lines = [x + ' ' * (colwidths[i]-len(x)) for x in lines] # Pad to col len - maxlinecount = max(maxlinecount, len(lines)) - columns.append(lines) - # Pad vertically - for i in range(len(columns)): - for j in range(maxlinecount-len(columns[i])): - columns[i].append(' ' * colwidths[i]) - result = '' - # Add vertical separators - for i in range(maxlinecount): - result = result + '|' - for j in range(len(columns)): - result = result + columns[j][i] + '|' - result = result + '\n' - return result - -def handleNodeList(nodelist): - "Processes given nodes; merges them if possible; returns ditem list" - ditems = [] - curditem = Ditem('') - for node in nodelist: - aditem = handleNode(node) - if curditem.merge(aditem): continue - ditems.append(curditem) - curditem = aditem - if not curditem.empty(): ditems.append(curditem) - return ditems - -def handleNode(node): - if node.nodeType == node.TEXT_NODE: - return handleText(node) - elif node.nodeName=='a': - return handleAnchor(node) - elif re.match('h\d', node.nodeName): - return handleHeading(node) - elif node.nodeName=='div' and node.getAttribute('class')=='cit': # HARDWIRED - return handleBlockQuote(node) - elif node.nodeName in ('body', 'div', 'p', 'td', 'th'): - return handleGenericBlock(node) - elif node.nodeName in ('em', 'i'): - return handleEmphasis(node) - elif node.nodeName in ('strong', 'b'): - return handleStrong(node) - elif node.nodeName in ('ol', 'ul', 'dl'): - return handleList(node) - elif node.nodeName in ('li', 'dd', 'dt'): - return handleListItem(node) - elif node.nodeName in ('table'): - return handleTable(node) - elif node.nodeName in ('tr'): - return handleTr(node) - elif node.nodeName in ('pre'): - return handlePre(node) - elif node.hasChildNodes(): - contents = handleNodeList(node.childNodes) - if len(contents) == 1: return contents[0] - if len(contents) == 0: return Ditem('') - result = BlockDitem(node.nodeName) - result.children = contents - return result - return Ditem('') - -def processChildren(node): - if node.hasChildNodes(): - return handleNodeList(node.childNodes) - else: - return () - -def mergeChildren(node): - contents = processChildren(node) - if len(contents)>1: raise Exception('Unexpected block elements') - if contents: return contents[0] - else: return Ditem('') - -def handleText(node): - return Ditem(node.data) - -def handleAnchor(node): - result = mergeChildren(node) - result.type = node.nodeName - result.text = result.text.strip() - if result.text == '': return result - target = node.getAttribute('href').strip() - if target=="" or target[0]=='#': return result # Ignore intrnl links - result.text = re.sub('\s+', ' ', result.text) - key = result.text.lower() - if hyperlinks.has_key(key) and hyperlinks[key]!=target: - # The following try-except is a quick hack to ensure that the - # program will not stop because of problems in the warning - # mechanism. One such specific problem is a UnicodeEncodeError - # when result.text contains difficult characters. - try: - warnings.warn("Ignoring second appearance of anchor '" + result.text + - "' with different target") - except: - pass - return result - hyperlinks[key] = target - result.text = '`'+result.text+'`_' - return result - -def handleHeading(node): - contents = mergeChildren(node) - if contents.empty(): return contents - result = HeadingDitem(node.nodeName) - result.children.append(contents) - return result - -def handleEmphasis(node): - result = mergeChildren(node) - result.type = node.nodeName - if result.text: - result.text = '*' + result.text + '*' - return result - -def handleStrong(node): - result = mergeChildren(node) - result.type = node.nodeName - if result.text: - result.text = '**' + result.text + '**' - return result - -def handleGenericBlock(node): - result = BlockDitem(node.nodeName) - result.children = processChildren(node) - return result - -def handleBlockQuote(node): - result = BlockQuoteDitem(node.nodeName) - result.children = processChildren(node) - return result - -def handleList(node): - result = ListDitem(node.nodeName) - result.children = processChildren(node) - return result - -def handleListItem(node): - result = ListItemDitem(node.nodeName) - result.children = processChildren(node) - return result - -def handleTable(node): - result = TableDitem(node.nodeName) - # Ignore table contents that are not tr - result.children = [x - for x in processChildren(node) if x.type=='tr'] - return result - -def handleTr(node): - result = TrDitem(node.nodeName) - # Ignore tr contents that are not th or td - result.children = [x - for x in processChildren(node) if x.type in ('th', 'td')] - return result - -def handlePre(node): - return PreDitem(mergeChildren(node).text) - -dom1 = xml.dom.minidom.parse(sys.argv[1]) -ditem = handleNode(dom1.getElementsByTagName("body")[0]) -ditem.propagate_indents() -(utf8_encode, utf8_decode, utf8_reader, utf8_writer) = codecs.lookup('utf-8') -outf = utf8_writer(sys.stdout) -outf.write(ditem.format(79) + '\n') -for h in hyperlinks.keys(): - outf.write('\n.. _`' + h + '`:\n ' + hyperlinks[h] + '\n') |