summaryrefslogtreecommitdiff
path: root/docutils
diff options
context:
space:
mode:
authorstrank <strank@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2008-07-28 15:24:27 +0000
committerstrank <strank@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2008-07-28 15:24:27 +0000
commit2ec2ed70dfae0edfb9c8df437cfa20b41e971fd1 (patch)
tree94b3b00b24408e3df8c0ef6ade26549f7355dcec /docutils
parentce856ebd1cf2b6781a5c84b4627db2e47c9ffa04 (diff)
downloaddocutils-2ec2ed70dfae0edfb9c8df437cfa20b41e971fd1.tar.gz
Merged trunk r5043:5619 to adjacent-citations branch.
git-svn-id: http://svn.code.sf.net/p/docutils/code/branches/adjacent-citations@5621 929543f6-e4f2-0310-98a6-ba3bd3dd1d04
Diffstat (limited to 'docutils')
-rw-r--r--docutils/__init__.py2
-rw-r--r--docutils/core.py8
-rw-r--r--docutils/frontend.py17
-rw-r--r--docutils/languages/__init__.py2
-rw-r--r--docutils/languages/pt_br.py2
-rw-r--r--docutils/nodes.py83
-rw-r--r--docutils/parsers/__init__.py2
-rw-r--r--docutils/parsers/rst/directives/__init__.py2
-rw-r--r--docutils/parsers/rst/directives/admonitions.py2
-rw-r--r--docutils/parsers/rst/directives/body.py2
-rw-r--r--docutils/parsers/rst/directives/images.py4
-rw-r--r--docutils/parsers/rst/directives/misc.py24
-rw-r--r--docutils/parsers/rst/directives/parts.py4
-rw-r--r--docutils/parsers/rst/directives/tables.py24
-rw-r--r--docutils/parsers/rst/languages/__init__.py2
-rw-r--r--docutils/parsers/rst/languages/de.py2
-rw-r--r--docutils/parsers/rst/roles.py12
-rw-r--r--docutils/parsers/rst/states.py11
-rw-r--r--docutils/readers/__init__.py2
-rw-r--r--docutils/readers/python/__init__.py2
-rw-r--r--docutils/readers/python/moduleparser.py64
-rw-r--r--docutils/statemachine.py10
-rw-r--r--docutils/transforms/frontmatter.py2
-rw-r--r--docutils/transforms/parts.py4
-rw-r--r--docutils/transforms/references.py30
-rw-r--r--docutils/transforms/writer_aux.py2
-rw-r--r--docutils/utils.py8
-rw-r--r--docutils/writers/__init__.py2
-rw-r--r--docutils/writers/html4css1/__init__.py65
-rw-r--r--docutils/writers/html4css1/html4css1.css2
-rw-r--r--docutils/writers/latex2e/__init__.py247
-rw-r--r--docutils/writers/newlatex2e/__init__.py4
-rw-r--r--docutils/writers/newlatex2e/unicode_map.py2
-rw-r--r--docutils/writers/s5_html/__init__.py2
34 files changed, 371 insertions, 282 deletions
diff --git a/docutils/__init__.py b/docutils/__init__.py
index 6991f3643..eca962fca 100644
--- a/docutils/__init__.py
+++ b/docutils/__init__.py
@@ -49,7 +49,7 @@ Subpackages:
__docformat__ = 'reStructuredText'
-__version__ = '0.5'
+__version__ = '0.6'
"""``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
diff --git a/docutils/core.py b/docutils/core.py
index f68f74cea..bf3b2a4f1 100644
--- a/docutils/core.py
+++ b/docutils/core.py
@@ -53,9 +53,11 @@ class Publisher:
"""A `docutils.writers.Writer` instance."""
for component in 'reader', 'parser', 'writer':
- assert not isinstance(getattr(self, component), StringType), \
- ('passed string as "%s" parameter; use "%s_name" instead'
- % (getattr(self, component), component, component))
+ assert not isinstance(getattr(self, component), StringType), (
+ 'passed string "%s" as "%s" parameter; pass an instance, '
+ 'or use the "%s_name" parameter instead (in '
+ 'docutils.core.publish_* convenience functions).'
+ % (getattr(self, component), component, component))
self.source = source
"""The source of input data, a `docutils.io.Input` instance."""
diff --git a/docutils/frontend.py b/docutils/frontend.py
index 034e30769..c21bd2c2d 100644
--- a/docutils/frontend.py
+++ b/docutils/frontend.py
@@ -193,7 +193,7 @@ def make_paths_absolute(pathdict, keys, base_path=None):
if base_path is None:
base_path = os.getcwd()
for key in keys:
- if pathdict.has_key(key):
+ if key in pathdict:
value = pathdict[key]
if isinstance(value, types.ListType):
value = [make_one_path_absolute(base_path, path)
@@ -225,7 +225,7 @@ class Values(optparse.Values):
other_dict = other_dict.__dict__
other_dict = other_dict.copy()
for setting in option_parser.lists.keys():
- if (hasattr(self, setting) and other_dict.has_key(setting)):
+ if (hasattr(self, setting) and setting in other_dict):
value = getattr(self, setting)
if value:
value += other_dict[setting]
@@ -359,12 +359,14 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
['--leave-comments'],
{'action': 'store_false', 'dest': 'strip_comments'}),
('Remove all elements with classes="<class>" from the document tree. '
+ 'Warning: potentially dangerous; use with caution. '
'(Multiple-use option.)',
['--strip-elements-with-class'],
{'action': 'append', 'dest': 'strip_elements_with_classes',
'metavar': '<class>', 'validator': validate_strip_class}),
('Remove all classes="<class>" attributes from elements in the '
- 'document tree. (Multiple-use option.)',
+ 'document tree. Warning: potentially dangerous; use with caution. '
+ '(Multiple-use option.)',
['--strip-class'],
{'action': 'append', 'dest': 'strip_classes',
'metavar': '<class>', 'validator': validate_strip_class}),
@@ -476,8 +478,9 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
config_section = 'general'
- version_template = ('%%prog (Docutils %s [%s])'
- % (docutils.__version__, docutils.__version_details__))
+ version_template = ('%%prog (Docutils %s [%s], Python %s, on %s)'
+ % (docutils.__version__, docutils.__version_details__,
+ sys.version.split()[0], sys.platform))
"""Default version message."""
def __init__(self, components=(), defaults=None, read_config_files=None,
@@ -582,7 +585,7 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
continue
for section in (tuple(component.config_section_dependencies or ())
+ (component.config_section,)):
- if applied.has_key(section):
+ if section in applied:
continue
applied[section] = 1
settings.update(parser.get_section(section), self)
@@ -696,7 +699,7 @@ Skipping "%s" configuration file.
if not self.has_section('general'):
self.add_section('general')
for key, value in options.items():
- if self.old_settings.has_key(key):
+ if key in self.old_settings:
section, setting = self.old_settings[key]
if not self.has_section(section):
self.add_section(section)
diff --git a/docutils/languages/__init__.py b/docutils/languages/__init__.py
index c721c0210..7d6521fc1 100644
--- a/docutils/languages/__init__.py
+++ b/docutils/languages/__init__.py
@@ -14,7 +14,7 @@ __docformat__ = 'reStructuredText'
_languages = {}
def get_language(language_code):
- if _languages.has_key(language_code):
+ if language_code in _languages:
return _languages[language_code]
module = __import__(language_code, globals(), locals())
_languages[language_code] = module
diff --git a/docutils/languages/pt_br.py b/docutils/languages/pt_br.py
index 92db002aa..f4adfbbf6 100644
--- a/docutils/languages/pt_br.py
+++ b/docutils/languages/pt_br.py
@@ -27,7 +27,7 @@ labels = {
'copyright': u'Copyright',
'dedication': u'Dedicat\u00F3ria',
'abstract': u'Resumo',
- 'attention': u'Atten\u00E7\u00E3o!',
+ 'attention': u'Aten\u00E7\u00E3o!',
'caution': u'Cuidado!',
'danger': u'PERIGO!',
'error': u'Erro',
diff --git a/docutils/nodes.py b/docutils/nodes.py
index ffb679b17..816befd4d 100644
--- a/docutils/nodes.py
+++ b/docutils/nodes.py
@@ -27,7 +27,6 @@ import re
import warnings
from types import IntType, SliceType, StringType, UnicodeType, \
TupleType, ListType, ClassType, TypeType
-from UserString import UserString
# ==============================
@@ -62,11 +61,7 @@ class Node:
return 1
def __str__(self):
- return self.__unicode__().encode('raw_unicode_escape')
-
- def __unicode__(self):
- # Override in subclass.
- raise NotImplementedError
+ return unicode(self).encode('raw_unicode_escape')
def asdom(self, dom=None):
"""Return a DOM **fragment** representation of this Node."""
@@ -273,7 +268,15 @@ class Node:
except IndexError:
return None
-class Text(Node, UserString):
+class reprunicode(unicode):
+ """
+ A class that removes the initial u from unicode's repr.
+ """
+
+ def __repr__(self):
+ return unicode.__repr__(self)[1:]
+
+class Text(Node, reprunicode):
"""
Instances are terminal nodes (leaves) containing text only; no child
@@ -286,38 +289,44 @@ class Text(Node, UserString):
children = ()
"""Text nodes have no children, and cannot have children."""
+ def __new__(cls, data, rawsource=None):
+ """Prevent the rawsource argument from propagating to str."""
+ return reprunicode.__new__(cls, data)
+
def __init__(self, data, rawsource=''):
- UserString.__init__(self, data)
self.rawsource = rawsource
"""The raw text from which this element was constructed."""
def __repr__(self):
- data = repr(self.data)
+ data = reprunicode.__repr__(self)
if len(data) > 70:
- data = repr(self.data[:64] + ' ...')
+ data = reprunicode.__repr__(self[:64] + ' ...')
return '<%s: %s>' % (self.tagname, data)
- def __len__(self):
- return len(self.data)
-
def shortrepr(self):
- data = repr(self.data)
+ data = reprunicode.__repr__(self)
if len(data) > 20:
- data = repr(self.data[:16] + ' ...')
+ data = reprunicode.__repr__(self[:16] + ' ...')
return '<%s: %s>' % (self.tagname, data)
def _dom_node(self, domroot):
- return domroot.createTextNode(self.data)
+ return domroot.createTextNode(unicode(self))
def astext(self):
- return self.data
+ return reprunicode(self)
- def __unicode__(self):
- return self.data
+ # Note about __unicode__: The implementation of __unicode__ here,
+ # and the one raising NotImplemented in the superclass Node had
+ # to be removed when changing Text to a subclass of unicode instead
+ # of UserString, since there is no way to delegate the __unicode__
+ # call to the superclass unicode:
+ # unicode itself does not have __unicode__ method to delegate to
+ # and calling unicode(self) or unicode.__new__ directly creates
+ # an infinite loop
def copy(self):
- return self.__class__(self.data)
+ return self.__class__(reprunicode(self), rawsource=self.rawsource)
def deepcopy(self):
return self.copy()
@@ -325,10 +334,19 @@ class Text(Node, UserString):
def pformat(self, indent=' ', level=0):
result = []
indent = indent * level
- for line in self.data.splitlines():
+ for line in self.splitlines():
result.append(indent + line + '\n')
return ''.join(result)
+ # rstrip and lstrip are used by substitution definitions where
+ # they are expected to return a Text instance, this was formerly
+ # taken care of by UserString. Note that then and now the
+ # rawsource member is lost.
+
+ def rstrip(self, chars=None):
+ return self.__class__(reprunicode.rstrip(self, chars))
+ def lstrip(self, chars=None):
+ return self.__class__(reprunicode.lstrip(self, chars))
class Element(Node):
@@ -539,10 +557,10 @@ class Element(Node):
return self.attributes.get(key, failobj)
def hasattr(self, attr):
- return self.attributes.has_key(attr)
+ return attr in self.attributes
def delattr(self, attr):
- if self.attributes.has_key(attr):
+ if attr in self.attributes:
del self.attributes[attr]
def setdefault(self, key, failobj=None):
@@ -550,6 +568,9 @@ class Element(Node):
has_key = hasattr
+ # support operator in
+ __contains__ = hasattr
+
def append(self, item):
self.setup_child(item)
self.children.append(item)
@@ -930,18 +951,18 @@ class document(Root, Structural, Element):
def set_id(self, node, msgnode=None):
for id in node['ids']:
- if self.ids.has_key(id) and self.ids[id] is not node:
+ if id in self.ids and self.ids[id] is not node:
msg = self.reporter.severe('Duplicate ID: "%s".' % id)
if msgnode != None:
msgnode += msg
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):
+ if id and id not in self.ids:
break
else:
id = ''
- while not id or self.ids.has_key(id):
+ while not id or id in self.ids:
id = (self.settings.id_prefix +
self.settings.auto_id_prefix + str(self.id_start))
self.id_start += 1
@@ -982,7 +1003,7 @@ class document(Root, Structural, Element):
The new target is invalidated regardless.
"""
for name in node['names']:
- if self.nameids.has_key(name):
+ if name in self.nameids:
self.set_duplicate_name_id(node, id, name, msgnode, explicit)
else:
self.nameids[name] = id
@@ -997,10 +1018,10 @@ class document(Root, Structural, Element):
level = 2
if old_id is not None:
old_node = self.ids[old_id]
- if node.has_key('refuri'):
+ if 'refuri' in node:
refuri = node['refuri']
if old_node['names'] \
- and old_node.has_key('refuri') \
+ and 'refuri' in old_node \
and old_node['refuri'] == refuri:
level = 1 # just inform if refuri's identical
if level > 1:
@@ -1031,7 +1052,7 @@ class document(Root, Structural, Element):
msgnode += msg
def has_name(self, name):
- return self.nameids.has_key(name)
+ return name in self.nameids
# "note" here is an imperative verb: "take note of".
def note_implicit_target(self, target, msgnode=None):
@@ -1091,7 +1112,7 @@ class document(Root, Structural, Element):
def note_substitution_def(self, subdef, def_name, msgnode=None):
name = whitespace_normalize_name(def_name)
- if self.substitution_defs.has_key(name):
+ if name in self.substitution_defs:
msg = self.reporter.error(
'Duplicate substitution definition name: "%s".' % name,
base_node=subdef)
diff --git a/docutils/parsers/__init__.py b/docutils/parsers/__init__.py
index 125ab7674..2683376f9 100644
--- a/docutils/parsers/__init__.py
+++ b/docutils/parsers/__init__.py
@@ -41,7 +41,7 @@ _parser_aliases = {
def get_parser_class(parser_name):
"""Return the Parser class from the `parser_name` module."""
parser_name = parser_name.lower()
- if _parser_aliases.has_key(parser_name):
+ if parser_name in _parser_aliases:
parser_name = _parser_aliases[parser_name]
module = __import__(parser_name, globals(), locals())
return module.Parser
diff --git a/docutils/parsers/rst/directives/__init__.py b/docutils/parsers/rst/directives/__init__.py
index 14ac03a99..30da65ecd 100644
--- a/docutils/parsers/rst/directives/__init__.py
+++ b/docutils/parsers/rst/directives/__init__.py
@@ -76,7 +76,7 @@ def directive(directive_name, language_module, document):
normname = directive_name.lower()
messages = []
msg_text = []
- if _directives.has_key(normname):
+ if normname in _directives:
return _directives[normname], messages
canonicalname = None
try:
diff --git a/docutils/parsers/rst/directives/admonitions.py b/docutils/parsers/rst/directives/admonitions.py
index bed3381b8..870b6659e 100644
--- a/docutils/parsers/rst/directives/admonitions.py
+++ b/docutils/parsers/rst/directives/admonitions.py
@@ -35,7 +35,7 @@ class BaseAdmonition(Directive):
self.lineno)
admonition_node += nodes.title(title_text, '', *textnodes)
admonition_node += messages
- if self.options.has_key('class'):
+ if 'class' in self.options:
classes = self.options['class']
else:
classes = ['admonition-' + nodes.make_id(title_text)]
diff --git a/docutils/parsers/rst/directives/body.py b/docutils/parsers/rst/directives/body.py
index 03c9c3fa6..0cc695726 100644
--- a/docutils/parsers/rst/directives/body.py
+++ b/docutils/parsers/rst/directives/body.py
@@ -39,7 +39,7 @@ class BasePseudoSection(Directive):
textnodes, messages = self.state.inline_text(title_text, self.lineno)
titles = [nodes.title(title_text, '', *textnodes)]
# Sidebar uses this code.
- if self.options.has_key('subtitle'):
+ if 'subtitle' in self.options:
textnodes, more_messages = self.state.inline_text(
self.options['subtitle'], self.lineno)
titles.append(nodes.subtitle(self.options['subtitle'], '',
diff --git a/docutils/parsers/rst/directives/images.py b/docutils/parsers/rst/directives/images.py
index 96bdb3353..59323bba0 100644
--- a/docutils/parsers/rst/directives/images.py
+++ b/docutils/parsers/rst/directives/images.py
@@ -46,7 +46,7 @@ class Image(Directive):
'class': directives.class_option}
def run(self):
- if self.options.has_key('align'):
+ if 'align' in self.options:
if isinstance(self.state, states.SubstitutionDef):
# Check for align_v_values.
if self.options['align'] not in self.align_v_values:
@@ -66,7 +66,7 @@ class Image(Directive):
reference = directives.uri(self.arguments[0])
self.options['uri'] = reference
reference_node = None
- if self.options.has_key('target'):
+ if 'target' in self.options:
block = states.escape2null(
self.options['target']).splitlines()
block = [line for line in block]
diff --git a/docutils/parsers/rst/directives/misc.py b/docutils/parsers/rst/directives/misc.py
index 5d5d34729..89c8364c7 100644
--- a/docutils/parsers/rst/directives/misc.py
+++ b/docutils/parsers/rst/directives/misc.py
@@ -86,7 +86,7 @@ class Include(Directive):
raise self.severe('Problem with "end-before" option of "%s" '
'directive:\nText not found.' % self.name)
include_text = include_text[:before_index]
- if self.options.has_key('literal'):
+ if 'literal' in self.options:
literal_block = nodes.literal_block(include_text, include_text,
source=path)
literal_block.line = 1
@@ -120,20 +120,20 @@ class Raw(Directive):
def run(self):
if (not self.state.document.settings.raw_enabled
or (not self.state.document.settings.file_insertion_enabled
- and (self.options.has_key('file')
- or self.options.has_key('url')))):
+ and ('file' in self.options
+ or 'url' in self.options))):
raise self.warning('"%s" directive disabled.' % self.name)
attributes = {'format': ' '.join(self.arguments[0].lower().split())}
encoding = self.options.get(
'encoding', self.state.document.settings.input_encoding)
if self.content:
- if self.options.has_key('file') or self.options.has_key('url'):
+ if 'file' in self.options or 'url' in self.options:
raise self.error(
'"%s" directive may not both specify an external file '
'and have content.' % self.name)
text = '\n'.join(self.content)
- elif self.options.has_key('file'):
- if self.options.has_key('url'):
+ elif 'file' in self.options:
+ if 'url' in self.options:
raise self.error(
'The "file" and "url" options may not be simultaneously '
'specified for the "%s" directive.' % self.name)
@@ -159,7 +159,7 @@ class Raw(Directive):
'Problem with "%s" directive:\n%s: %s'
% (self.name, error.__class__.__name__, error))
attributes['source'] = path
- elif self.options.has_key('url'):
+ elif 'url' in self.options:
source = self.options['url']
# Do not import urllib2 at the top of the module because
# it may fail due to broken SSL dependencies, and it takes
@@ -244,12 +244,12 @@ class Unicode(Directive):
'Invalid context: the "%s" directive can only be used within '
'a substitution definition.' % self.name)
substitution_definition = self.state_machine.node
- if self.options.has_key('trim'):
+ if 'trim' in self.options:
substitution_definition.attributes['ltrim'] = 1
substitution_definition.attributes['rtrim'] = 1
- if self.options.has_key('ltrim'):
+ if 'ltrim' in self.options:
substitution_definition.attributes['ltrim'] = 1
- if self.options.has_key('rtrim'):
+ if 'rtrim' in self.options:
substitution_definition.attributes['rtrim'] = 1
codes = self.comment_pattern.split(self.arguments[0])[0].split()
element = nodes.Element()
@@ -349,7 +349,7 @@ class Role(Directive):
nodes.literal_block(self.block_text, self.block_text),
line=self.lineno)
return messages + [error]
- if not options.has_key('class'):
+ if 'class' not in options:
try:
options['class'] = directives.class_option(new_role_name)
except ValueError, detail:
@@ -373,7 +373,7 @@ class DefaultRole(Directive):
def run(self):
if not self.arguments:
- if roles._roles.has_key(''):
+ if '' in roles._roles:
# restore the "default" default role
del roles._roles['']
return []
diff --git a/docutils/parsers/rst/directives/parts.py b/docutils/parsers/rst/directives/parts.py
index da1586275..6ef8c905c 100644
--- a/docutils/parsers/rst/directives/parts.py
+++ b/docutils/parsers/rst/directives/parts.py
@@ -57,13 +57,13 @@ class Contents(Directive):
title = nodes.title(title_text, '', *text_nodes)
else:
messages = []
- if self.options.has_key('local'):
+ if 'local' in self.options:
title = None
else:
title = nodes.title('', language.labels['contents'])
topic = nodes.topic(classes=['contents'])
topic['classes'] += self.options.get('class', [])
- if self.options.has_key('local'):
+ if 'local' in self.options:
topic['classes'].append('local')
if title:
name = title.astext()
diff --git a/docutils/parsers/rst/directives/tables.py b/docutils/parsers/rst/directives/tables.py
index 639ce8d1f..5527c9f0b 100644
--- a/docutils/parsers/rst/directives/tables.py
+++ b/docutils/parsers/rst/directives/tables.py
@@ -49,7 +49,7 @@ class Table(Directive):
source = self.state_machine.get_source(self.lineno - 1)
table_head = []
max_header_cols = 0
- if self.options.has_key('header'): # separate table header in option
+ if 'header' in self.options: # separate table header in option
rows, max_header_cols = self.parse_csv_data_into_rows(
self.options['header'].split('\n'), self.HeaderDialect(),
source)
@@ -88,7 +88,7 @@ class Table(Directive):
raise SystemMessagePropagation(error)
def get_column_widths(self, max_cols):
- if self.options.has_key('widths'):
+ if 'widths' in self.options:
col_widths = self.options['widths']
if len(col_widths) != max_cols:
error = self.state_machine.reporter.error(
@@ -170,13 +170,13 @@ class CSVTable(Table):
quoting = csv.QUOTE_MINIMAL
def __init__(self, options):
- if options.has_key('delim'):
+ if 'delim' in options:
self.delimiter = str(options['delim'])
- if options.has_key('keepspace'):
+ if 'keepspace' in options:
self.skipinitialspace = False
- if options.has_key('quote'):
+ if 'quote' in options:
self.quotechar = str(options['quote'])
- if options.has_key('escape'):
+ if 'escape' in options:
self.doublequote = False
self.escapechar = str(options['escape'])
csv.Dialect.__init__(self)
@@ -206,8 +206,8 @@ class CSVTable(Table):
def run(self):
try:
if (not self.state.document.settings.file_insertion_enabled
- and (self.options.has_key('file')
- or self.options.has_key('url'))):
+ and ('file' in self.options
+ or 'url' in self.options)):
warning = self.state_machine.reporter.warning(
'File and URL access deactivated; ignoring "%s" '
'directive.' % self.name, nodes.literal_block(
@@ -253,7 +253,7 @@ class CSVTable(Table):
'encoding', self.state.document.settings.input_encoding)
if self.content:
# CSV data is from directive content.
- if self.options.has_key('file') or self.options.has_key('url'):
+ if 'file' in self.options or 'url' in self.options:
error = self.state_machine.reporter.error(
'"%s" directive may not both specify an external file and'
' have content.' % self.name, nodes.literal_block(
@@ -261,9 +261,9 @@ class CSVTable(Table):
raise SystemMessagePropagation(error)
source = self.content.source(0)
csv_data = self.content
- elif self.options.has_key('file'):
+ elif 'file' in self.options:
# CSV data is from an external file.
- if self.options.has_key('url'):
+ if 'url' in self.options:
error = self.state_machine.reporter.error(
'The "file" and "url" options may not be simultaneously'
' specified for the "%s" directive.' % self.name,
@@ -289,7 +289,7 @@ class CSVTable(Table):
% (self.name, error), nodes.literal_block(
self.block_text, self.block_text), line=self.lineno)
raise SystemMessagePropagation(severe)
- elif self.options.has_key('url'):
+ elif 'url' in self.options:
# CSV data is from a URL.
# Do not import urllib2 at the top of the module because
# it may fail due to broken SSL dependencies, and it takes
diff --git a/docutils/parsers/rst/languages/__init__.py b/docutils/parsers/rst/languages/__init__.py
index 18c884748..962802245 100644
--- a/docutils/parsers/rst/languages/__init__.py
+++ b/docutils/parsers/rst/languages/__init__.py
@@ -15,7 +15,7 @@ __docformat__ = 'reStructuredText'
_languages = {}
def get_language(language_code):
- if _languages.has_key(language_code):
+ if language_code in _languages:
return _languages[language_code]
try:
module = __import__(language_code, globals(), locals())
diff --git a/docutils/parsers/rst/languages/de.py b/docutils/parsers/rst/languages/de.py
index ecdde3837..300a8a30f 100644
--- a/docutils/parsers/rst/languages/de.py
+++ b/docutils/parsers/rst/languages/de.py
@@ -1,6 +1,6 @@
# $Id$
# Authors: Engelbert Gruber <grubert@users.sourceforge.net>;
-# Felix Wiemann <Felix.Wiemann@ososo.de>
+# Lea Wiemann <LeWiemann@gmail.com>
# Copyright: This module has been placed in the public domain.
# New language mappings are welcome. Before doing a new translation, please
diff --git a/docutils/parsers/rst/roles.py b/docutils/parsers/rst/roles.py
index 1da1395e9..062d53e50 100644
--- a/docutils/parsers/rst/roles.py
+++ b/docutils/parsers/rst/roles.py
@@ -101,7 +101,7 @@ def role(role_name, language_module, lineno, reporter):
messages = []
msg_text = []
- if _roles.has_key(normname):
+ if normname in _roles:
return _roles[normname], messages
if role_name:
@@ -135,7 +135,7 @@ def role(role_name, language_module, lineno, reporter):
messages.append(message)
# Look the role up in the registry, and return it.
- if _role_registry.has_key(canonicalname):
+ if canonicalname in _role_registry:
role_fn = _role_registry[canonicalname]
register_local_role(normname, role_fn)
return role_fn, messages
@@ -171,7 +171,7 @@ def set_implicit_options(role_fn):
"""
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'):
+ elif 'class' not in role_fn.options:
role_fn.options['class'] = directives.class_option
def register_generic_role(canonical_name, node_class):
@@ -294,7 +294,7 @@ def rfc_reference_role(role, rawtext, text, lineno, inliner,
register_canonical_role('rfc-reference', rfc_reference_role)
def raw_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
- if not options.has_key('format'):
+ if 'format' not in options:
msg = inliner.reporter.error(
'No format (Writer name) is associated with this role: "%s".\n'
'The "raw" role cannot be used directly.\n'
@@ -340,7 +340,7 @@ 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')
+ if 'class' in options:
+ assert 'classes' not in options
options['classes'] = options['class']
del options['class']
diff --git a/docutils/parsers/rst/states.py b/docutils/parsers/rst/states.py
index 50f5dd082..d5efb20e5 100644
--- a/docutils/parsers/rst/states.py
+++ b/docutils/parsers/rst/states.py
@@ -512,8 +512,8 @@ class Inliner:
non_whitespace_before = r'(?<![ \n])'
non_whitespace_escape_before = r'(?<![ \n\x00])'
non_whitespace_after = r'(?![ \n])'
- # Alphanumerics with isolated internal [-._] chars (i.e. not 2 together):
- simplename = r'(?:(?!_)\w)+(?:[-._](?:(?!_)\w)+)*'
+ # Alphanumerics with isolated internal [-._+:] chars (i.e. not 2 together):
+ simplename = r'(?:(?!_)\w)+(?:[-._+:](?:(?!_)\w)+)*'
# Valid URI characters (see RFC 2396 & RFC 2732);
# final \x00 allows backslash escapes in URIs:
uric = r"""[-_.!~*'()[\];/:@&=+$,%a-zA-Z0-9\x00]"""
@@ -901,8 +901,8 @@ class Inliner:
return self.reference(match, lineno, anonymous=1)
def standalone_uri(self, match, lineno):
- if not match.group('scheme') or urischemes.schemes.has_key(
- match.group('scheme').lower()):
+ if (not match.group('scheme')
+ or match.group('scheme').lower() in urischemes.schemes):
if match.group('email'):
addscheme = 'mailto:'
else:
@@ -2249,7 +2249,8 @@ class Body(RSTState):
if expmatch:
try:
return method(self, expmatch)
- except MarkupError, (message, lineno): # never reached?
+ except MarkupError, error: # never reached?
+ message, lineno = error.args
errors.append(self.reporter.warning(message, line=lineno))
break
nodelist, blank_finish = self.comment(match)
diff --git a/docutils/readers/__init__.py b/docutils/readers/__init__.py
index 74db893f9..a28248f70 100644
--- a/docutils/readers/__init__.py
+++ b/docutils/readers/__init__.py
@@ -101,7 +101,7 @@ _reader_aliases = {}
def get_reader_class(reader_name):
"""Return the Reader class from the `reader_name` module."""
reader_name = reader_name.lower()
- if _reader_aliases.has_key(reader_name):
+ if reader_name in _reader_aliases:
reader_name = _reader_aliases[reader_name]
module = __import__(reader_name, globals(), locals())
return module.Reader
diff --git a/docutils/readers/python/__init__.py b/docutils/readers/python/__init__.py
index da8fb22d2..eac284a7e 100644
--- a/docutils/readers/python/__init__.py
+++ b/docutils/readers/python/__init__.py
@@ -94,7 +94,7 @@ class DocstringFormattingVisitor(nodes.SparseNodeVisitor):
visitation, so parser instances are cached.
"""
parser_name = parsers._parser_aliases.get(parser_name, parser_name)
- if not self.parsers.has_key(parser_name):
+ if parser_name not in self.parsers:
cls = parsers.get_parser_class(parser_name)
self.parsers[parser_name] = cls()
return self.parsers[parser_name]
diff --git a/docutils/readers/python/moduleparser.py b/docutils/readers/python/moduleparser.py
index 5e63c9876..fadb3586b 100644
--- a/docutils/readers/python/moduleparser.py
+++ b/docutils/readers/python/moduleparser.py
@@ -53,78 +53,78 @@ The module parser will produce this module documentation tree::
<docstring lineno="5">
Additional docstring
<attribute lineno="7">
- <object_name>
- __docformat__
+ <object_name>
+ __docformat__
<expression_value lineno="7">
'reStructuredText'
<attribute lineno="9">
- <object_name>
- a
+ <object_name>
+ a
<expression_value lineno="9">
1
<docstring lineno="10">
Attribute docstring
<class_section lineno="12">
- <object_name>
- C
+ <object_name>
+ C
<class_base>
- Super
+ Super
<docstring lineno="12">
C's docstring
<attribute lineno="16">
- <object_name>
- class_attribute
+ <object_name>
+ class_attribute
<expression_value lineno="16">
1
<docstring lineno="17">
class_attribute's docstring
<method_section lineno="19">
- <object_name>
- __init__
+ <object_name>
+ __init__
<docstring lineno="19">
__init__'s docstring
<parameter_list lineno="19">
<parameter lineno="19">
- <object_name>
- self
+ <object_name>
+ self
<parameter lineno="19">
- <object_name>
- text
+ <object_name>
+ text
<parameter_default lineno="19">
None
<attribute lineno="22">
- <object_name>
- self.instance_attribute
+ <object_name>
+ self.instance_attribute
<expression_value lineno="22">
(text * 7 + ' whaddyaknow')
<docstring lineno="24">
instance_attribute's docstring
<function_section lineno="27">
- <object_name>
- f
+ <object_name>
+ f
<docstring lineno="27">
f's docstring
<parameter_list lineno="27">
<parameter lineno="27">
- <object_name>
- x
+ <object_name>
+ x
<comment>
# parameter x
<parameter lineno="27">
- <object_name>
- y
+ <object_name>
+ y
<parameter_default lineno="27">
a * 5
<comment>
# parameter y
<parameter excess_positional="1" lineno="27">
- <object_name>
- args
+ <object_name>
+ args
<comment>
# parameter args
<attribute lineno="33">
- <object_name>
- f.function_attribute
+ <object_name>
+ f.function_attribute
<expression_value lineno="33">
1
<docstring lineno="34">
@@ -525,14 +525,14 @@ class TokenParser:
def note_token(self):
if self.type == tokenize.NL:
return
- del_ws = self.del_ws_prefix.has_key(self.string)
- append_ws = not self.no_ws_suffix.has_key(self.string)
- if self.openers.has_key(self.string):
+ del_ws = self.string in self.del_ws_prefix
+ append_ws = self.string not in self.no_ws_suffix
+ if self.string in self.openers:
self.stack.append(self.string)
if (self._type == token.NAME
- or self.closers.has_key(self._string)):
+ or self._string in self.closers):
del_ws = 1
- elif self.closers.has_key(self.string):
+ elif self.string in self.closers:
assert self.stack[-1] == self.closers[self.string]
self.stack.pop()
elif self.string == '`':
diff --git a/docutils/statemachine.py b/docutils/statemachine.py
index 514e5dbd1..c29f128a7 100644
--- a/docutils/statemachine.py
+++ b/docutils/statemachine.py
@@ -377,7 +377,7 @@ class StateMachine:
self.next_line(len(block) - 1)
return block
except UnexpectedIndentationError, error:
- block, source, lineno = error
+ block, source, lineno = error.args
self.next_line(len(block) - 1) # advance to last line of block
raise
@@ -441,7 +441,7 @@ class StateMachine:
added.
"""
statename = state_class.__name__
- if self.states.has_key(statename):
+ if statename in self.states:
raise DuplicateStateError(statename)
self.states[statename] = state_class(self, self.debug)
@@ -629,9 +629,9 @@ class State:
Exceptions: `DuplicateTransitionError`, `UnknownTransitionError`.
"""
for name in names:
- if self.transitions.has_key(name):
+ if name in self.transitions:
raise DuplicateTransitionError(name)
- if not transitions.has_key(name):
+ if name not in transitions:
raise UnknownTransitionError(name)
self.transition_order[:0] = names
self.transitions.update(transitions)
@@ -644,7 +644,7 @@ class State:
Exception: `DuplicateTransitionError`.
"""
- if self.transitions.has_key(name):
+ if name in self.transitions:
raise DuplicateTransitionError(name)
self.transition_order[:0] = [name]
self.transitions[name] = transition
diff --git a/docutils/transforms/frontmatter.py b/docutils/transforms/frontmatter.py
index eae149a44..cd537f910 100644
--- a/docutils/transforms/frontmatter.py
+++ b/docutils/transforms/frontmatter.py
@@ -388,7 +388,7 @@ class DocInfo(Transform):
try:
name = field[0][0].astext()
normedname = nodes.fully_normalize_name(name)
- if not (len(field) == 2 and bibliofields.has_key(normedname)
+ if not (len(field) == 2 and normedname in bibliofields
and self.check_empty_biblio_field(field, name)):
raise TransformError
canonical = bibliofields[normedname]
diff --git a/docutils/transforms/parts.py b/docutils/transforms/parts.py
index 39cb74f75..26fcdb684 100644
--- a/docutils/transforms/parts.py
+++ b/docutils/transforms/parts.py
@@ -80,7 +80,7 @@ class Contents(Transform):
def apply(self):
details = self.startnode.details
- if details.has_key('local'):
+ if 'local' in details:
startnode = self.startnode.parent.parent
while not (isinstance(startnode, nodes.section)
or isinstance(startnode, nodes.document)):
@@ -89,7 +89,7 @@ class Contents(Transform):
else:
startnode = self.document
self.toc_id = self.startnode.parent['ids'][0]
- if details.has_key('backlinks'):
+ if 'backlinks' in details:
self.backlinks = details['backlinks']
else:
self.backlinks = self.document.settings.toc_backlinks
diff --git a/docutils/transforms/references.py b/docutils/transforms/references.py
index 097877ee9..c45fdb0da 100644
--- a/docutils/transforms/references.py
+++ b/docutils/transforms/references.py
@@ -240,7 +240,7 @@ class IndirectHyperlinks(Transform):
del target.multiply_indirect
if reftarget.hasattr('refuri'):
target['refuri'] = reftarget['refuri']
- if target.has_key('refid'):
+ if 'refid' in target:
del target['refid']
elif reftarget.hasattr('refid'):
target['refid'] = reftarget['refid']
@@ -257,7 +257,7 @@ class IndirectHyperlinks(Transform):
target.resolved = 1
def nonexistent_indirect_target(self, target):
- if self.document.nameids.has_key(target['refname']):
+ if target['refname'] in self.document.nameids:
self.indirect_target_error(target, 'which is a duplicate, and '
'cannot be used as a unique reference')
else:
@@ -505,7 +505,7 @@ class Footnotes(Transform):
while 1:
label = str(startnum)
startnum += 1
- if not self.document.nameids.has_key(label):
+ if label not in self.document.nameids:
break
footnote.insert(0, nodes.label('', label))
for name in footnote['names']:
@@ -600,12 +600,12 @@ class Footnotes(Transform):
"""
for footnote in self.document.footnotes:
for label in footnote['names']:
- if self.document.footnote_refs.has_key(label):
+ if label in self.document.footnote_refs:
reflist = self.document.footnote_refs[label]
self.resolve_references(footnote, reflist)
for citation in self.document.citations:
for label in citation['names']:
- if self.document.citation_refs.has_key(label):
+ if label in self.document.citation_refs:
reflist = self.document.citation_refs[label]
self.resolve_references(citation, reflist)
@@ -666,11 +666,11 @@ class Substitutions(Transform):
for ref in subreflist:
refname = ref['refname']
key = None
- if defs.has_key(refname):
+ if refname in defs:
key = refname
else:
normed_name = refname.lower()
- if normed.has_key(normed_name):
+ if normed_name in normed:
key = normed[normed_name]
if key is None:
msg = self.document.reporter.error(
@@ -686,14 +686,14 @@ class Substitutions(Transform):
subdef = defs[key]
parent = ref.parent
index = parent.index(ref)
- if (subdef.attributes.has_key('ltrim')
- or subdef.attributes.has_key('trim')):
+ if ('ltrim' in subdef.attributes
+ or 'trim' in subdef.attributes):
if index > 0 and isinstance(parent[index - 1],
nodes.Text):
parent.replace(parent[index - 1],
parent[index - 1].rstrip())
- if (subdef.attributes.has_key('rtrim')
- or subdef.attributes.has_key('trim')):
+ if ('rtrim' in subdef.attributes
+ or 'trim' in subdef.attributes):
if (len(parent) > index + 1
and isinstance(parent[index + 1], nodes.Text)):
parent.replace(parent[index + 1],
@@ -764,7 +764,7 @@ class TargetNotes(Transform):
continue
footnote = self.make_target_footnote(target['refuri'], refs,
notes)
- if not notes.has_key(target['refuri']):
+ if target['refuri'] not in notes:
notes[target['refuri']] = footnote
nodelist.append(footnote)
# Take care of anonymous references.
@@ -774,13 +774,13 @@ class TargetNotes(Transform):
if ref.hasattr('refuri'):
footnote = self.make_target_footnote(ref['refuri'], [ref],
notes)
- if not notes.has_key(ref['refuri']):
+ if ref['refuri'] not in notes:
notes[ref['refuri']] = footnote
nodelist.append(footnote)
self.startnode.replace_self(nodelist)
def make_target_footnote(self, refuri, refs, notes):
- if notes.has_key(refuri): # duplicate?
+ if refuri in notes: # duplicate?
footnote = notes[refuri]
assert len(footnote['names']) == 1
footnote_name = footnote['names'][0]
@@ -873,7 +873,7 @@ class DanglingReferencesVisitor(nodes.SparseNodeVisitor):
if resolver_function(node):
break
else:
- if self.document.nameids.has_key(refname):
+ if refname in self.document.nameids:
msg = self.document.reporter.error(
'Duplicate target name, cannot be used as a unique '
'reference: "%s".' % (node['refname']), base_node=node)
diff --git a/docutils/transforms/writer_aux.py b/docutils/transforms/writer_aux.py
index 6be338338..0db085fb0 100644
--- a/docutils/transforms/writer_aux.py
+++ b/docutils/transforms/writer_aux.py
@@ -1,5 +1,5 @@
# $Id$
-# Author: Felix Wiemann <Felix.Wiemann@ososo.de>
+# Author: Lea Wiemann <LeWiemann@gmail.com>
# Copyright: This module has been placed in the public domain.
"""
diff --git a/docutils/utils.py b/docutils/utils.py
index 456f3eed9..b88ffbbc1 100644
--- a/docutils/utils.py
+++ b/docutils/utils.py
@@ -161,7 +161,7 @@ class Reporter:
Raise an exception or generate a warning if appropriate.
"""
attributes = kwargs.copy()
- if kwargs.has_key('base_node'):
+ if 'base_node' in kwargs:
source, line = get_source_line(kwargs['base_node'])
del attributes['base_node']
if source is not None:
@@ -308,7 +308,7 @@ def assemble_option_dict(option_list, options_spec):
convertor = options_spec[name] # raises KeyError if unknown
if convertor is None:
raise KeyError(name) # or if explicitly disabled
- if options.has_key(name):
+ if name in options:
raise DuplicateOptionError('duplicate option "%s"' % name)
try:
options[name] = convertor(value)
@@ -404,9 +404,9 @@ def clean_rcs_keywords(paragraph, keyword_substitutions):
if len(paragraph) == 1 and isinstance(paragraph[0], nodes.Text):
textnode = paragraph[0]
for pattern, substitution in keyword_substitutions:
- match = pattern.search(textnode.data)
+ match = pattern.search(textnode)
if match:
- textnode.data = pattern.sub(substitution, textnode.data)
+ paragraph[0] = nodes.Text(pattern.sub(substitution, textnode))
return
def relative_path(source, target):
diff --git a/docutils/writers/__init__.py b/docutils/writers/__init__.py
index 39e1ecd5b..8e3bd1aaa 100644
--- a/docutils/writers/__init__.py
+++ b/docutils/writers/__init__.py
@@ -127,7 +127,7 @@ _writer_aliases = {
def get_writer_class(writer_name):
"""Return the Writer class from the `writer_name` module."""
writer_name = writer_name.lower()
- if _writer_aliases.has_key(writer_name):
+ if writer_name in _writer_aliases:
writer_name = _writer_aliases[writer_name]
module = __import__(writer_name, globals(), locals())
return module.Writer
diff --git a/docutils/writers/html4css1/__init__.py b/docutils/writers/html4css1/__init__.py
index 693672b76..57d2c6ef0 100644
--- a/docutils/writers/html4css1/__init__.py
+++ b/docutils/writers/html4css1/__init__.py
@@ -353,13 +353,13 @@ class HTMLTranslator(nodes.NodeVisitor):
for (name, value) in attributes.items():
atts[name.lower()] = value
classes = node.get('classes', [])
- if atts.has_key('class'):
+ if 'class' in atts:
classes.append(atts['class'])
if classes:
atts['class'] = ' '.join(classes)
- assert not atts.has_key('id')
+ assert 'id' not in atts
ids.extend(node.get('ids', []))
- if atts.has_key('ids'):
+ if 'ids' in atts:
ids.extend(atts['ids'])
del atts['ids']
if ids:
@@ -712,7 +712,7 @@ class HTMLTranslator(nodes.NodeVisitor):
assert not self.context, 'len(context) = %s' % len(self.context)
def visit_emphasis(self, node):
- self.body.append('<em>')
+ self.body.append(self.starttag(node, 'em', ''))
def depart_emphasis(self, node):
self.body.append('</em>')
@@ -731,9 +731,9 @@ class HTMLTranslator(nodes.NodeVisitor):
tagname = 'td'
del atts['class']
node.parent.column += 1
- if node.has_key('morerows'):
+ if 'morerows' in node:
atts['rowspan'] = node['morerows'] + 1
- if node.has_key('morecols'):
+ if 'morecols' in node:
atts['colspan'] = node['morecols'] + 1
node.parent.column += node['morecols']
self.body.append(self.starttag(node, tagname, '', **atts))
@@ -752,9 +752,9 @@ class HTMLTranslator(nodes.NodeVisitor):
usable.
"""
atts = {}
- if node.has_key('start'):
+ if 'start' in node:
atts['start'] = node['start']
- if node.has_key('enumtype'):
+ if 'enumtype' in node:
atts['class'] = node['enumtype']
# @@@ To do: prefix, suffix. How? Change prefix/suffix to a
# single "format" attribute? Use CSS2?
@@ -941,26 +941,26 @@ class HTMLTranslator(nodes.NodeVisitor):
def visit_image(self, node):
atts = {}
atts['src'] = node['uri']
- if node.has_key('width'):
+ if 'width' in node:
atts['width'] = node['width']
- if node.has_key('height'):
+ if 'height' in node:
atts['height'] = node['height']
- if node.has_key('scale'):
- if Image and not (node.has_key('width')
- and node.has_key('height')):
+ if 'scale' in node:
+ if Image and not ('width' in node
+ and 'height' in node):
try:
im = Image.open(str(atts['src']))
except (IOError, # Source image can't be found or opened
UnicodeError): # PIL doesn't like Unicode paths.
pass
else:
- if not atts.has_key('width'):
+ if 'width' not in atts:
atts['width'] = str(im.size[0])
- if not atts.has_key('height'):
+ if 'height' not in atts:
atts['height'] = str(im.size[1])
del im
for att_name in 'width', 'height':
- if atts.has_key(att_name):
+ if att_name in atts:
match = re.match(r'([0-9.]+)(\S*)$', atts[att_name])
assert match
atts[att_name] = '%s%s' % (
@@ -968,7 +968,7 @@ class HTMLTranslator(nodes.NodeVisitor):
match.group(2))
style = []
for att_name in 'width', 'height':
- if atts.has_key(att_name):
+ if att_name in atts:
if re.match(r'^[0-9.]+$', atts[att_name]):
# Interpret unitless values as pixels.
atts[att_name] += 'px'
@@ -984,7 +984,7 @@ class HTMLTranslator(nodes.NodeVisitor):
suffix = ''
else:
suffix = '\n'
- if node.has_key('align'):
+ if 'align' in node:
if node['align'] == 'center':
# "align" attribute is set in surrounding "div" element.
self.body.append('<div align="center" class="align-center">')
@@ -1167,12 +1167,11 @@ class HTMLTranslator(nodes.NodeVisitor):
if child is node:
break
return 0
+ parent_length = len([n for n in node.parent if not isinstance(
+ n, (nodes.Invisible, nodes.label))])
if ( self.compact_simple
or self.compact_field_list
- or (self.compact_p
- and (len(node.parent) == 1
- or len(node.parent) == 2
- and isinstance(node.parent[0], nodes.label)))):
+ or self.compact_p and parent_length == 1):
return 1
return 0
@@ -1210,17 +1209,19 @@ class HTMLTranslator(nodes.NodeVisitor):
raise nodes.SkipNode
def visit_reference(self, node):
- if node.has_key('refuri'):
- href = node['refuri']
+ atts = {'class': 'reference'}
+ if 'refuri' in node:
+ atts['href'] = node['refuri']
if ( self.settings.cloak_email_addresses
- and href.startswith('mailto:')):
- href = self.cloak_mailto(href)
+ and atts['href'].startswith('mailto:')):
+ atts['href'] = self.cloak_mailto(atts['href'])
self.in_mailto = 1
+ atts['class'] += ' external'
else:
- assert node.has_key('refid'), \
+ assert 'refid' in node, \
'References must have "refuri" or "refid" attribute.'
- href = '#' + node['refid']
- atts = {'href': href, 'class': 'reference'}
+ atts['href'] = '#' + node['refid']
+ atts['class'] += ' internal'
if not isinstance(node.parent, nodes.TextElement):
assert len(node) == 1 and isinstance(node[0], nodes.image)
atts['class'] += ' image-reference'
@@ -1277,7 +1278,7 @@ class HTMLTranslator(nodes.NodeVisitor):
self.depart_docinfo_item()
def visit_strong(self, node):
- self.body.append('<strong>')
+ self.body.append(self.starttag(node, 'strong', ''))
def depart_strong(self, node):
self.body.append('</strong>')
@@ -1363,8 +1364,8 @@ class HTMLTranslator(nodes.NodeVisitor):
self.body.append('</table>\n')
def visit_target(self, node):
- if not (node.has_key('refuri') or node.has_key('refid')
- or node.has_key('refname')):
+ if not ('refuri' in node or 'refid' in node
+ or 'refname' in node):
self.body.append(self.starttag(node, 'span', '', CLASS='target'))
self.context.append('</span>')
else:
diff --git a/docutils/writers/html4css1/html4css1.css b/docutils/writers/html4css1/html4css1.css
index 331a2979a..345f1cc85 100644
--- a/docutils/writers/html4css1/html4css1.css
+++ b/docutils/writers/html4css1/html4css1.css
@@ -106,7 +106,7 @@ div.line-block div.line-block {
margin-left: 1.5em }
div.sidebar {
- margin-left: 1em ;
+ margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
diff --git a/docutils/writers/latex2e/__init__.py b/docutils/writers/latex2e/__init__.py
index 0c459147e..4db7b67bf 100644
--- a/docutils/writers/latex2e/__init__.py
+++ b/docutils/writers/latex2e/__init__.py
@@ -21,6 +21,8 @@ from types import ListType
from docutils import frontend, nodes, languages, writers, utils
from docutils.writers.newlatex2e import unicode_map
+from docutils.transforms.references import DanglingReferencesVisitor
+
class Writer(writers.Writer):
supported = ('latex','latex2e')
@@ -74,6 +76,10 @@ class Writer(writers.Writer):
['--use-latex-toc'],
{'default': 0, 'action': 'store_true',
'validator': frontend.validate_boolean}),
+ ('Add parts on top of the section hierarchy.',
+ ['--use-part-section'],
+ {'default': 0, 'action': 'store_true',
+ 'validator': frontend.validate_boolean}),
('Let LaTeX print author and date, do not show it in docutils '
'document info.',
['--use-latex-docinfo'],
@@ -110,8 +116,12 @@ class Writer(writers.Writer):
'for compound enumerated lists. Default is "-".',
['--section-enumerator-separator'],
{'default': '-', 'metavar': '<char>'}),
+ ('When possibile, use the specified environment for literal-blocks. '
+ 'Default is quoting of whitespace and special chars.',
+ ['--literal-block-env'],
+ {'default': '', }),
('When possibile, use verbatim for literal-blocks. '
- 'Default is to always use the mbox environment.',
+ 'Compatibility alias for "--literal-block-env=verbatim".',
['--use-verbatim-when-possible'],
{'default': 0, 'action': 'store_true',
'validator': frontend.validate_boolean}),
@@ -153,6 +163,9 @@ class Writer(writers.Writer):
config_section = 'latex2e writer'
config_section_dependencies = ('writers',)
+ visitor_attributes = ("head_prefix", "head",
+ "body_prefix", "body", "body_suffix")
+
output = None
"""Final translated form of `document`."""
@@ -164,11 +177,15 @@ class Writer(writers.Writer):
visitor = self.translator_class(self.document)
self.document.walkabout(visitor)
self.output = visitor.astext()
- self.head_prefix = visitor.head_prefix
- self.head = visitor.head
- self.body_prefix = visitor.body_prefix
- self.body = visitor.body
- self.body_suffix = visitor.body_suffix
+ # copy parts
+ for attr in self.visitor_attributes:
+ setattr(self, attr, getattr(visitor, attr))
+
+ def assemble_parts(self):
+ writers.Writer.assemble_parts(self)
+ for part in self.visitor_attributes:
+ self.parts[part] = ''.join(getattr(self, part))
+
"""
Notes on LaTeX
@@ -177,6 +194,9 @@ Notes on LaTeX
* LaTeX does not support multiple tocs in one document.
(might be no limitation except for docutils documentation)
+ The "minitoc" latex package can produce per-chapter tocs in
+ book and report document classes.
+
* width
* linewidth - width of a line in the local environment
@@ -276,13 +296,13 @@ class Babel:
return text.replace('"', self.double_quote_replacment)
def get_language(self):
- if self._ISO639_TO_BABEL.has_key(self.language):
+ if self.language in self._ISO639_TO_BABEL:
return self._ISO639_TO_BABEL[self.language]
else:
# support dialects.
- l = self.language.split("_")[0]
- if self._ISO639_TO_BABEL.has_key(l):
- return self._ISO639_TO_BABEL[l]
+ lang = self.language.split("_")[0]
+ if lang in self._ISO639_TO_BABEL:
+ return self._ISO639_TO_BABEL[lang]
return None
@@ -336,22 +356,9 @@ latex_headings = {
class DocumentClass:
"""Details of a LaTeX document class."""
- # BUG: LaTeX has no deeper sections (actually paragrah is no
- # section either).
- # BUG: No support for unknown document classes. Make 'article'
- # default?
- _class_sections = {
- 'book': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
- 'scrbook': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
- 'report': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
- 'scrreprt': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
- 'article': ( 'section', 'subsection', 'subsubsection' ),
- 'scrartcl': ( 'section', 'subsection', 'subsubsection' ),
- }
- _deepest_section = 'subsubsection'
-
- def __init__(self, document_class):
+ def __init__(self, document_class, with_part=False):
self.document_class = document_class
+ self._with_part = with_part
def section(self, level):
""" Return the section name at the given level for the specific
@@ -359,11 +366,16 @@ class DocumentClass:
Level is 1,2,3..., as level 0 is the title."""
- sections = self._class_sections[self.document_class]
+ sections = [ 'section', 'subsection', 'subsubsection',
+ 'paragraph', 'subparagraph' ]
+ if self.document_class in ('book', 'report', 'scrreprt', 'scrbook'):
+ sections.insert(0, 'chapter')
+ if self._with_part:
+ sections.insert(0, 'part')
if level <= len(sections):
return sections[level-1]
else:
- return self._deepest_section
+ return sections[-1]
class Table:
""" Manage a table while traversing.
@@ -384,6 +396,7 @@ class Table:
self._attrs = {}
self._col_width = []
self._rowspan = []
+ self.stubs = []
def open(self):
self._open = 1
@@ -396,8 +409,10 @@ class Table:
self._col_specs = None
self.caption = None
self._attrs = {}
+ self.stubs = []
def is_open(self):
return self._open
+
def set_table_style(self, table_style):
if not table_style in ('standard','booktabs','borderless','nolines'):
return
@@ -413,7 +428,7 @@ class Table:
def set(self,attr,value):
self._attrs[attr] = value
def get(self,attr):
- if self._attrs.has_key(attr):
+ if attr in self._attrs:
return self._attrs[attr]
return None
def get_vertical_bar(self):
@@ -422,7 +437,12 @@ class Table:
return ''
# horizontal lines are drawn below a row, because we.
def get_opening(self):
- return '\\begin{%s}[c]' % self._latex_type
+ if self._latex_type == 'longtable':
+ # otherwise longtable might move before paragraph and subparagraph
+ prefix = '\\leavevmode\n'
+ else:
+ prefix = ''
+ return '%s\\begin{%s}[c]' % (prefix, self._latex_type)
def get_closing(self):
line = ""
if self._table_style == 'booktabs':
@@ -431,8 +451,10 @@ class Table:
lines = '\\hline\n'
return '%s\\end{%s}' % (line,self._latex_type)
- def visit_colspec(self,node):
+ def visit_colspec(self, node):
self._col_specs.append(node)
+ # "stubs" list is an attribute of the tgroup element:
+ self.stubs.append(node.attributes.get('stub'))
def get_colspecs(self):
"""
@@ -466,7 +488,7 @@ class Table:
colwidth = factor * float(node['colwidth']+1) / width
self._col_width.append(colwidth+0.005)
self._rowspan.append(0)
- latex_table_spec += "%sp{%.2f\\locallinewidth}" % (bar,colwidth+0.005)
+ latex_table_spec += "%sp{%.3f\\locallinewidth}" % (bar,colwidth+0.005)
return latex_table_spec+bar
def get_column_width(self):
@@ -487,7 +509,8 @@ class Table:
# a.append('\\hline\n')
if self._table_style == 'booktabs':
a.append('\\midrule\n')
- a.append('\\endhead\n')
+ if self._latex_type == 'longtable':
+ a.append('\\endhead\n')
# for longtable one could add firsthead, foot and lastfoot
self._in_thead = 0
return a
@@ -534,6 +557,10 @@ class Table:
return self._cell_in_row
def visit_entry(self):
self._cell_in_row += 1
+ def is_stub_column(self):
+ if len(self.stubs) >= self._cell_in_row:
+ return self.stubs[self._cell_in_row-1]
+ return False
class LaTeXTranslator(nodes.NodeVisitor):
@@ -541,12 +568,19 @@ class LaTeXTranslator(nodes.NodeVisitor):
# When options are given to the documentclass, latex will pass them
# to other packages, as done with babel.
# Dummy settings might be taken from document settings
-
+
+ # Templates
+ # ---------
+
latex_head = '\\documentclass[%s]{%s}\n'
- linking = '\\usepackage[colorlinks=%s,linkcolor=%s,urlcolor=%s]{hyperref}\n'
+ linking = "\\ifthenelse{\\isundefined{\\hypersetup}}{\n" \
+ +"\\usepackage[colorlinks=%s,linkcolor=%s,urlcolor=%s]{hyperref}\n" \
+ +"}{}\n"
stylesheet = '\\input{%s}\n'
# add a generated on day , machine by user using docutils version.
- generator = '%% generator Docutils: http://docutils.sourceforge.net/\n'
+ generator = '% generated by Docutils <http://docutils.sourceforge.net/>\n'
+ # Config setting defaults
+ # -----------------------
# use latex tableofcontents or let docutils do it.
use_latex_toc = 0
@@ -592,6 +626,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
if self.settings.use_bibtex:
self.bibtex = self.settings.use_bibtex.split(",",1)
+ # TODO avoid errors on not declared citations.
else:
self.bibtex = None
# language: labels, bibliographic_fields, and author_separators.
@@ -601,11 +636,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.author_separator = self.language.author_separators[0]
self.d_options = self.settings.documentoptions
if self.babel.get_language():
- self.d_options += ',%s' % \
- self.babel.get_language()
+ self.d_options += ',%s' % self.babel.get_language()
- self.d_class = DocumentClass(settings.documentclass)
+ self.d_class = DocumentClass(settings.documentclass,
+ settings.use_part_section)
# object for a table while proccessing.
+ self.table_stack = []
self.active_table = Table('longtable',settings.table_style)
# HACK. Should have more sophisticated typearea handling.
@@ -663,7 +699,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
'\\usepackage{color}\n',
'\\usepackage{multirow}\n',
'\\usepackage{ifthen}\n', # before hyperref!
- self.linking % (self.colorlinks, self.hyperlink_color, self.hyperlink_color),
self.typearea,
self.generator,
# latex lengths
@@ -687,17 +722,25 @@ class LaTeXTranslator(nodes.NodeVisitor):
if stylesheet:
settings.record_dependencies.add(stylesheet)
self.head_prefix.append(self.stylesheet % (stylesheet))
-
+ # hyperref after stylesheet
+ # TODO conditionally if no hyperref is used dont include
+ self.head_prefix.append( self.linking % (
+ self.colorlinks, self.hyperlink_color, self.hyperlink_color))
+
+ #
+ if self.settings.literal_block_env != '':
+ self.settings.use_verbatim_when_possible = True
if self.linking: # and maybe check for pdf
self.pdfinfo = [ ]
self.pdfauthor = None
- # pdftitle, pdfsubject, pdfauthor, pdfkeywords, pdfcreator, pdfproducer
+ # pdftitle, pdfsubject, pdfauthor, pdfkeywords,
+ # pdfcreator, pdfproducer
else:
self.pdfinfo = None
# NOTE: Latex wants a date and an author, rst puts this into
- # docinfo, so normally we donot want latex author/date handling.
+ # docinfo, so normally we do not 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
+ # self.astext() adds \title{...} \author{...} \date{...}, even if the
# "..." are empty strings.
self.head = [ ]
# separate title, so we can appen subtitle.
@@ -788,7 +831,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
#"iso-8859-8": "" # hebrew
#"iso-8859-10": "" # latin6, more complete iso-8859-4
}
- if tr.has_key(docutils_encoding.lower()):
+ if docutils_encoding.lower() in tr:
return tr[docutils_encoding.lower()]
# convert: latin-1 and utf-8 and similar things
return docutils_encoding.replace("_", "").replace("-", "").lower()
@@ -824,7 +867,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
return text
def ensure_math(self, text):
- if not self.__dict__.has_key('ensure_math_re'):
+ if not 'ensure_math_re' in self.__dict__:
chars = {
# lnot,pm,twosuperior,threesuperior,mu,onesuperior,times,div
'latin1' : '\xac\xb1\xb2\xb3\xb5\xb9\xd7\xf7' ,
@@ -848,10 +891,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
# compile the regexps once. do it here so one can see them.
#
# first the braces.
- if not self.__dict__.has_key('encode_re_braces'):
+ if not 'encode_re_braces' in self.__dict__:
self.encode_re_braces = re.compile(r'([{}])')
text = self.encode_re_braces.sub(r'{\\\1}',text)
- if not self.__dict__.has_key('encode_re_bslash'):
+ if not 'encode_re_bslash' in self.__dict__:
# find backslash: except in the form '{\{}' or '{\}}'.
self.encode_re_bslash = re.compile(r'(?<!{)(\\)(?![{}]})')
# then the backslash: except in the form from line above:
@@ -909,6 +952,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
# ! LaTeX Error: There's no line here to end.
text = text.replace("\n", '~\\\\\n')
elif self.mbox_newline:
+ # TODO dead code: remove after 0.5 release
if self.literal_block:
closings = "}" * len(self.literal_block_stack)
openings = "".join(self.literal_block_stack)
@@ -924,15 +968,26 @@ class LaTeXTranslator(nodes.NodeVisitor):
text = self.ensure_math(text)
return text
+ def literal_block_env(self, begin_or_end):
+ env = 'verbatim'
+ opt = ''
+ if self.settings.literal_block_env != '':
+ (none, env, opt, none) = re.split("(\w+)(.*)",
+ self.settings.literal_block_env)
+ if begin_or_end == 'begin':
+ return '\\begin{%s}%s\n' % (env, opt)
+ return '\n\\end{%s}\n' % (env, )
+
+
+
def attval(self, text,
whitespace=re.compile('[\n\r\t\v\f]')):
"""Cleanse, encode, and return attribute value text."""
return self.encode(whitespace.sub(' ', text))
def astext(self):
- if self.pdfinfo is not None:
- if self.pdfauthor:
- self.pdfinfo.append('pdfauthor={%s}' % self.pdfauthor)
+ if self.pdfinfo is not None and self.pdfauthor:
+ self.pdfinfo.append('pdfauthor={%s}' % self.pdfauthor)
if self.pdfinfo:
pdfinfo = '\\hypersetup{\n' + ',\n'.join(self.pdfinfo) + '\n}\n'
else:
@@ -1070,9 +1125,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.inside_citation_reference_label = 1
else:
href = ''
- if node.has_key('refid'):
+ if 'refid' in node:
href = node['refid']
- elif node.has_key('refname'):
+ elif 'refname' in node:
href = self.document.nameids[node['refname']]
self.body.append('[\\hyperlink{%s}{' % href)
@@ -1169,10 +1224,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append( '\\end{description}\n' )
def visit_definition_list_item(self, node):
- self.body.append('%[visit_definition_list_item]\n')
+ pass
def depart_definition_list_item(self, node):
- self.body.append('%[depart_definition_list_item]\n')
+ pass
def visit_description(self, node):
self.body.append( ' ' )
@@ -1250,9 +1305,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body_prefix.append('\\begin{document}\n')
# titled document?
if self.use_latex_docinfo or len(node) and isinstance(node[0], nodes.title):
- self.body_prefix.append('\\maketitle\n\n')
+ self.body_prefix.append('\\maketitle\n')
# alternative use titlepage environment.
# \begin{titlepage}
+ # ...
self.body.append('\n\\setlength{\\locallinewidth}{\\linewidth}\n')
def depart_document(self, node):
@@ -1302,17 +1358,17 @@ class LaTeXTranslator(nodes.NodeVisitor):
# IN WORK BUG TODO HACK continues here
# multirow in LaTeX simply will enlarge the cell over several rows
# (the following n if n is positive, the former if negative).
- if node.has_key('morerows') and node.has_key('morecols'):
+ if 'morerows' in node and 'morecols' in node:
raise NotImplementedError('Cells that '
'span multiple rows *and* columns are not supported, sorry.')
- if node.has_key('morerows'):
+ if 'morerows' in node:
count = node['morerows'] + 1
self.active_table.set_rowspan(self.active_table.get_entry_number()-1,count)
self.body.append('\\multirow{%d}{%s}{' % \
(count,self.active_table.get_column_width()))
self.context.append('}')
# BUG following rows must have empty cells.
- elif node.has_key('morecols'):
+ elif 'morecols' in node:
# the vertical bar before column is missing if it is the first column.
# the one after always.
if self.active_table.get_entry_number() == 1:
@@ -1330,6 +1386,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
if isinstance(node.parent.parent, nodes.thead):
self.body.append('\\textbf{')
self.context.append('}')
+ elif self.active_table.is_stub_column():
+ self.body.append('\\textbf{')
+ self.context.append('}')
else:
self.context.append('')
@@ -1357,10 +1416,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
'lowerroman':'roman',
'upperroman':'Roman' }
enum_suffix = ""
- if node.has_key('suffix'):
+ if 'suffix' in node:
enum_suffix = node['suffix']
enum_prefix = ""
- if node.has_key('prefix'):
+ if 'prefix' in node:
enum_prefix = node['prefix']
if self.compound_enumerators:
pref = ""
@@ -1372,9 +1431,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
for ctype, cname in self._enumeration_counters:
enum_prefix += '\\%s{%s}.' % (ctype, cname)
enum_type = "arabic"
- if node.has_key('enumtype'):
+ if 'enumtype' in node:
enum_type = node['enumtype']
- if enum_style.has_key(enum_type):
+ if enum_type in enum_style:
enum_type = enum_style[enum_type]
counter_name = "listcnt%d" % len(self._enumeration_counters)
@@ -1392,7 +1451,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('{\n')
self.body.append('\\usecounter{%s}\n' % counter_name)
# set start after usecounter, because it initializes to zero.
- if node.has_key('start'):
+ if 'start' in node:
self.body.append('\\addtocounter{%s}{%d}\n' \
% (counter_name,node['start']-1))
## set rightmargin equal to leftmargin
@@ -1456,7 +1515,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append(':]')
def visit_figure(self, node):
- if (not node.attributes.has_key('align') or
+ if ('align' not in node.attributes or
node.attributes['align'] == 'center'):
# centering does not add vertical space like center.
align = '\n\\centering'
@@ -1503,9 +1562,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append("\\footnotemark["+self.encode(node.astext())+"]")
raise nodes.SkipNode
href = ''
- if node.has_key('refid'):
+ if 'refid' in node:
href = node['refid']
- elif node.has_key('refname'):
+ elif 'refname' in node:
href = self.document.nameids[node['refname']]
format = self.settings.footnote_references
if format == 'brackets':
@@ -1589,18 +1648,18 @@ class LaTeXTranslator(nodes.NodeVisitor):
post = []
include_graphics_options = []
inline = isinstance(node.parent, nodes.TextElement)
- if attrs.has_key('scale'):
+ if 'scale' in attrs:
# Could also be done with ``scale`` option to
# ``\includegraphics``; doing it this way for consistency.
pre.append('\\scalebox{%f}{' % (attrs['scale'] / 100.0,))
post.append('}')
- if attrs.has_key('width'):
+ if 'width' in attrs:
include_graphics_options.append('width=%s' % (
self.latex_image_length(attrs['width']), ))
- if attrs.has_key('height'):
+ if 'height' in attrs:
include_graphics_options.append('height=%s' % (
self.latex_image_length(attrs['height']), ))
- if attrs.has_key('align'):
+ if 'align' in attrs:
align_prepost = {
# By default latex aligns the top of an image.
(1, 'top'): ('', ''),
@@ -1707,13 +1766,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
# table border and literal block.
# BUG: fails if normal text preceeds the literal block.
self.body.append('\\begin{quote}')
+ self.context.append('\\end{quote}\n')
else:
self.body.append('\n')
+ self.context.append('\n')
if (self.settings.use_verbatim_when_possible and (len(node) == 1)
# in case of a parsed-literal containing just a "**bold**" word:
and isinstance(node[0], nodes.Text)):
self.verbatim = 1
- self.body.append('\\begin{verbatim}\n')
+ self.body.append(self.literal_block_env('begin'))
else:
self.literal_block = 1
self.insert_none_breaking_blanks = 1
@@ -1723,17 +1784,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_literal_block(self, node):
if self.verbatim:
- self.body.append('\n\\end{verbatim}\\end{quote}\n')
+ self.body.append(self.literal_block_env('end'))
self.verbatim = 0
else:
- if self.active_table.is_open():
- self.body.append('\n}\n')
- else:
- self.body.append('\n')
- self.body.append('}\\end{quote}\n')
+ self.body.append('\n}')
self.insert_none_breaking_blanks = 0
self.literal_block = 0
# obey end: self.body.append('}\n')
+ self.body.append(self.context.pop())
def visit_meta(self, node):
self.body.append('[visit_meta]\n')
@@ -1775,9 +1833,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('] ')
def visit_option_list(self, node):
- # force new line after definition
- if isinstance(node.parent, nodes.definition):
- self.body.append('~\n')
self.body.append('\\begin{optionlist}{3cm}\n')
def depart_option_list(self, node):
@@ -1830,16 +1885,16 @@ class LaTeXTranslator(nodes.NodeVisitor):
# BUG: hash_char "#" is trouble some in LaTeX.
# mbox and other environment do not like the '#'.
hash_char = '\\#'
- if node.has_key('refuri'):
+ if 'refuri' in node:
href = node['refuri'].replace('#',hash_char)
- elif node.has_key('refid'):
+ elif 'refid' in node:
href = hash_char + node['refid']
- elif node.has_key('refname'):
+ elif 'refname' in node:
href = hash_char + self.document.nameids[node['refname']]
else:
raise AssertionError('Unknown reference.')
- self.body.append('\\href{%s}{' % href)
- if self._reference_label and not node.has_key('refuri'):
+ self.body.append('\\href{%s}{' % href.replace("%", "\\%"))
+ if self._reference_label and 'refuri' not in node:
self.body.append('\\%s{%s}}' % (self._reference_label,
href.replace(hash_char, '')))
raise nodes.SkipNode
@@ -1935,8 +1990,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_table(self, node):
if self.active_table.is_open():
- print 'nested tables are not supported'
- raise AssertionError
+ self.table_stack.append(self.active_table)
+ # nesting longtable does not work (e.g. 2007-04-18)
+ self.active_table = Table('tabular',self.settings.table_style)
self.active_table.open()
for cl in node['classes']:
self.active_table.set_table_style(cl)
@@ -1945,12 +2001,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_table(self, node):
self.body.append(self.active_table.get_closing() + '\n')
self.active_table.close()
- self.active_table.set_table_style(self.settings.table_style)
+ if len(self.table_stack)>0:
+ self.active_table = self.table_stack.pop()
+ else:
+ self.active_table.set_table_style(self.settings.table_style)
def visit_target(self, node):
# 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')):
+ if not ('refuri' in node or 'refid' in node
+ or 'refname' in node):
for id in node['ids']:
self.body.append('\\hypertarget{%s}{' % id)
self.context.append('}' * len(node['ids']))
@@ -1978,7 +2037,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_term(self, node):
# definition list term.
- self.body.append('}] ')
+ # \leavevmode results in a line break if the term is followed by a item list.
+ self.body.append('}] \leavevmode ')
def visit_tgroup(self, node):
#self.body.append(self.starttag(node, 'colgroup'))
@@ -2038,7 +2098,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
(l, text, id))
def visit_title(self, node):
- """Only 3 section levels are supported by LaTeX article (AFAIR)."""
+ """Section and other titles."""
if isinstance(node.parent, nodes.topic):
# the table of contents.
@@ -2085,7 +2145,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
section_name = self.d_class.section(self.section_level)
self.body.append('\\%s%s{' % (section_name, section_star))
-
+ # MAYBE postfix paragraph and subparagraph with \leavemode to
+ # ensure floatables stay in the section and text starts on a new line.
self.context.append('}\n')
def depart_title(self, node):
diff --git a/docutils/writers/newlatex2e/__init__.py b/docutils/writers/newlatex2e/__init__.py
index 08058cb2d..2830fd556 100644
--- a/docutils/writers/newlatex2e/__init__.py
+++ b/docutils/writers/newlatex2e/__init__.py
@@ -1,5 +1,5 @@
# $Id$
-# Author: Felix Wiemann <Felix.Wiemann@ososo.de>
+# Author: Lea Wiemann <LeWiemann@gmail.com>
# Copyright: This module has been placed in the public domain.
"""
@@ -676,7 +676,7 @@ class LaTeXTranslator(nodes.SparseNodeVisitor):
# Move IDs into TextElements. This won't work for images.
# Need to review this.
for node in document.traverse(nodes.Element):
- if node.has_key('ids') and not isinstance(node,
+ if 'ids' in node and not isinstance(node,
nodes.TextElement):
next_text_element = node.next_node(nodes.TextElement)
if next_text_element:
diff --git a/docutils/writers/newlatex2e/unicode_map.py b/docutils/writers/newlatex2e/unicode_map.py
index f5b019dcc..c0d63b6fe 100644
--- a/docutils/writers/newlatex2e/unicode_map.py
+++ b/docutils/writers/newlatex2e/unicode_map.py
@@ -1,5 +1,5 @@
# $Id$
-# Author: Felix Wiemann <Felix.Wiemann@ososo.de>
+# Author: Lea Wiemann <LeWiemann@gmail.com>
# Copyright: This file has been placed in the public domain.
# This is a mapping of Unicode characters to LaTeX equivalents.
diff --git a/docutils/writers/s5_html/__init__.py b/docutils/writers/s5_html/__init__.py
index 486c03f4a..73a1ec66f 100644
--- a/docutils/writers/s5_html/__init__.py
+++ b/docutils/writers/s5_html/__init__.py
@@ -251,7 +251,7 @@ class S5HTMLTranslator(html4css1.HTMLTranslator):
"""
source = os.path.join(source_dir, name)
dest = os.path.join(dest_dir, name)
- if self.theme_files_copied.has_key(dest):
+ if dest in self.theme_files_copied:
return 1
else:
self.theme_files_copied[dest] = 1