merge with 0.6

This commit is contained in:
Georg Brandl 2009-08-06 23:03:49 +02:00
commit 137f37b2fc
10 changed files with 99 additions and 36 deletions

17
CHANGES
View File

@ -38,6 +38,23 @@ Release 1.0 (in development)
Release 0.6.3 (in development) Release 0.6.3 (in development)
============================== ==============================
* #220: Fix CSS so that displaymath really is centered.
* #222: Allow the "Footnotes" header to be translated.
* #225: Don't add whitespace in generated HTML after inline tags.
* #227: Make ``literalinclude`` work when the document's path
name contains non-ASCII characters.
* #229: Fix autodoc failures with members that raise errors
on ``getattr()``.
* #205: When copying files, don't copy full stat info, only
modification times.
* #232: Support non-ASCII metadata in Qt help builder.
* Properly format bullet lists nested in definition lists for LaTeX. * Properly format bullet lists nested in definition lists for LaTeX.
* Section titles are now allowed inside ``only`` directives. * Section titles are now allowed inside ``only`` directives.

View File

@ -88,9 +88,10 @@ units as well as normal text:
.. note:: .. note::
If the *title* of the rubric is "Footnotes", this rubric is ignored by If the *title* of the rubric is "Footnotes" (or the selected language's
the LaTeX writer, since it is assumed to only contain footnote equivalent), this rubric is ignored by the LaTeX writer, since it is
definitions and therefore would create an empty heading. assumed to only contain footnote definitions and therefore would create an
empty heading.
.. directive:: centered .. directive:: centered

View File

