diff --git a/CHANGES b/CHANGES index 657aa3fb6..520e41f98 100644 --- a/CHANGES +++ b/CHANGES @@ -109,6 +109,15 @@ Release 1.1 (in development) Release 1.0.7 (in development) ============================== +* #347: Fix wrong generation of directives of static methods in + autosummary. + +* #599: Import PIL as ``from PIL import Image``. + +* #558: Fix longtables with captions in LaTeX output. + +* Make token references work as hyperlinks again in LaTeX output. + * #572: Show warnings by default when reference labels cannot be found. @@ -150,6 +159,8 @@ Release 1.0.7 (in development) * Fix tracebacks occurring for duplicate C++ domain objects. +* Fix JavaScript domain links to objects with ``$`` in their name. + Release 1.0.6 (Jan 04, 2011) ============================ diff --git a/EXAMPLES b/EXAMPLES index d19adb81b..37b8b1560 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -27,6 +27,7 @@ Documentation using the default theme * Google Wave API: http://wave-robot-python-client.googlecode.com/svn/trunk/pydocs/index.html * GSL Shell: http://www.nongnu.org/gsl-shell/ * Heapkeeper: http://heapkeeper.org/ +* Hands-on Python Tutorial: http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/ * Hedge: http://documen.tician.de/hedge/ * Kaa: http://doc.freevo.org/api/kaa/ * Leo: http://webpages.charter.net/edreamleo/front.html @@ -79,6 +80,7 @@ Documentation using a customized version of the default theme * simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html * Sprox: http://sprox.org/ * TurboGears: http://turbogears.org/2.0/docs/ +* Zentyal: http://doc.zentyal.org/ * Zope: http://docs.zope.org/zope2/index.html * zc.async: http://packages.python.org/zc.async/1.5.0/ @@ -140,6 +142,7 @@ Documentation using a custom theme/integrated in a site * Open ERP: http://doc.openerp.com/ * OpenLayers: http://docs.openlayers.org/ * PyEphem: http://rhodesmill.org/pyephem/ +* German Plone 4.0 user manual: http://www.hasecke.com/plone-benutzerhandbuch/4.0/ * Pylons: http://pylonshq.com/docs/en/0.9.7/ * PyMOTW: http://www.doughellmann.com/PyMOTW/ * qooxdoo: http://manual.qooxdoo.org/current @@ -167,6 +170,13 @@ Homepages and other non-documentation sites Books produced using Sphinx --------------------------- -* The ``repoze.bfg`` Web Application Framework: +* "The ``repoze.bfg`` Web Application Framework": http://www.amazon.com/repoze-bfg-Web-Application-Framework-Version/dp/0615345379 * A Theoretical Physics Reference book: http://theoretical-physics.net/ +* "Simple and Steady Way of Learning for Software Engineering" (in Japanese): + http://www.amazon.co.jp/dp/477414259X/ +* "Expert Python Programming" (Japanese translation): + http://www.amazon.co.jp/dp/4048686291/ +* "Pomodoro Technique Illustrated" (Japanese translation): + http://www.amazon.co.jp/dp/4048689525/ + diff --git a/doc/config.rst b/doc/config.rst index f032bcc1f..d8a07fa9b 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -377,6 +377,7 @@ documentation on :ref:`intl` for details. * ``fr`` -- French * ``hr`` -- Croatian * ``it`` -- Italian + * ``ja`` -- Japanese * ``lt`` -- Lithuanian * ``nl`` -- Dutch * ``pl`` -- Polish diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py index ddc6fb5c6..e946e0d39 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -179,7 +179,7 @@ class EpubBuilder(StandaloneHTMLBuilder): name = name.replace('<', '<') name = name.replace('>', '>') name = name.replace('"', '"') - name = name.replace('\'', ''') + name = name.replace('\'', ''') return name def get_refnodes(self, doctree, result): @@ -408,6 +408,14 @@ class EpubBuilder(StandaloneHTMLBuilder): spine.append(_spine_template % { 'idref': self.esc(self.make_id(item['refuri'])) }) + for info in self.domain_indices: + spine.append(_spine_template % { + 'idref': self.esc(self.make_id(info[0] + self.out_suffix)) + }) + if self.config.html_use_index: + spine.append(_spine_template % { + 'idref': self.esc(self.make_id('genindex' + self.out_suffix)) + }) # add the optional cover content_tmpl = _content_template diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py index b00546a06..3369338c2 100644 --- a/sphinx/builders/latex.py +++ b/sphinx/builders/latex.py @@ -46,10 +46,6 @@ class LaTeXBuilder(Builder): return 'all documents' # for now def get_target_uri(self, docname, typ=None): - if typ == 'token': - # token references are always inside production lists and must be - # replaced by \token{} in LaTeX - return '@token' if docname not in self.docnames: raise NoUri else: diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py index 57cee8f9c..73edf4515 100644 --- a/sphinx/domains/javascript.py +++ b/sphinx/domains/javascript.py @@ -96,7 +96,8 @@ class JSObject(ObjectDescription): indextext = self.get_index_text(objectname, name_obj) if indextext: self.indexnode['entries'].append(('single', indextext, - fullname, '')) + fullname.replace('$', '_S_'), + '')) def get_index_text(self, objectname, name_obj): name, obj = name_obj @@ -208,8 +209,10 @@ class JavaScriptDomain(Domain): name, obj = self.find_obj(env, objectname, target, typ, searchorder) if not obj: return None - return make_refnode(builder, fromdocname, obj[0], name, contnode, name) + return make_refnode(builder, fromdocname, obj[0], + name.replace('$', '_S_'), contnode, name) def get_objects(self): for refname, (docname, type) in self.data['objects'].iteritems(): - yield refname, refname, type, docname, refname, 1 + yield refname, refname, type, docname, \ + refname.replace('$', '_S_'), 1 diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index e0271697e..aad8b9f6e 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -133,27 +133,19 @@ except AttributeError: return False isgetsetdescriptor = ismemberdescriptor -def get_documenter(obj): +def get_documenter(obj, parent): """Get an autodoc.Documenter class suitable for documenting the given object. """ - import sphinx.ext.autodoc as autodoc + from sphinx.ext.autodoc import AutoDirective, DataDocumenter - if inspect.isclass(obj): - if issubclass(obj, Exception): - return autodoc.ExceptionDocumenter - return autodoc.ClassDocumenter - elif inspect.ismodule(obj): - return autodoc.ModuleDocumenter - elif inspect.ismethod(obj) or inspect.ismethoddescriptor(obj): - return autodoc.MethodDocumenter - elif (ismemberdescriptor(obj) or isgetsetdescriptor(obj) - or inspect.isdatadescriptor(obj)): - return autodoc.AttributeDocumenter - elif inspect.isroutine(obj): - return autodoc.FunctionDocumenter + classes = [cls for cls in AutoDirective._registry.values() + if cls.can_document_member(obj, '', False, parent)] + if classes: + classes.sort(key=lambda cls: cls.priority) + return classes[-1] else: - return autodoc.DataDocumenter + return DataDocumenter # -- .. autosummary:: ---------------------------------------------------------- @@ -238,7 +230,7 @@ class Autosummary(Directive): display_name = name.split('.')[-1] try: - obj, real_name = import_by_name(name, prefixes=prefixes) + real_name, obj, parent = import_by_name(name, prefixes=prefixes) except ImportError: self.warn('failed to import %s' % name) items.append((name, '', '', name)) @@ -246,7 +238,7 @@ class Autosummary(Directive): # NB. using real_name here is important, since Documenters # handle module prefixes slightly differently - documenter = get_documenter(obj)(self, real_name) + documenter = get_documenter(obj, parent)(self, real_name) if not documenter.parse_name(): self.warn('failed to parse name %s' % real_name) items.append((display_name, '', '', real_name)) @@ -383,7 +375,8 @@ def import_by_name(name, prefixes=[None]): prefixed_name = '.'.join([prefix, name]) else: prefixed_name = name - return _import_by_name(prefixed_name), prefixed_name + obj, parent = _import_by_name(prefixed_name) + return prefixed_name, obj, parent except ImportError: tried.append(prefixed_name) raise ImportError('no module named %s' % ' or '.join(tried)) @@ -398,7 +391,8 @@ def _import_by_name(name): if modname: try: __import__(modname) - return getattr(sys.modules[modname], name_parts[-1]) + mod = sys.modules[modname] + return getattr(mod, name_parts[-1]), mod except (ImportError, IndexError, AttributeError): pass @@ -416,12 +410,14 @@ def _import_by_name(name): break if last_j < len(name_parts): + parent = None obj = sys.modules[modname] for obj_name in name_parts[last_j:]: + parent = obj obj = getattr(obj, obj_name) - return obj + return obj, parent else: - return sys.modules[modname] + return sys.modules[modname], None except (ValueError, ImportError, AttributeError, KeyError), e: raise ImportError(*e.args) @@ -443,7 +439,7 @@ def autolink_role(typ, rawtext, etext, lineno, inliner, prefixes = [None] #prefixes.insert(0, inliner.document.settings.env.currmodule) try: - obj, name = import_by_name(pnode['reftarget'], prefixes) + name, obj, parent = import_by_name(pnode['reftarget'], prefixes) except ImportError: content = pnode[0] r[0][0] = nodes.emphasis(rawtext, content[0].astext(), diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 389d55a59..fecb5689a 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -108,7 +108,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', ensuredir(path) try: - obj, name = import_by_name(name) + name, obj, parent = import_by_name(name) except ImportError, e: warn('[autosummary] failed to import %r: %s' % (name, e)) continue @@ -124,7 +124,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', f = open(fn, 'w') try: - doc = get_documenter(obj) + doc = get_documenter(obj, parent) if template_name is not None: template = template_env.get_template(template_name) @@ -138,7 +138,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', def get_members(obj, typ, include_public=[]): items = [ name for name in dir(obj) - if get_documenter(getattr(obj, name)).objtype == typ + if get_documenter(getattr(obj, name), obj).objtype == typ ] public = [x for x in items if x in include_public or not x.startswith('_')] @@ -212,7 +212,7 @@ def find_autosummary_in_docstring(name, module=None, filename=None): See `find_autosummary_in_lines`. """ try: - obj, real_name = import_by_name(name) + real_name, obj, parent = import_by_name(name) lines = pydoc.getdoc(obj).splitlines() return find_autosummary_in_lines(lines, module=name, filename=filename) except AttributeError: diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index 29439f7cd..fba083bf4 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -85,7 +85,7 @@ class InheritanceGraph(object): """Import a class using its fully-qualified *name*.""" try: path, base = class_sig_re.match(name).groups() - except ValueError: + except (AttributeError, ValueError): raise InheritanceException('Invalid class or module %r specified ' 'for inheritance diagram' % name) diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index c9f993aeb..d021c60bd 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -71,7 +71,8 @@ class MathDirective(Directive): node['docname'] = self.state.document.settings.env.docname ret = [node] node.line = self.lineno - node.source = self.src + if hasattr(self, 'src'): + node.source = self.src if node['label']: tnode = nodes.target('', '', ids=['equation-' + node['label']]) self.state.document.note_explicit_target(tnode) diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py index f9b97e3d8..629bce30f 100644 --- a/sphinx/jinja2glue.py +++ b/sphinx/jinja2glue.py @@ -41,6 +41,15 @@ def accesskey(context, key): return 'accesskey="%s"' % key return '' +class idgen(object): + def __init__(self): + self.id = 0 + def current(self): + return self.id + def next(self): + self.id += 1 + return self.id + class SphinxFileSystemLoader(FileSystemLoader): """ @@ -109,6 +118,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader): self.environment.filters['toint'] = _toint self.environment.globals['debug'] = contextfunction(pformat) self.environment.globals['accesskey'] = contextfunction(accesskey) + self.environment.globals['idgen'] = idgen if use_i18n: self.environment.install_gettext_translations( builder.app.translator) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index be0a02848..21a3d8941 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -220,21 +220,12 @@ \addtolength{\py@argswidth}{\linewidth}% \item[#1\code{(}\py@sigparams{#2}{#3}]} -% This version is being checked in for the historical record; it shows -% how I've managed to get some aspects of this to work. It will not -% be used in practice, so a subsequent revision will change things -% again. This version has problems, but shows how to do something -% that proved more tedious than I'd expected, so I don't want to lose -% the example completely. +% Production lists % -\newcommand{\grammartoken}[1]{\texttt{#1}} -\newenvironment{productionlist}[1][\@undefined]{ - \def\optional##1{{\Large[}##1{\Large]}} - \def\production##1##2{\hypertarget{grammar-token-##1}{}% - \code{##1}&::=&\code{##2}\\} - \def\productioncont##1{& &\code{##1}\\} - \def\token##1{##1} - \let\grammartoken=\token +\newenvironment{productionlist}{ +% \def\optional##1{{\Large[}##1{\Large]}} + \def\production##1##2{\\\code{##1}&::=&\code{##2}} + \def\productioncont##1{\\& &\code{##1}} \parindent=2em \indent \begin{tabular}{lcl} diff --git a/sphinx/themes/basic/domainindex.html b/sphinx/themes/basic/domainindex.html index 8d98c429d..947a01ea8 100644 --- a/sphinx/themes/basic/domainindex.html +++ b/sphinx/themes/basic/domainindex.html @@ -19,7 +19,7 @@ {% endblock %} {% block body %} - {%- set curr_group = 0 %} + {%- set groupid = idgen() %}

