diff --git a/AUTHORS b/AUTHORS index 259c0949c..09be75330 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,6 +13,7 @@ Other contributors, listed alphabetically, are: * Martin Hans -- autodoc improvements * Dave Kuhlman -- original LaTeX writer * Thomas Lamb -- linkcheck builder +* Dan MacKinlay -- metadata fixes * Will Maier -- directory HTML builder * Christopher Perkins -- autosummary integration * Benjamin Peterson -- unittests diff --git a/CHANGES b/CHANGES index 5a1d732bb..2b66530c3 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,9 @@ Release 1.0 (in development) * Support for docutils 0.4 has been removed. +* #284: All docinfo metadata is now put into the document metadata, not + just the author. + * Added new HTML theme ``agogo``, created by Andi Albrecht. * The ``toctree()`` callable in templates now has a ``maxdepth`` diff --git a/sphinx/environment.py b/sphinx/environment.py index f309823d1..6d4528bc2 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -12,12 +12,10 @@ import re import os import time -import heapq import types import codecs import imghdr import string -import difflib import cPickle as pickle from os import path from glob import glob @@ -834,6 +832,7 @@ class BuildEnvironment: def process_metadata(self, docname, doctree): """ Process the docinfo part of the doctree as metadata. + Keep processing minimal -- just return what docutils says. """ self.metadata[docname] = md = {} try: @@ -845,10 +844,12 @@ class BuildEnvironment: # nothing to see here return for node in docinfo: - if node.__class__ is nodes.author: - # handled specially by docutils - md['author'] = node.astext() - elif node.__class__ is nodes.field: + # nodes are multiply inherited... + if isinstance(node, nodes.authors): + md['authors'] = [author.astext() for author in node] + elif isinstance(node, nodes.TextElement): # e.g. author + md[node.__class__.__name__] = node.astext() + else: name, body = node md[name.astext()] = body.astext() del doctree[0] diff --git a/tests/root/contents.txt b/tests/root/contents.txt index 2d7ba8fb0..6955ec623 100644 --- a/tests/root/contents.txt +++ b/tests/root/contents.txt @@ -22,6 +22,7 @@ Contents: math autodoc autosummary + metadata Python diff --git a/tests/root/metadata.txt b/tests/root/metadata.txt new file mode 100644 index 000000000..9b3044ba8 --- /dev/null +++ b/tests/root/metadata.txt @@ -0,0 +1,53 @@ +:Author: David Goodger +:Address: 123 Example Street + Example, EX Canada + A1B 2C3 +:Contact: goodger@python.org +:Authors: Me; Myself; I +:organization: humankind +:date: $Date: 2006-05-21 22:44:42 +0200 (Son, 21 Mai 2006) $ +:status: This is a "work in progress" +:revision: $Revision: 4564 $ +:version: 1 +:copyright: This document has been placed in the public domain. You + may do with it as you wish. You may copy, modify, + redistribute, reattribute, sell, buy, rent, lease, + destroy, or improve it, quote it at length, excerpt, + incorporate, collate, fold, staple, or mutilate it, or do + anything else to it that your or anyone else's heart + desires. +:field name: This is a generic bibliographic field. +:field name 2: + Generic bibliographic fields may contain multiple body elements. + + Like this. + +:Dedication: + + For Docutils users & co-developers. + +:abstract: + + This document is a demonstration of the reStructuredText markup + language, containing examples of all basic reStructuredText + constructs and many advanced constructs. + +.. meta:: + :keywords: reStructuredText, demonstration, demo, parser + :description lang=en: A demonstration of the reStructuredText + markup language, containing examples of all basic + constructs and many advanced constructs. + +================================ + reStructuredText Demonstration +================================ + +.. Above is the document title, and below is the subtitle. + They are transformed from section titles after parsing. + +-------------------------------- + Examples of Syntax Constructs +-------------------------------- + +.. bibliographic fields (which also require a transform): + diff --git a/tests/test_metadata.py b/tests/test_metadata.py new file mode 100644 index 000000000..9675947ac --- /dev/null +++ b/tests/test_metadata.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +""" + test_metadata + ~~~~~~~~~~~~~ + + Test our handling of metadata in files with bibliographic metadata. + + :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +# adapted from an example of bibliographic metadata at +# http://docutils.sourceforge.net/docs/user/rst/demo.txt + +from util import * + +from nose.tools import assert_equals + +from sphinx.environment import BuildEnvironment + +app = env = None +warnings = [] + +def setup_module(): + # Is there a better way of generating this doctree than manually iterating? + global app, env + app = TestApp(srcdir='(temp)') + env = BuildEnvironment(app.srcdir, app.doctreedir, app.config) + # Huh. Why do I need to do this? + env.set_warnfunc(lambda *args: warnings.append(args)) + msg, num, it = env.update(app.config, app.srcdir, app.doctreedir, app) + for docname in it: + pass + +def teardown_module(): + app.cleanup() + +def test_docinfo(): + """ + Inspect the 'docinfo' metadata stored in the first node of the document. + Note this doesn't give us access to data stored in subsequence blocks + that might be considered document metadata, such as 'abstract' or + 'dedication' blocks, or the 'meta' role. Doing otherwise is probably more + messing with the internals of sphinx than this rare use case merits. + """ + exampledocinfo = env.metadata['metadata'] + expecteddocinfo = { + 'author': u'David Goodger', + 'authors': [u'Me', u'Myself', u'I'], + 'address': u'123 Example Street\nExample, EX Canada\nA1B 2C3', + 'field name': u'This is a generic bibliographic field.', + 'field name 2': (u'Generic bibliographic fields may contain multiple ' + u'body elements.\n\nLike this.'), + 'status': u'This is a "work in progress"', + 'version': u'1', + 'copyright': (u'This document has been placed in the public domain. ' + u'You\nmay do with it as you wish. You may copy, modify,' + u'\nredistribute, reattribute, sell, buy, rent, lease,\n' + u'destroy, or improve it, quote it at length, excerpt,\n' + u'incorporate, collate, fold, staple, or mutilate it, or ' + u'do\nanything else to it that your or anyone else\'s ' + u'heart\ndesires.'), + 'contact': u'goodger@python.org', + 'date': u'2006-05-21', + 'organization': u'humankind', + 'revision': u'4564', + } + # I like this way of comparing dicts - easier to see the error. + for key in exampledocinfo: + yield assert_equals, exampledocinfo.get(key), expecteddocinfo.get(key) + # but then we still have to check for missing keys + yield assert_equals, set(expecteddocinfo.keys()), set(exampledocinfo.keys())