@ -12,6 +12,7 @@
import os import os
import re import re
import cgi import cgi
import codecs
from os import path from os import path
from docutils import nodes from docutils import nodes
@ -28,7 +29,7 @@ _idpattern = re.compile(
# It contains references to compressed help files which should be # It contains references to compressed help files which should be
# included in the collection. # included in the collection.
# It may contain various other information for customizing Qt Assistant. # It may contain various other information for customizing Qt Assistant.
collection_template = '''\ collection_template = u'''\
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<QHelpCollectionProject version="1.0"> <QHelpCollectionProject version="1.0">
<docFiles> <docFiles>
@ -50,7 +51,7 @@ collection_template = '''\
# It contains the table of contents, indices and references to the # It contains the table of contents, indices and references to the
# actual documentation files (*.html). # actual documentation files (*.html).
# In addition it defines a unique namespace for the documentation. # In addition it defines a unique namespace for the documentation.
project_template = '''\ project_template = u'''\
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<QtHelpProject version="1.0"> <QtHelpProject version="1.0">
<namespace>%(outname)s.org.%(outname)s.%(nversion)s</namespace> <namespace>%(outname)s.org.%(outname)s.%(nversion)s</namespace>
@ -109,7 +110,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
def build_qhcp(self, outdir, outname): def build_qhcp(self, outdir, outname):
self.info('writing collection project file...') self.info('writing collection project file...')
f = open(path.join(outdir, outname+'.qhcp'), 'w') f = codecs.open(path.join(outdir, outname+'.qhcp'), 'w', 'utf-8')
try: try:
f.write(collection_template % {'outname': outname}) f.write(collection_template % {'outname': outname})
finally: finally:
@ -161,7 +162,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
projectfiles = '\n'.join(projectfiles) projectfiles = '\n'.join(projectfiles)
# write the project file # write the project file
f = open(path.join(outdir, outname+'.qhp'), 'w') f = codecs.open(path.join(outdir, outname+'.qhp'), 'w', 'utf-8')
try: try:
nversion = self.config.version.replace('.', '_') nversion = self.config.version.replace('.', '_')
nversion = nversion.replace(' ', '_') nversion = nversion.replace(' ', '_')

View File

@ -103,7 +103,13 @@ class LiteralInclude(Directive):
else: else:
docdir = path.dirname(env.doc2path(env.docname, base=None)) docdir = path.dirname(env.doc2path(env.docname, base=None))
rel_fn = path.normpath(path.join(docdir, filename)) rel_fn = path.normpath(path.join(docdir, filename))
fn = path.join(env.srcdir, rel_fn) try:
fn = path.join(env.srcdir, rel_fn)
except UnicodeDecodeError:
# the source directory is a bytestring with non-ASCII characters;
# let's try to encode the rel_fn in the file system encoding
rel_fn = rel_fn.encode(sys.getfilesystemencoding())
fn = path.join(env.srcdir, rel_fn)
if 'pyobject' in self.options and 'lines' in self.options: if 'pyobject' in self.options and 'lines' in self.options:
return [document.reporter.warning( return [document.reporter.warning(

View File

@ -25,6 +25,7 @@ from sphinx.util import rpartition, nested_parse_with_titles, force_decode
from sphinx.pycode import ModuleAnalyzer, PycodeError from sphinx.pycode import ModuleAnalyzer, PycodeError
from sphinx.application import ExtensionError from sphinx.application import ExtensionError
from sphinx.util.compat import Directive from sphinx.util.compat import Directive
from sphinx.util.inspect import isdescriptor, safe_getmembers, safe_getattr
from sphinx.util.docstrings import prepare_docstring from sphinx.util.docstrings import prepare_docstring
@ -194,25 +195,6 @@ def between(marker, what=None, keepempty=False):
return process return process
def safe_getattr(obj, name, *defargs):
try:
return getattr(obj, name, *defargs)
except Exception:
# this is a catch-all for all the weird things that some modules do
# with attribute access
if defargs:
return defargs[0]
raise AttributeError
def isdescriptor(x):
"""Check if the object is some kind of descriptor."""
for item in '__get__', '__set__', '__delete__':
if hasattr(safe_getattr(x, item, None), '__call__'):
return True
return False
class Documenter(object): class Documenter(object):
""" """
A Documenter knows how to autodocument a single object type. When A Documenter knows how to autodocument a single object type. When
@ -492,9 +474,9 @@ class Documenter(object):
% (mname, self.fullname)) % (mname, self.fullname))
return False, ret return False, ret
elif self.options.inherited_members: elif self.options.inherited_members:
# getmembers() uses dir() which pulls in members from all # safe_getmembers() uses dir() which pulls in members from all
# base classes # base classes
return False, inspect.getmembers(self.object) return False, safe_getmembers(self.object)
else: else:
# __dict__ contains only the members directly defined in # __dict__ contains only the members directly defined in
# the class (but get them via getattr anyway, to e.g. get # the class (but get them via getattr anyway, to e.g. get
@ -734,7 +716,7 @@ class ModuleDocumenter(Documenter):
if not hasattr(self.object, '__all__'): if not hasattr(self.object, '__all__'):
# for implicit module members, check __module__ to avoid # for implicit module members, check __module__ to avoid
# documenting imported objects # documenting imported objects
return True, inspect.getmembers(self.object) return True, safe_getmembers(self.object)
else: else:
memberlist = self.object.__all__ memberlist = self.object.__all__
else: else:

View File

@ -378,7 +378,7 @@ img.math {
vertical-align: middle; vertical-align: middle;
} }
div.math p { div.body div.math p {
text-align: center; text-align: center;
} }

View File

@ -12,6 +12,7 @@
import os import os
import re import re
import sys import sys
import stat
import time import time
import types import types
import shutil import shutil
@ -399,11 +400,22 @@ def movefile(source, dest):
os.rename(source, dest) os.rename(source, dest)
def copytimes(source, dest):
"""Copy a file's modification times."""
st = os.stat(source)
mode = stat.S_IMODE(st.st_mode)
if hasattr(os, 'utime'):
os.utime(dest, (st.st_atime, st.st_mtime))
def copyfile(source, dest): def copyfile(source, dest):
"""Copy a file and its modification times, if possible.""" """Copy a file and its modification times, if possible."""
shutil.copyfile(source, dest) shutil.copyfile(source, dest)
try: shutil.copystat(source, dest) try:
except shutil.Error: pass # don't do full copystat because the source may be read-only
copytimes(source, dest)
except shutil.Error:
pass
def copy_static_entry(source, target, builder, context={}): def copy_static_entry(source, target, builder, context={}):

43
sphinx/util/inspect.py Normal file
View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
"""
sphinx.util.inspect
~~~~~~~~~~~~~~~~~~~
Helpers for inspecting Python modules.
:copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
def isdescriptor(x):
"""Check if the object is some kind of descriptor."""
for item in '__get__', '__set__', '__delete__':
if hasattr(safe_getattr(x, item, None), '__call__'):
return True
return False
def safe_getattr(obj, name, *defargs):
"""A getattr() that turns all exceptions into AttributeErrors."""
try:
return getattr(obj, name, *defargs)
except Exception:
# this is a catch-all for all the weird things that some modules do
# with attribute access
if defargs:
return defargs[0]
raise AttributeError(name)
def safe_getmembers(object, predicate=None):
"""A version of inspect.getmembers() that uses safe_getattr()."""
results = []
for key in dir(object):
try:
value = safe_getattr(object, key, None)
except AttributeError:
continue
if not predicate or predicate(value):
results.append((key, value))
results.sort()
return results

View File

@ -123,7 +123,7 @@ class HTMLTranslator(BaseTranslator):
self.body.append('<span class="optional">]</span>') self.body.append('<span class="optional">]</span>')
def visit_desc_annotation(self, node): def visit_desc_annotation(self, node):
self.body.append(self.starttag(node, 'em', CLASS='property')) self.body.append(self.starttag(node, 'em', '', CLASS='property'))
def depart_desc_annotation(self, node): def depart_desc_annotation(self, node):
self.body.append('</em>') self.body.append('</em>')
@ -457,7 +457,7 @@ class HTMLTranslator(BaseTranslator):
attrs = {} attrs = {}
if node.hasattr('explanation'): if node.hasattr('explanation'):
attrs['title'] = node['explanation'] attrs['title'] = node['explanation']
self.body.append(self.starttag(node, 'abbr', **attrs)) self.body.append(self.starttag(node, 'abbr', '', **attrs))
def depart_abbreviation(self, node): def depart_abbreviation(self, node):
self.body.append('</abbr>') self.body.append('</abbr>')

View File

@ -574,7 +574,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append("\n\n") self.body.append("\n\n")
def visit_rubric(self, node): def visit_rubric(self, node):
if len(node.children) == 1 and node.children[0].astext() == 'Footnotes': if len(node.children) == 1 and node.children[0].astext() in \
('Footnotes', _('Footnotes')):
raise nodes.SkipNode raise nodes.SkipNode
self.body.append('\\paragraph{') self.body.append('\\paragraph{')
self.context.append('}\n') self.context.append('}\n')