{{ indextitle }}

@@ -33,15 +33,14 @@ {%- for letter, entries in content %} - + {%- for (name, grouptype, page, anchor, extra, qualifier, description) in entries %} - {%- if grouptype == 1 %}{% set curr_group = curr_group + 1 %}{% endif %} - +
 
- {{ letter }}
+ {{ letter }}
{% if grouptype == 1 -%} - + {%- endif %} {% if grouptype == 2 %}   {% endif %} {% if page %}{% endif -%} diff --git a/sphinx/themes/basic/genindex-single.html b/sphinx/themes/basic/genindex-single.html index b6fa6a855..fedd3ea0e 100644 --- a/sphinx/themes/basic/genindex-single.html +++ b/sphinx/themes/basic/genindex-single.html @@ -34,9 +34,9 @@

{% trans key=key %}Index – {{ key }}{% endtrans %}

- +
{%- for column in entries|slice(2) if column %} -
+
{%- for entryname, (links, subitems) in column %} {{ indexentries(entryname, links) }} {%- if subitems %} diff --git a/sphinx/themes/basic/genindex.html b/sphinx/themes/basic/genindex.html index 536f09639..0cabdc182 100644 --- a/sphinx/themes/basic/genindex.html +++ b/sphinx/themes/basic/genindex.html @@ -43,9 +43,9 @@ {%- for key, entries in genindexentries %}

