diff options
| author | georg.brandl <devnull@localhost> | 2008-07-18 22:55:36 +0000 |
|---|---|---|
| committer | georg.brandl <devnull@localhost> | 2008-07-18 22:55:36 +0000 |
| commit | 31075afed9f8fa008a3ed2a9ff0d7ed024ff8564 (patch) | |
| tree | 1dc24530c825039c6e2c0cfe649847b274241a56 | |
| parent | 7ab43cdfa391f4d647228378a8b2a252529697d2 (diff) | |
| download | sphinx-31075afed9f8fa008a3ed2a9ff0d7ed024ff8564.tar.gz | |
Merged revisions 64808,65013,65076,65100-65101,65119,65121-65123 via svnmerge from
svn+ssh://pythondev@svn.python.org/doctools/branches/0.4.x
........
r64808 | georg.brandl | 2008-07-08 21:39:33 +0200 (Tue, 08 Jul 2008) | 2 lines
Allow relocation of source and doctree dir.
........
r65013 | georg.brandl | 2008-07-16 15:25:30 +0200 (Wed, 16 Jul 2008) | 2 lines
Remove curious quote.
........
r65076 | georg.brandl | 2008-07-17 22:43:01 +0200 (Thu, 17 Jul 2008) | 2 lines
Add a test for sphinx.quickstart.
........
r65100 | georg.brandl | 2008-07-18 14:41:54 +0200 (Fri, 18 Jul 2008) | 2 lines
Fix phony targets.
........
r65101 | georg.brandl | 2008-07-18 14:55:03 +0200 (Fri, 18 Jul 2008) | 2 lines
Fix problems in "make check".
........
r65119 | georg.brandl | 2008-07-18 23:06:42 +0200 (Fri, 18 Jul 2008) | 2 lines
Emit a more precise error message in autodoc.
........
r65121 | georg.brandl | 2008-07-18 23:41:35 +0200 (Fri, 18 Jul 2008) | 2 lines
Warn if a toctree-included document doesn't contain a title.
........
r65122 | georg.brandl | 2008-07-18 23:51:28 +0200 (Fri, 18 Jul 2008) | 2 lines
Don't use \samp{} for code with whitespaces, only for :samp:`code`.
........
r65123 | georg.brandl | 2008-07-19 00:49:46 +0200 (Sat, 19 Jul 2008) | 2 lines
Put inheritance info always on its own line.
........
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | TODO | 4 | ||||
| -rw-r--r-- | sphinx/__init__.py | 2 | ||||
| -rw-r--r-- | sphinx/builder.py | 2 | ||||
| -rw-r--r-- | sphinx/environment.py | 14 | ||||
| -rw-r--r-- | sphinx/ext/autodoc.py | 8 | ||||
| -rw-r--r-- | sphinx/latexwriter.py | 2 | ||||
| -rw-r--r-- | sphinx/quickstart.py | 20 | ||||
| -rw-r--r-- | sphinx/roles.py | 10 | ||||
| -rw-r--r-- | sphinx/templates/genindex-split.html | 4 | ||||
| -rw-r--r-- | sphinx/templates/genindex.html | 2 | ||||
| -rw-r--r-- | sphinx/util/__init__.py | 2 | ||||
| -rw-r--r-- | sphinx/util/console.py | 5 | ||||
| -rw-r--r-- | tests/path.py | 2 | ||||
| -rw-r--r-- | tests/test_quickstart.py | 144 | ||||
| -rw-r--r-- | tests/util.py | 2 | ||||
| -rwxr-xr-x | utils/check_sources.py | 12 |
17 files changed, 203 insertions, 34 deletions
@@ -2,7 +2,7 @@ PYTHON ?= python export PYTHONPATH = $(shell echo "$$PYTHONPATH"):./sphinx -.PHONY: all check clean clean-pyc pylint reindent testserver +.PHONY: all check clean clean-pyc clean-patchfiles pylint reindent test all: clean-pyc check @@ -1,6 +1,10 @@ Sphinx TODO =========== +- specify node visit functions when adding nodes to app +- allow extensions to add static files +- decide which static files to include +- verbose option - remove redundant <ul>s in tocs - autoattribute in autodoc - range and object options for literalinclude diff --git a/sphinx/__init__.py b/sphinx/__init__.py index 4f67ca4d..b40838fa 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -29,7 +29,7 @@ def usage(argv, msg=None): print >>sys.stderr print >>sys.stderr, """\ Sphinx v%s -Usage: %s [options] sourcedir outdir [filenames...]" +Usage: %s [options] sourcedir outdir [filenames...] Options: -b <builder> -- builder to use; default is html -a -- write all files; default is to only write new and changed files -E -- don't use a saved environment, always read all files diff --git a/sphinx/builder.py b/sphinx/builder.py index 988f1df3..5f137ee6 100644 --- a/sphinx/builder.py +++ b/sphinx/builder.py @@ -211,7 +211,7 @@ class Builder(object): warnings = [] self.env.set_warnfunc(warnings.append) self.info(bold('updating environment: '), nonl=1) - iterator = self.env.update(self.config, self.app) + iterator = self.env.update(self.config, self.srcdir, self.doctreedir, self.app) # the first item in the iterator is a summary message self.info(iterator.next()) for docname in self.status_iterator(iterator, 'reading... ', purple): diff --git a/sphinx/environment.py b/sphinx/environment.py index f0696ced..039d3c38 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -396,7 +396,7 @@ class BuildEnvironment: return added, changed, removed - def update(self, config, app=None): + def update(self, config, srcdir, doctreedir, app=None): """(Re-)read all files new or changed since last update. Yields a summary and then docnames as it processes them. Store all environment docnames in the canonical format (ie using SEP as a separator in place of @@ -416,6 +416,9 @@ class BuildEnvironment: break else: msg = '' + # the source and doctree directories may have been relocated + self.srcdir = srcdir + self.doctreedir = doctreedir self.find_files(config) added, changed, removed = self.get_outdated_files(config_changed) msg += '%s added, %s changed, %s removed' % (len(added), len(changed), @@ -807,10 +810,15 @@ class BuildEnvironment: for includefile in includefiles: try: toc = self.tocs[includefile].deepcopy() + if not toc.children: + # empty toc means: no titles will show up in the toctree + self.warn(docname, 'toctree contains reference to document ' + '%r that doesn\'t have a title: no link will be ' + 'generated' % includefile) except KeyError: # this is raised if the included file does not exist - self.warn(docname, 'toctree contains ref to nonexisting ' - 'file %r' % includefile) + self.warn(docname, 'toctree contains reference to nonexisting ' + 'document %r' % includefile) else: # if titles_only is given, only keep the main title and # sub-toctrees diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index 45dcb7b9..74f59c13 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -355,10 +355,11 @@ def generate_rst(what, name, members, options, add_content, document, lineno, modfile = None # e.g. for builtin and C modules for part in objpath: todoc = getattr(todoc, part) - except (ImportError, AttributeError): + except (ImportError, AttributeError), err: warnings.append(document.reporter.warning( - 'autodoc can\'t import/find %s %r, check your spelling ' - 'and sys.path' % (what, str(fullname)), line=lineno)) + 'autodoc can\'t import/find %s %r, it reported error: "%s",' + 'please check your spelling and sys.path' % + (what, str(fullname), err), line=lineno)) return warnings, result # check __module__ of object if wanted (for members not given explicitly) @@ -416,6 +417,7 @@ def generate_rst(what, name, members, options, add_content, document, lineno, u':class:`%s.%s`' % (b.__module__, b.__name__) for b in todoc.__bases__] result.append(indent + u' Bases: %s' % ', '.join(bases), '<autodoc>') + result.append(u'', '<autodoc>') # the module directive doesn't have content if what != 'module': diff --git a/sphinx/latexwriter.py b/sphinx/latexwriter.py index 70905aab..036fdf7c 100644 --- a/sphinx/latexwriter.py +++ b/sphinx/latexwriter.py @@ -873,7 +873,7 @@ class LaTeXTranslator(nodes.NodeVisitor): content = self.encode(node.astext().strip()) if self.in_title: self.body.append(r'\texttt{%s}' % content) - elif re.search('[ \t\n]', content): + elif node.has_key('role') and node['role'] == 'samp': self.body.append(r'\samp{%s}' % content) else: self.body.append(r'\code{%s}' % content) diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index f452e212..d5781a68 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -16,6 +16,8 @@ from sphinx.util import make_filename from sphinx.util.console import purple, bold, red, nocolor +PROMPT_PREFIX = '> ' + QUICKSTART_CONF = '''\ # -*- coding: utf-8 -*- # @@ -176,7 +178,8 @@ htmlhelp_basename = '%(project_fn)sdoc' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). latex_documents = [ - ('%(master)s', '%(project_fn)s.tex', '%(project)s Documentation', '%(author)s', 'manual'), + ('%(master)s', '%(project_fn)s.tex', '%(project)s Documentation', + '%(author)s', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -231,7 +234,8 @@ PAPER = # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d %(rbuilddir)s/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) %(rsrcdir)s +ALLSPHINXOPTS = -d %(rbuilddir)s/doctrees $(PAPEROPT_$(PAPER)) \ +$(SPHINXOPTS) %(rsrcdir)s .PHONY: help clean html web pickle htmlhelp latex changes linkcheck @@ -333,9 +337,9 @@ def ok(x): def do_prompt(d, key, text, default=None, validator=nonempty): while True: if default: - prompt = purple('> %s [%s]: ' % (text, default)) + prompt = purple(PROMPT_PREFIX + '%s [%s]: ' % (text, default)) else: - prompt = purple('> ' + text + ': ') + prompt = purple(PROMPT_PREFIX + text + ': ') x = raw_input(prompt) if default and not x: x = default @@ -364,7 +368,7 @@ Enter the root path for documentation.''' You have two options for placing the build directory for Sphinx output. Either, you use a directory ".build" within the root path, or you separate "source" and "build" directories within the root path.''' - do_prompt(d, 'sep', 'Separate source and build directories (y/n)', 'n', + do_prompt(d, 'sep', 'Separate source and build directories (y/N)', 'n', boolean) print ''' Inside the root directory, two more directories will be created; ".templates" @@ -399,14 +403,14 @@ document is a custom template, you can also set this to another filename.''' print ''' Please indicate if you want to use one of the following Sphinx extensions:''' do_prompt(d, 'ext_autodoc', 'autodoc: automatically insert docstrings ' - 'from modules (y/n)', 'n', boolean) + 'from modules (y/N)', 'n', boolean) do_prompt(d, 'ext_doctest', 'doctest: automatically test code snippets ' - 'in doctest blocks (y/n)', 'n', boolean) + 'in doctest blocks (y/N)', 'n', boolean) print ''' If you are under Unix, a Makefile can be generated for you so that you only have to run e.g. `make html' instead of invoking sphinx-build directly.''' - do_prompt(d, 'makefile', 'Create Makefile? (y/n)', + do_prompt(d, 'makefile', 'Create Makefile? (Y/n)', os.name == 'posix' and 'y' or 'n', boolean) d['project_fn'] = make_filename(d['project']) diff --git a/sphinx/roles.py b/sphinx/roles.py index 618b741c..2cfca3d8 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -195,17 +195,17 @@ _litvar_re = re.compile('{([^}]+)}') def emph_literal_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): text = utils.unescape(text) - retnodes = [] pos = 0 + retnode = nodes.literal(role=typ) for m in _litvar_re.finditer(text): if m.start() > pos: txt = text[pos:m.start()] - retnodes.append(nodes.literal(txt, txt)) - retnodes.append(nodes.emphasis('', '', nodes.literal(m.group(1), m.group(1)))) + retnode += nodes.Text(txt, txt) + retnode += nodes.emphasis(m.group(1), m.group(1)) pos = m.end() if pos < len(text): - retnodes.append(nodes.literal(text[pos:], text[pos:])) - return retnodes, [] + retnode += nodes.Text(text[pos:], text[pos:]) + return [retnode], [] specific_docroles = { diff --git a/sphinx/templates/genindex-split.html b/sphinx/templates/genindex-split.html index 957fd4c3..be6da9e2 100644 --- a/sphinx/templates/genindex-split.html +++ b/sphinx/templates/genindex-split.html @@ -5,7 +5,7 @@ <h1 id="index">Index</h1> <p>Index pages by letter:</p> - + <p>{% for key, dummy in genindexentries -%} <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a> {% if not loop.last %}| {% endif %} @@ -25,5 +25,5 @@ {%- endfor %}</p> <p><a href="{{ pathto('genindex-all') }}"><strong>Full index on one page</strong></a></p> -{% endif %} +{% endif %} {% endblock %} diff --git a/sphinx/templates/genindex.html b/sphinx/templates/genindex.html index a11a65a0..ec55b70e 100644 --- a/sphinx/templates/genindex.html +++ b/sphinx/templates/genindex.html @@ -52,5 +52,5 @@ {%- endfor %}</p> <p><a href="{{ pathto('genindex-all') }}"><strong>Full index on one page</strong></a></p> -{% endif %} +{% endif %} {% endblock %} diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 4dc6502c..e1621a76 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -250,7 +250,7 @@ def patfilter(names, pat): Adapted from fnmatch module. """ result = [] - if not pat in _pat_cache: + if pat not in _pat_cache: _pat_cache[pat] = re.compile(_translate_pattern(pat)) match = _pat_cache[pat].match return filter(match, names) diff --git a/sphinx/util/console.py b/sphinx/util/console.py index ea41e249..05ab7e50 100644 --- a/sphinx/util/console.py +++ b/sphinx/util/console.py @@ -38,6 +38,9 @@ def print_and_backspace(text, func): def nocolor(): codes.clear() +def coloron(): + codes.update(_orig_codes) + def colorize(name, text): return codes.get(name, '') + text + codes.get('reset', '') @@ -73,5 +76,7 @@ for i, (dark, light) in enumerate(_colors): codes[dark] = '\x1b[%im' % (i+30) codes[light] = '\x1b[%i;01m' % (i+30) +_orig_codes = codes.copy() + for _name in codes: create_color_func(_name) diff --git a/tests/path.py b/tests/path.py index b4829662..5ce1d118 100644 --- a/tests/path.py +++ b/tests/path.py @@ -353,7 +353,7 @@ class path(_base): whose names match the given pattern. For example, d.files('*.pyc'). """ - + return [p for p in self.listdir(pattern) if p.isfile()] def walk(self, pattern=None, errors='strict'): diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py new file mode 100644 index 00000000..51c9feb1 --- /dev/null +++ b/tests/test_quickstart.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +""" + test_quickstart + ~~~~~~~~~~~~~~~ + + Test the sphinx.quickstart module. + + :copyright: 2008 by Georg Brandl. + :license: BSD. +""" + +import sys +import time +import __builtin__ + +from util import * + +from sphinx import quickstart as qs +from sphinx.util.console import nocolor, coloron + +def setup_module(): + nocolor() + +def mock_raw_input(answers, needanswer=False): + called = set() + def raw_input(prompt): + if prompt in called: + raise AssertionError('answer for %r missing and no default ' + 'present' % prompt) + called.add(prompt) + for question in answers: + if prompt.startswith(qs.PROMPT_PREFIX + question): + return answers[question] + if needanswer: + raise AssertionError('answer for %r missing' % prompt) + return '' + return raw_input + +def teardown_module(): + qs.raw_input = __builtin__.raw_input + coloron() + + +def test_do_prompt(): + d = {} + answers = { + 'Q2': 'v2', + 'Q3': 'v3', + 'Q4': 'yes', + 'Q5': 'no', + 'Q6': 'foo', + } + qs.raw_input = mock_raw_input(answers) + try: + qs.do_prompt(d, 'k1', 'Q1') + except AssertionError: + assert 'k1' not in d + else: + assert False, 'AssertionError not raised' + qs.do_prompt(d, 'k1', 'Q1', default='v1') + assert d['k1'] == 'v1' + qs.do_prompt(d, 'k3', 'Q3', default='v3_default') + assert d['k3'] == 'v3' + qs.do_prompt(d, 'k2', 'Q2') + assert d['k2'] == 'v2' + qs.do_prompt(d, 'k4', 'Q4', validator=qs.boolean) + assert d['k4'] == 'yes' + qs.do_prompt(d, 'k5', 'Q5', validator=qs.boolean) + assert d['k5'] == 'no' + raises(AssertionError, qs.do_prompt, d, 'k6', 'Q6', validator=qs.boolean) + +@with_tempdir +def test_quickstart_defaults(tempdir): + answers = { + 'Root path': tempdir, + 'Project name': 'Sphinx Test', + 'Author name': 'Georg Brandl', + 'Project version': '0.1', + } + qs.raw_input = mock_raw_input(answers) + qs.inner_main([]) + + conffile = tempdir / 'conf.py' + assert conffile.isfile() + ns = {} + execfile(conffile, ns) + assert ns['extensions'] == [] + assert ns['templates_path'] == ['.templates'] + assert ns['source_suffix'] == '.rst' + assert ns['master_doc'] == 'index' + assert ns['project'] == 'Sphinx Test' + assert ns['copyright'] == '%s, Georg Brandl' % time.strftime('%Y') + assert ns['version'] == '0.1' + assert ns['release'] == '0.1' + assert ns['html_static_path'] == ['.static'] + assert ns['latex_documents'] == [ + ('index', 'SphinxTest.tex', 'Sphinx Test Documentation', + 'Georg Brandl', 'manual')] + + assert (tempdir / '.static').isdir() + assert (tempdir / '.templates').isdir() + assert (tempdir / 'index.rst').isfile() + assert (tempdir / 'Makefile').isfile() + +@with_tempdir +def test_quickstart_all_answers(tempdir): + answers = { + 'Root path': tempdir, + 'Separate source and build': 'y', + 'Name prefix for templates': '_', + 'Project name': 'Sphinx Test', + 'Author name': 'Georg Brandl', + 'Project version': '0.1', + 'Project release': '0.1.1', + 'Source file suffix': '.txt', + 'Name of your master document': 'contents', + 'autodoc': 'y', + 'doctest': 'yes', + 'Create Makefile': 'no', + } + qs.raw_input = mock_raw_input(answers, needanswer=True) + qs.inner_main([]) + + conffile = tempdir / 'source' / 'conf.py' + assert conffile.isfile() + ns = {} + execfile(conffile, ns) + assert ns['extensions'] == ['sphinx.ext.autodoc', 'sphinx.ext.doctest'] + assert ns['templates_path'] == ['_templates'] + assert ns['source_suffix'] == '.txt' + assert ns['master_doc'] == 'contents' + assert ns['project'] == 'Sphinx Test' + assert ns['copyright'] == '%s, Georg Brandl' % time.strftime('%Y') + assert ns['version'] == '0.1' + assert ns['release'] == '0.1.1' + assert ns['html_static_path'] == ['_static'] + assert ns['latex_documents'] == [ + ('contents', 'SphinxTest.tex', 'Sphinx Test Documentation', + 'Georg Brandl', 'manual')] + + assert (tempdir / 'build').isdir() + assert (tempdir / 'source' / '_static').isdir() + assert (tempdir / 'source' / '_templates').isdir() + assert (tempdir / 'source' / 'contents.txt').isfile() diff --git a/tests/util.py b/tests/util.py index 033cc934..754a4dda 100644 --- a/tests/util.py +++ b/tests/util.py @@ -19,7 +19,7 @@ from path import path __all__ = [ 'raises', 'raises_msg', 'ErrorOutput', 'TestApp', - 'with_tempdir', 'write_file', + 'path', 'with_tempdir', 'write_file', ] diff --git a/utils/check_sources.py b/utils/check_sources.py index 52525607..0f834fca 100755 --- a/utils/check_sources.py +++ b/utils/check_sources.py @@ -7,7 +7,7 @@ Make sure each Python file has a correct file header including copyright and license information. - :copyright: 2006-2007 by Georg Brandl. + :copyright: 2006-2008 by Georg Brandl. :license: GNU GPL, see LICENSE for more details. """ @@ -57,15 +57,17 @@ def check_style_and_encoding(fn, lines): for lno, line in enumerate(lines): if len(line) > 90: yield lno+1, "line too long" + if lno < 2: + co = coding_re.search(line) + if co: + encoding = co.group(1) + if line.strip().startswith('#'): + continue m = not_ix_re.search(line) if m: yield lno+1, '"' + m.group() + '"' if is_const_re.search(line): yield lno+1, 'using == None/True/False' - if lno < 2: - co = coding_re.search(line) - if co: - encoding = co.group(1) try: line.decode(encoding) except UnicodeDecodeError, err: |
