[Zope-Checkins] SVN: Zope/trunk/lib/python/docutils/ update to
docutils 0.3.9
Andreas Jung
andreas at andreas-jung.com
Sun Oct 9 10:31:38 EDT 2005
Log message for revision 39013:
update to docutils 0.3.9
Changed:
U Zope/trunk/lib/python/docutils/__init__.py
U Zope/trunk/lib/python/docutils/core.py
U Zope/trunk/lib/python/docutils/examples.py
U Zope/trunk/lib/python/docutils/frontend.py
U Zope/trunk/lib/python/docutils/io.py
U Zope/trunk/lib/python/docutils/languages/__init__.py
U Zope/trunk/lib/python/docutils/languages/af.py
U Zope/trunk/lib/python/docutils/languages/cs.py
U Zope/trunk/lib/python/docutils/languages/de.py
U Zope/trunk/lib/python/docutils/languages/en.py
U Zope/trunk/lib/python/docutils/languages/eo.py
U Zope/trunk/lib/python/docutils/languages/es.py
U Zope/trunk/lib/python/docutils/languages/fi.py
U Zope/trunk/lib/python/docutils/languages/fr.py
U Zope/trunk/lib/python/docutils/languages/it.py
U Zope/trunk/lib/python/docutils/languages/pt_br.py
U Zope/trunk/lib/python/docutils/languages/ru.py
U Zope/trunk/lib/python/docutils/languages/sk.py
U Zope/trunk/lib/python/docutils/languages/sv.py
U Zope/trunk/lib/python/docutils/languages/zh_tw.py
U Zope/trunk/lib/python/docutils/nodes.py
U Zope/trunk/lib/python/docutils/parsers/__init__.py
U Zope/trunk/lib/python/docutils/parsers/rst/__init__.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/__init__.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/admonitions.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/body.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/html.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/images.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/misc.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/parts.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/references.py
U Zope/trunk/lib/python/docutils/parsers/rst/directives/tables.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/__init__.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/af.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/cs.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/de.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/en.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/eo.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/es.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/fi.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/fr.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/it.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/pt_br.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/ru.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/sk.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/sv.py
U Zope/trunk/lib/python/docutils/parsers/rst/languages/zh_tw.py
U Zope/trunk/lib/python/docutils/parsers/rst/roles.py
U Zope/trunk/lib/python/docutils/parsers/rst/states.py
U Zope/trunk/lib/python/docutils/parsers/rst/tableparser.py
U Zope/trunk/lib/python/docutils/readers/__init__.py
U Zope/trunk/lib/python/docutils/readers/pep.py
U Zope/trunk/lib/python/docutils/readers/python/__init__.py
U Zope/trunk/lib/python/docutils/readers/python/moduleparser.py
U Zope/trunk/lib/python/docutils/readers/python/pynodes.py
U Zope/trunk/lib/python/docutils/readers/standalone.py
U Zope/trunk/lib/python/docutils/statemachine.py
U Zope/trunk/lib/python/docutils/transforms/__init__.py
U Zope/trunk/lib/python/docutils/transforms/components.py
U Zope/trunk/lib/python/docutils/transforms/frontmatter.py
U Zope/trunk/lib/python/docutils/transforms/misc.py
U Zope/trunk/lib/python/docutils/transforms/parts.py
U Zope/trunk/lib/python/docutils/transforms/peps.py
U Zope/trunk/lib/python/docutils/transforms/references.py
U Zope/trunk/lib/python/docutils/transforms/universal.py
U Zope/trunk/lib/python/docutils/utils.py
U Zope/trunk/lib/python/docutils/writers/__init__.py
U Zope/trunk/lib/python/docutils/writers/docutils_xml.py
U Zope/trunk/lib/python/docutils/writers/html4css1.py
U Zope/trunk/lib/python/docutils/writers/latex2e.py
U Zope/trunk/lib/python/docutils/writers/pep_html.py
U Zope/trunk/lib/python/docutils/writers/pseudoxml.py
-=-
Modified: Zope/trunk/lib/python/docutils/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at python.org
-# Revision: $Revision: 1.2.10.9 $
-# Date: $Date: 2005/01/07 13:26:01 $
+# Revision: $Revision: 3374 $
+# Date: $Date: 2005-05-26 23:21:48 +0200 (Thu, 26 May 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -51,7 +51,7 @@
__docformat__ = 'reStructuredText'
-__version__ = '0.3.7'
+__version__ = '0.3.9'
"""``major.minor.micro`` version number. The micro number is bumped for API
changes, for new functionality, and for interim project releases. The minor
number is bumped whenever there is a significant project release. The major
Modified: Zope/trunk/lib/python/docutils/core.py
===================================================================
--- Zope/trunk/lib/python/docutils/core.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/core.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger
# Contact: goodger at python.org
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:01 $
+# Revision: $Revision: 2987 $
+# Date: $Date: 2005-02-26 19:17:59 +0100 (Sat, 26 Feb 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -197,6 +197,7 @@
self.writer.assemble_parts()
except Exception, error:
if self.settings.traceback: # propagate exceptions?
+ self.debugging_dumps(document)
raise
self.report_Exception(error)
exit = 1
@@ -210,6 +211,8 @@
return output
def debugging_dumps(self, document):
+ if not document:
+ return
if self.settings.dump_settings:
print >>sys.stderr, '\n::: Runtime settings:'
print >>sys.stderr, pprint.pformat(self.settings.__dict__)
Modified: Zope/trunk/lib/python/docutils/examples.py
===================================================================
--- Zope/trunk/lib/python/docutils/examples.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/examples.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,18 +1,19 @@
# Authors: David Goodger
# Contact: goodger at python.org
-# Revision: $Revision: 1.1.4.3 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 3247 $
+# Date: $Date: 2005-04-23 21:23:57 +0200 (Sat, 23 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
This module contains practical examples of Docutils client code.
-Importing this module is not recommended; its contents are subject to change
-in future Docutils releases. Instead, it is recommended that you copy and
-paste the parts you need into your own code, modifying as necessary.
+Importing this module from client code is not recommended; its contents are
+subject to change in future Docutils releases. Instead, it is recommended
+that you copy and paste the parts you need into your own code, modifying as
+necessary.
"""
-from docutils import core
+from docutils import core, io
def html_parts(input_string, source_path=None, destination_path=None,
@@ -72,3 +73,23 @@
if output_encoding != 'unicode':
fragment = fragment.encode(output_encoding)
return fragment
+
+def internals(input_string, source_path=None, destination_path=None,
+ input_encoding='unicode'):
+ """
+ Return the document tree and publisher, for exploring Docutils internals.
+
+ Parameters: see `html_parts()`.
+ """
+ overrides = {'input_encoding': input_encoding}
+ output, pub = core.publish_programmatically(
+ source_class=io.StringInput, source=input_string,
+ source_path=source_path,
+ destination_class=io.NullOutput, destination=None,
+ destination_path=destination_path,
+ reader=None, reader_name='standalone',
+ parser=None, parser_name='restructuredtext',
+ writer=None, writer_name='null',
+ settings=None, settings_spec=None, settings_overrides=overrides,
+ config_section=None, enable_exit_status=None)
+ return pub.writer.document, pub
Modified: Zope/trunk/lib/python/docutils/frontend.py
===================================================================
--- Zope/trunk/lib/python/docutils/frontend.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/frontend.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.8 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 3358 $
+# Date: $Date: 2005-05-21 02:00:25 +0200 (Sat, 21 May 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -124,6 +124,13 @@
None, sys.exc_info()[2])
return value
+def validate_nonnegative_int(setting, value, option_parser,
+ config_parser=None, config_section=None):
+ value = int(value)
+ if value < 0:
+ raise ValueError('negative value; must be positive or zero')
+ return value
+
def validate_threshold(setting, value, option_parser,
config_parser=None, config_section=None):
try:
@@ -333,10 +340,10 @@
'validator': validate_threshold}),
('Report all system messages, info-level and higher. (Same as '
'"--report=info".)',
- ['--verbose', '-v'], {'action': 'store_const', 'const': 'info',
+ ['--verbose', '-v'], {'action': 'store_const', 'const': 1,
'dest': 'report_level'}),
('Do not report any system messages. (Same as "--report=none".)',
- ['--quiet', '-q'], {'action': 'store_const', 'const': 'none',
+ ['--quiet', '-q'], {'action': 'store_const', 'const': 5,
'dest': 'report_level'}),
('Set the threshold (<level>) at or above which system messages are '
'converted to exceptions, halting execution immediately by '
@@ -429,6 +436,9 @@
['--version', '-V'], {'action': 'version'}),
('Show this help message and exit.',
['--help', '-h'], {'action': 'help'}),
+ # Typically not useful for non-programmatical use.
+ (SUPPRESS_HELP, ['--id-prefix'], {'default': ''}),
+ (SUPPRESS_HELP, ['--auto-id-prefix'], {'default': 'id'}),
# Hidden options, for development use only:
(SUPPRESS_HELP, ['--dump-settings'], {'action': 'store_true'}),
(SUPPRESS_HELP, ['--dump-internals'], {'action': 'store_true'}),
Modified: Zope/trunk/lib/python/docutils/io.py
===================================================================
--- Zope/trunk/lib/python/docutils/io.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/io.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 3138 $
+# Date: $Date: 2005-03-27 17:05:34 +0200 (Sun, 27 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -70,32 +70,42 @@
if (self.encoding and self.encoding.lower() == 'unicode'
or isinstance(data, UnicodeType)):
return data
- encodings = [self.encoding, 'utf-8']
- try:
- encodings.append(locale.nl_langinfo(locale.CODESET))
- except:
- pass
- try:
- encodings.append(locale.getlocale()[1])
- except:
- pass
- try:
- encodings.append(locale.getdefaultlocale()[1])
- except:
- pass
- encodings.append('latin-1')
+ encodings = [self.encoding]
+ if not self.encoding:
+ # Apply heuristics only if no encoding is explicitly given.
+ encodings.append('utf-8')
+ try:
+ encodings.append(locale.nl_langinfo(locale.CODESET))
+ except:
+ pass
+ try:
+ encodings.append(locale.getlocale()[1])
+ except:
+ pass
+ try:
+ encodings.append(locale.getdefaultlocale()[1])
+ except:
+ pass
+ encodings.append('latin-1')
+ error = None
+ error_details = ''
for enc in encodings:
if not enc:
continue
try:
decoded = unicode(data, enc, self.error_handler)
self.successful_encoding = enc
- return decoded
- except (UnicodeError, LookupError):
+ # Return decoded, removing BOMs.
+ return decoded.replace(u'\ufeff', u'')
+ except (UnicodeError, LookupError), error:
pass
+ if error is not None:
+ error_details = '\n(%s: %s)' % (error.__class__.__name__, error)
raise UnicodeError(
- 'Unable to decode input data. Tried the following encodings: %s.'
- % ', '.join([repr(enc) for enc in encodings if enc]))
+ 'Unable to decode input data. Tried the following encodings: '
+ '%s.%s'
+ % (', '.join([repr(enc) for enc in encodings if enc]),
+ error_details))
class Output(TransformSpec):
Modified: Zope/trunk/lib/python/docutils/languages/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# Internationalization details are documented in
Modified: Zope/trunk/lib/python/docutils/languages/af.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/af.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/af.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Jannie Hofmeyr
# Contact: jhsh at sun.ac.za
-# Revision: $Revision: 1.1.2.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/cs.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/cs.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/cs.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Marek Blaha
# Contact: mb at dat.cz
-# Revision: $Revision: 1.1.4.4 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/de.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/de.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/de.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger; Gunnar Schwant
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/en.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/en.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/en.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/eo.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/eo.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/eo.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Marcelo Huerta San Martin
# Contact: richieadler at users.sourceforge.net
-# Revision: $Revision: 1.1.2.5 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/es.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/es.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/es.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,8 +1,8 @@
# -*- coding: iso-8859-1 -*-
# Author: Marcelo Huerta San Martín
# Contact: mghsm at uol.com.ar
-# Revision: $Revision: 1.1.2.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/fi.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/fi.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/fi.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Asko Soukka
# Contact: asko.soukka at iki.fi
-# Revision: $Revision: 1.1.2.1 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2609 $
+# Date: $Date: 2004-09-13 21:25:33 +0200 (Mon, 13 Sep 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/fr.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/fr.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/fr.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Stefane Fermigier
# Contact: sf at fermigier.com
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/it.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/it.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/it.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Nicola Larosa
# Contact: docutils at tekNico.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2944 $
+# Date: $Date: 2005-01-20 13:11:50 +0100 (Thu, 20 Jan 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -45,7 +45,7 @@
'autori': 'authors',
'organizzazione': 'organization',
'indirizzo': 'address',
- 'contatti': 'contact',
+ 'contatto': 'contact',
'versione': 'version',
'revisione': 'revision',
'status': 'status',
Modified: Zope/trunk/lib/python/docutils/languages/pt_br.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/pt_br.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/pt_br.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.1.4.4 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2333 $
+# Date: $Date: 2004-06-20 22:51:22 +0200 (Sun, 20 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/ru.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/ru.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/ru.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Roman Suzi
# Contact: rnd at onego.ru
-# Revision: $Revision: 1.1.2.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2999 $
+# Date: $Date: 2005-03-03 20:35:02 +0100 (Thu, 03 Mar 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -46,21 +46,21 @@
"""Mapping of node class name to label text."""
bibliographic_fields = {
- u'\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f': u'abstract',
- u'\u0410\u0434\u0440\u0435\u0441': u'address',
- u'\u0410\u0432\u0442\u043e\u0440': u'author',
- u'\u0410\u0432\u0442\u043e\u0440\u044b': u'authors',
- u'\u041a\u043e\u043d\u0442\u0430\u043a\u0442': u'contact',
- u'\u041f\u0440\u0430\u0432\u0430 \u043a\u043e\u043f\u0438\u0440\u043e'
+ u'\u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f': u'abstract',
+ u'\u0430\u0434\u0440\u0435\u0441': u'address',
+ u'\u0430\u0432\u0442\u043e\u0440': u'author',
+ u'\u0430\u0432\u0442\u043e\u0440\u044b': u'authors',
+ u'\u043a\u043e\u043d\u0442\u0430\u043a\u0442': u'contact',
+ u'\u043f\u0440\u0430\u0432\u0430 \u043a\u043e\u043f\u0438\u0440\u043e'
u'\u0432\u0430\u043d\u0438\u044f': u'copyright',
- u'\u0414\u0430\u0442\u0430': u'date',
- u'\u041f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0438\u0435':
+ u'\u0434\u0430\u0442\u0430': u'date',
+ u'\u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0438\u0435':
u'dedication',
- u'\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f':
+ u'\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f':
u'organization',
- u'\u0420\u0435\u0434\u0430\u043a\u0446\u0438\u044f': u'revision',
- u'\u0421\u0442\u0430\u0442\u0443\u0441': u'status',
- u'\u0412\u0435\u0440\u0441\u0438\u044f': u'version'}
+ u'\u0440\u0435\u0434\u0430\u043a\u0446\u0438\u044f': u'revision',
+ u'\u0441\u0442\u0430\u0442\u0443\u0441': u'status',
+ u'\u0432\u0435\u0440\u0441\u0438\u044f': u'version'}
"""Russian (lowcased) to canonical name mapping for bibliographic fields."""
author_separators = [';', ',']
Modified: Zope/trunk/lib/python/docutils/languages/sk.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/sk.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/sk.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# :Author: Miroslav Vasko
# :Contact: zemiak at zoznam.sk
-# :Revision: $Revision: 1.2.10.7 $
-# :Date: $Date: 2005/01/07 13:26:02 $
+# :Revision: $Revision: 2224 $
+# :Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# :Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/sv.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/sv.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/sv.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Adam Chodorowski
# Contact: chodorowski at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/languages/zh_tw.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/zh_tw.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/languages/zh_tw.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Joe YS Jaw
# Contact: joeysj at users.sourceforge.net
-# Revision: $Revision: 1.1.2.1 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2608 $
+# Date: $Date: 2004-09-13 21:09:56 +0200 (Mon, 13 Sep 2004) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
Modified: Zope/trunk/lib/python/docutils/nodes.py
===================================================================
--- Zope/trunk/lib/python/docutils/nodes.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/nodes.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 3358 $
+# Date: $Date: 2005-05-21 02:00:25 +0200 (Sat, 21 May 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -26,6 +26,8 @@
import sys
import os
import re
+import copy
+import warnings
import xml.dom.minidom
from types import IntType, SliceType, StringType, UnicodeType, \
TupleType, ListType
@@ -103,7 +105,7 @@
or replaced occurs after the current node, the old node will
still be traversed, and any new nodes will not.
- Within ``visit`` methods (and ``depart`` methods for
+ Within ``visit`` methods (and ``depart`` methods for
`walkabout()`), `TreePruningException` subclasses may be raised
(`SkipChildren`, `SkipSiblings`, `SkipNode`, `SkipDeparture`).
@@ -111,15 +113,15 @@
``visit`` implementation for each `Node` subclass encountered.
"""
visitor.document.reporter.debug(
- 'calling dispatch_visit for %s' % self.__class__.__name__,
- category='nodes.Node.walk')
+ 'docutils.nodes.Node.walk calling dispatch_visit for %s'
+ % self.__class__.__name__)
try:
visitor.dispatch_visit(self)
except (SkipChildren, SkipNode):
return
except SkipDeparture: # not applicable; ignore
pass
- children = self.get_children()
+ children = self.children
try:
for child in children[:]:
child.walk(visitor)
@@ -138,8 +140,8 @@
"""
call_depart = 1
visitor.document.reporter.debug(
- 'calling dispatch_visit for %s' % self.__class__.__name__,
- category='nodes.Node.walkabout')
+ 'docutils.nodes.Node.walkabout calling dispatch_visit for %s'
+ % self.__class__.__name__)
try:
try:
visitor.dispatch_visit(self)
@@ -147,7 +149,7 @@
return
except SkipDeparture:
call_depart = 0
- children = self.get_children()
+ children = self.children
try:
for child in children[:]:
child.walkabout(visitor)
@@ -157,11 +159,84 @@
pass
if call_depart:
visitor.document.reporter.debug(
- 'calling dispatch_departure for %s' % self.__class__.__name__,
- category='nodes.Node.walkabout')
+ 'docutils.nodes.Node.walkabout calling dispatch_departure '
+ 'for %s' % self.__class__.__name__)
visitor.dispatch_departure(self)
+ def traverse(self, condition=None,
+ include_self=1, descend=1, siblings=0, ascend=0):
+ """
+ Return an iterable containing
+ * self (if include_self is true)
+ * all descendants in tree traversal order (if descend is true)
+ * all siblings (if siblings is true) and their descendants (if
+ also descend is true)
+ * the siblings of the parent (if ascend is true) and their
+ descendants (if also descend is true), and so on
+
+ If ascend is true, assume siblings to be true as well.
+
+ For example, given the following tree::
+
+ <paragraph>
+ <emphasis> <--- emphasis.traverse() and
+ <strong> <--- strong.traverse() are called.
+ Foo
+ Bar
+ <reference name="Baz" refid="baz">
+ Baz
+
+ Then list(emphasis.traverse()) equals ::
+
+ [<emphasis>, <strong>, <#text: Foo>, <#text: Bar>]
+
+ and list(strong.traverse(ascend=1)) equals ::
+
+ [<strong>, <#text: Foo>, <#text: Bar>, <reference>, <#text: Baz>]
+ """
+ r = []
+ if ascend:
+ siblings=1
+ if include_self and (condition is None or condition(self)):
+ r.append(self)
+ if descend and len(self.children):
+ for child in self:
+ r.extend(child.traverse(
+ include_self=1, descend=1, siblings=0, ascend=0,
+ condition=condition))
+ if siblings or ascend:
+ node = self
+ while node.parent:
+ index = node.parent.index(node)
+ for sibling in node.parent[index+1:]:
+ r.extend(sibling.traverse(include_self=1, descend=descend,
+ siblings=0, ascend=0,
+ condition=condition))
+ if not ascend:
+ break
+ else:
+ node = node.parent
+ return r
+
+
+ def next_node(self, condition=None,
+ include_self=0, descend=1, siblings=0, ascend=0):
+ """
+ Return the first node in the iterable returned by traverse(),
+ or None if the iterable is empty.
+
+ Parameter list is the same as of traverse. Note that
+ include_self defaults to 0, though.
+ """
+ iterable = self.traverse(condition=condition,
+ include_self=include_self, descend=descend,
+ siblings=siblings, ascend=ascend)
+ try:
+ return iterable[0]
+ except IndexError:
+ return None
+
class Text(Node, UserString):
"""
@@ -172,6 +247,9 @@
tagname = '#text'
+ children = ()
+ """Text nodes have no children, and cannot have children."""
+
def __init__(self, data, rawsource=''):
UserString.__init__(self, data)
@@ -209,11 +287,7 @@
result.append(indent + line + '\n')
return ''.join(result)
- def get_children(self):
- """Text nodes have no children. Return []."""
- return []
-
class Element(Node):
"""
@@ -225,6 +299,12 @@
element['att'] = 'value'
+ There are two special attributes: 'ids' and 'names'. Both are
+ lists of unique identifiers, and names serve as human interfaces
+ to IDs. Names are case- and whitespace-normalized (see the
+ fully_normalize_name() function), and IDs conform to the regular
+ expression ``[a-z](-?[a-z0-9]+)*`` (see the make_id() function).
+
Elements also emulate lists for child nodes (element nodes and/or text
nodes), indexing by integer. To get the first child node, use::
@@ -245,6 +325,10 @@
This is equivalent to ``element.extend([node1, node2])``.
"""
+ attr_defaults = {'ids': [], 'classes': [], 'names': [],
+ 'dupnames': [], 'backrefs': []}
+ """Default attributes."""
+
tagname = None
"""The element generic identifier. If None, it is set as an instance
attribute to the name of the class."""
@@ -261,7 +345,7 @@
self.extend(children) # maintain parent info
- self.attributes = {}
+ self.attributes = copy.deepcopy(self.attr_defaults)
"""Dictionary of attribute {name: value}."""
for att, value in attributes.items():
@@ -272,7 +356,7 @@
def _dom_node(self, domroot):
element = domroot.createElement(self.tagname)
- for attribute, value in self.attributes.items():
+ for attribute, value in self.attlist():
if isinstance(value, ListType):
value = ' '.join(['%s' % v for v in value])
element.setAttribute(attribute, '%s' % value)
@@ -287,16 +371,16 @@
if len(data) > 60:
data = data[:56] + ' ...'
break
- if self.hasattr('name'):
+ if self['names']:
return '<%s "%s": %s>' % (self.__class__.__name__,
- self.attributes['name'], data)
+ '; '.join(self['names']), data)
else:
return '<%s: %s>' % (self.__class__.__name__, data)
def shortrepr(self):
- if self.hasattr('name'):
+ if self['names']:
return '<%s "%s"...>' % (self.__class__.__name__,
- self.attributes['name'])
+ '; '.join(self['names']))
else:
return '<%s...>' % self.tagname
@@ -382,20 +466,24 @@
def __iadd__(self, other):
"""Append a node or a list of nodes to `self.children`."""
if isinstance(other, Node):
- self.setup_child(other)
- self.children.append(other)
+ self.append(other)
elif other is not None:
- for node in other:
- self.setup_child(node)
- self.children.extend(other)
+ self.extend(other)
return self
def astext(self):
return self.child_text_separator.join(
[child.astext() for child in self.children])
+ def non_default_attributes(self):
+ atts = {}
+ for key, value in self.attributes.items():
+ if self.is_not_default(key):
+ atts[key] = value
+ return atts
+
def attlist(self):
- attlist = self.attributes.items()
+ attlist = self.non_default_attributes().items()
attlist.sort()
return attlist
@@ -420,8 +508,7 @@
def extend(self, item):
for node in item:
- self.setup_child(node)
- self.children.extend(item)
+ self.append(node)
def insert(self, index, item):
if isinstance(item, Node):
@@ -439,6 +526,15 @@
def index(self, item):
return self.children.index(item)
+ def is_not_default(self, key):
+ try:
+ return self[key] != self.attr_defaults[key]
+ except KeyError:
+ return 1
+
+ def clear(self):
+ self.children = []
+
def replace(self, old, new):
"""Replace one child `Node` with another child or children."""
index = self.index(old)
@@ -482,12 +578,10 @@
if not isinstance(childclass, TupleType):
childclass = (childclass,)
for index in range(start, min(len(self), end)):
- match = 0
for c in childclass:
if isinstance(self.children[index], c):
- match = 1
break
- if not match:
+ else:
return index
return None
@@ -496,25 +590,41 @@
[child.pformat(indent, level+1)
for child in self.children])
- def get_children(self):
- """Return this element's children."""
- return self.children
-
def copy(self):
return self.__class__(**self.attributes)
def set_class(self, name):
- """Add a new name to the "class" attribute."""
- self.attributes['class'] = (self.attributes.get('class', '') + ' '
- + name.lower()).strip()
+ """Add a new class to the "classes" attribute."""
+ warnings.warn('docutils.nodes.Element.set_class deprecated; '
+ "append to Element['classes'] list attribute directly",
+ DeprecationWarning, stacklevel=2)
+ assert ' ' not in name
+ self['classes'].append(name.lower())
+ def note_referenced_by(self, name=None, id=None):
+ """Note that this Element has been referenced by its name
+ `name` or id `id`."""
+ self.referenced = 1
+ # Element.expect_referenced_by_* dictionaries map names or ids
+ # to nodes whose ``referenced`` attribute is set to true as
+ # soon as this node is referenced by the given name or id.
+ # Needed for target propagation.
+ by_name = getattr(self, 'expect_referenced_by_name', {}).get(name)
+ by_id = getattr(self, 'expect_referenced_by_id', {}).get(id)
+ if by_name:
+ assert name is not None
+ by_name.referenced = 1
+ if by_id:
+ assert id is not None
+ by_id.referenced = 1
+
class TextElement(Element):
"""
An element which directly contains text.
- Its children are all `Text` or `TextElement` subclass nodes. You can
+ Its children are all `Text` or `Inline` subclass nodes. You can
check whether an element's context is inline simply by checking whether
its immediate parent is a `TextElement` instance (including subclasses).
This is handy for nodes like `image` that can appear both inline and as
@@ -557,7 +667,7 @@
class BackLinkable:
def add_backref(self, refid):
- self.setdefault('backrefs', []).append(refid)
+ self['backrefs'].append(refid)
# ====================
@@ -568,15 +678,12 @@
class Titular: pass
-class PreDecorative:
- """Category of Node which may occur before Decorative Nodes."""
-
-class PreBibliographic(PreDecorative):
+class PreBibliographic:
"""Category of Node which may occur before Bibliographic Nodes."""
-class Bibliographic(PreDecorative): pass
+class Bibliographic: pass
-class Decorative: pass
+class Decorative(PreBibliographic): pass
class Structural: pass
@@ -584,7 +691,8 @@
class General(Body): pass
-class Sequential(Body): pass
+class Sequential(Body):
+ """List-like elements."""
class Admonition(Body): pass
@@ -604,9 +712,6 @@
referenced = 0
- indirect_reference_name = None
- """Holds the whitespace_normalized_name (contains mixed case) of a target"""
-
class Labeled:
"""Contains a `label` as its first element."""
@@ -717,6 +822,9 @@
self.transformer = docutils.transforms.Transformer(self)
"""Storage for transforms to be applied to this document."""
+ self.decoration = None
+ """Document's `decoration` node."""
+
self.document = self
def asdom(self, dom=xml.dom.minidom):
@@ -726,21 +834,23 @@
return domroot
def set_id(self, node, msgnode=None):
- if node.has_key('id'):
- id = node['id']
+ for id in node['ids']:
if self.ids.has_key(id) and self.ids[id] is not node:
msg = self.reporter.severe('Duplicate ID: "%s".' % id)
if msgnode != None:
msgnode += msg
- else:
- if node.has_key('name'):
- id = make_id(node['name'])
+ if not node['ids']:
+ for name in node['names']:
+ id = self.settings.id_prefix + make_id(name)
+ if id and not self.ids.has_key(id):
+ break
else:
id = ''
- while not id or self.ids.has_key(id):
- id = 'id%s' % self.id_start
- self.id_start += 1
- node['id'] = id
+ while not id or self.ids.has_key(id):
+ id = (self.settings.id_prefix +
+ self.settings.auto_id_prefix + str(self.id_start))
+ self.id_start += 1
+ node['ids'].append(id)
self.ids[id] = node
return id
@@ -775,8 +885,7 @@
both old and new targets are external and refer to identical URIs.
The new target is invalidated regardless.
"""
- if node.has_key('name'):
- name = node['name']
+ for name in node['names']:
if self.nameids.has_key(name):
self.set_duplicate_name_id(node, id, name, msgnode, explicit)
else:
@@ -794,30 +903,30 @@
old_node = self.ids[old_id]
if node.has_key('refuri'):
refuri = node['refuri']
- if old_node.has_key('name') \
+ if old_node['names'] \
and old_node.has_key('refuri') \
and old_node['refuri'] == refuri:
level = 1 # just inform if refuri's identical
if level > 1:
- dupname(old_node)
+ dupname(old_node, name)
self.nameids[name] = None
msg = self.reporter.system_message(
level, 'Duplicate explicit target name: "%s".' % name,
backrefs=[id], base_node=node)
if msgnode != None:
msgnode += msg
- dupname(node)
+ dupname(node, name)
else:
self.nameids[name] = id
if old_id is not None:
old_node = self.ids[old_id]
- dupname(old_node)
+ dupname(old_node, name)
else:
if old_id is not None and not old_explicit:
self.nameids[name] = None
old_node = self.ids[old_id]
- dupname(old_node)
- dupname(node)
+ dupname(old_node, name)
+ dupname(node, name)
if not explicit or (not old_explicit and old_id is not None):
msg = self.reporter.info(
'Duplicate implicit target name: "%s".' % name,
@@ -851,7 +960,7 @@
def note_indirect_target(self, target):
self.indirect_targets.append(target)
- if target.has_key('name'):
+ if target['names']:
self.note_refname(target)
def note_anonymous_target(self, target):
@@ -895,7 +1004,8 @@
self.note_refname(ref)
def note_substitution_def(self, subdef, def_name, msgnode=None):
- name = subdef['name'] = whitespace_normalize_name(def_name)
+ name = whitespace_normalize_name(def_name)
+ subdef['names'].append(name)
if self.substitution_defs.has_key(name):
msg = self.reporter.error(
'Duplicate substitution definition name: "%s".' % name,
@@ -903,7 +1013,7 @@
if msgnode != None:
msgnode += msg
oldnode = self.substitution_defs[name]
- dupname(oldnode)
+ dupname(oldnode, name)
# keep only the last definition:
self.substitution_defs[name] = subdef
# case-insensitive mapping:
@@ -933,7 +1043,17 @@
return self.__class__(self.settings, self.reporter,
**self.attributes)
+ def get_decoration(self):
+ if not self.decoration:
+ self.decoration = decoration()
+ index = self.first_child_not_matching_class(Titular)
+ if index is None:
+ self.append(self.decoration)
+ else:
+ self.insert(index, self.decoration)
+ return self.decoration
+
# ================
# Title Elements
# ================
@@ -964,7 +1084,19 @@
# Decorative Elements
# =====================
-class decoration(Decorative, Element): pass
+class decoration(Decorative, Element):
+
+ def get_header(self):
+ if not len(self.children) or not isinstance(self.children[0], header):
+ self.insert(0, header())
+ return self.children[0]
+
+ def get_footer(self):
+ if not len(self.children) or not isinstance(self.children[-1], footer):
+ self.append(footer())
+ return self.children[-1]
+
+
class header(Decorative, Element): pass
class footer(Decorative, Element): pass
@@ -1061,7 +1193,7 @@
class line_block(General, Element): pass
-class line(General, TextElement):
+class line(Part, TextElement):
indent = None
@@ -1081,8 +1213,8 @@
class comment(Special, Invisible, FixedTextElement): pass
class substitution_definition(Special, Invisible, TextElement): pass
class target(Special, Invisible, Inline, TextElement, Targetable): pass
-class footnote(General, Element, Labeled, BackLinkable): pass
-class citation(General, Element, Labeled, BackLinkable): pass
+class footnote(General, BackLinkable, Element, Labeled, Targetable): pass
+class citation(General, BackLinkable, Element, Labeled, Targetable): pass
class label(Part, TextElement): pass
class figure(General, Element): pass
class caption(Part, TextElement): pass
@@ -1096,7 +1228,7 @@
class entry(Part, Element): pass
-class system_message(Special, PreBibliographic, Element, BackLinkable):
+class system_message(Special, BackLinkable, PreBibliographic, Element):
def __init__(self, message=None, *children, **attributes):
if message:
@@ -1210,7 +1342,7 @@
class subscript(Inline, TextElement): pass
-class image(General, Inline, TextElement):
+class image(General, Inline, Element):
def astext(self):
return self.get('alt', '')
@@ -1306,8 +1438,8 @@
node_name = node.__class__.__name__
method = getattr(self, 'visit_' + node_name, self.unknown_visit)
self.document.reporter.debug(
- 'calling %s for %s' % (method.__name__, node_name),
- category='nodes.NodeVisitor.dispatch_visit')
+ 'docutils.nodes.NodeVisitor.dispatch_visit calling %s for %s'
+ % (method.__name__, node_name))
return method(node)
def dispatch_departure(self, node):
@@ -1319,8 +1451,8 @@
node_name = node.__class__.__name__
method = getattr(self, 'depart_' + node_name, self.unknown_departure)
self.document.reporter.debug(
- 'calling %s for %s' % (method.__name__, node_name),
- category='nodes.NodeVisitor.dispatch_departure')
+ 'docutils.nodes.NodeVisitor.dispatch_departure calling %s for %s'
+ % (method.__name__, node_name))
return method(node)
def unknown_visit(self, node):
@@ -1357,6 +1489,7 @@
subclasses), subclass `NodeVisitor` instead.
"""
+
class GenericNodeVisitor(NodeVisitor):
"""
@@ -1398,10 +1531,11 @@
setattr(GenericNodeVisitor, "visit_" + _name, _call_default_visit)
setattr(GenericNodeVisitor, "depart_" + _name, _call_default_departure)
setattr(SparseNodeVisitor, 'visit_' + _name, _nop)
- setattr(SparseNodeVisitor, 'depart' + _name, _nop)
+ setattr(SparseNodeVisitor, 'depart_' + _name, _nop)
_add_node_class_names(node_class_names)
+
class TreeCopyVisitor(GenericNodeVisitor):
"""
@@ -1534,9 +1668,12 @@
_non_id_chars = re.compile('[^a-z0-9]+')
_non_id_at_ends = re.compile('^[-0-9]+|-+$')
-def dupname(node):
- node['dupname'] = node['name']
- del node['name']
+def dupname(node, name):
+ node['dupnames'].append(name)
+ node['names'].remove(name)
+ # Assume that this method is referenced, even though it isn't; we
+ # don't want to throw unnecessary system_messages.
+ node.referenced = 1
def fully_normalize_name(name):
"""Return a case- and whitespace-normalized name."""
Modified: Zope/trunk/lib/python/docutils/parsers/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:03 $
+# Revision: $Revision: 1645 $
+# Date: $Date: 2003-08-27 22:50:43 +0200 (Wed, 27 Aug 2003) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/parsers/rst/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:03 $
+# Revision: $Revision: 3171 $
+# Date: $Date: 2005-04-05 17:26:16 +0200 (Tue, 05 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -112,7 +112,23 @@
('Leave spaces before footnote references.',
['--leave-footnote-reference-space'],
{'action': 'store_false', 'dest': 'trim_footnote_reference_space',
- 'validator': frontend.validate_boolean}),))
+ 'validator': frontend.validate_boolean}),
+ ('Disable directives that insert the contents of external file '
+ '("include" & "raw"); replaced with a "warning" system message.',
+ ['--no-file-insertion'],
+ {'action': 'store_false', 'default': 1,
+ 'dest': 'file_insertion_enabled'}),
+ ('Enable directives that insert the contents of external file '
+ '("include" & "raw"). Enabled by default.',
+ ['--file-insertion-enabled'],
+ {'action': 'store_true', 'dest': 'file_insertion_enabled'}),
+ ('Disable the "raw" directives; replaced with a "warning" '
+ 'system message.',
+ ['--no-raw'],
+ {'action': 'store_false', 'default': 1, 'dest': 'raw_enabled'}),
+ ('Enable the "raw" directive. Enabled by default.',
+ ['--raw-enabled'],
+ {'action': 'store_true', 'dest': 'raw_enabled'}),))
config_section = 'restructuredtext parser'
config_section_dependencies = ('parsers',)
@@ -128,11 +144,10 @@
def parse(self, inputstring, document):
"""Parse `inputstring` and populate `document`, a document tree."""
self.setup_parse(inputstring, document)
- debug = document.reporter[''].debug
self.statemachine = states.RSTStateMachine(
state_classes=self.state_classes,
initial_state=self.initial_state,
- debug=debug)
+ debug=document.reporter.debug_flag)
inputlines = docutils.statemachine.string2lines(
inputstring, tab_width=document.settings.tab_width,
convert_whitespace=1)
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at python.org
-# Revision: $Revision: 1.2.10.8 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -113,10 +113,13 @@
#'questions': ('body', 'question_list'),
'table': ('tables', 'table'),
'csv-table': ('tables', 'csv_table'),
+ 'list-table': ('tables', 'list_table'),
'image': ('images', 'image'),
'figure': ('images', 'figure'),
'contents': ('parts', 'contents'),
'sectnum': ('parts', 'sectnum'),
+ 'header': ('parts', 'header'),
+ 'footer': ('parts', 'footer'),
#'footnotes': ('parts', 'footnotes'),
#'citations': ('parts', 'citations'),
'target-notes': ('references', 'target_notes'),
@@ -250,18 +253,27 @@
Return the path argument unwrapped (with newlines removed).
(Directive option conversion function.)
- Raise ``ValueError`` if no argument is found or if the path contains
- internal whitespace.
+ Raise ``ValueError`` if no argument is found.
"""
if argument is None:
raise ValueError('argument required but none supplied')
else:
path = ''.join([s.strip() for s in argument.splitlines()])
- if path.find(' ') == -1:
- return path
- else:
- raise ValueError('path contains whitespace')
+ return path
+def uri(argument):
+ """
+ Return the URI argument with whitespace removed.
+ (Directive option conversion function.)
+
+ Raise ``ValueError`` if no argument is found.
+ """
+ if argument is None:
+ raise ValueError('argument required but none supplied')
+ else:
+ uri = ''.join(argument.split())
+ return uri
+
def nonnegative_int(argument):
"""
Check for a nonnegative integer argument; raise ``ValueError`` if not.
@@ -274,7 +286,7 @@
def class_option(argument):
"""
- Convert the argument into an ID-compatible string and return it.
+ Convert the argument into a list of ID-compatible strings and return it.
(Directive option conversion function.)
Raise ``ValueError`` if no argument is found.
@@ -288,7 +300,7 @@
if not class_name:
raise ValueError('cannot make "%s" into a class name' % name)
class_names.append(class_name)
- return ' '.join(class_names)
+ return class_names
unicode_pattern = re.compile(
r'(?:0x|x|\\x|U\+?|\\u)([0-9a-f]+)$|&#x([0-9a-f]+);$', re.IGNORECASE)
@@ -296,10 +308,13 @@
def unicode_code(code):
r"""
Convert a Unicode character code to a Unicode character.
+ (Directive option conversion function.)
Codes may be decimal numbers, hexadecimal numbers (prefixed by ``0x``,
``x``, ``\x``, ``U+``, ``u``, or ``\u``; e.g. ``U+262E``), or XML-style
numeric character entities (e.g. ``☮``). Other text remains as-is.
+
+ Raise ValueError for illegal Unicode code values.
"""
try:
if code.isdigit(): # decimal number
@@ -315,6 +330,10 @@
raise ValueError('code too large (%s)' % detail)
def single_char_or_unicode(argument):
+ """
+ A single character is returned as-is. Unicode characters codes are
+ converted as in `unicode_code`. (Directive option conversion function.)
+ """
char = unicode_code(argument)
if len(char) > 1:
raise ValueError('%r invalid; must be a single character or '
@@ -322,6 +341,10 @@
return char
def single_char_or_whitespace_or_unicode(argument):
+ """
+ As with `single_char_or_unicode`, but "tab" and "space" are also supported.
+ (Directive option conversion function.)
+ """
if argument == 'tab':
char = '\t'
elif argument == 'space':
@@ -331,12 +354,23 @@
return char
def positive_int(argument):
+ """
+ Converts the argument into an integer. Raises ValueError for negative,
+ zero, or non-integer values. (Directive option conversion function.)
+ """
value = int(argument)
if value < 1:
raise ValueError('negative or zero value; must be positive')
return value
def positive_int_list(argument):
+ """
+ Converts a space- or comma-separated list of values into a Python list
+ of integers.
+ (Directive option conversion function.)
+
+ Raises ValueError for non-positive-integer values.
+ """
if ',' in argument:
entries = argument.split(',')
else:
@@ -344,6 +378,12 @@
return [positive_int(entry) for entry in entries]
def encoding(argument):
+ """
+ Verfies the encoding argument by lookup.
+ (Directive option conversion function.)
+
+ Raises ValueError for unknown encodings.
+ """
try:
codecs.lookup(argument)
except LookupError:
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/admonitions.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/admonitions.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/admonitions.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3155 $
+# Date: $Date: 2005-04-02 23:57:06 +0200 (Sat, 02 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -30,10 +30,10 @@
admonition_node += nodes.title(title_text, '', *textnodes)
admonition_node += messages
if options.has_key('class'):
- class_value = options['class']
+ classes = options['class']
else:
- class_value = 'admonition-' + nodes.make_id(title_text)
- admonition_node.set_class(class_value)
+ classes = ['admonition-' + nodes.make_id(title_text)]
+ admonition_node['classes'] += classes
state.nested_parse(content, content_offset, admonition_node)
return [admonition_node]
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/body.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/body.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/body.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at python.org
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3206 $
+# Date: $Date: 2005-04-12 01:16:11 +0200 (Tue, 12 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -16,14 +16,16 @@
import sys
from docutils import nodes
from docutils.parsers.rst import directives
+from docutils.parsers.rst.roles import set_classes
def topic(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine,
node_class=nodes.topic):
- if not state_machine.match_titles:
+ if not (state_machine.match_titles
+ or isinstance(state_machine.node, nodes.sidebar)):
error = state_machine.reporter.error(
- 'The "%s" directive may not be used within topics, sidebars, '
+ 'The "%s" directive may not be used within topics '
'or body elements.' % name,
nodes.literal_block(block_text, block_text), line=lineno)
return [error]
@@ -44,8 +46,7 @@
messages.extend(more_messages)
text = '\n'.join(content)
node = node_class(text, *(titles + messages))
- if options.has_key('class'):
- node.set_class(options['class'])
+ node['classes'] += options.get('class', [])
if text:
state.nested_parse(content, content_offset, node)
return [node]
@@ -56,6 +57,11 @@
def sidebar(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
+ if isinstance(state_machine.node, nodes.sidebar):
+ error = state_machine.reporter.error(
+ 'The "%s" directive may not be used within a sidebar element.'
+ % name, nodes.literal_block(block_text, block_text), line=lineno)
+ return [error]
return topic(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine,
node_class=nodes.sidebar)
@@ -72,7 +78,7 @@
'Content block expected for the "%s" directive; none found.'
% name, nodes.literal_block(block_text, block_text), line=lineno)
return [warning]
- block = nodes.line_block()
+ block = nodes.line_block(classes=options.get('class', []))
node_list = [block]
for line_text in content:
text_nodes, messages = state.inline_text(line_text.strip(),
@@ -91,6 +97,7 @@
def parsed_literal(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
+ set_classes(options)
return block(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine,
node_class=nodes.literal_block)
@@ -124,7 +131,7 @@
def epigraph(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
block_quote, messages = state.block_quote(content, content_offset)
- block_quote.set_class('epigraph')
+ block_quote['classes'].append('epigraph')
return [block_quote] + messages
epigraph.content = 1
@@ -132,7 +139,7 @@
def highlights(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
block_quote, messages = state.block_quote(content, content_offset)
- block_quote.set_class('highlights')
+ block_quote['classes'].append('highlights')
return [block_quote] + messages
highlights.content = 1
@@ -140,7 +147,7 @@
def pull_quote(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
block_quote, messages = state.block_quote(content, content_offset)
- block_quote.set_class('pull-quote')
+ block_quote['classes'].append('pull-quote')
return [block_quote] + messages
pull_quote.content = 1
@@ -154,8 +161,7 @@
nodes.literal_block(block_text, block_text), line=lineno)
return [error]
node = nodes.compound(text)
- if options.has_key('class'):
- node.set_class(options['class'])
+ node['classes'] += options.get('class', [])
state.nested_parse(content, content_offset, node)
return [node]
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/html.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/html.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/html.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3038 $
+# Date: $Date: 2005-03-14 17:16:57 +0100 (Mon, 14 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -34,7 +34,7 @@
'Empty meta directive.',
nodes.literal_block(block_text, block_text), line=lineno)
node += error
- return node.get_children()
+ return node.children
meta.content = 1
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/images.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/images.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/images.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3347 $
+# Date: $Date: 2005-05-18 20:17:33 +0200 (Wed, 18 May 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -14,27 +14,43 @@
import sys
from docutils import nodes, utils
from docutils.parsers.rst import directives, states
-from docutils.nodes import whitespace_normalize_name
+from docutils.nodes import fully_normalize_name
+from docutils.parsers.rst.roles import set_classes
try:
import Image # PIL
except ImportError:
Image = None
-align_values = ('top', 'middle', 'bottom', 'left', 'center', 'right')
+align_h_values = ('left', 'center', 'right')
+align_v_values = ('top', 'middle', 'bottom')
+align_values = align_v_values + align_h_values
def align(argument):
return directives.choice(argument, align_values)
def image(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
+ if options.has_key('align'):
+ # check for align_v values only
+ if isinstance(state, states.SubstitutionDef):
+ if options['align'] not in align_v_values:
+ error = state_machine.reporter.error(
+ 'Error in "%s" directive: "%s" is not a valid value for '
+ 'the "align" option within a substitution definition. '
+ 'Valid values for "align" are: "%s".'
+ % (name, options['align'], '", "'.join(align_v_values)),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [error]
+ elif options['align'] not in align_h_values:
+ error = state_machine.reporter.error(
+ 'Error in "%s" directive: "%s" is not a valid value for '
+ 'the "align" option. Valid values for "align" are: "%s".'
+ % (name, options['align'], '", "'.join(align_h_values)),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [error]
messages = []
- reference = ''.join(arguments[0].split('\n'))
- if reference.find(' ') != -1:
- error = state_machine.reporter.error(
- 'Image URI contains whitespace.',
- nodes.literal_block(block_text, block_text), line=lineno)
- return [error]
+ reference = directives.uri(arguments[0])
options['uri'] = reference
reference_node = None
if options.has_key('target'):
@@ -44,12 +60,13 @@
if target_type == 'refuri':
reference_node = nodes.reference(refuri=data)
elif target_type == 'refname':
- reference_node = nodes.reference(
- refname=data, name=whitespace_normalize_name(options['target']))
+ reference_node = nodes.reference(refname=data,
+ name=fully_normalize_name(options['target']))
state.document.note_refname(reference_node)
else: # malformed target
messages.append(data) # data is a system message
del options['target']
+ set_classes(options)
image_node = nodes.image(block_text, **options)
if reference_node:
reference_node += image_node
@@ -66,31 +83,38 @@
'target': directives.unchanged_required,
'class': directives.class_option}
+def figure_align(argument):
+ return directives.choice(argument, align_h_values)
+
def figure(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
figwidth = options.setdefault('figwidth')
- figclass = options.setdefault('figclass')
+ figclasses = options.setdefault('figclass')
+ align = options.setdefault('align')
del options['figwidth']
del options['figclass']
+ del options['align']
(image_node,) = image(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine)
if isinstance(image_node, nodes.system_message):
return [image_node]
figure_node = nodes.figure('', image_node)
if figwidth == 'image':
- if Image:
+ if Image and state.document.settings.file_insertion_enabled:
# PIL doesn't like Unicode paths:
try:
i = Image.open(str(image_node['uri']))
except (IOError, UnicodeError):
pass
else:
- state.document.settings.record_dependencies.add(reference)
+ state.document.settings.record_dependencies.add(image_node['uri'])
figure_node['width'] = i.size[0]
elif figwidth is not None:
figure_node['width'] = figwidth
- if figclass:
- figure_node.set_class(figclass)
+ if figclasses:
+ figure_node['classes'] += figclasses
+ if align:
+ figure_node['align'] = align
if content:
node = nodes.Element() # anonymous container for parsing
state.nested_parse(content, content_offset, node)
@@ -119,4 +143,5 @@
figure.options = {'figwidth': figwidth_value,
'figclass': directives.class_option}
figure.options.update(image.options)
+figure.options['align'] = figure_align
figure.content = 1
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/misc.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/misc.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/misc.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger, Dethe Elza
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3129 $
+# Date: $Date: 2005-03-26 17:21:28 +0100 (Sat, 26 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""Miscellaneous directives."""
@@ -24,15 +24,19 @@
def include(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
"""Include a reST file as part of the content of this reST file."""
+ import pdb
+ pdb.set_trace()
+
+ print '1'
+ if not state.document.settings.file_insertion_enabled:
+ warning = state_machine.reporter.warning(
+ '"%s" directive disabled.' % name,
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [warning]
source = state_machine.input_lines.source(
lineno - state_machine.input_offset - 1)
source_dir = os.path.dirname(os.path.abspath(source))
- path = ''.join(arguments[0].splitlines())
- if path.find(' ') != -1:
- error = state_machine.reporter.error(
- '"%s" directive path contains whitespace.' % name,
- nodes.literal_block(block_text, block_text), line=lineno)
- return [error]
+ path = directives.path(arguments[0])
path = os.path.normpath(os.path.join(source_dir, path))
path = utils.relative_path(None, path)
encoding = options.get('encoding', state.document.settings.input_encoding)
@@ -48,7 +52,14 @@
% (name, error.__class__.__name__, error),
nodes.literal_block(block_text, block_text), line=lineno)
return [severe]
- include_text = include_file.read()
+ try:
+ include_text = include_file.read()
+ except UnicodeError, error:
+ severe = state_machine.reporter.severe(
+ 'Problem with "%s" directive:\n%s: %s'
+ % (name, error.__class__.__name__, error),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [severe]
if options.has_key('literal'):
literal_block = nodes.literal_block(include_text, include_text,
source=path)
@@ -74,6 +85,14 @@
Content may be included inline (content section of directive) or
imported from a file or url.
"""
+ print 2
+ if ( not state.document.settings.raw_enabled
+ or (not state.document.settings.file_insertion_enabled
+ and (options.has_key('file') or options.has_key('url'))) ):
+ warning = state_machine.reporter.warning(
+ '"%s" directive disabled.' % name,
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [warning]
attributes = {'format': ' '.join(arguments[0].lower().split())}
encoding = options.get('encoding', state.document.settings.input_encoding)
if content:
@@ -106,7 +125,14 @@
'Problems with "%s" directive path:\n%s.' % (name, error),
nodes.literal_block(block_text, block_text), line=lineno)
return [severe]
- text = raw_file.read()
+ try:
+ text = raw_file.read()
+ except UnicodeError, error:
+ severe = state_machine.reporter.severe(
+ 'Problem with "%s" directive:\n%s: %s'
+ % (name, error.__class__.__name__, error),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [severe]
attributes['source'] = path
elif options.has_key('url'):
if not urllib2:
@@ -128,7 +154,14 @@
raw_file = io.StringInput(
source=raw_text, source_path=source, encoding=encoding,
error_handler=state.document.settings.input_encoding_error_handler)
- text = raw_file.read()
+ try:
+ text = raw_file.read()
+ except UnicodeError, error:
+ severe = state_machine.reporter.severe(
+ 'Problem with "%s" directive:\n%s: %s'
+ % (name, error.__class__.__name__, error),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [severe]
attributes['source'] = source
else:
error = state_machine.reporter.warning(
@@ -140,7 +173,7 @@
raw.arguments = (1, 0, 1)
raw.options = {'file': directives.path,
- 'url': directives.path,
+ 'url': directives.uri,
'encoding': directives.encoding}
raw.content = 1
@@ -160,8 +193,7 @@
messages = []
for node in element:
if isinstance(node, nodes.system_message):
- if node.has_key('backrefs'):
- del node['backrefs']
+ node['backrefs'] = []
messages.append(node)
error = state_machine.reporter.error(
'Error in "%s" directive: may contain a single paragraph '
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/parts.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/parts.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/parts.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger, Dmitry Jemerov
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3199 $
+# Date: $Date: 2005-04-09 03:32:29 +0200 (Sat, 09 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -26,10 +26,24 @@
def contents(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
- """Table of contents."""
+ """
+ Table of contents.
+
+ The table of contents is generated in two passes: initial parse and
+ transform. During the initial parse, a 'pending' element is generated
+ which acts as a placeholder, storing the TOC title and any options
+ internally. At a later stage in the processing, the 'pending' element is
+ replaced by a 'topic' element, a title and the table of contents proper.
+ """
+ if not (state_machine.match_titles
+ or isinstance(state_machine.node, nodes.sidebar)):
+ error = state_machine.reporter.error(
+ 'The "%s" directive may not be used within topics '
+ 'or body elements.' % name,
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [error]
document = state_machine.document
language = languages.get_language(document.settings.language_code)
-
if arguments:
title_text = arguments[0]
text_nodes, messages = state.inline_text(title_text, lineno)
@@ -40,24 +54,17 @@
title = None
else:
title = nodes.title('', language.labels['contents'])
-
- topic = nodes.topic(CLASS='contents')
-
- cls = options.get('class')
- if cls:
- topic.set_class(cls)
-
+ topic = nodes.topic(classes=['contents'])
+ topic['classes'] += options.get('class', [])
if title:
name = title.astext()
topic += title
else:
name = language.labels['contents']
-
name = nodes.fully_normalize_name(name)
if not document.has_name(name):
- topic['name'] = name
+ topic['names'].append(name)
document.note_implicit_target(topic)
-
pending = nodes.pending(parts.Contents, rawsource=block_text)
pending.details.update(options)
document.note_pending(pending)
@@ -82,3 +89,36 @@
'start': int,
'prefix': directives.unchanged_required,
'suffix': directives.unchanged_required}
+
+def header_footer(node, name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ """Contents of document header or footer."""
+ if not content:
+ warning = state_machine.reporter.warning(
+ 'Content block expected for the "%s" directive; none found.'
+ % name, nodes.literal_block(block_text, block_text),
+ line=lineno)
+ node.append(nodes.paragraph(
+ '', 'Problem with the "%s" directive: no content supplied.' % name))
+ return [warning]
+ text = '\n'.join(content)
+ state.nested_parse(content, content_offset, node)
+ return []
+
+def header(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ decoration = state_machine.document.get_decoration()
+ node = decoration.get_header()
+ return header_footer(node, name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine)
+
+header.content = 1
+
+def footer(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ decoration = state_machine.document.get_decoration()
+ node = decoration.get_footer()
+ return header_footer(node, name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine)
+
+footer.content = 1
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/references.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/references.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/references.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger, Dmitry Jemerov
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 856 $
+# Date: $Date: 2002-10-24 03:01:53 +0200 (Thu, 24 Oct 2002) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/tables.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/tables.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/tables.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger, David Priest
# Contact: goodger at python.org
-# Revision: $Revision: 1.1.2.3 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3165 $
+# Date: $Date: 2005-04-05 04:55:06 +0200 (Tue, 05 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -44,7 +44,6 @@
return [warning]
title, messages = make_title(arguments, state, lineno)
node = nodes.Element() # anonymous container for parsing
- text = '\n'.join(content)
state.nested_parse(content, content_offset, node)
if len(node) != 1 or not isinstance(node[0], nodes.table):
error = state_machine.reporter.error(
@@ -54,8 +53,7 @@
line=lineno)
return [error]
table_node = node[0]
- if options.has_key('class'):
- table_node.set_class(options['class'])
+ table_node['classes'] += options.get('class', [])
if title:
table_node.insert(0, title)
return [table_node] + messages
@@ -116,6 +114,12 @@
def csv_table(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
try:
+ if ( not state.document.settings.file_insertion_enabled
+ and (options.has_key('file') or options.has_key('url')) ):
+ warning = state_machine.reporter.warning(
+ '"%s" directive disabled.' % name,
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [warning]
check_requirements(name, lineno, block_text, state_machine)
title, messages = make_title(arguments, state, lineno)
csv_data, source = get_csv_data(
@@ -126,8 +130,10 @@
csv_data, DocutilsDialect(options), source, options)
max_cols = max(max_cols, max_header_cols)
header_rows = options.get('header-rows', 0) # default 0
+ stub_columns = options.get('stub-columns', 0) # default 0
check_table_dimensions(
- rows, header_rows, name, lineno, block_text, state_machine)
+ rows, header_rows, stub_columns, name, lineno,
+ block_text, state_machine)
table_head.extend(rows[:header_rows])
table_body = rows[header_rows:]
col_widths = get_column_widths(
@@ -141,19 +147,19 @@
nodes.literal_block(block_text, block_text), line=lineno)
return [error]
table = (col_widths, table_head, table_body)
- table_node = state.build_table(table, content_offset)
- if options.has_key('class'):
- table_node.set_class(options['class'])
+ table_node = state.build_table(table, content_offset, stub_columns)
+ table_node['classes'] += options.get('class', [])
if title:
table_node.insert(0, title)
return [table_node] + messages
csv_table.arguments = (0, 1, 1)
csv_table.options = {'header-rows': directives.nonnegative_int,
+ 'stub-columns': directives.nonnegative_int,
'header': directives.unchanged,
'widths': directives.positive_int_list,
'file': directives.path,
- 'url': directives.path,
+ 'url': directives.uri,
'encoding': directives.encoding,
'class': directives.class_option,
# field delimiter char
@@ -206,7 +212,8 @@
state.document.settings.record_dependencies.add(source)
csv_file = io.FileInput(
source_path=source, encoding=encoding,
- error_handler=state.document.settings.input_encoding_error_handler,
+ error_handler
+ =state.document.settings.input_encoding_error_handler,
handle_io_errors=None)
csv_data = csv_file.read().splitlines()
except IOError, error:
@@ -270,20 +277,34 @@
max_cols = max(max_cols, len(row))
return rows, max_cols
-def check_table_dimensions(rows, header_rows, name, lineno, block_text,
- state_machine):
+def check_table_dimensions(rows, header_rows, stub_columns, name, lineno,
+ block_text, state_machine):
if len(rows) < header_rows:
error = state_machine.reporter.error(
'%s header row(s) specified but only %s row(s) of data supplied '
'("%s" directive).' % (header_rows, len(rows), name),
nodes.literal_block(block_text, block_text), line=lineno)
raise SystemMessagePropagation(error)
- elif len(rows) == header_rows > 0:
+ if len(rows) == header_rows > 0:
error = state_machine.reporter.error(
'Insufficient data supplied (%s row(s)); no data remaining for '
'table body, required by "%s" directive.' % (len(rows), name),
nodes.literal_block(block_text, block_text), line=lineno)
raise SystemMessagePropagation(error)
+ for row in rows:
+ if len(row) < stub_columns:
+ error = state_machine.reporter.error(
+ '%s stub column(s) specified but only %s columns(s) of data '
+ 'supplied ("%s" directive).' % (stub_columns, len(row), name),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ raise SystemMessagePropagation(error)
+ if len(row) == stub_columns > 0:
+ error = state_machine.reporter.error(
+ 'Insufficient data supplied (%s columns(s)); no data remaining '
+ 'for table body, required by "%s" directive.'
+ % (len(row), name),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ raise SystemMessagePropagation(error)
def get_column_widths(max_cols, name, options, lineno, block_text,
state_machine):
@@ -295,8 +316,13 @@
% (name, max_cols),
nodes.literal_block(block_text, block_text), line=lineno)
raise SystemMessagePropagation(error)
+ elif max_cols:
+ col_widths = [100 / max_cols] * max_cols
else:
- col_widths = [100 / max_cols] * max_cols
+ error = state_machine.reporter.error(
+ 'No table data detected in CSV file.',
+ nodes.literal_block(block_text, block_text), line=lineno)
+ raise SystemMessagePropagation(error)
return col_widths
def extend_short_rows_with_empty_cells(columns, parts):
@@ -304,3 +330,112 @@
for row in part:
if len(row) < columns:
row.extend([(0, 0, 0, [])] * (columns - len(row)))
+
+def list_table(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ """
+ Implement tables whose data is encoded as a uniform two-level bullet list.
+ For further ideas, see
+ http://docutils.sf.net/docs/dev/rst/alternatives.html#list-driven-tables
+ """
+ if not content:
+ error = state_machine.reporter.error(
+ 'The "%s" directive is empty; content required.' % name,
+ nodes.literal_block(block_text, block_text), line=lineno)
+ return [error]
+ title, messages = make_title(arguments, state, lineno)
+ node = nodes.Element() # anonymous container for parsing
+ state.nested_parse(content, content_offset, node)
+ try:
+ num_cols, col_widths = check_list_content(
+ node, name, options, content, lineno, block_text, state_machine)
+ table_data = [[item.children for item in row_list[0]]
+ for row_list in node[0]]
+ header_rows = options.get('header-rows', 0) # default 0
+ stub_columns = options.get('stub-columns', 0) # default 0
+ check_table_dimensions(
+ table_data, header_rows, stub_columns, name, lineno,
+ block_text, state_machine)
+ except SystemMessagePropagation, detail:
+ return [detail.args[0]]
+ table_node = build_table_from_list(table_data, col_widths,
+ header_rows, stub_columns)
+ table_node['classes'] += options.get('class', [])
+ if title:
+ table_node.insert(0, title)
+ return [table_node] + messages
+
+list_table.arguments = (0, 1, 1)
+list_table.options = {'header-rows': directives.nonnegative_int,
+ 'stub-columns': directives.nonnegative_int,
+ 'widths': directives.positive_int_list,
+ 'class': directives.class_option}
+list_table.content = 1
+
+def check_list_content(node, name, options, content, lineno, block_text,
+ state_machine):
+ if len(node) != 1 or not isinstance(node[0], nodes.bullet_list):
+ error = state_machine.reporter.error(
+ 'Error parsing content block for the "%s" directive: '
+ 'exactly one bullet list expected.' % name,
+ nodes.literal_block(block_text, block_text), line=lineno)
+ raise SystemMessagePropagation(error)
+ list_node = node[0]
+ # Check for a uniform two-level bullet list:
+ for item_index in range(len(list_node)):
+ item = list_node[item_index]
+ if len(item) != 1 or not isinstance(item[0], nodes.bullet_list):
+ error = state_machine.reporter.error(
+ 'Error parsing content block for the "%s" directive: '
+ 'two-level bullet list expected, but row %s does not contain '
+ 'a second-level bullet list.' % (name, item_index + 1),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ raise SystemMessagePropagation(error)
+ elif item_index:
+ if len(item[0]) != num_cols:
+ error = state_machine.reporter.error(
+ 'Error parsing content block for the "%s" directive: '
+ 'uniform two-level bullet list expected, but row %s does '
+ 'not contain the same number of items as row 1 (%s vs %s).'
+ % (name, item_index + 1, len(item[0]), num_cols),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ raise SystemMessagePropagation(error)
+ else:
+ num_cols = len(item[0])
+ col_widths = get_column_widths(
+ num_cols, name, options, lineno, block_text, state_machine)
+ if len(col_widths) != num_cols:
+ error = state_machine.reporter.error(
+ 'Error parsing "widths" option of the "%s" directive: '
+ 'number of columns does not match the table data (%s vs %s).'
+ % (name, len(col_widths), num_cols),
+ nodes.literal_block(block_text, block_text), line=lineno)
+ raise SystemMessagePropagation(error)
+ return num_cols, col_widths
+
+def build_table_from_list(table_data, col_widths, header_rows, stub_columns):
+ table = nodes.table()
+ tgroup = nodes.tgroup(cols=len(col_widths))
+ table += tgroup
+ for col_width in col_widths:
+ colspec = nodes.colspec(colwidth=col_width)
+ if stub_columns:
+ colspec.attributes['stub'] = 1
+ stub_columns -= 1
+ tgroup += colspec
+ rows = []
+ for row in table_data:
+ row_node = nodes.row()
+ for cell in row:
+ entry = nodes.entry()
+ entry += cell
+ row_node += entry
+ rows.append(row_node)
+ if header_rows:
+ thead = nodes.thead()
+ thead.extend(rows[:header_rows])
+ tgroup += thead
+ tbody = nodes.tbody()
+ tbody.extend(rows[header_rows:])
+ tgroup += tbody
+ return table
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 2224 $
+# Date: $Date: 2004-06-05 21:40:46 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
# Internationalization details are documented in
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/af.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/af.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/af.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Jannie Hofmeyr
# Contact: jhsh at sun.ac.za
-# Revision: $Revision: 1.1.2.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -42,6 +42,7 @@
#'faq': 'questions',
'table (translation required)': 'table',
'csv-table (translation required)': 'csv-table',
+ 'list-table (translation required)': 'list-table',
'meta': 'meta',
#'beeldkaart': 'imagemap',
'beeld': 'image',
@@ -55,6 +56,8 @@
'inhoud': 'contents',
'sectnum': 'sectnum',
'section-numbering': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#'voetnote': 'footnotes',
#'aanhalings': 'citations',
'teikennotas': 'target-notes',
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/cs.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/cs.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/cs.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Marek Blaha
# Contact: mb at dat.cz
-# Revision: $Revision: 1.1.4.4 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -43,6 +43,7 @@
#'faq': 'questions',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
u'meta (translation required)': 'meta',
#'imagemap': 'imagemap',
u'image (translation required)': 'image', # obrazek
@@ -56,6 +57,8 @@
u'obsah': 'contents',
u'sectnum (translation required)': 'sectnum',
u'section-numbering (translation required)': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#'footnotes': 'footnotes',
#'citations': 'citations',
u'target-notes (translation required)': 'target-notes',
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/de.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/de.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/de.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: Engelbert Gruber; Felix Wiemann
# Contact: grubert at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -42,6 +42,7 @@
#'fragen': 'questions',
'tabelle': 'table',
'csv-tabelle': 'csv-table',
+ 'list-table (translation required)': 'list-table',
'meta': 'meta',
#'imagemap': 'imagemap',
'bild': 'image',
@@ -59,6 +60,8 @@
'kapitel-nummerierung': 'sectnum',
'abschnitts-nummerierung': 'sectnum',
u'linkziel-fu\xdfnoten': 'target-notes',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#u'fu\xdfnoten': 'footnotes',
#'zitate': 'citations',
}
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/en.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/en.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/en.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -41,6 +41,7 @@
#'questions': 'questions',
'table': 'table',
'csv-table': 'csv-table',
+ 'list-table': 'list-table',
#'qa': 'questions',
#'faq': 'questions',
'meta': 'meta',
@@ -56,6 +57,8 @@
'contents': 'contents',
'sectnum': 'sectnum',
'section-numbering': 'sectnum',
+ 'header': 'header',
+ 'footer': 'footer',
#'footnotes': 'footnotes',
#'citations': 'citations',
'target-notes': 'target-notes',
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/eo.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/eo.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/eo.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Marcelo Huerta San Martin
# Contact: richieadler at users.sourceforge.net
-# Revision: $Revision: 1.1.2.5 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3189 $
+# Date: $Date: 2005-04-08 05:05:45 +0200 (Fri, 08 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -48,6 +48,7 @@
u'tabelo': 'table',
u'tabelo-vdk': 'csv-table', # "valoroj disigitaj per komoj"
u'tabelo-csv': 'csv-table',
+ u'tabelo-lista': 'list-table',
u'meta': 'meta',
#'imagemap': 'imagemap',
u'bildo': 'image',
@@ -62,6 +63,8 @@
u'enhavo': 'contents',
u'seknum': 'sectnum',
u'sekcia-numerado': 'sectnum',
+ u'kapsekcio': 'header',
+ u'piedsekcio': 'footer',
#'footnotes': 'footnotes',
#'citations': 'citations',
u'celaj-notoj': 'target-notes',
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/es.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/es.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/es.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,8 +1,8 @@
# -*- coding: iso-8859-1 -*-
# Author: Marcelo Huerta San Martín
# Contact: richieadler at users.sourceforge.net
-# Revision: $Revision: 1.1.2.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3190 $
+# Date: $Date: 2005-04-08 05:06:12 +0200 (Fri, 08 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -50,6 +50,7 @@
u'tabla': 'table',
u'tabla-vsc': 'csv-table',
u'tabla-csv': 'csv-table',
+ u'tabla-lista': 'list-table',
u'meta': 'meta',
#'imagemap': 'imagemap',
u'imagen': 'image',
@@ -67,6 +68,8 @@
u'numeracion-seccion': 'sectnum',
u'numeraci\u00f3n-secci\u00f3n': 'sectnum',
u'notas-destino': 'target-notes',
+ u'cabecera': 'header',
+ u'pie': 'footer',
#'footnotes': 'footnotes',
#'citations': 'citations',
u'restructuredtext-test-directive': 'restructuredtext-test-directive'}
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/fi.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/fi.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/fi.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Asko Soukka
# Contact: asko.soukka at iki.fi
-# Revision: $Revision: 1.1.2.1 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -39,6 +39,7 @@
u'lainaus': u'pull-quote',
u'taulukko': u'table',
u'csv-taulukko': u'csv-table',
+ u'list-table (translation required)': 'list-table',
u'compound (translation required)': 'compound',
#u'kysymykset': u'questions',
u'meta': u'meta',
@@ -53,6 +54,8 @@
u'rooli': u'role',
u'sis\u00e4llys': u'contents',
u'kappale': u'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#u'alaviitteet': u'footnotes',
#u'viitaukset': u'citations',
u'target-notes (translation required)': u'target-notes'}
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/fr.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/fr.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/fr.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger; William Dode
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -44,6 +44,7 @@
#u'faq': 'questions',
u'tableau': 'table',
u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
u'm\u00E9ta': 'meta',
#u'imagemap (translation required)': 'imagemap',
u'image': 'image',
@@ -60,6 +61,8 @@
u'sectnum': 'sectnum',
u'section-num\u00E9rot\u00E9e': 'sectnum',
u'liens': 'target-notes',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#u'footnotes (translation required)': 'footnotes',
#u'citations (translation required)': 'citations',
}
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/it.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/it.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/it.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,13 +1,13 @@
# Author: Nicola Larosa, Lele Gaifax
# Contact: docutils at tekNico.net, lele at seldati.it
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
-# New language mappings are welcome. Before doing a new translation, please
-# read <http://docutils.sf.net/docs/howto/i18n.html>. Two files must be
-# translated for each language: one in docutils/languages, the other in
-# docutils/parsers/rst/languages.
+# Beware: the italian translation of the reStructuredText documentation
+# at http://docit.bice.dyndns.org/static/ReST, in particular
+# http://docit.bice.dyndns.org/static/ReST/ref/rst/directives.html, needs
+# to be synced with the content of this file.
"""
Italian-language mappings for language-dependent features of
@@ -34,14 +34,15 @@
'blocco-interpretato': 'parsed-literal',
'rubrica': 'rubric',
'epigrafe': 'epigraph',
- 'evidenzia': 'highlights',
- 'pull-quote (translation required)': 'pull-quote',
- 'compound (translation required)': 'compound',
+ 'punti-salienti': 'highlights',
+ 'estratto-evidenziato': 'pull-quote',
+ 'composito': 'compound',
#'questions': 'questions',
#'qa': 'questions',
#'faq': 'questions',
'tabella': 'table',
- 'csv-table (translation required)': 'csv-table',
+ 'tabella-csv': 'csv-table',
+ 'tabella-elenco': 'list-table',
'meta': 'meta',
#'imagemap': 'imagemap',
'immagine': 'image',
@@ -53,9 +54,12 @@
'classe': 'class',
'ruolo': 'role',
'indice': 'contents',
+ 'contenuti': 'contents',
'seznum': 'sectnum',
'sezioni-autonumerate': 'sectnum',
'annota-riferimenti-esterni': 'target-notes',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#'footnotes': 'footnotes',
#'citations': 'citations',
'restructuredtext-test-directive': 'restructuredtext-test-directive'}
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/pt_br.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/pt_br.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/pt_br.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.1.4.4 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -43,6 +43,7 @@
#'faq': 'questions',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
'meta': 'meta',
#'imagemap': 'imagemap',
'imagem': 'image',
@@ -56,6 +57,8 @@
u'\u00EDndice': 'contents',
'numsec': 'sectnum',
u'numera\u00E7\u00E3o-de-se\u00E7\u00F5es': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#u'notas-de-rorap\u00E9': 'footnotes',
#u'cita\u00E7\u00F5es': 'citations',
u'links-no-rodap\u00E9': 'target-notes',
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/ru.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/ru.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/ru.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Roman Suzi
# Contact: rnd at onego.ru
-# Revision: $Revision: 1.1.2.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -26,6 +26,7 @@
u'compound (translation required)': 'compound',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
u'\u0441\u044b\u0440\u043e\u0439': u'raw',
u'\u0437\u0430\u043c\u0435\u043d\u0430': u'replace',
u'\u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f-\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430-restructuredtext':
@@ -60,7 +61,9 @@
u'\u0441\u043e\u0432\u0435\u0442': u'hint',
u'\u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435': u'contents',
u'\u0442\u0435\u043c\u0430': u'topic',
- u'\u044d\u043f\u0438\u0433\u0440\u0430\u0444': u'epigraph'}
+ u'\u044d\u043f\u0438\u0433\u0440\u0430\u0444': u'epigraph',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',}
"""Russian name to registered (in directives/__init__.py) directive name
mapping."""
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/sk.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/sk.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/sk.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Miroslav Vasko
# Contact: zemiak at zoznam.sk
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -42,6 +42,7 @@
#u'faq': 'questions',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
u'meta': 'meta',
#u'imagemap': 'imagemap',
u'obr\xe1zok': 'image',
@@ -56,6 +57,8 @@
u'\xe8as\x9d': 'sectnum',
u'\xe8as\x9d-\xe8\xedslovanie': 'sectnum',
u'cie\xbeov\xe9-pozn\xe1mky': 'target-notes',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#u'footnotes': 'footnotes',
#u'citations': 'citations',
}
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/sv.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/sv.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/sv.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Adam Chodorowski
# Contact: chodorowski at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -42,6 +42,7 @@
# u'vanliga-fr\u00e5gor': 'questions',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
+ u'list-table (translation required)': 'list-table',
u'meta': 'meta',
# u'bildkarta': 'imagemap', # FIXME: Translation might be too literal.
u'bild': 'image',
@@ -55,6 +56,8 @@
u'inneh\u00e5ll': 'contents',
u'sektionsnumrering': 'sectnum',
u'target-notes (translation required)': 'target-notes',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
# u'fotnoter': 'footnotes',
# u'citeringar': 'citations',
}
Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/zh_tw.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/zh_tw.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/zh_tw.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.1.2.1 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 3184 $
+# Date: $Date: 2005-04-07 21:36:11 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
@@ -41,6 +41,7 @@
#'questions (translation required)': 'questions',
'table (translation required)': 'table',
'csv-table (translation required)': 'csv-table',
+ 'list-table (translation required)': 'list-table',
#'qa (translation required)': 'questions',
#'faq (translation required)': 'questions',
'meta (translation required)': 'meta',
@@ -56,6 +57,8 @@
'contents (translation required)': 'contents',
'sectnum (translation required)': 'sectnum',
'section-numbering (translation required)': 'sectnum',
+ u'header (translation required)': 'header',
+ u'footer (translation required)': 'footer',
#'footnotes (translation required)': 'footnotes',
#'citations (translation required)': 'citations',
'target-notes (translation required)': 'target-notes',
Modified: Zope/trunk/lib/python/docutils/parsers/rst/roles.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/roles.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/roles.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: Edward Loper
# Contact: edloper at gradient.cis.upenn.edu
-# Revision: $Revision: 1.1.4.4 $
-# Date: $Date: 2005/01/07 13:26:03 $
+# Revision: $Revision: 3155 $
+# Date: $Date: 2005-04-02 23:57:06 +0200 (Sat, 02 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -174,7 +174,7 @@
if not hasattr(role_fn, 'options') or role_fn.options is None:
role_fn.options = {'class': directives.class_option}
elif not role_fn.options.has_key('class'):
- role_fn.options['class'] = directives.class_option
+ role_fn.options['class'] = directives.class_option
def register_generic_role(canonical_name, node_class):
"""For roles which simply wrap a given `node_class` around the text."""
@@ -195,6 +195,7 @@
def __call__(self, role, rawtext, text, lineno, inliner,
options={}, content=[]):
+ set_classes(options)
return [self.node_class(rawtext, utils.unescape(text), **options)], []
@@ -233,6 +234,7 @@
""""""
# Once nested inline markup is implemented, this and other methods should
# recursively call inliner.nested_parse().
+ set_classes(options)
return [nodes.inline(rawtext, utils.unescape(text), **options)], []
generic_custom_role.options = {'class': directives.class_option}
@@ -265,6 +267,7 @@
return [prb], [msg]
# Base URL mainly used by inliner.pep_reference; so this is correct:
ref = inliner.document.settings.pep_base_url + inliner.pep_url % pepnum
+ set_classes(options)
return [nodes.reference(rawtext, 'PEP ' + utils.unescape(text), refuri=ref,
**options)], []
@@ -284,6 +287,7 @@
return [prb], [msg]
# Base URL mainly used by inliner.rfc_reference, so this is correct:
ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
+ set_classes(options)
node = nodes.reference(rawtext, 'RFC ' + utils.unescape(text), refuri=ref,
**options)
return [node], []
@@ -299,10 +303,11 @@
'an associated format.' % role, line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
+ set_classes(options)
node = nodes.raw(rawtext, utils.unescape(text, 1), **options)
return [node], []
-raw_role.options = {'format': directives.class_option}
+raw_role.options = {'format': directives.unchanged}
register_canonical_role('raw', raw_role)
@@ -329,3 +334,14 @@
# This should remain unimplemented, for testing purposes:
register_canonical_role('restructuredtext-unimplemented-role',
unimplemented_role)
+
+
+def set_classes(options):
+ """
+ Auxiliary function to set options['classes'] and delete
+ options['class'].
+ """
+ if options.has_key('class'):
+ assert not options.has_key('classes')
+ options['classes'] = options['class']
+ del options['class']
Modified: Zope/trunk/lib/python/docutils/parsers/rst/states.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/states.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/states.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:03 $
+# Revision: $Revision: 3253 $
+# Date: $Date: 2005-04-25 17:08:01 +0200 (Mon, 25 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -365,7 +365,7 @@
textnodes, title_messages = self.inline_text(title, lineno)
titlenode = nodes.title(title, '', *textnodes)
name = normalize_name(titlenode.astext())
- section_node['name'] = name
+ section_node['names'].append(name)
section_node += titlenode
section_node += messages
section_node += title_messages
@@ -533,7 +533,7 @@
emailc = r"""[-_!~*'{|}/#?^`&=+$%a-zA-Z0-9\x00]"""
email_pattern = r"""
%(emailc)s+(?:\.%(emailc)s+)* # name
- @ # at
+ (?<!\x00)@ # at
%(emailc)s+(?:\.%(emailc)s*)* # host
%(uri_end)s # final URI char
"""
@@ -787,7 +787,7 @@
else:
if target:
reference['refuri'] = uri
- target['name'] = refname
+ target['names'].append(refname)
self.document.note_external_target(target)
self.document.note_explicit_target(target, self.parent)
node_list.append(target)
@@ -829,7 +829,7 @@
assert len(inlines) == 1
target = inlines[0]
name = normalize_name(target.astext())
- target['name'] = name
+ target['names'].append(name)
self.document.note_explicit_target(target, self.parent)
return before, inlines, remaining, sysmessages
@@ -1036,10 +1036,10 @@
pats['alphanum'] = '[a-zA-Z0-9]'
pats['alphanumplus'] = '[a-zA-Z0-9_-]'
pats['enum'] = ('(%(arabic)s|%(loweralpha)s|%(upperalpha)s|%(lowerroman)s'
- '|%(upperroman)s)' % enum.sequencepats)
+ '|%(upperroman)s|#)' % enum.sequencepats)
pats['optname'] = '%(alphanum)s%(alphanumplus)s*' % pats
# @@@ Loosen up the pattern? Allow Unicode?
- pats['optarg'] = '(%(alpha)s%(alphanumplus)s*|<%(alphanum)s[^ <>]+>)' % pats
+ pats['optarg'] = '(%(alpha)s%(alphanumplus)s*|<[^<>]+>)' % pats
pats['shortopt'] = r'(-|\+)%(alphanum)s( ?%(optarg)s)?' % pats
pats['longopt'] = r'(--|/)%(optname)s([ =]%(optarg)s)?' % pats
pats['option'] = r'(%(shortopt)s|%(longopt)s)' % pats
@@ -1182,7 +1182,10 @@
raise statemachine.TransitionCorrection('text')
enumlist = nodes.enumerated_list()
self.parent += enumlist
- enumlist['enumtype'] = sequence
+ if sequence == '#':
+ enumlist['enumtype'] = 'arabic'
+ else:
+ enumlist['enumtype'] = sequence
enumlist['prefix'] = self.enum.formatinfo[format].prefix
enumlist['suffix'] = self.enum.formatinfo[format].suffix
if ordinal != 1:
@@ -1199,7 +1202,9 @@
input_offset=self.state_machine.abs_line_offset() + 1,
node=enumlist, initial_state='EnumeratedList',
blank_finish=blank_finish,
- extra_settings={'lastordinal': ordinal, 'format': format})
+ extra_settings={'lastordinal': ordinal,
+ 'format': format,
+ 'auto': sequence == '#'})
self.goto_line(newline_offset)
if not blank_finish:
self.parent += self.unindent_warning('Enumerated list')
@@ -1232,7 +1237,9 @@
raise ParserError('enumerator format not matched')
text = groupdict[format][self.enum.formatinfo[format].start
:self.enum.formatinfo[format].end]
- if expected_sequence:
+ if text == '#':
+ sequence = '#'
+ elif expected_sequence:
try:
if self.enum.sequenceregexps[expected_sequence].match(text):
sequence = expected_sequence
@@ -1249,10 +1256,13 @@
break
else: # shouldn't happen
raise ParserError('enumerator sequence not matched')
- try:
- ordinal = self.enum.converters[sequence](text)
- except roman.InvalidRomanNumeralError:
- ordinal = None
+ if sequence == '#':
+ ordinal = 1
+ else:
+ try:
+ ordinal = self.enum.converters[sequence](text)
+ except roman.InvalidRomanNumeralError:
+ ordinal = None
return format, sequence, text, ordinal
def is_enumerated_list_item(self, ordinal, sequence, format):
@@ -1260,7 +1270,7 @@
Check validity based on the ordinal value and the second line.
Return true iff the ordinal is valid and the second line is blank,
- indented, or starts with the next enumerator.
+ indented, or starts with the next enumerator or an auto-enumerator.
"""
if ordinal is None:
return None
@@ -1273,9 +1283,11 @@
self.state_machine.previous_line()
if not next_line[:1].strip(): # blank or indented
return 1
- next_enumerator = self.make_enumerator(ordinal + 1, sequence, format)
+ next_enumerator, auto_enumerator = self.make_enumerator(
+ ordinal + 1, sequence, format)
try:
- if next_line.startswith(next_enumerator):
+ if ( next_line.startswith(next_enumerator) or
+ next_line.startswith(auto_enumerator) ):
return 1
except TypeError:
pass
@@ -1283,11 +1295,14 @@
def make_enumerator(self, ordinal, sequence, format):
"""
- Construct and return an enumerated list item marker.
+ Construct and return the next enumerated list item marker, and an
+ auto-enumerator ("#" instead of the regular enumerator).
Return ``None`` for invalid (out of range) ordinals.
- """
- if sequence == 'arabic':
+ """ #"
+ if sequence == '#':
+ enumerator = '#'
+ elif sequence == 'arabic':
enumerator = str(ordinal)
else:
if sequence.endswith('alpha'):
@@ -1310,7 +1325,10 @@
raise ParserError('unknown enumerator sequence: "%s"'
% sequence)
formatinfo = self.enum.formatinfo[format]
- return formatinfo.prefix + enumerator + formatinfo.suffix + ' '
+ next_enumerator = (formatinfo.prefix + enumerator + formatinfo.suffix
+ + ' ')
+ auto_enumerator = formatinfo.prefix + '#' + formatinfo.suffix + ' '
+ return next_enumerator, auto_enumerator
def field_marker(self, match, context, next_state):
"""Field list item."""
@@ -1415,14 +1433,20 @@
delimiter = ' '
firstopt = tokens[0].split('=')
if len(firstopt) > 1:
+ # "--opt=value" form
tokens[:1] = firstopt
delimiter = '='
elif (len(tokens[0]) > 2
and ((tokens[0].startswith('-')
and not tokens[0].startswith('--'))
or tokens[0].startswith('+'))):
+ # "-ovalue" form
tokens[:1] = [tokens[0][:2], tokens[0][2:]]
delimiter = ''
+ if len(tokens) > 1 and (tokens[1].startswith('<')
+ and tokens[-1].endswith('>')):
+ # "-o <value1 value2>" form; join all values into one token
+ tokens[1:] = [' '.join(tokens[1:])]
if 0 < len(tokens) <= 2:
option = nodes.option(optionstring)
option += nodes.option_string(tokens[0], tokens[0])
@@ -1432,7 +1456,7 @@
optlist.append(option)
else:
raise MarkupError(
- 'wrong numer of option tokens (=%s), should be 1 or 2: '
+ 'wrong number of option tokens (=%s), should be 1 or 2: '
'"%s"' % (len(tokens), optionstring),
self.state_machine.abs_line_number() + 1)
return optlist
@@ -1541,7 +1565,8 @@
table = self.build_table(tabledata, tableline)
nodelist = [table] + messages
except tableparser.TableMarkupError, detail:
- nodelist = self.malformed_table(block, str(detail)) + messages
+ nodelist = self.malformed_table(
+ block, ' '.join(detail.args)) + messages
else:
nodelist = messages
return nodelist, blank_finish
@@ -1633,13 +1658,17 @@
line=lineno)
return [error]
- def build_table(self, tabledata, tableline):
- colspecs, headrows, bodyrows = tabledata
+ def build_table(self, tabledata, tableline, stub_columns=0):
+ colwidths, headrows, bodyrows = tabledata
table = nodes.table()
- tgroup = nodes.tgroup(cols=len(colspecs))
+ tgroup = nodes.tgroup(cols=len(colwidths))
table += tgroup
- for colspec in colspecs:
- tgroup += nodes.colspec(colwidth=colspec)
+ for colwidth in colwidths:
+ colspec = nodes.colspec(colwidth=colwidth)
+ if stub_columns:
+ colspec.attributes['stub'] = 1
+ stub_columns -= 1
+ tgroup += colspec
if headrows:
thead = nodes.thead()
tgroup += thead
@@ -1727,7 +1756,7 @@
name = name[1:] # autonumber label
footnote['auto'] = 1
if name:
- footnote['name'] = name
+ footnote['names'].append(name)
self.document.note_autofootnote(footnote)
elif name == '*': # auto-symbol
name = ''
@@ -1735,7 +1764,7 @@
self.document.note_symbol_footnote(footnote)
else: # manually numbered
footnote += nodes.label('', label)
- footnote['name'] = name
+ footnote['names'].append(name)
self.document.note_footnote(footnote)
if name:
self.document.note_explicit_target(footnote, footnote)
@@ -1754,7 +1783,7 @@
citation = nodes.citation('\n'.join(indented))
citation.line = lineno
citation += nodes.label('', label)
- citation['name'] = name
+ citation['names'].append(name)
self.document.note_citation(citation)
self.document.note_explicit_target(citation, citation)
if indented:
@@ -1790,7 +1819,6 @@
target_type, data = self.parse_target(block, block_text, lineno)
if target_type == 'refname':
target = nodes.target(block_text, '', refname=normalize_name(data))
- target.indirect_reference_name = data
self.add_target(target_name, '', target, lineno)
self.document.note_indirect_target(target)
return target
@@ -1816,15 +1844,8 @@
refname = self.is_reference(reference)
if refname:
return 'refname', refname
- reference = ''.join([line.strip() for line in block])
- if reference.find(' ') == -1:
- return 'refuri', unescape(reference)
- else:
- warning = self.reporter.warning(
- 'Hyperlink target contains whitespace. Perhaps a footnote '
- 'was intended?',
- nodes.literal_block(block_text, block_text), line=lineno)
- return 'malformed', warning
+ reference = ''.join([''.join(line.split()) for line in block])
+ return 'refuri', unescape(reference)
def is_reference(self, reference):
match = self.explicit.patterns.reference.match(
@@ -1837,7 +1858,7 @@
target.line = lineno
if targetname:
name = normalize_name(unescape(targetname))
- target['name'] = name
+ target['names'].append(name)
if refuri:
uri = self.inliner.adjust_uri(refuri)
if uri:
@@ -1851,6 +1872,8 @@
else: # anonymous target
if refuri:
target['refuri'] = refuri
+ else:
+ self.document.note_internal_target(target)
target['anonymous'] = 1
self.document.note_anonymous_target(target)
@@ -1960,7 +1983,8 @@
directive_fn, option_presets))
except MarkupError, detail:
error = self.reporter.error(
- 'Error in "%s" directive:\n%s.' % (type_name, detail),
+ 'Error in "%s" directive:\n%s.' % (type_name,
+ ' '.join(detail.args)),
nodes.literal_block(block_text, block_text), line=lineno)
return [error], blank_finish
result = directive_fn(type_name, arguments, options, content, lineno,
@@ -2071,9 +2095,9 @@
except KeyError, detail:
return 0, ('unknown option: "%s"' % detail.args[0])
except (ValueError, TypeError), detail:
- return 0, ('invalid option value: %s' % detail)
+ return 0, ('invalid option value: %s' % ' '.join(detail.args))
except utils.ExtensionOptionError, detail:
- return 0, ('invalid option data: %s' % detail)
+ return 0, ('invalid option data: %s' % ' '.join(detail.args))
if blank_finish:
return 1, options
else:
@@ -2127,13 +2151,13 @@
re.compile(r"""
\.\.[ ]+ # explicit markup start
_ # target indicator
- (?![ ]) # first char. not space
+ (?![ ]|$) # first char. not space or EOL
""", re.VERBOSE)),
(substitution_def,
re.compile(r"""
\.\.[ ]+ # explicit markup start
\| # substitution indicator
- (?![ ]) # first char. not space
+ (?![ ]|$) # first char. not space or EOL
""", re.VERBOSE)),
(directive,
re.compile(r"""
@@ -2240,7 +2264,7 @@
def rfc2822(self, match, context, next_state):
"""RFC2822-style field list item."""
- fieldlist = nodes.field_list(CLASS='rfc2822')
+ fieldlist = nodes.field_list(classes=['rfc2822'])
self.parent += fieldlist
field, blank_finish = self.rfc2822_field(match)
fieldlist += field
@@ -2347,12 +2371,15 @@
"""Enumerated list item."""
format, sequence, text, ordinal = self.parse_enumerator(
match, self.parent['enumtype'])
- if (sequence != self.parent['enumtype'] or
- format != self.format or
- ordinal != (self.lastordinal + 1) or
- not self.is_enumerated_list_item(ordinal, sequence, format)):
+ if ( format != self.format
+ or (sequence != '#' and (sequence != self.parent['enumtype']
+ or self.auto
+ or ordinal != (self.lastordinal + 1)))
+ or not self.is_enumerated_list_item(ordinal, sequence, format)):
# different enumeration: new list
self.invalid_input()
+ if sequence == '#':
+ self.auto = 1
listitem, blank_finish = self.list_item(match.end())
self.parent += listitem
self.blank_finish = blank_finish
@@ -2475,7 +2502,7 @@
def embedded_directive(self, match, context, next_state):
nodelist, blank_finish = self.directive(match,
- alt=self.parent['name'])
+ alt=self.parent['names'][0])
self.parent += nodelist
if not self.state_machine.at_eof():
self.blank_finish = blank_finish
Modified: Zope/trunk/lib/python/docutils/parsers/rst/tableparser.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/tableparser.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/parsers/rst/tableparser.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:04 $
+# Revision: $Revision: 1574 $
+# Date: $Date: 2003-07-06 00:38:28 +0200 (Sun, 06 Jul 2003) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/readers/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/readers/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger; Ueli Schlaepfer
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:05 $
+# Revision: $Revision: 1645 $
+# Date: $Date: 2003-08-27 22:50:43 +0200 (Wed, 27 Aug 2003) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/readers/pep.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/pep.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/readers/pep.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:05 $
+# Revision: $Revision: 3129 $
+# Date: $Date: 2005-03-26 17:21:28 +0100 (Sat, 26 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -31,9 +31,9 @@
config_section_dependencies = ('readers', 'standalone reader')
default_transforms = (references.Substitutions,
+ references.PropagateTargets,
peps.Headers,
peps.Contents,
- references.ChainedTargets,
references.AnonymousHyperlinks,
references.IndirectHyperlinks,
peps.TargetNotes,
Modified: Zope/trunk/lib/python/docutils/readers/python/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/python/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/readers/python/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.3.2.5 $
-# Date: $Date: 2005/01/07 13:26:05 $
+# Revision: $Revision: 3038 $
+# Date: $Date: 2005-03-14 17:16:57 +0100 (Mon, 14 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -88,7 +88,7 @@
node['docformat'] = docformat
parser = self.get_parser(docformat)
parser.parse(text, self.document)
- for child in self.document.get_children():
+ for child in self.document.children:
node.append(child)
self.document.current_source = self.document.current_line = None
del self.document[:]
Modified: Zope/trunk/lib/python/docutils/readers/python/moduleparser.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/python/moduleparser.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/readers/python/moduleparser.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.3.2.5 $
-# Date: $Date: 2005/01/07 13:26:05 $
+# Revision: $Revision: 2449 $
+# Date: $Date: 2004-07-25 03:45:27 +0200 (Sun, 25 Jul 2004) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/readers/python/pynodes.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/python/pynodes.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/readers/python/pynodes.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -3,8 +3,8 @@
"""
:Author: David Goodger
:Contact: goodger at users.sourceforge.net
-:Revision: $Revision: 1.1.4.4 $
-:Date: $Date: 2005/01/07 13:26:05 $
+:Revision: $Revision: 1881 $
+:Date: $Date: 2004-03-24 00:21:11 +0100 (Wed, 24 Mar 2004) $
:Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/readers/standalone.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/standalone.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/readers/standalone.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:05 $
+# Revision: $Revision: 3353 $
+# Date: $Date: 2005-05-19 02:49:14 +0200 (Thu, 19 May 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -37,15 +37,26 @@
'default).',
['--no-doc-info'],
{'dest': 'docinfo_xform', 'action': 'store_false', 'default': 1,
- 'validator': frontend.validate_boolean}),))
+ 'validator': frontend.validate_boolean}),
+ ('Activate the promotion of lone subsection titles to '
+ 'section subtitles (disabled by default).',
+ ['--section-subtitles'],
+ {'dest': 'sectsubtitle_xform', 'action': 'store_true', 'default': 0,
+ 'validator': frontend.validate_boolean}),
+ ('Deactivate the promotion of lone subsection titles.',
+ ['--no-section-subtitles'],
+ {'dest': 'sectsubtitle_xform', 'action': 'store_false',
+ 'validator': frontend.validate_boolean}),
+ ))
config_section = 'standalone reader'
config_section_dependencies = ('readers',)
default_transforms = (references.Substitutions,
+ references.PropagateTargets,
frontmatter.DocTitle,
+ frontmatter.SectionSubTitle,
frontmatter.DocInfo,
- references.ChainedTargets,
references.AnonymousHyperlinks,
references.IndirectHyperlinks,
references.Footnotes,
Modified: Zope/trunk/lib/python/docutils/statemachine.py
===================================================================
--- Zope/trunk/lib/python/docutils/statemachine.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/statemachine.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 2299 $
+# Date: $Date: 2004-06-17 23:46:50 +0200 (Thu, 17 Jun 2004) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/transforms/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/transforms/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger, Ueli Schlaepfer
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:05 $
+# Revision: $Revision: 3066 $
+# Date: $Date: 2005-03-21 18:33:42 +0100 (Mon, 21 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -59,8 +59,8 @@
self.language = languages.get_language(
document.settings.language_code)
"""Language module local to this document."""
-
+
def apply(self):
"""Override to apply the transform to the document tree."""
raise NotImplementedError('subclass must override this method')
@@ -164,7 +164,6 @@
decorated_list.sort()
self.unknown_reference_resolvers.extend([f[1] for f in decorated_list])
-
def apply_transforms(self):
"""Apply all of the stored transforms, in priority order."""
self.document.reporter.attach_observer(
Modified: Zope/trunk/lib/python/docutils/transforms/components.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/components.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/transforms/components.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 853 $
+# Date: $Date: 2002-10-24 02:51:10 +0200 (Thu, 24 Oct 2002) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/transforms/frontmatter.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/frontmatter.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/transforms/frontmatter.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,17 +1,19 @@
# Authors: David Goodger, Ueli Schlaepfer
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 3351 $
+# Date: $Date: 2005-05-19 00:27:52 +0200 (Thu, 19 May 2005) $
# Copyright: This module has been placed in the public domain.
"""
-Transforms related to the front matter of a document (information
-found before the main text):
+Transforms related to the front matter of a document or a section
+(information found before the main text):
- `DocTitle`: Used to transform a lone top level section's title to
the document title, and promote a remaining lone top-level section's
title to the document subtitle.
+- `SectionTitle`: Used to transform a lone subsection into a subtitle.
+
- `DocInfo`: Used to transform a bibliographic field list into docinfo
elements.
"""
@@ -23,9 +25,102 @@
from docutils.transforms import TransformError, Transform
-class DocTitle(Transform):
+class TitlePromoter(Transform):
"""
+ Abstract base class for DocTitle and SectionSubTitle transforms.
+ """
+
+ def promote_title(self, node):
+ """
+ Transform the following tree::
+
+ <node>
+ <section>
+ <title>
+ ...
+
+ into ::
+
+ <node>
+ <title>
+ ...
+
+ `node` is normally a document.
+ """
+ # `node` must not have a title yet.
+ assert not (len(node) and isinstance(node[0], nodes.title))
+ section, index = self.candidate_index(node)
+ if index is None:
+ return None
+ # Transfer the section's attributes to the node:
+ node.attributes.update(section.attributes)
+ # setup_child is called automatically for all nodes.
+ node[:] = (section[:1] # section title
+ + node[:index] # everything that was in the
+ # node before the section
+ + section[1:]) # everything that was in the section
+ assert isinstance(node[0], nodes.title)
+ return 1
+
+ def promote_subtitle(self, node):
+ """
+ Transform the following node tree::
+
+ <node>
+ <title>
+ <section>
+ <title>
+ ...
+
+ into ::
+
+ <node>
+ <title>
+ <subtitle>
+ ...
+ """
+ subsection, index = self.candidate_index(node)
+ if index is None:
+ return None
+ subtitle = nodes.subtitle()
+ # Transfer the subsection's attributes to the new subtitle:
+ # This causes trouble with list attributes! To do: Write a
+ # test case which catches direct access to the `attributes`
+ # dictionary and/or write a test case which shows problems in
+ # this particular case.
+ subtitle.attributes.update(subsection.attributes)
+ # We're losing the subtitle's attributes here! To do: Write a
+ # test case which shows this behavior.
+ # Transfer the contents of the subsection's title to the
+ # subtitle:
+ subtitle[:] = subsection[0][:]
+ node[:] = (node[:1] # title
+ + [subtitle]
+ # everything that was before the section:
+ + node[1:index]
+ # everything that was in the subsection:
+ + subsection[1:])
+ return 1
+
+ def candidate_index(self, node):
+ """
+ Find and return the promotion candidate and its index.
+
+ Return (None, None) if no valid candidate was found.
+ """
+ index = node.first_child_not_matching_class(
+ nodes.PreBibliographic)
+ if index is None or len(node) > (index + 1) or \
+ not isinstance(node[index], nodes.section):
+ return None, None
+ else:
+ return node[index], index
+
+
+class DocTitle(TitlePromoter):
+
+ """
In reStructuredText_, there is no way to specify a document title
and subtitle explicitly. Instead, we can supply the document title
(and possibly the subtitle as well) implicitly, and use this
@@ -50,7 +145,7 @@
Once parsed, it looks like this::
<document>
- <section name="top-level title">
+ <section names="top-level title">
<title>
Top-Level Title
<paragraph>
@@ -58,7 +153,7 @@
After running the DocTitle transform, we have::
- <document name="top-level title">
+ <document names="top-level title">
<title>
Top-Level Title
<paragraph>
@@ -85,10 +180,10 @@
After parsing and running the Section Promotion transform, the
result is::
- <document name="top-level title">
+ <document names="top-level title">
<title>
Top-Level Title
- <subtitle name="second-level title">
+ <subtitle names="second-level title">
Second-Level Title
<paragraph>
A paragraph.
@@ -107,56 +202,49 @@
def apply(self):
if not getattr(self.document.settings, 'doctitle_xform', 1):
return
- if self.promote_document_title():
- self.promote_document_subtitle()
+ if self.promote_title(self.document):
+ self.promote_subtitle(self.document)
- def promote_document_title(self):
- section, index = self.candidate_index()
- if index is None:
- return None
- document = self.document
- # Transfer the section's attributes to the document element (at root):
- document.attributes.update(section.attributes)
- document[:] = (section[:1] # section title
- + document[:index] # everything that was in the
- # document before the section
- + section[1:]) # everything that was in the section
- return 1
- def promote_document_subtitle(self):
- subsection, index = self.candidate_index()
- if index is None:
- return None
- subtitle = nodes.subtitle()
- # Transfer the subsection's attributes to the new subtitle:
- subtitle.attributes.update(subsection.attributes)
- # Transfer the contents of the subsection's title to the subtitle:
- subtitle[:] = subsection[0][:]
- document = self.document
- document[:] = (document[:1] # document title
- + [subtitle]
- # everything that was before the section:
- + document[1:index]
- # everything that was in the subsection:
- + subsection[1:])
- return 1
+class SectionSubTitle(TitlePromoter):
- def candidate_index(self):
- """
- Find and return the promotion candidate and its index.
+ """
+ This works like document subtitles, but for sections. For example, ::
- Return (None, None) if no valid candidate was found.
- """
- document = self.document
- index = document.first_child_not_matching_class(
- nodes.PreBibliographic)
- if index is None or len(document) > (index + 1) or \
- not isinstance(document[index], nodes.section):
- return None, None
- else:
- return document[index], index
+ <section>
+ <title>
+ Title
+ <section>
+ <title>
+ Subtitle
+ ...
+ is transformed into ::
+ <section>
+ <title>
+ Title
+ <subtitle>
+ Subtitle
+ ...
+
+ For details refer to the docstring of DocTitle.
+ """
+
+ default_priority = 350
+
+ def apply(self):
+ if not getattr(self.document.settings, 'sectsubtitle_xform', 1):
+ return
+ for section in self.document.traverse(lambda n:
+ isinstance(n, nodes.section)):
+ # On our way through the node tree, we are deleting
+ # sections, but we call self.promote_subtitle for those
+ # sections nonetheless. To do: Write a test case which
+ # shows the problem and discuss on Docutils-develop.
+ self.promote_subtitle(section)
+
+
class DocInfo(Transform):
"""
@@ -189,7 +277,7 @@
Status
<field_body>
<paragraph>
- $RCSfile: frontmatter.py,v $
+ $RCSfile$
...
After running the bibliographic field list transform, the
@@ -258,11 +346,10 @@
candidate = document[index]
if isinstance(candidate, nodes.field_list):
biblioindex = document.first_child_not_matching_class(
- nodes.Titular)
+ (nodes.Titular, nodes.Decorative))
nodelist = self.extract_bibliographic(candidate)
del document[index] # untransformed field list (candidate)
document[biblioindex:biblioindex] = nodelist
- return
def extract_bibliographic(self, field_list):
docinfo = nodes.docinfo()
@@ -294,7 +381,7 @@
raise TransformError
title = nodes.title(name, labels[canonical])
topics[canonical] = biblioclass(
- '', title, CLASS=canonical, *field[1].children)
+ '', title, classes=[canonical], *field[1].children)
else:
docinfo.append(biblioclass('', *field[1].children))
except TransformError:
Modified: Zope/trunk/lib/python/docutils/transforms/misc.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/misc.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/transforms/misc.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 3155 $
+# Date: $Date: 2005-04-02 23:57:06 +0200 (Sat, 02 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -45,7 +45,6 @@
def apply(self):
pending = self.startnode
- class_value = pending.details['class']
parent = pending.parent
child = pending
while parent:
@@ -55,7 +54,7 @@
if (isinstance(element, nodes.Invisible) or
isinstance(element, nodes.system_message)):
continue
- element.set_class(class_value)
+ element['classes'] += pending.details['class']
pending.parent.remove(pending)
return
else:
Modified: Zope/trunk/lib/python/docutils/transforms/parts.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/parts.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/transforms/parts.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger, Ueli Schlaepfer, Dmitry Jemerov
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 3199 $
+# Date: $Date: 2005-04-09 03:32:29 +0200 (Sat, 09 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -54,7 +54,7 @@
generated = nodes.generated(
'', (self.prefix + '.'.join(numbers) + self.suffix
+ u'\u00a0' * 3),
- CLASS='sectnum')
+ classes=['sectnum'])
title.insert(0, generated)
title['auto'] = 1
if depth < self.maxdepth:
@@ -84,14 +84,13 @@
details = self.startnode.details
if details.has_key('local'):
startnode = self.startnode.parent.parent
- # @@@ generate an error if the startnode (directive) not at
- # section/document top-level? Drag it up until it is?
- while not isinstance(startnode, nodes.Structural):
+ while not (isinstance(startnode, nodes.section)
+ or isinstance(startnode, nodes.document)):
+ # find the ToC root: a direct ancestor of startnode
startnode = startnode.parent
else:
startnode = self.document
-
- self.toc_id = self.startnode.parent['id']
+ self.toc_id = self.startnode.parent['ids'][0]
if details.has_key('backlinks'):
self.backlinks = details['backlinks']
else:
@@ -117,15 +116,17 @@
title = section[0]
auto = title.get('auto') # May be set by SectNum.
entrytext = self.copy_and_filter(title)
- reference = nodes.reference('', '', refid=section['id'],
+ reference = nodes.reference('', '', refid=section['ids'][0],
*entrytext)
ref_id = self.document.set_id(reference)
entry = nodes.paragraph('', '', reference)
item = nodes.list_item('', entry)
- if self.backlinks == 'entry':
- title['refid'] = ref_id
- elif self.backlinks == 'top':
- title['refid'] = self.toc_id
+ if (self.backlinks in ('entry', 'top') and title.next_node(
+ lambda n: isinstance(n, nodes.reference)) is None):
+ if self.backlinks == 'entry':
+ title['refid'] = ref_id
+ elif self.backlinks == 'top':
+ title['refid'] = self.toc_id
if level < depth:
subsects = self.build_contents(section, level)
item += subsects
@@ -133,7 +134,7 @@
if entries:
contents = nodes.bullet_list('', *entries)
if auto:
- contents.set_class('auto-toc')
+ contents['classes'].append('auto-toc')
return contents
else:
return []
@@ -148,7 +149,7 @@
class ContentsFilter(nodes.TreeCopyVisitor):
def get_entry_text(self):
- return self.get_tree_copy().get_children()
+ return self.get_tree_copy().children
def visit_citation_reference(self, node):
raise nodes.SkipNode
Modified: Zope/trunk/lib/python/docutils/transforms/peps.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/peps.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/transforms/peps.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 3129 $
+# Date: $Date: 2005-03-26 17:21:28 +0100 (Sat, 26 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -46,7 +46,7 @@
raise DataError('Document tree is empty.')
header = self.document[0]
if not isinstance(header, nodes.field_list) or \
- header.get('class') != 'rfc2822':
+ 'rfc2822' not in header['classes']:
raise DataError('Document does not begin with an RFC-2822 '
'header; it is not a PEP.')
pep = None
@@ -149,10 +149,10 @@
language = languages.get_language(self.document.settings.language_code)
name = language.labels['contents']
title = nodes.title('', name)
- topic = nodes.topic('', title, CLASS='contents')
+ topic = nodes.topic('', title, classes=['contents'])
name = nodes.fully_normalize_name(name)
if not self.document.has_name(name):
- topic['name'] = name
+ topic['names'].append(name)
self.document.note_implicit_target(topic)
pending = nodes.pending(parts.Contents)
topic += pending
@@ -244,7 +244,7 @@
node.parent.replace(node, mask_email(node))
def visit_field_list(self, node):
- if node.hasattr('class') and node['class'] == 'rfc2822':
+ if 'rfc2822' in node['classes']:
raise nodes.SkipNode
def visit_tgroup(self, node):
@@ -254,7 +254,7 @@
def visit_colspec(self, node):
self.entry += 1
if self.pep_table and self.entry == 2:
- node['class'] = 'num'
+ node['classes'].append('num')
def visit_row(self, node):
self.entry = 0
@@ -262,7 +262,7 @@
def visit_entry(self, node):
self.entry += 1
if self.pep_table and self.entry == 2 and len(node) == 1:
- node['class'] = 'num'
+ node['classes'].append('num')
p = node[0]
if isinstance(p, nodes.paragraph) and len(p) == 1:
text = p.astext()
Modified: Zope/trunk/lib/python/docutils/transforms/references.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/references.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/transforms/references.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 3149 $
+# Date: $Date: 2005-03-30 22:51:06 +0200 (Wed, 30 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -16,89 +16,77 @@
from docutils.transforms import TransformError, Transform
-indices = xrange(sys.maxint)
+class PropagateTargets(Transform):
-
-class ChainedTargets(Transform):
-
"""
- Attributes "refuri" and "refname" are migrated from the final direct
- target up the chain of contiguous adjacent internal targets, using
- `ChainedTargetResolver`.
- """
+ Propagate empty internal targets to the next element.
- default_priority = 420
+ Given the following nodes::
- def apply(self):
- visitor = ChainedTargetResolver(self.document)
- self.document.walk(visitor)
+ <target ids="internal1" names="internal1">
+ <target anonymous="1" ids="id1">
+ <target ids="internal2" names="internal2">
+ <paragraph>
+ This is a test.
+ PropagateTargets propagates the ids and names of the internal
+ targets preceding the paragraph to the paragraph itself::
-class ChainedTargetResolver(nodes.SparseNodeVisitor):
-
+ <target refid="internal1">
+ <target anonymous="1" refid="id1">
+ <target refid="internal2">
+ <paragraph ids="internal2 id1 internal1" names="internal2 internal1">
+ This is a test.
"""
- Copy reference attributes up the length of a hyperlink target chain.
- "Chained targets" are multiple adjacent internal hyperlink targets which
- "point to" an external or indirect target. After the transform, all
- chained targets will effectively point to the same place.
+ default_priority = 260
- Given the following ``document`` as input::
+ def apply(self):
+ for target in self.document.internal_targets:
+ if not (len(target) == 0 and
+ not (target.attributes.has_key('refid') or
+ target.attributes.has_key('refuri') or
+ target.attributes.has_key('refname'))):
+ continue
+ next_node = target.next_node(ascend=1)
+ # Do not move names and ids into Invisibles (we'd lose the
+ # attributes) or different Targetables (e.g. footnotes).
+ if (next_node is not None and
+ ((not isinstance(next_node, nodes.Invisible) and
+ not isinstance(next_node, nodes.Targetable)) or
+ isinstance(next_node, nodes.target))):
+ next_node['ids'].extend(target['ids'])
+ next_node['names'].extend(target['names'])
+ # Set defaults for next_node.expect_referenced_by_name/id.
+ if not hasattr(next_node, 'expect_referenced_by_name'):
+ next_node.expect_referenced_by_name = {}
+ if not hasattr(next_node, 'expect_referenced_by_id'):
+ next_node.expect_referenced_by_id = {}
+ for id in target['ids']:
+ # Update IDs to node mapping.
+ self.document.ids[id] = next_node
+ # If next_node is referenced by id ``id``, this
+ # target shall be marked as referenced.
+ next_node.expect_referenced_by_id[id] = target
+ for name in target['names']:
+ next_node.expect_referenced_by_name[name] = target
+ # If there are any expect_referenced_by_... attributes
+ # in target set, copy them to next_node.
+ next_node.expect_referenced_by_name.update(
+ getattr(target, 'expect_referenced_by_name', {}))
+ next_node.expect_referenced_by_id.update(
+ getattr(target, 'expect_referenced_by_id', {}))
+ # Set refid to point to the first former ID of target
+ # which is now an ID of next_node.
+ target['refid'] = target['ids'][0]
+ # Clear ids and names; they have been moved to
+ # next_node.
+ target['ids'] = []
+ target['names'] = []
+ self.document.note_refid(target)
+ self.document.note_internal_target(next_node)
- <document>
- <target id="a" name="a">
- <target id="b" name="b">
- <target id="c" name="c" refuri="http://chained.external.targets">
- <target id="d" name="d">
- <paragraph>
- I'm known as "d".
- <target id="e" name="e">
- <target id="id1">
- <target id="f" name="f" refname="d">
- ``ChainedTargetResolver(document).walk()`` will transform the above into::
-
- <document>
- <target id="a" name="a" refuri="http://chained.external.targets">
- <target id="b" name="b" refuri="http://chained.external.targets">
- <target id="c" name="c" refuri="http://chained.external.targets">
- <target id="d" name="d">
- <paragraph>
- I'm known as "d".
- <target id="e" name="e" refname="d">
- <target id="id1" refname="d">
- <target id="f" name="f" refname="d">
- """
-
- def unknown_visit(self, node):
- pass
-
- def visit_target(self, node):
- if node.hasattr('refuri'):
- attname = 'refuri'
- call_if_named = self.document.note_external_target
- elif node.hasattr('refname'):
- attname = 'refname'
- call_if_named = self.document.note_indirect_target
- elif node.hasattr('refid'):
- attname = 'refid'
- call_if_named = None
- else:
- return
- attval = node[attname]
- index = node.parent.index(node)
- for i in range(index - 1, -1, -1):
- sibling = node.parent[i]
- if not isinstance(sibling, nodes.target) \
- or sibling.hasattr('refuri') \
- or sibling.hasattr('refname') \
- or sibling.hasattr('refid'):
- break
- sibling[attname] = attval
- if sibling.hasattr('name') and call_if_named:
- call_if_named(sibling)
-
-
class AnonymousHyperlinks(Transform):
"""
@@ -109,8 +97,8 @@
internal
<reference anonymous="1">
external
- <target anonymous="1" id="id1">
- <target anonymous="1" id="id2" refuri="http://external">
+ <target anonymous="1" ids="id1">
+ <target anonymous="1" ids="id2" refuri="http://external">
Corresponding references are linked via "refid" or resolved via "refuri"::
@@ -119,8 +107,8 @@
text
<reference anonymous="1" refuri="http://external">
external
- <target anonymous="1" id="id1">
- <target anonymous="1" id="id2" refuri="http://external">
+ <target anonymous="1" ids="id1">
+ <target anonymous="1" ids="id2" refuri="http://external">
"""
default_priority = 440
@@ -140,16 +128,28 @@
prbid = self.document.set_id(prb)
msg.add_backref(prbid)
ref.parent.replace(ref, prb)
+ for target in self.document.anonymous_targets:
+ # Assume that all anonymous targets have been
+ # referenced to avoid generating lots of
+ # system_messages.
+ target.referenced = 1
return
for ref, target in zip(self.document.anonymous_refs,
self.document.anonymous_targets):
- if target.hasattr('refuri'):
- ref['refuri'] = target['refuri']
- ref.resolved = 1
- else:
- ref['refid'] = target['id']
- self.document.note_refid(ref)
target.referenced = 1
+ while 1:
+ if target.hasattr('refuri'):
+ ref['refuri'] = target['refuri']
+ ref.resolved = 1
+ break
+ else:
+ if not target['ids']:
+ # Propagated target.
+ target = self.document.ids[target['refid']]
+ continue
+ ref['refid'] = target['ids'][0]
+ self.document.note_refid(ref)
+ break
class IndirectHyperlinks(Transform):
@@ -213,20 +213,24 @@
self.resolve_indirect_references(target)
def resolve_indirect_target(self, target):
- refname = target['refname']
- reftarget_id = self.document.nameids.get(refname)
- if not reftarget_id:
- # Check the unknown_reference_resolvers
- for resolver_function in (self.document.transformer
- .unknown_reference_resolvers):
- if resolver_function(target):
- break
- else:
- self.nonexistent_indirect_target(target)
- return
+ refname = target.get('refname')
+ if refname is None:
+ reftarget_id = target['refid']
+ else:
+ reftarget_id = self.document.nameids.get(refname)
+ if not reftarget_id:
+ # Check the unknown_reference_resolvers
+ for resolver_function in \
+ self.document.transformer.unknown_reference_resolvers:
+ if resolver_function(target):
+ break
+ else:
+ self.nonexistent_indirect_target(target)
+ return
reftarget = self.document.ids[reftarget_id]
+ reftarget.note_referenced_by(id=reftarget_id)
if isinstance(reftarget, nodes.target) \
- and not reftarget.resolved and reftarget.hasattr('refname'):
+ and not reftarget.resolved and reftarget.hasattr('refname'):
if hasattr(target, 'multiply_indirect'):
#and target.multiply_indirect):
#del target.multiply_indirect
@@ -237,21 +241,23 @@
del target.multiply_indirect
if reftarget.hasattr('refuri'):
target['refuri'] = reftarget['refuri']
- if target.hasattr('name'):
+ if target['names']:
self.document.note_external_target(target)
+ if target.has_key('refid'):
+ del target['refid']
elif reftarget.hasattr('refid'):
target['refid'] = reftarget['refid']
self.document.note_refid(target)
else:
- try:
- target['refid'] = reftarget['id']
+ if reftarget['ids']:
+ target['refid'] = reftarget_id
self.document.note_refid(target)
- except KeyError:
+ else:
self.nonexistent_indirect_target(target)
return
- del target['refname']
+ if refname is not None:
+ del target['refname']
target.resolved = 1
- reftarget.referenced = 1
def nonexistent_indirect_target(self, target):
if self.document.nameids.has_key(target['refname']):
@@ -265,18 +271,19 @@
def indirect_target_error(self, target, explanation):
naming = ''
- if target.hasattr('name'):
- naming = '"%s" ' % target['name']
- reflist = self.document.refnames.get(target['name'], [])
- else:
- reflist = self.document.refids.get(target['id'], [])
- naming += '(id="%s")' % target['id']
+ reflist = []
+ if target['names']:
+ naming = '"%s" ' % target['names'][0]
+ for name in target['names']:
+ reflist.extend(self.document.refnames.get(name, []))
+ for id in target['ids']:
+ reflist.extend(self.document.refids.get(id, []))
+ naming += '(id="%s")' % target['ids'][0]
msg = self.document.reporter.error(
'Indirect hyperlink target %s refers to target "%s", %s.'
- % (naming, target['refname'], explanation),
- base_node=target)
+ % (naming, target['refname'], explanation), base_node=target)
msgid = self.document.set_id(msg)
- for ref in reflist:
+ for ref in uniq(reflist):
prb = nodes.problematic(
ref.rawsource, ref.rawsource, refid=msgid)
prbid = self.document.set_id(prb)
@@ -296,43 +303,34 @@
else:
return
attval = target[attname]
- if target.hasattr('name'):
- name = target['name']
- try:
- reflist = self.document.refnames[name]
- except KeyError, instance:
- if target.referenced:
- return
- msg = self.document.reporter.info(
- 'Indirect hyperlink target "%s" is not referenced.'
- % name, base_node=target)
- target.referenced = 1
- return
- delatt = 'refname'
- else:
- id = target['id']
- try:
- reflist = self.document.refids[id]
- except KeyError, instance:
- if target.referenced:
- return
- msg = self.document.reporter.info(
- 'Indirect hyperlink target id="%s" is not referenced.'
- % id, base_node=target)
- target.referenced = 1
- return
- delatt = 'refid'
- for ref in reflist:
- if ref.resolved:
- continue
- del ref[delatt]
- ref[attname] = attval
- if not call_if_named or ref.hasattr('name'):
- call_method(ref)
- ref.resolved = 1
- if isinstance(ref, nodes.target):
- self.resolve_indirect_references(ref)
- target.referenced = 1
+ for name in target['names']:
+ reflist = self.document.refnames.get(name, [])
+ if reflist:
+ target.note_referenced_by(name=name)
+ for ref in reflist:
+ if ref.resolved:
+ continue
+ del ref['refname']
+ ref[attname] = attval
+ if not call_if_named or ref['names']:
+ call_method(ref)
+ ref.resolved = 1
+ if isinstance(ref, nodes.target):
+ self.resolve_indirect_references(ref)
+ for id in target['ids']:
+ reflist = self.document.refids.get(id, [])
+ if reflist:
+ target.note_referenced_by(id=id)
+ for ref in reflist:
+ if ref.resolved:
+ continue
+ del ref['refid']
+ ref[attname] = attval
+ if not call_if_named or ref['names']:
+ call_method(ref)
+ ref.resolved = 1
+ if isinstance(ref, nodes.target):
+ self.resolve_indirect_references(ref)
class ExternalTargets(Transform):
@@ -357,74 +355,59 @@
def apply(self):
for target in self.document.external_targets:
- if target.hasattr('refuri') and target.hasattr('name'):
- name = target['name']
+ if target.hasattr('refuri'):
refuri = target['refuri']
- try:
- reflist = self.document.refnames[name]
- except KeyError, instance:
- # @@@ First clause correct???
- if not isinstance(target, nodes.target) or target.referenced:
- continue
- msg = self.document.reporter.info(
- 'External hyperlink target "%s" is not referenced.'
- % name, base_node=target)
- target.referenced = 1
- continue
- for ref in reflist:
- if ref.resolved:
- continue
- del ref['refname']
- ref['refuri'] = refuri
- ref.resolved = 1
- target.referenced = 1
+ for name in target['names']:
+ reflist = self.document.refnames.get(name, [])
+ if reflist:
+ target.note_referenced_by(name=name)
+ for ref in reflist:
+ if ref.resolved:
+ continue
+ del ref['refname']
+ ref['refuri'] = refuri
+ ref.resolved = 1
class InternalTargets(Transform):
- """
- Given::
+ default_priority = 660
- <paragraph>
- <reference refname="direct internal">
- direct internal
- <target id="id1" name="direct internal">
+ def apply(self):
+ for target in self.document.internal_targets:
+ self.resolve_reference_ids(target)
- The "refname" attribute is replaced by "refid" linking to the target's
- "id"::
+ def resolve_reference_ids(self, target):
+ """
+ Given::
- <paragraph>
- <reference refid="id1">
- direct internal
- <target id="id1" name="direct internal">
- """
+ <paragraph>
+ <reference refname="direct internal">
+ direct internal
+ <target id="id1" name="direct internal">
- default_priority = 660
+ The "refname" attribute is replaced by "refid" linking to the target's
+ "id"::
- def apply(self):
- for target in self.document.internal_targets:
- if target.hasattr('refuri') or target.hasattr('refid') \
- or not target.hasattr('name'):
- continue
- name = target['name']
- refid = target['id']
- try:
- reflist = self.document.refnames[name]
- except KeyError, instance:
- if target.referenced:
- continue
- msg = self.document.reporter.info(
- 'Internal hyperlink target "%s" is not referenced.'
- % name, base_node=target)
- target.referenced = 1
- continue
+ <paragraph>
+ <reference refid="id1">
+ direct internal
+ <target id="id1" name="direct internal">
+ """
+ if target.hasattr('refuri') or target.hasattr('refid') \
+ or not target['names']:
+ return
+ for name in target['names']:
+ refid = self.document.nameids[name]
+ reflist = self.document.refnames.get(name, [])
+ if reflist:
+ target.note_referenced_by(name=name)
for ref in reflist:
if ref.resolved:
continue
del ref['refname']
ref['refid'] = refid
ref.resolved = 1
- target.referenced = 1
class Footnotes(Transform):
@@ -532,19 +515,17 @@
if not self.document.nameids.has_key(label):
break
footnote.insert(0, nodes.label('', label))
- if footnote.hasattr('dupname'):
- continue
- if footnote.hasattr('name'):
- name = footnote['name']
+ for name in footnote['names']:
for ref in self.document.footnote_refs.get(name, []):
ref += nodes.Text(label)
ref.delattr('refname')
- ref['refid'] = footnote['id']
- footnote.add_backref(ref['id'])
+ assert len(footnote['ids']) == len(ref['ids']) == 1
+ ref['refid'] = footnote['ids'][0]
+ footnote.add_backref(ref['ids'][0])
self.document.note_refid(ref)
ref.resolved = 1
- else:
- footnote['name'] = label
+ if not footnote['names'] and not footnote['dupnames']:
+ footnote['names'].append(label)
self.document.note_explicit_target(footnote, footnote)
self.autofootnote_labels.append(label)
return startnum
@@ -577,7 +558,8 @@
footnote = self.document.ids[id]
ref['refid'] = id
self.document.note_refid(ref)
- footnote.add_backref(ref['id'])
+ assert len(ref['ids']) == 1
+ footnote.add_backref(ref['ids'][0])
ref.resolved = 1
i += 1
@@ -612,9 +594,10 @@
ref.parent.replace(ref, prb)
break
footnote = self.document.symbol_footnotes[i]
- ref['refid'] = footnote['id']
+ assert len(footnote['ids']) == 1
+ ref['refid'] = footnote['ids'][0]
self.document.note_refid(ref)
- footnote.add_backref(ref['id'])
+ footnote.add_backref(ref['ids'][0])
i += 1
def resolve_footnotes_and_citations(self):
@@ -623,24 +606,26 @@
references.
"""
for footnote in self.document.footnotes:
- label = footnote['name']
- if self.document.footnote_refs.has_key(label):
- reflist = self.document.footnote_refs[label]
- self.resolve_references(footnote, reflist)
+ for label in footnote['names']:
+ if self.document.footnote_refs.has_key(label):
+ reflist = self.document.footnote_refs[label]
+ self.resolve_references(footnote, reflist)
for citation in self.document.citations:
- label = citation['name']
- if self.document.citation_refs.has_key(label):
- reflist = self.document.citation_refs[label]
- self.resolve_references(citation, reflist)
+ for label in citation['names']:
+ if self.document.citation_refs.has_key(label):
+ reflist = self.document.citation_refs[label]
+ self.resolve_references(citation, reflist)
def resolve_references(self, note, reflist):
- id = note['id']
+ assert len(note['ids']) == 1
+ id = note['ids'][0]
for ref in reflist:
if ref.resolved:
continue
ref.delattr('refname')
ref['refid'] = id
- note.add_backref(ref['id'])
+ assert len(ref['ids']) == 1
+ note.add_backref(ref['ids'][0])
ref.resolved = 1
note.resolved = 1
@@ -680,7 +665,9 @@
def apply(self):
defs = self.document.substitution_defs
normed = self.document.substitution_names
- for refname, refs in self.document.substitution_refs.items():
+ subreflist = self.document.substitution_refs.items()
+ subreflist.sort()
+ for refname, refs in subreflist:
for ref in refs:
key = None
if defs.has_key(refname):
@@ -715,7 +702,7 @@
and isinstance(parent[index + 1], nodes.Text)):
parent.replace(parent[index + 1],
parent[index + 1].lstrip())
- parent.replace(ref, subdef.get_children())
+ parent.replace(ref, subdef.children)
self.document.substitution_refs = None # release replaced references
@@ -734,11 +721,12 @@
notes = {}
nodelist = []
for target in self.document.external_targets:
- name = target.get('name')
- if not name:
- print >>sys.stderr, 'no name on target: %r' % target
- continue
- refs = self.document.refnames.get(name, [])
+ names = target['names']
+ # Only named targets.
+ assert names
+ refs = []
+ for name in names:
+ refs.extend(self.document.refnames.get(name, []))
if not refs:
continue
footnote = self.make_target_footnote(target, refs, notes)
@@ -760,14 +748,16 @@
refuri = target['refuri']
if notes.has_key(refuri): # duplicate?
footnote = notes[refuri]
- footnote_name = footnote['name']
+ assert len(footnote['names']) == 1
+ footnote_name = footnote['names'][0]
else: # original
footnote = nodes.footnote()
footnote_id = self.document.set_id(footnote)
- # Use a colon; they can't be produced inside names by the parser:
- footnote_name = 'target_note: ' + footnote_id
+ # Use uppercase letters and a colon; they can't be
+ # produced inside names by the parser.
+ footnote_name = 'TARGET_NOTE: ' + footnote_id
footnote['auto'] = 1
- footnote['name'] = footnote_name
+ footnote['names'] = [footnote_name]
footnote_paragraph = nodes.paragraph()
footnote_paragraph += nodes.reference('', refuri, refuri=refuri)
footnote += footnote_paragraph
@@ -786,3 +776,11 @@
reflist.insert(0, nodes.Text(' '))
ref.parent.insert(index, reflist)
return footnote
+
+
+def uniq(L):
+ r = []
+ for item in L:
+ if not item in r:
+ r.append(item)
+ return r
Modified: Zope/trunk/lib/python/docutils/transforms/universal.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/universal.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/transforms/universal.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger, Ueli Schlaepfer
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 3186 $
+# Date: $Date: 2005-04-07 21:51:45 +0200 (Thu, 07 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -32,19 +32,16 @@
default_priority = 820
def apply(self):
- header = self.generate_header()
- footer = self.generate_footer()
- if header or footer:
- decoration = nodes.decoration()
- decoration += header
- decoration += footer
- document = self.document
- index = document.first_child_not_matching_class(
- nodes.PreDecorative)
- if index is None:
- document += decoration
- else:
- document[index:index] = [decoration]
+ header_nodes = self.generate_header()
+ if header_nodes:
+ decoration = self.document.get_decoration()
+ header = decoration.get_header()
+ header.extend(header_nodes)
+ footer_nodes = self.generate_footer()
+ if footer_nodes:
+ decoration = self.document.get_decoration()
+ footer = decoration.get_footer()
+ footer.extend(footer_nodes)
def generate_header(self):
return None
@@ -79,9 +76,7 @@
nodes.reference('', 'reStructuredText', refuri='http://'
'docutils.sourceforge.net/rst.html'),
nodes.Text(' source.\n')])
- footer = nodes.footer()
- footer += nodes.paragraph('', '', *text)
- return footer
+ return [nodes.paragraph('', '', *text)]
else:
return None
@@ -97,13 +92,13 @@
def apply(self):
unfiltered = self.document.transform_messages
- threshold = self.document.reporter['writer'].report_level
+ threshold = self.document.reporter.report_level
messages = []
for msg in unfiltered:
if msg['level'] >= threshold and not msg.parent:
messages.append(msg)
if messages:
- section = nodes.section(CLASS='system-messages')
+ section = nodes.section(classes=['system-messages'])
# @@@ get this from the language module?
section += nodes.title('', 'Docutils System Messages')
section += messages
@@ -130,7 +125,7 @@
pass
def visit_system_message(self, node):
- if node['level'] < self.document.reporter['writer'].report_level:
+ if node['level'] < self.document.reporter.report_level:
node.parent.remove(node)
@@ -167,6 +162,21 @@
if self.document.settings.expose_internals:
visitor = InternalAttributeExposer(self.document)
self.document.walk(visitor)
+ # *After* resolving all references, check for unreferenced
+ # targets:
+ for target in self.document.traverse():
+ if isinstance(target, nodes.target) and not target.referenced:
+ if target['names']:
+ naming = target['names'][0]
+ elif target['ids']:
+ naming = target['ids'][0]
+ else:
+ # Hack: Propagated targets always have their refid
+ # attribute set.
+ naming = target['refid']
+ self.document.reporter.info(
+ 'Hyperlink target "%s" is not referenced.'
+ % naming, base_node=target)
class FinalCheckVisitor(nodes.SparseNodeVisitor):
@@ -206,7 +216,7 @@
else:
del node['refname']
node['refid'] = id
- self.document.ids[id].referenced = 1
+ self.document.ids[id].note_referenced_by(id=id)
node.resolved = 1
visit_footnote_reference = visit_citation_reference = visit_reference
Modified: Zope/trunk/lib/python/docutils/utils.py
===================================================================
--- Zope/trunk/lib/python/docutils/utils.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/utils.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:02 $
+# Revision: $Revision: 3253 $
+# Date: $Date: 2005-04-25 17:08:01 +0200 (Mon, 25 Apr 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -13,6 +13,7 @@
import sys
import os
import os.path
+import warnings
from types import StringType, UnicodeType
from docutils import ApplicationError, DataError
from docutils import frontend, nodes
@@ -39,37 +40,21 @@
There is typically one Reporter object per process. A Reporter object is
instantiated with thresholds for reporting (generating warnings) and
halting processing (raising exceptions), a switch to turn debug output on
- or off, and an I/O stream for warnings. These are stored in the default
- reporting category, '' (zero-length string).
+ or off, and an I/O stream for warnings. These are stored as instance
+ attributes.
- Multiple reporting categories [#]_ may be set, each with its own reporting
- and halting thresholds, debugging switch, and warning stream
- (collectively a `ConditionSet`). Categories are hierarchical dotted-name
- strings that look like attribute references: 'spam', 'spam.eggs',
- 'neeeow.wum.ping'. The 'spam' category is the ancestor of
- 'spam.bacon.eggs'. Unset categories inherit stored conditions from their
- closest ancestor category that has been set.
+ When a system message is generated, its level is compared to the stored
+ thresholds, and a warning or error is generated as appropriate. Debug
+ messages are produced iff the stored debug switch is on, independently of
+ other thresholds. Message output is sent to the stored warning stream if
+ not set to ''.
- When a system message is generated, the stored conditions from its
- category (or ancestor if unset) are retrieved. The system message level
- is compared to the thresholds stored in the category, and a warning or
- error is generated as appropriate. Debug messages are produced iff the
- stored debug switch is on. Message output is sent to the stored warning
- stream if not set to ''.
-
- The default category is '' (empty string). By convention, Writers should
- retrieve reporting conditions from the 'writer' category (which, unless
- explicitly set, defaults to the conditions of the default category).
-
The Reporter class also employs a modified form of the "Observer" pattern
[GoF95]_ to track system messages generated. The `attach_observer` method
should be called before parsing, with a bound method or function which
accepts system messages. The observer can be removed with
`detach_observer`, and another added in its place.
- .. [#] The concept of "categories" was inspired by the log4j project:
- http://jakarta.apache.org/log4j/.
-
.. [GoF95] Gamma, Helm, Johnson, Vlissides. *Design Patterns: Elements of
Reusable Object-Oriented Software*. Addison-Wesley, Reading, MA, USA,
1995.
@@ -81,10 +66,7 @@
def __init__(self, source, report_level, halt_level, stream=None,
debug=0, encoding='ascii', error_handler='replace'):
"""
- Initialize the `ConditionSet` forthe `Reporter`'s default category.
-
:Parameters:
-
- `source`: The path to or description of the source data.
- `report_level`: The level at or above which warning output will
be sent to `stream`.
@@ -101,6 +83,23 @@
self.source = source
"""The path to or description of the source data."""
+ self.encoding = encoding
+ """The character encoding for the stderr output."""
+
+ self.error_handler = error_handler
+ """The character encoding error handler."""
+
+ self.debug_flag = debug
+ """Show debug (level=0) system messages?"""
+
+ self.report_level = report_level
+ """The level at or above which warning output will be sent
+ to `self.stream`."""
+
+ self.halt_level = halt_level
+ """The level at or above which `SystemMessage` exceptions
+ will be raised, halting execution."""
+
if stream is None:
stream = sys.stderr
elif type(stream) in (StringType, UnicodeType):
@@ -111,16 +110,9 @@
elif type(stream) == UnicodeType:
stream = open(stream.encode(), 'w')
- self.encoding = encoding
- """The character encoding for the stderr output."""
+ self.stream = stream
+ """Where warning output is sent."""
- self.error_handler = error_handler
- """The character encoding error handler."""
-
- self.categories = {'': ConditionSet(debug, report_level, halt_level,
- stream)}
- """Mapping of category names to conditions. Default category is ''."""
-
self.observers = []
"""List of bound methods or functions to call with each system_message
created."""
@@ -130,24 +122,16 @@
def set_conditions(self, category, report_level, halt_level,
stream=None, debug=0):
+ warnings.warn('docutils.utils.Reporter.set_conditions deprecated; '
+ 'set attributes via configuration settings or directly',
+ DeprecationWarning, stacklevel=2)
+ self.report_level = report_level
+ self.halt_level = halt_level
if stream is None:
stream = sys.stderr
- self.categories[category] = ConditionSet(debug, report_level,
- halt_level, stream)
+ self.stream = stream
+ self.debug = debug
- def unset_conditions(self, category):
- if category and self.categories.has_key(category):
- del self.categories[category]
-
- __delitem__ = unset_conditions
-
- def get_conditions(self, category):
- while not self.categories.has_key(category):
- category = category[:category.rfind('.') + 1][:-1]
- return self.categories[category]
-
- __getitem__ = get_conditions
-
def attach_observer(self, observer):
"""
The `observer` parameter is a function or bound method which takes one
@@ -169,9 +153,6 @@
Raise an exception or generate a warning if appropriate.
"""
attributes = kwargs.copy()
- category = kwargs.get('category', '')
- if kwargs.has_key('category'):
- del attributes['category']
if kwargs.has_key('base_node'):
source, line = get_source_line(kwargs['base_node'])
del attributes['base_node']
@@ -183,16 +164,13 @@
msg = nodes.system_message(message, level=level,
type=self.levels[level],
*children, **attributes)
- debug, report_level, halt_level, stream = self[category].astuple()
- if (level >= report_level or debug and level == 0) and stream:
+ if self.stream and (level >= self.report_level
+ or self.debug_flag and level == 0):
msgtext = msg.astext().encode(self.encoding, self.error_handler)
- if category:
- print >>stream, msgtext, '[%s]' % category
- else:
- print >>stream, msgtext
- if level >= halt_level:
+ print >>self.stream, msgtext
+ if level >= self.halt_level:
raise SystemMessage(msg, level)
- if level > 0 or debug:
+ if level > 0 or self.debug_flag:
self.notify_observers(msg)
self.max_level = max(level, self.max_level)
return msg
@@ -203,7 +181,8 @@
effect on the processing. Level-0 system messages are handled
separately from the others.
"""
- return self.system_message(0, *args, **kwargs)
+ if self.debug_flag:
+ return self.system_message(0, *args, **kwargs)
def info(self, *args, **kwargs):
"""
@@ -235,25 +214,6 @@
return self.system_message(4, *args, **kwargs)
-class ConditionSet:
-
- """
- A set of two thresholds (`report_level` & `halt_level`), a switch
- (`debug`), and an I/O stream (`stream`), corresponding to one `Reporter`
- category.
- """
-
- def __init__(self, debug, report_level, halt_level, stream):
- self.debug = debug
- self.report_level = report_level
- self.halt_level = halt_level
- self.stream = stream
-
- def astuple(self):
- return (self.debug, self.report_level, self.halt_level,
- self.stream)
-
-
class ExtensionOptionError(DataError): pass
class BadOptionError(ExtensionOptionError): pass
class BadOptionDataError(ExtensionOptionError): pass
@@ -346,7 +306,7 @@
options[name] = convertor(value)
except (ValueError, TypeError), detail:
raise detail.__class__('(option: "%s"; value: %r)\n%s'
- % (name, value, detail))
+ % (name, value, ' '.join(detail.args)))
return options
Modified: Zope/trunk/lib/python/docutils/writers/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/__init__.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/writers/__init__.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 2321 $
+# Date: $Date: 2004-06-20 14:28:08 +0200 (Sun, 20 Jun 2004) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/writers/docutils_xml.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/docutils_xml.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/writers/docutils_xml.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 2223 $
+# Date: $Date: 2004-06-05 21:32:15 +0200 (Sat, 05 Jun 2004) $
# Copyright: This module has been placed in the public domain.
"""
Modified: Zope/trunk/lib/python/docutils/writers/html4css1.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/html4css1.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/writers/html4css1.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.7 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 3367 $
+# Date: $Date: 2005-05-26 02:44:13 +0200 (Thu, 26 May 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -63,6 +63,20 @@
['--initial-header-level'],
{'choices': '1 2 3 4 5 6'.split(), 'default': '1',
'metavar': '<level>'}),
+ ('Specify the maximum width (in characters) for one-column field '
+ 'names. Longer field names will span an entire row of the table '
+ 'used to render the field list. Default is 14 characters. '
+ 'Use 0 for "no limit".',
+ ['--field-name-limit'],
+ {'default': 14, 'metavar': '<level>',
+ 'validator': frontend.validate_nonnegative_int}),
+ ('Specify the maximum width (in characters) for options in option '
+ 'lists. Longer options will span an entire row of the table used '
+ 'to render the option list. Default is 14 characters. '
+ 'Use 0 for "no limit".',
+ ['--option-limit'],
+ {'default': 14, 'metavar': '<level>',
+ 'validator': frontend.validate_nonnegative_int}),
('Format for footnote references: one of "superscript" or '
'"brackets". Default is "brackets".',
['--footnote-references'],
@@ -87,7 +101,12 @@
('Omit the XML declaration. Use with caution.',
['--no-xml-declaration'],
{'dest': 'xml_declaration', 'default': 1, 'action': 'store_false',
- 'validator': frontend.validate_boolean}),))
+ 'validator': frontend.validate_boolean}),
+ ('Scramble email addresses to confuse harvesters. '
+ 'For example, "abc at example.org" will become '
+ '``<a href="mailto:%61%62%63%40...">abc at example dot org</a>``.',
+ ['--cloak-email-addresses'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),))
relative_path_settings = ('stylesheet_path',)
@@ -99,10 +118,9 @@
self.translator_class = HTMLTranslator
def translate(self):
- visitor = self.translator_class(self.document)
+ self.visitor = visitor = self.translator_class(self.document)
self.document.walkabout(visitor)
self.output = visitor.astext()
- self.visitor = visitor
for attr in ('head_prefix', 'stylesheet', 'head', 'body_prefix',
'body_pre_docinfo', 'docinfo', 'body', 'fragment',
'body_suffix'):
@@ -111,7 +129,9 @@
def assemble_parts(self):
writers.Writer.assemble_parts(self)
for part in ('title', 'subtitle', 'docinfo', 'body', 'header',
- 'footer', 'meta', 'stylesheet', 'fragment'):
+ 'footer', 'meta', 'stylesheet', 'fragment',
+ 'html_prolog', 'html_head', 'html_title', 'html_subtitle',
+ 'html_body'):
self.parts[part] = ''.join(getattr(self.visitor, part))
@@ -163,16 +183,15 @@
' PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
' "http://www.w3.org/TR/xhtml1/DTD/'
'xhtml1-transitional.dtd">\n')
- html_head = ('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="%s" '
- 'lang="%s">\n<head>\n')
- content_type = ('<meta http-equiv="Content-Type" content="text/html; '
- 'charset=%s" />\n')
+ head_prefix_template = ('<html xmlns="http://www.w3.org/1999/xhtml"'
+ ' xml:lang="%s" lang="%s">\n<head>\n')
+ content_type = ('<meta http-equiv="Content-Type"'
+ ' content="text/html; charset=%s" />\n')
generator = ('<meta name="generator" content="Docutils %s: '
'http://docutils.sourceforge.net/" />\n')
stylesheet_link = '<link rel="stylesheet" href="%s" type="text/css" />\n'
embedded_stylesheet = '<style type="text/css">\n\n%s\n</style>\n'
- named_tags = {'a': 1, 'applet': 1, 'form': 1, 'frame': 1, 'iframe': 1,
- 'img': 1, 'map': 1}
+ named_tags = ['a', 'applet', 'form', 'frame', 'iframe', 'img', 'map']
words_and_spaces = re.compile(r'\S+| +|\n')
def __init__(self, document):
@@ -182,14 +201,17 @@
self.language = languages.get_language(lcode)
self.meta = [self.content_type % settings.output_encoding,
self.generator % docutils.__version__]
- self.head_prefix = [
- self.doctype,
- self.html_head % (lcode, lcode)]
- self.head_prefix.extend(self.meta)
+ self.head_prefix = []
+ self.html_prolog = []
if settings.xml_declaration:
- self.head_prefix.insert(0, self.xml_declaration
+ self.head_prefix.append(self.xml_declaration
% settings.output_encoding)
- self.head = []
+ # encoding not interpolated:
+ self.html_prolog.append(self.xml_declaration)
+ self.head_prefix.extend([self.doctype,
+ self.head_prefix_template % (lcode, lcode)])
+ self.html_prolog.append(self.doctype)
+ self.head = self.meta[:]
if settings.embed_stylesheet:
stylesheet = utils.get_stylesheet_reference(settings,
os.path.join(os.getcwd(), 'dummy'))
@@ -199,7 +221,8 @@
else:
stylesheet = utils.get_stylesheet_reference(settings)
if stylesheet:
- self.stylesheet = [self.stylesheet_link % stylesheet]
+ self.stylesheet = [self.stylesheet_link
+ % self.encode(stylesheet)]
else:
self.stylesheet = []
self.body_prefix = ['</head>\n<body>\n']
@@ -215,7 +238,7 @@
# A heterogenous stack used in conjunction with the tree traversal.
# Make sure that the pops correspond to the pushes:
self.context = []
- self.topic_class = ''
+ self.topic_classes = []
self.colspecs = []
self.compact_p = 1
self.compact_simple = None
@@ -225,7 +248,12 @@
self.subtitle = []
self.header = []
self.footer = []
+ self.html_head = [self.content_type] # charset not interpolated
+ self.html_title = []
+ self.html_subtitle = []
+ self.html_body = []
self.in_document_title = 0
+ self.in_mailto = 0
def astext(self):
return ''.join(self.head_prefix + self.head
@@ -245,6 +273,20 @@
text = text.replace(u'\u00a0', " ")
return text
+ def cloak_mailto(self, uri):
+ """Try to hide a mailto: URL from harvesters."""
+ addr = uri.split(':', 1)[1]
+ if '?' in addr:
+ addr, query = addr.split('?', 1)
+ query = '?' + query
+ else:
+ query = ''
+ escaped = ['%%%02X' % ord(c) for c in addr]
+ return 'mailto:%s%s' % (''.join(escaped), query)
+
+ def cloak_email(self, addr):
+ return addr.replace('@', ' at ').replace('.', ' dot ')
+
def attval(self, text,
whitespace=re.compile('[\n\r\t\v\f]')):
"""Cleanse, HTML encode, and return attribute value text."""
@@ -256,17 +298,21 @@
are extracted), tag name, and optional attributes.
"""
tagname = tagname.lower()
+ prefix = []
atts = {}
for (name, value) in attributes.items():
atts[name.lower()] = value
- for att in ('class',): # append to node attribute
- if node.has_key(att) or atts.has_key(att):
- atts[att] = \
- (node.get(att, '') + ' ' + atts.get(att, '')).strip()
- for att in ('id',): # node attribute overrides
- if node.has_key(att):
- atts[att] = node[att]
- if atts.has_key('id') and self.named_tags.has_key(tagname):
+ classes = node.get('classes', [])
+ if atts.has_key('class'):
+ classes.append(atts['class'])
+ if classes:
+ atts['class'] = ' '.join(classes)
+ assert not atts.has_key('id')
+ if node.get('ids'):
+ atts['id'] = node['ids'][0]
+ for id in node['ids'][1:]:
+ prefix.append('<span id="%s"></span>' % id)
+ if atts.has_key('id') and tagname in self.named_tags:
atts['name'] = atts['id'] # for compatibility with old browsers
attlist = atts.items()
attlist.sort()
@@ -285,19 +331,23 @@
except TypeError: # for Python 2.1 compatibility:
uval = unicode(str(value))
parts.append('%s="%s"' % (name.lower(), self.attval(uval)))
- return '<%s%s>%s' % (' '.join(parts), infix, suffix)
+ return ''.join(prefix) + '<%s%s>' % (' '.join(parts), infix) + suffix
def emptytag(self, node, tagname, suffix='\n', **attributes):
"""Construct and return an XML-compatible empty tag."""
return self.starttag(node, tagname, suffix, infix=' /', **attributes)
def set_first_last(self, node):
- if len(node):
- node[0].set_class('first')
- node[-1].set_class('last')
+ children = [n for n in node if not isinstance(n, nodes.Invisible)]
+ if children:
+ children[0]['classes'].append('first')
+ children[-1]['classes'].append('last')
def visit_Text(self, node):
- self.body.append(self.encode(node.astext()))
+ text = node.astext()
+ if self.in_mailto and self.settings.cloak_email_addresses:
+ text = self.cloak_email(text)
+ self.body.append(self.encode(text))
def depart_Text(self, node):
pass
@@ -389,7 +439,7 @@
self.compact_p = None
self.compact_simple = (self.settings.compact_lists and
(self.compact_simple
- or self.topic_class == 'contents'
+ or self.topic_classes == ['contents']
or self.check_simple_list(node)))
if self.compact_simple and not old_compact_simple:
atts['class'] = 'simple'
@@ -425,14 +475,9 @@
'</tbody>\n</table>\n')
def visit_citation_reference(self, node):
- href = ''
- if node.has_key('refid'):
- href = '#' + node['refid']
- elif node.has_key('refname'):
- href = '#' + self.document.nameids[node['refname']]
- self.body.append(self.starttag(node, 'a', '[',
- CLASS='citation-reference',
- **(href and {'href': href} or {})))
+ href = '#' + node['refid']
+ self.body.append(self.starttag(
+ node, 'a', '[', CLASS='citation-reference', href=href))
def depart_citation_reference(self, node):
self.body.append(']</a>')
@@ -446,6 +491,8 @@
def visit_colspec(self, node):
self.colspecs.append(node)
+ # "stubs" list is an attribute of the tgroup element:
+ node.parent.stubs.append(node.attributes.get('stub'))
def depart_colspec(self, node):
pass
@@ -470,10 +517,10 @@
def visit_compound(self, node):
self.body.append(self.starttag(node, 'div', CLASS='compound'))
if len(node) > 1:
- node[0].set_class('compound-first')
- node[-1].set_class('compound-last')
+ node[0]['classes'].append('compound-first')
+ node[-1]['classes'].append('compound-last')
for child in node[1:-1]:
- child.set_class('compound-middle')
+ child['classes'].append('compound-middle')
def depart_compound(self, node):
self.body.append('</div>\n')
@@ -562,9 +609,9 @@
% self.language.labels[name])
if len(node):
if isinstance(node[0], nodes.Element):
- node[0].set_class('first')
+ node[0]['classes'].append('first')
if isinstance(node[-1], nodes.Element):
- node[-1].set_class('last')
+ node[-1]['classes'].append('last')
def depart_docinfo_item(self):
self.body.append('</td></tr>\n')
@@ -579,12 +626,17 @@
# empty or untitled document?
if not len(node) or not isinstance(node[0], nodes.title):
# for XHTML conformance, modulo IE6 appeasement:
- self.head.insert(0, '<title></title>\n')
+ self.head.append('<title></title>\n')
def depart_document(self, node):
self.fragment.extend(self.body)
self.body_prefix.append(self.starttag(node, 'div', CLASS='document'))
self.body_suffix.insert(0, '</div>\n')
+ # skip content-type meta tag with interpolated charset value:
+ self.html_head.extend(self.head[1:])
+ self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo
+ + self.docinfo + self.body
+ + self.body_suffix[:-1])
def visit_emphasis(self, node):
self.body.append('<em>')
@@ -593,15 +645,24 @@
self.body.append('</em>')
def visit_entry(self, node):
+ atts = {'class': []}
if isinstance(node.parent.parent, nodes.thead):
+ atts['class'].append('head')
+ if node.parent.parent.parent.stubs[node.parent.column]:
+ # "stubs" list is an attribute of the tgroup element
+ atts['class'].append('stub')
+ if atts['class']:
tagname = 'th'
+ atts['class'] = ' '.join(atts['class'])
else:
tagname = 'td'
- atts = {}
+ del atts['class']
+ node.parent.column += 1
if node.has_key('morerows'):
atts['rowspan'] = node['morerows'] + 1
if node.has_key('morecols'):
atts['colspan'] = node['morecols'] + 1
+ node.parent.column += node['morecols']
self.body.append(self.starttag(node, tagname, '', **atts))
self.context.append('</%s>\n' % tagname.lower())
if len(node) == 0: # empty cell
@@ -629,7 +690,7 @@
self.compact_p = None
self.compact_simple = (self.settings.compact_lists and
(self.compact_simple
- or self.topic_class == 'contents'
+ or self.topic_classes == ['contents']
or self.check_simple_list(node)))
if self.compact_simple and not old_compact_simple:
atts['class'] = (atts.get('class', '') + ' simple').strip()
@@ -675,7 +736,8 @@
atts['class'] = 'docinfo-name'
else:
atts['class'] = 'field-name'
- if len(node.astext()) > 14:
+ if ( self.settings.field_name_limit
+ and len(node.astext()) > self.settings.field_name_limit):
atts['colspan'] = 2
self.context.append('</tr>\n<tr><td> </td>')
else:
@@ -690,6 +752,8 @@
atts = {'class': 'figure'}
if node.get('width'):
atts['style'] = 'width: %spx' % node['width']
+ if node.get('align'):
+ atts['align'] = node['align']
self.body.append(self.starttag(node, 'div', **atts))
def depart_figure(self, node):
@@ -700,9 +764,10 @@
def depart_footer(self, node):
start = self.context.pop()
- footer = (['<hr class="docutils footer" />\n',
- self.starttag(node, 'div', CLASS='footer')]
- + self.body[start:] + ['</div>\n'])
+ footer = [self.starttag(node, 'div', CLASS='footer'),
+ '<hr class="footer" />\n']
+ footer.extend(self.body[start:])
+ footer.append('\n</div>\n')
self.footer.extend(footer)
self.body_suffix[:0] = footer
del self.body[start:]
@@ -718,12 +783,13 @@
def footnote_backrefs(self, node):
backlinks = []
- if self.settings.footnote_backlinks and node.hasattr('backrefs'):
- backrefs = node['backrefs']
+ backrefs = node['backrefs']
+ if self.settings.footnote_backlinks and backrefs:
if len(backrefs) == 1:
self.context.append('')
- self.context.append('<a class="fn-backref" href="#%s" '
- 'name="%s">' % (backrefs[0], node['id']))
+ self.context.append(
+ '<a class="fn-backref" href="#%s" name="%s">'
+ % (backrefs[0], node['ids'][0]))
else:
i = 1
for backref in backrefs:
@@ -731,41 +797,34 @@
% (backref, i))
i += 1
self.context.append('<em>(%s)</em> ' % ', '.join(backlinks))
- self.context.append('<a name="%s">' % node['id'])
+ self.context.append('<a name="%s">' % node['ids'][0])
else:
self.context.append('')
- self.context.append('<a name="%s">' % node['id'])
+ self.context.append('<a name="%s">' % node['ids'][0])
# If the node does not only consist of a label.
if len(node) > 1:
# If there are preceding backlinks, we do not set class
# 'first', because we need to retain the top-margin.
if not backlinks:
- node[1].set_class('first')
- node[-1].set_class('last')
+ node[1]['classes'].append('first')
+ node[-1]['classes'].append('last')
def depart_footnote(self, node):
self.body.append('</td></tr>\n'
'</tbody>\n</table>\n')
def visit_footnote_reference(self, node):
- href = ''
- if node.has_key('refid'):
- href = '#' + node['refid']
- elif node.has_key('refname'):
- href = '#' + self.document.nameids[node['refname']]
+ href = '#' + node['refid']
format = self.settings.footnote_references
if format == 'brackets':
suffix = '['
self.context.append(']')
- elif format == 'superscript':
+ else:
+ assert format == 'superscript'
suffix = '<sup>'
self.context.append('</sup>')
- else: # shouldn't happen
- suffix = '???'
- self.content.append('???')
self.body.append(self.starttag(node, 'a', suffix,
- CLASS='footnote-reference',
- **(href and {'href': href} or {})))
+ CLASS='footnote-reference', href=href))
def depart_footnote_reference(self, node):
self.body.append(self.context.pop() + '</a>')
@@ -783,9 +842,9 @@
start = self.context.pop()
header = [self.starttag(node, 'div', CLASS='header')]
header.extend(self.body[start:])
- header.append('<hr class="docutils header"/>\n</div>\n')
+ header.append('\n<hr class="header"/>\n</div>\n')
self.body_prefix.extend(header)
- self.header = header
+ self.header.extend(header)
del self.body[start:]
def visit_hint(self, node):
@@ -795,9 +854,9 @@
self.depart_admonition()
def visit_image(self, node):
- atts = node.attributes.copy()
- if atts.has_key('class'):
- del atts['class'] # prevent duplication with node attrs
+ atts = node.non_default_attributes()
+ if atts.has_key('classes'):
+ del atts['classes'] # prevent duplication with node attrs
atts['src'] = atts['uri']
del atts['uri']
if atts.has_key('scale'):
@@ -832,9 +891,8 @@
self.body.append(self.emptytag(node, 'img', '', **atts))
def image_div_atts(self, image_node):
- div_atts = {'class': 'image'}
- if image_node.attributes.has_key('class'):
- div_atts['class'] += ' ' + image_node.attributes['class']
+ div_atts = {}
+ div_atts['class'] = ' '.join(['image'] + image_node['classes'])
if image_node.attributes.has_key('align'):
div_atts['align'] = self.attval(image_node.attributes['align'])
div_atts['class'] += ' align-%s' % div_atts['align']
@@ -885,14 +943,15 @@
def visit_list_item(self, node):
self.body.append(self.starttag(node, 'li', ''))
if len(node):
- node[0].set_class('first')
+ node[0]['classes'].append('first')
def depart_list_item(self, node):
self.body.append('</li>\n')
def visit_literal(self, node):
"""Process text to prevent tokens from wrapping."""
- self.body.append(self.starttag(node, 'tt', '', CLASS='docutils literal'))
+ self.body.append(
+ self.starttag(node, 'tt', '', CLASS='docutils literal'))
text = node.astext()
for token in self.words_and_spaces.findall(text):
if token.strip():
@@ -916,7 +975,7 @@
self.body.append('\n</pre>\n')
def visit_meta(self, node):
- meta = self.emptytag(node, 'meta', **node.attributes)
+ meta = self.emptytag(node, 'meta', **node.non_default_attributes())
self.add_meta(meta)
def depart_meta(self, node):
@@ -935,8 +994,10 @@
def visit_option(self, node):
if self.context[-1]:
self.body.append(', ')
+ self.body.append(self.starttag(node, 'span', '', CLASS='option'))
def depart_option(self, node):
+ self.body.append('</span>')
self.context[-1] += 1
def visit_option_argument(self, node):
@@ -948,12 +1009,14 @@
def visit_option_group(self, node):
atts = {}
- if len(node.astext()) > 14:
+ if ( self.settings.option_limit
+ and len(node.astext()) > self.settings.option_limit):
atts['colspan'] = 2
self.context.append('</tr>\n<tr><td> </td>')
else:
self.context.append('')
- self.body.append(self.starttag(node, 'td', **atts))
+ self.body.append(
+ self.starttag(node, 'td', CLASS='option-group', **atts))
self.body.append('<kbd>')
self.context.append(0) # count number of options
@@ -980,10 +1043,10 @@
self.body.append('</tr>\n')
def visit_option_string(self, node):
- self.body.append(self.starttag(node, 'span', '', CLASS='option'))
+ pass
def depart_option_string(self, node):
- self.body.append('</span>')
+ pass
def visit_organization(self, node):
self.visit_docinfo_item(node, 'organization')
@@ -999,12 +1062,16 @@
isinstance(node.parent, nodes.compound)):
# Never compact paragraphs in document or compound.
return 0
- if ((node.attributes in ({}, {'class': 'first'}, {'class': 'last'},
- {'class': 'first last'})) and
- (self.compact_simple or
- self.compact_p and (len(node.parent) == 1 or
- len(node.parent) == 2 and
- isinstance(node.parent[0], nodes.label)))):
+ for key, value in node.attlist():
+ if (node.is_not_default(key) and
+ not (key == 'classes' and value in
+ ([], ['first'], ['last'], ['first', 'last']))):
+ # Attribute which needs to survive.
+ return 0
+ if (self.compact_simple or
+ self.compact_p and (len(node.parent) == 1 or
+ len(node.parent) == 2 and
+ isinstance(node.parent[0], nodes.label))):
return 1
return 0
@@ -1021,7 +1088,7 @@
def visit_problematic(self, node):
if node.hasattr('refid'):
self.body.append('<a href="#%s" name="%s">' % (node['refid'],
- node['id']))
+ node['ids'][0]))
self.context.append('</a>')
else:
self.context.append('')
@@ -1033,12 +1100,11 @@
def visit_raw(self, node):
if 'html' in node.get('format', '').split():
- add_class = node.attributes.get('class') is not None
t = isinstance(node.parent, nodes.TextElement) and 'span' or 'div'
- if add_class:
+ if node['classes']:
self.body.append(self.starttag(node, t, suffix=''))
self.body.append(node.astext())
- if add_class:
+ if node['classes']:
self.body.append('</%s>' % t)
# Keep non-HTML raw text out of output:
raise nodes.SkipNode
@@ -1052,19 +1118,23 @@
div_atts['class'] += ' image-reference'
self.body.append(self.starttag({}, 'div', '', **div_atts))
self.context.append('</div>\n')
- href = ''
if node.has_key('refuri'):
href = node['refuri']
- elif node.has_key('refid'):
+ if ( self.settings.cloak_email_addresses
+ and href.startswith('mailto:')):
+ href = self.cloak_mailto(href)
+ self.in_mailto = 1
+ else:
+ assert node.has_key('refid'), \
+ 'References must have "refuri" or "refid" attribute.'
href = '#' + node['refid']
- elif node.has_key('refname'):
- href = '#' + self.document.nameids[node['refname']]
self.body.append(self.starttag(node, 'a', '', CLASS='reference',
- **(href and {'href': href} or {})))
+ href=href))
def depart_reference(self, node):
self.body.append('</a>')
self.body.append(self.context.pop())
+ self.in_mailto = 0
def visit_revision(self, node):
self.visit_docinfo_item(node, 'revision', meta=None)
@@ -1074,6 +1144,7 @@
def visit_row(self, node):
self.body.append(self.starttag(node, 'tr', ''))
+ node.column = 0
def depart_row(self, node):
self.body.append('</tr>\n')
@@ -1135,6 +1206,12 @@
self.body.append(self.starttag(node, 'h2', '', CLASS='subtitle'))
self.context.append('</h2>\n')
self.in_document_title = len(self.body)
+ elif isinstance(node.parent, nodes.section):
+ tag = 'h%s' % (self.section_level + self.initial_header_level - 1)
+ self.body.append(
+ self.starttag(node, tag, '', CLASS='section-subtitle') +
+ self.starttag({}, 'span', '', CLASS='section-subtitle'))
+ self.context.append('</span></%s>\n' % tag)
def depart_subtitle(self, node):
self.body.append(self.context.pop())
@@ -1142,6 +1219,7 @@
self.subtitle = self.body[self.in_document_title:-1]
self.in_document_title = 0
self.body_pre_docinfo.extend(self.body)
+ self.html_subtitle.extend(self.body)
del self.body[:]
def visit_superscript(self, node):
@@ -1151,16 +1229,16 @@
self.body.append('</sup>')
def visit_system_message(self, node):
- if node['level'] < self.document.reporter['writer'].report_level:
+ if node['level'] < self.document.reporter.report_level:
# Level is too low to display:
raise nodes.SkipNode
self.body.append(self.starttag(node, 'div', CLASS='system-message'))
self.body.append('<p class="system-message-title">')
attr = {}
backref_text = ''
- if node.hasattr('id'):
- attr['name'] = node['id']
- if node.hasattr('backrefs'):
+ if node['ids']:
+ attr['name'] = node['ids'][0]
+ if len(node['backrefs']):
backrefs = node['backrefs']
if len(backrefs) == 1:
backref_text = ('; <em><a href="#%s">backlink</a></em>'
@@ -1200,8 +1278,8 @@
def visit_target(self, node):
if not (node.has_key('refuri') or node.has_key('refid')
or node.has_key('refname')):
- self.body.append(self.starttag(node, 'a', '', CLASS='target'))
- self.context.append('</a>')
+ self.body.append(self.starttag(node, 'span', '', CLASS='target'))
+ self.context.append('</span>')
else:
self.context.append('')
@@ -1231,6 +1309,7 @@
self.body.append(self.starttag(node, 'colgroup'))
# Appended by thead or tbody:
self.context.append('</colgroup>\n')
+ node.stubs = []
def depart_tgroup(self, node):
pass
@@ -1273,6 +1352,7 @@
check_id = 1
close_tag = '</caption>\n'
elif self.section_level == 0:
+ assert node.parent is self.document
# document title
self.head.append('<title>%s</title>\n'
% self.encode(node.astext()))
@@ -1280,21 +1360,26 @@
self.context.append('</h1>\n')
self.in_document_title = len(self.body)
else:
+ assert isinstance(node.parent, nodes.section)
h_level = self.section_level + self.initial_header_level - 1
+ atts = {}
+ if (len(node.parent) >= 2 and
+ isinstance(node.parent[1], nodes.subtitle)):
+ atts['CLASS'] = 'with-subtitle'
self.body.append(
- self.starttag(node, 'h%s' % h_level, ''))
+ self.starttag(node, 'h%s' % h_level, '', **atts))
atts = {}
- if node.parent.hasattr('id'):
- atts['name'] = node.parent['id']
+ if node.parent['ids']:
+ atts['name'] = node.parent['ids'][0]
if node.hasattr('refid'):
atts['class'] = 'toc-backref'
atts['href'] = '#' + node['refid']
self.body.append(self.starttag({}, 'a', '', **atts))
self.context.append('</a></h%s>\n' % (h_level))
if check_id:
- if node.parent.hasattr('id'):
+ if node.parent['ids']:
self.body.append(
- self.starttag({}, 'a', '', name=node.parent['id']))
+ self.starttag({}, 'a', '', name=node.parent['ids'][0]))
self.context.append('</a>' + close_tag)
else:
self.context.append(close_tag)
@@ -1305,6 +1390,7 @@
self.title = self.body[self.in_document_title:-1]
self.in_document_title = 0
self.body_pre_docinfo.extend(self.body)
+ self.html_title.extend(self.body)
del self.body[:]
def visit_title_reference(self, node):
@@ -1315,11 +1401,11 @@
def visit_topic(self, node):
self.body.append(self.starttag(node, 'div', CLASS='topic'))
- self.topic_class = node.get('class')
+ self.topic_classes = node['classes']
def depart_topic(self, node):
self.body.append('</div>\n')
- self.topic_class = ''
+ self.topic_classes = []
def visit_transition(self, node):
self.body.append(self.emptytag(node, 'hr', CLASS='docutils'))
@@ -1364,7 +1450,7 @@
def visit_list_item(self, node):
children = []
- for child in node.get_children():
+ for child in node.children:
if not isinstance(child, nodes.Invisible):
children.append(child)
if (children and isinstance(children[0], nodes.paragraph)
Modified: Zope/trunk/lib/python/docutils/writers/latex2e.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/latex2e.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/writers/latex2e.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,8 +1,8 @@
"""
:Author: Engelbert Gruber
:Contact: grubert at users.sourceforge.net
-:Revision: $Revision: 1.1.2.7 $
-:Date: $Date: 2005/01/07 13:26:06 $
+:Revision: $Revision: 3367 $
+:Date: $Date: 2005-05-26 02:44:13 +0200 (Thu, 26 May 2005) $
:Copyright: This module has been placed in the public domain.
LaTeX2e document tree Writer.
@@ -349,7 +349,7 @@
return self._deepest_section
class Table:
- """ Manage a table while traversing.
+ """ Manage a table while traversing.
Maybe change to a mixin defining the visit/departs, but then
class Table internal variables are in the Translator.
"""
@@ -381,7 +381,7 @@
return ''
def get_latex_type(self):
return self._latex_type
-
+
def set(self,attr,value):
self._attrs[attr] = value
def get(self,attr):
@@ -442,7 +442,7 @@
return latex_table_spec+bar
def get_column_width(self):
- """ return columnwidth for current cell (not multicell)
+ """ return columnwidth for current cell (not multicell)
"""
return "%.2f\\locallinewidth" % self._col_width[self._cell_in_row-1]
@@ -471,7 +471,7 @@
for i in range(len(self._rowspan)):
if (self._rowspan[i]>0):
self._rowspan[i] -= 1
-
+
if self._table_style == 'standard':
rowspans = []
for i in range(len(self._rowspan)):
@@ -507,7 +507,7 @@
def visit_entry(self):
self._cell_in_row += 1
-
+
class LaTeXTranslator(nodes.NodeVisitor):
# When options are given to the documentclass, latex will pass them
@@ -664,21 +664,24 @@
# NOTE: Latex wants a date and an author, rst puts this into
# docinfo, so normally we donot want latex author/date handling.
# latex article has its own handling of date and author, deactivate.
+ # So we always emit \title{...} \author{...} \date{...}, even if the
+ # "..." are empty strings.
self.head = [ ]
- if not self.use_latex_docinfo:
- self.head.extend( [ '\\author{}\n', '\\date{}\n' ] )
+ # separate title, so we can appen subtitle.
+ self.title = ''
+ # if use_latex_docinfo: collects lists of author/organization/contact/address lines
+ self.author_stack = []
+ self.date = ''
+
self.body_prefix = ['\\raggedbottom\n']
- # separate title, so we can appen subtitle.
- self.title = ""
self.body = []
self.body_suffix = ['\n']
self.section_level = 0
self.context = []
- self.topic_class = ''
+ self.topic_classes = []
# column specification for tables
self.table_caption = None
- # do we have one or more authors
- self.author_stack = None
+
# Flags to encode
# ---------------
# verbatim: to tell encode not to encode.
@@ -878,15 +881,19 @@
return self.encode(whitespace.sub(' ', text))
def astext(self):
- if self.pdfinfo:
+ if self.pdfinfo is not None:
if self.pdfauthor:
self.pdfinfo.append('pdfauthor={%s}' % self.pdfauthor)
+ if self.pdfinfo:
pdfinfo = '\\hypersetup{\n' + ',\n'.join(self.pdfinfo) + '\n}\n'
else:
pdfinfo = ''
- title = '\\title{%s}\n' % self.title
- return ''.join(self.head_prefix + [title]
- + self.head + [pdfinfo]
+ head = '\\title{%s}\n\\author{%s}\n\\date{%s}\n' % \
+ (self.title,
+ ' \\and\n'.join(['~\\\\\n'.join(author_lines)
+ for author_lines in self.author_stack]),
+ self.date)
+ return ''.join(self.head_prefix + [head] + self.head + [pdfinfo]
+ self.body_prefix + self.body + self.body_suffix)
def visit_Text(self, node):
@@ -927,14 +934,10 @@
def visit_authors(self, node):
# not used: visit_author is called anyway for each author.
- if self.use_latex_docinfo:
- self.author_stack = []
+ pass
def depart_authors(self, node):
- if self.use_latex_docinfo:
- self.head.append('\\author{%s}\n' % \
- ' \\and '.join(self.author_stack) )
- self.author_stack = None
+ pass
def visit_block_quote(self, node):
self.body.append( '\\begin{quote}\n')
@@ -943,14 +946,14 @@
self.body.append( '\\end{quote}\n')
def visit_bullet_list(self, node):
- if self.topic_class == 'contents':
+ if self.topic_classes == ['contents']:
if not self.use_latex_toc:
self.body.append( '\\begin{list}{}{}\n' )
else:
self.body.append( '\\begin{itemize}\n' )
def depart_bullet_list(self, node):
- if self.topic_class == 'contents':
+ if self.topic_classes == ['contents']:
if not self.use_latex_toc:
self.body.append( '\\end{list}\n' )
else:
@@ -998,7 +1001,8 @@
self.context.append(len(self.body))
else:
self.body.append('\\begin{figure}[b]')
- self.body.append('\\hypertarget{%s}' % node['id'])
+ for id in node['ids']:
+ self.body.append('\\hypertarget{%s}' % id)
def depart_citation(self, node):
if self._use_latex_citations:
@@ -1128,15 +1132,23 @@
self.pdfauthor = self.attval(node.astext())
else:
self.pdfauthor += self.author_separator + self.attval(node.astext())
- if self.use_latex_docinfo:
- if self.author_stack == None:
- self.head.append('\\author{%s}\n' % self.attval(node.astext()))
+ if self.use_latex_docinfo:
+ if name in ('author', 'organization', 'contact', 'address'):
+ # We attach these to the last author. If any of them precedes
+ # the first author, put them in a separate "author" group (for
+ # no better semantics).
+ if name == 'author' or not self.author_stack:
+ self.author_stack.append([])
+ if name == 'address': # newlines are meaningful
+ self.insert_newline = 1
+ text = self.encode(node.astext())
+ self.insert_newline = 0
else:
- self.author_stack.append( self.attval(node.astext()) )
+ text = self.attval(node.astext())
+ self.author_stack[-1].append(text)
raise nodes.SkipNode
- elif name == 'date':
- if self.use_latex_docinfo:
- self.head.append('\\date{%s}\n' % self.attval(node.astext()))
+ elif name == 'date':
+ self.date = self.attval(node.astext())
raise nodes.SkipNode
self.docinfo.append('\\textbf{%s}: &\n\t' % self.language_label(name))
if name == 'address':
@@ -1169,7 +1181,7 @@
def visit_document(self, node):
self.body_prefix.append('\\begin{document}\n')
# titled document?
- if len(node) and isinstance(node[0], nodes.title):
+ if self.use_latex_docinfo or len(node) and isinstance(node[0], nodes.title):
self.body_prefix.append('\\maketitle\n\n')
# alternative use titlepage environment.
# \begin{titlepage}
@@ -1186,7 +1198,7 @@
for bi in self._bibitems:
self.body.append('\\bibitem[%s]{%s}{%s}\n' % (bi[0], bi[0], bi[1]))
self.body.append('\\end{thebibliography}\n')
-
+
self.body_suffix.append('\\end{document}\n')
def visit_emphasis(self, node):
@@ -1204,7 +1216,10 @@
# if the firstrow is a multirow, this actually is the second row.
# this gets hairy if rowspans follow each other.
if self.active_table.get_rowspan(0):
- self.body.append(' & ')
+ count = 0
+ while self.active_table.get_rowspan(count):
+ count += 1
+ self.body.append(' & ')
self.active_table.visit_entry() # increment cell count
else:
self.body.append(' & ')
@@ -1384,7 +1399,8 @@
self.body.append('{')
else:
self.body.append('\\begin{figure}[b]')
- self.body.append('\\hypertarget{%s}' % node['id'])
+ for id in node['ids']:
+ self.body.append('\\hypertarget{%s}' % id)
def depart_footnote(self, node):
if self.use_latex_footnotes:
@@ -1692,7 +1708,7 @@
def visit_paragraph(self, node):
index = node.parent.index(node)
- if not (self.topic_class == 'contents' or
+ if not (self.topic_classes == ['contents'] or
(isinstance(node.parent, nodes.compound) and
index > 0 and
not isinstance(node.parent[index - 1], nodes.paragraph) and
@@ -1799,17 +1815,19 @@
if isinstance(node.parent, nodes.sidebar):
self.body.append('~\\\\\n\\textbf{')
self.context.append('}\n\\smallskip\n')
- else:
+ elif isinstance(node.parent, nodes.document):
self.title = self.title + \
'\\\\\n\\large{%s}\n' % self.encode(node.astext())
raise nodes.SkipNode
+ elif isinstance(node.parent, nodes.section):
+ self.body.append('\\textbf{')
+ self.context.append('}\\vspace{0.2cm}\n\n\\noindent ')
def depart_subtitle(self, node):
- if isinstance(node.parent, nodes.sidebar):
- self.body.append(self.context.pop())
+ self.body.append(self.context.pop())
def visit_system_message(self, node):
- if node['level'] < self.document.reporter['writer'].report_level:
+ if node['level'] < self.document.reporter.report_level:
raise nodes.SkipNode
def depart_system_message(self, node):
@@ -1830,8 +1848,9 @@
# BUG: why not (refuri or refid or refname) means not footnote ?
if not (node.has_key('refuri') or node.has_key('refid')
or node.has_key('refname')):
- self.body.append('\\hypertarget{%s}{' % node['id'])
- self.context.append('}')
+ for id in node['ids']:
+ self.body.append('\\hypertarget{%s}{' % id)
+ self.context.append('}' * len(node['ids']))
else:
self.context.append('')
@@ -1849,11 +1868,11 @@
pass
def visit_term(self, node):
- self.body.append('\\item[')
+ self.body.append('\\item[{')
def depart_term(self, node):
# definition list term.
- self.body.append('] ')
+ self.body.append('}] ')
def visit_tgroup(self, node):
#self.body.append(self.starttag(node, 'colgroup'))
@@ -1895,8 +1914,9 @@
def bookmark(self, node):
"""Append latex href and pdfbookmarks for titles.
"""
- if node.parent.hasattr('id'):
- self.body.append('\\hypertarget{%s}{}\n' % node.parent['id'])
+ if node.parent['ids']:
+ for id in node.parent['ids']:
+ self.body.append('\\hypertarget{%s}{}\n' % id)
if not self.use_latex_toc:
# BUG level depends on style. pdflatex allows level 0 to 3
# ToC would be the only on level 0 so i choose to decrement the rest.
@@ -1907,8 +1927,9 @@
l = l-1
# pdftex does not like "_" subscripts in titles
text = self.encode(node.astext())
- self.body.append('\\pdfbookmark[%d]{%s}{%s}\n' % \
- (l,text,node.parent['id']))
+ for id in node.parent['ids']:
+ self.body.append('\\pdfbookmark[%d]{%s}{%s}\n' % \
+ (l, text, id))
def visit_title(self, node):
"""Only 3 section levels are supported by LaTeX article (AFAIR)."""
@@ -1957,10 +1978,10 @@
self.body.append(self.context.pop())
def visit_topic(self, node):
- self.topic_class = node.get('class')
- if self.use_latex_toc:
+ self.topic_classes = node['classes']
+ if 'contents' in node['classes'] and self.use_latex_toc:
self.body.append('\\tableofcontents\n\n\\bigskip\n')
- self.topic_class = ''
+ self.topic_classes = []
raise nodes.SkipNode
def visit_inline(self, node): # titlereference
@@ -1970,7 +1991,7 @@
self.body.append( '}' )
def depart_topic(self, node):
- self.topic_class = ''
+ self.topic_classes = []
self.body.append('\n')
def visit_rubric(self, node):
Modified: Zope/trunk/lib/python/docutils/writers/pep_html.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/pep_html.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/writers/pep_html.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Author: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 3129 $
+# Date: $Date: 2005-03-26 17:21:28 +0100 (Sat, 26 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
@@ -11,7 +11,6 @@
__docformat__ = 'reStructuredText'
-import random
import sys
import docutils
from docutils import frontend, nodes, utils
@@ -22,8 +21,7 @@
settings_spec = html4css1.Writer.settings_spec + (
'PEP/HTML-Specific Options',
- """The HTML --footnote-references option's default is set to """
- '"brackets".',
+ None,
(('Specify a template file. Default is "pep-html-template".',
['--template'],
{'default': 'pep-html-template', 'metavar': '<file>'}),
@@ -32,10 +30,12 @@
{'default': '..', 'metavar': '<URL>'}),
('Home URL prefix for PEPs. Default is "." (current directory).',
['--pep-home'],
- {'default': '.', 'metavar': '<URL>'}),))
+ {'default': '.', 'metavar': '<URL>'}),
+ # For testing.
+ (frontend.SUPPRESS_HELP,
+ ['--no-random'],
+ {'action': 'store_true', 'validator': frontend.validate_boolean}),))
- settings_default_overrides = {'footnote_references': 'brackets'}
-
relative_path_settings = (html4css1.Writer.relative_path_settings
+ ('template',))
@@ -66,7 +66,11 @@
header = self.document[index]
pepnum = header[0][1].astext()
subs['pep'] = pepnum
- subs['banner'] = random.randrange(64)
+ if settings.no_random:
+ subs['banner'] = 0
+ else:
+ import random
+ subs['banner'] = random.randrange(64)
try:
subs['pepnum'] = '%04i' % int(pepnum)
except ValueError:
@@ -82,5 +86,5 @@
def depart_field_list(self, node):
html4css1.HTMLTranslator.depart_field_list(self, node)
- if node.get('class') == 'rfc2822':
+ if 'rfc2822' in node['classes']:
self.body.append('<hr />\n')
Modified: Zope/trunk/lib/python/docutils/writers/pseudoxml.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/pseudoxml.py 2005-10-09 14:31:06 UTC (rev 39012)
+++ Zope/trunk/lib/python/docutils/writers/pseudoxml.py 2005-10-09 14:31:37 UTC (rev 39013)
@@ -1,7 +1,7 @@
# Authors: David Goodger
# Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.2.10.6 $
-# Date: $Date: 2005/01/07 13:26:06 $
+# Revision: $Revision: 1645 $
+# Date: $Date: 2003-08-27 22:50:43 +0200 (Wed, 27 Aug 2003) $
# Copyright: This module has been placed in the public domain.
"""
More information about the Zope-Checkins
mailing list