{{ key }}

- +
{%- for column in entries|slice(2) if column %} -
+
{%- for entryname, (links, subitems) in column %} {{ indexentries(entryname, links) }} {%- if subitems %} diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t index cd5149620..1be372847 100644 --- a/sphinx/themes/basic/static/basic.css_t +++ b/sphinx/themes/basic/static/basic.css_t @@ -413,7 +413,7 @@ dl.glossary dt { } .footnote:target { - background-color: #ffa + background-color: #ffa; } .line-block { diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 5719aca23..eb5c76fa9 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -21,7 +21,7 @@ from sphinx.locale import admonitionlabels, versionlabels, _ from sphinx.util.smartypants import sphinx_smarty_pants try: - import Image # check for the Python Imaging Library + from PIL import Image # check for the Python Imaging Library except ImportError: Image = None @@ -249,6 +249,12 @@ class HTMLTranslator(BaseTranslator): def visit_doctest_block(self, node): self.visit_literal_block(node) + # overwritten to add the
(for XHTML compliance) + def visit_block_quote(self, node): + self.body.append(self.starttag(node, 'blockquote') + '
') + def depart_block_quote(self, node): + self.body.append('
\n') + # overwritten def visit_literal(self, node): self.body.append(self.starttag(node, 'tt', '', diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 2b24a35ac..43dad160c 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -267,10 +267,10 @@ class LaTeXTranslator(nodes.NodeVisitor): '\\label{%s}' % self.idescape(id) def hyperlink(self, id): - return '{\\hyperref[%s]{' % (self.idescape(id)) + return '{\\hyperref[%s]{' % self.idescape(id) def hyperpageref(self, id): - return '\\autopageref*{%s}' % (self.idescape(id)) + return '\\autopageref*{%s}' % self.idescape(id) def idescape(self, id): return str(unicode(id).translate(tex_replace_map)) @@ -423,8 +423,9 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_production(self, node): if node['tokenname']: - self.body.append('\\production{%s}{' % - self.encode(node['tokenname'])) + tn = node['tokenname'] + self.body.append(self.hypertarget('grammar-token-' + tn)) + self.body.append('\\production{%s}{' % self.encode(tn)) else: self.body.append('\\productioncont{') def depart_production(self, node): @@ -658,8 +659,7 @@ class LaTeXTranslator(nodes.NodeVisitor): else: self.body.append('{|' + ('L|' * self.table.colcount) + '}\n') if self.table.longtable and self.table.caption is not None: - self.body.append(u'\\capstart\\caption{%s} \\\\\n' % - self.table.caption) + self.body.append(u'\\caption{%s} \\\\\n' % self.table.caption) if self.table.caption is not None: for id in self.next_table_ids: self.body.append(self.hypertarget(id, anchor=False)) @@ -1151,12 +1151,6 @@ class LaTeXTranslator(nodes.NodeVisitor): self.context.append('}} (%s)' % self.hyperpageref(id)) else: self.context.append('}}') - elif uri.startswith('@token'): - if self.in_production_list: - self.body.append('\\token{') - else: - self.body.append('\\grammartoken{') - self.context.append('}') else: self.builder.warn('unusable reference target found: %s' % uri, (self.curfilestack[-1], node.line))