From a4ca76db7e43d76eba79e3dbd9955dba3ff26e1e Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Thu, 7 Jan 2010 14:35:24 +0100 Subject: [PATCH 01/17] Fix long line. --- sphinx/environment.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sphinx/environment.py b/sphinx/environment.py index 5c9b45f0a..e21364268 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -1232,7 +1232,8 @@ class BuildEnvironment: # keywords are referenced by named labels docname, labelid, _ = self.labels.get(target, ('','','')) if not docname: - #self.warn(node['refdoc'], 'unknown keyword: %s' % target) + #self.warn(node['refdoc'], + # 'unknown keyword: %s' % target) newnode = contnode else: newnode = nodes.reference('', '') From ebe51c181e7d30ee24a7a02f67ca72deca5ae3bf Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Thu, 7 Jan 2010 15:33:47 +0100 Subject: [PATCH 02/17] Add a "how do I do google analytics" entry, thanks tonfa. --- doc/faq.rst | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/doc/faq.rst b/doc/faq.rst index 34502dc41..54aef384c 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -53,6 +53,39 @@ github pages `_ to prepare Sphinx HTML output. +Google Analytics + You can use a custom ``layout.html`` template, like this: + + .. code-block:: html+django + + {% extends "!layout.html" %} + + {%- block extrahead %} + {{ super() }} + + {% endblock %} + + {% block footer %} + {{ super() }} + + {% endblock %} + .. _api role: http://git.savannah.gnu.org/cgit/kenozooid.git/tree/doc/extapi.py .. _xhtml to reST: http://docutils.sourceforge.net/sandbox/xhtml2rest/xhtml2rest.py From c49c9b288be5878eda0388241396487cf34fc18d Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 09:18:35 +0000 Subject: [PATCH 03/17] Make refdoc node attribute optional. --- sphinx/environment.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sphinx/environment.py b/sphinx/environment.py index 1b89b8c06..5f0128dcb 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -1172,6 +1172,7 @@ class BuildEnvironment: typ = node['reftype'] target = node['reftarget'] + refdoc = node.get('refdoc', fromdocname) try: if typ == 'ref': @@ -1181,7 +1182,7 @@ class BuildEnvironment: docname, labelid = self.anonlabels.get(target, ('','')) sectname = node.astext() if not docname: - self.warn(node['refdoc'], 'undefined label: %s' % + self.warn(refdoc, 'undefined label: %s' % target, node.line) else: # reference to the named label; the final node will @@ -1189,8 +1190,7 @@ class BuildEnvironment: docname, labelid, sectname = self.labels.get(target, ('','','')) if not docname: - self.warn( - node['refdoc'], + self.warn(refdoc, 'undefined label: %s' % target + ' -- if you ' 'don\'t give a link caption the label must ' 'precede a section header.', node.line) @@ -1216,10 +1216,10 @@ class BuildEnvironment: elif typ == 'doc': # directly reference to document by source name; # can be absolute or relative - docname = docname_join(node['refdoc'], target) + docname = docname_join(refdoc, target) if docname not in self.all_docs: - self.warn(node['refdoc'], - 'unknown document: %s' % docname, node.line) + self.warn(refdoc, 'unknown document: %s' % docname, + node.line) newnode = contnode else: if node['refcaption']: @@ -1236,8 +1236,7 @@ class BuildEnvironment: # keywords are referenced by named labels docname, labelid, _ = self.labels.get(target, ('','','')) if not docname: - #self.warn(node['refdoc'], - # 'unknown keyword: %s' % target) + #self.warn(refdoc, 'unknown keyword: %s' % target) newnode = contnode else: newnode = nodes.reference('', '') @@ -1266,12 +1265,11 @@ class BuildEnvironment: ('', '')) if not docname: if typ == 'term': - self.warn(node['refdoc'], + self.warn(refdoc, 'term not in glossary: %s' % target, node.line) elif typ == 'citation': - self.warn(node['refdoc'], - 'citation not found: %s' % target, + self.warn(refdoc, 'citation not found: %s' % target, node.line) newnode = contnode else: From c197c29f2e0ee3397b050fcdbb6b7daba27aa8e8 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 09:35:18 +0000 Subject: [PATCH 04/17] #313: fix search on Internet Explorer; add underscore.js to JavaScript libs. --- sphinx/builders/html.py | 3 ++- sphinx/themes/basic/static/doctools.js | 15 ++++++++++----- sphinx/themes/basic/static/searchtools.js | 2 +- sphinx/themes/basic/static/underscore.js | 16 ++++++++++++++++ 4 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 sphinx/themes/basic/static/underscore.js diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index cdabcd65c..e6f078b04 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -70,7 +70,8 @@ class StandaloneHTMLBuilder(Builder): embedded = False # for things like HTML help or Qt help: suppresses sidebar # This is a class attribute because it is mutated by Sphinx.add_javascript. - script_files = ['_static/jquery.js', '_static/doctools.js'] + script_files = ['_static/jquery.js', '_static/underscore.js', + '_static/doctools.js'] # Dito for this one. css_files = [] diff --git a/sphinx/themes/basic/static/doctools.js b/sphinx/themes/basic/static/doctools.js index cb6f30e56..c2bd1ac51 100644 --- a/sphinx/themes/basic/static/doctools.js +++ b/sphinx/themes/basic/static/doctools.js @@ -9,6 +9,11 @@ * */ +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + /** * make the code below compatible with browsers without * an installed firebug like debugger @@ -18,7 +23,7 @@ if (!window.console || !console.firebug) { "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {} + window.console[names[i]] = function() {}; } /** @@ -53,7 +58,7 @@ jQuery.getQueryParameters = function(s) { result[key] = [value]; } return result; -} +}; /** * small function to check if an array contains @@ -65,7 +70,7 @@ jQuery.contains = function(arr, item) { return true; } return false; -} +}; /** * highlight a given string on a jquery object by wrapping it in @@ -88,14 +93,14 @@ jQuery.fn.highlightText = function(text, className) { } else if (!jQuery(node).is("button, select, textarea")) { jQuery.each(node.childNodes, function() { - highlight(this) + highlight(this); }); } } return this.each(function() { highlight(this); }); -} +}; /** * Small JavaScript module for the documentation. diff --git a/sphinx/themes/basic/static/searchtools.js b/sphinx/themes/basic/static/searchtools.js index 2e9b5bee6..ba91e30c4 100644 --- a/sphinx/themes/basic/static/searchtools.js +++ b/sphinx/themes/basic/static/searchtools.js @@ -312,7 +312,7 @@ var Search = { var tmp = query.split(/\s+/); var object = (tmp.length == 1) ? tmp[0].toLowerCase() : null; for (var i = 0; i < tmp.length; i++) { - if (stopwords.indexOf(tmp[i]) != -1 || tmp[i].match(/^\d+$/)) { + if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/)) { // skip this word continue; } diff --git a/sphinx/themes/basic/static/underscore.js b/sphinx/themes/basic/static/underscore.js new file mode 100644 index 000000000..9146e0860 --- /dev/null +++ b/sphinx/themes/basic/static/underscore.js @@ -0,0 +1,16 @@ +(function(){var j=this,n=j._,i=function(a){this._wrapped=a},m=typeof StopIteration!=="undefined"?StopIteration:"__break__",b=j._=function(a){return new i(a)};if(typeof exports!=="undefined")exports._=b;var k=Array.prototype.slice,o=Array.prototype.unshift,p=Object.prototype.toString,q=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;b.VERSION="0.5.5";b.each=function(a,c,d){try{if(a.forEach)a.forEach(c,d);else if(b.isArray(a)||b.isArguments(a))for(var e=0,f=a.length;e=e.computed&&(e={value:f,computed:g})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;gf?1:0}),"value")};b.sortedIndex=function(a,c,d){d=d||b.identity;for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.zip=function(){for(var a=b.toArray(arguments),c=b.max(b.pluck(a,"length")),d=new Array(c),e=0;e0?f-c:c-f)>=0)return e;e[g++]=f}};b.bind=function(a,c){var d=b.rest(arguments,2);return function(){return a.apply(c||j,d.concat(b.toArray(arguments)))}};b.bindAll=function(a){var c=b.rest(arguments);if(c.length==0)c=b.functions(a);b.each(c,function(d){a[d]=b.bind(a[d],a)}); +return a};b.delay=function(a,c){var d=b.rest(arguments,2);return setTimeout(function(){return a.apply(a,d)},c)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(b.rest(arguments)))};b.wrap=function(a,c){return function(){var d=[a].concat(b.toArray(arguments));return c.apply(c,d)}};b.compose=function(){var a=b.toArray(arguments);return function(){for(var c=b.toArray(arguments),d=a.length-1;d>=0;d--)c=[a[d].apply(this,c)];return c[0]}};b.keys=function(a){if(b.isArray(a))return b.range(0,a.length); +var c=[];for(var d in a)q.call(a,d)&&c.push(d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=function(a){return b.select(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a,c){for(var d in c)a[d]=c[d];return a};b.clone=function(a){if(b.isArray(a))return a.slice(0);return b.extend({},a)};b.tap=function(a,c){c(a);return a};b.isEqual=function(a,c){if(a===c)return true;var d=typeof a;if(d!=typeof c)return false;if(a==c)return true;if(!a&&c||a&&!c)return false; +if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return true;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return false;if(a.length&&a.length!==c.length)return false;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return false;for(var f in a)if(!b.isEqual(a[f],c[f]))return false;return true};b.isEmpty=function(a){return b.keys(a).length== +0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=function(a){return!!(a&&a.concat&&a.unshift)};b.isArguments=function(a){return a&&b.isNumber(a.length)&&!b.isArray(a)&&!r.call(a,"length")};b.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return p.call(a)==="[object Number]"};b.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};b.isRegExp=function(a){return!!(a&& +a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};b.isNaN=function(a){return b.isNumber(a)&&isNaN(a)};b.isNull=function(a){return a===null};b.isUndefined=function(a){return typeof a=="undefined"};b.noConflict=function(){j._=n;return this};b.identity=function(a){return a};b.breakLoop=function(){throw m;};var s=0;b.uniqueId=function(a){var c=s++;return a?a+c:c};b.template=function(a,c){a=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+a.replace(/[\r\t\n]/g, +" ").replace(/'(?=[^%]*%>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<%=(.+?)%>/g,"',$1,'").split("<%").join("');").split("%>").join("p.push('")+"');}return p.join('');");return c?a(c):a};b.forEach=b.each;b.foldl=b.inject=b.reduce;b.foldr=b.reduceRight;b.filter=b.select;b.every=b.all;b.some=b.any;b.head=b.first;b.tail=b.rest;b.methods=b.functions;var l=function(a,c){return c?b(a).chain():a};b.each(b.functions(b),function(a){var c=b[a];i.prototype[a]=function(){var d=b.toArray(arguments); +o.call(d,this._wrapped);return l(c.apply(b,d),this._chain)}});b.each(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){c.apply(this._wrapped,arguments);return l(this._wrapped,this._chain)}});b.each(["concat","join","slice"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){return l(c.apply(this._wrapped,arguments),this._chain)}});i.prototype.chain=function(){this._chain=true;return this};i.prototype.value=function(){return this._wrapped}})(); From 403b01f38b187eb17ec69196aa14e246f9c726da Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 09:43:34 +0000 Subject: [PATCH 05/17] #315: update bug reporting information. --- sphinx/cmdline.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py index 8a069b325..dc3269e23 100644 --- a/sphinx/cmdline.py +++ b/sphinx/cmdline.py @@ -198,10 +198,13 @@ def main(argv): tbpath = save_traceback() print >>error, red('The full traceback has been saved ' 'in %s, if you want to report the ' - 'issue to the author.' % tbpath) + 'issue to the developers.' % tbpath) print >>error, ('Please also report this if it was a user ' 'error, so that a better error message ' 'can be provided next time.') - print >>error, ('Send reports to sphinx-dev@googlegroups.com. ' - 'Thanks!') + print >>error, ( + 'Either send bugs to the mailing list at ' + ',\n' + 'or report them in the tracker at ' + '. Thanks!') return 1 From c8321d3020760fb2ec1c51df8bb91e436096172c Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 09:55:07 +0000 Subject: [PATCH 06/17] #316: catch "broken pipe" OSErrors when communicating with graphviz; get stdout/stderr anyway. This happens e.g. when dot does not support the selected output format. --- CHANGES | 3 +++ sphinx/ext/graphviz.py | 23 +++++++++++++++++------ sphinx/util/__init__.py | 1 + 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index c6004c3f0..119950f22 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ Release 0.6.4 (in development) ============================== +* #316: Catch OSErrors occurring when calling graphviz with + arguments it doesn't understand. + * Restore compatibility with Pygments >= 1.2. * #295: Fix escaping of hyperref targets in LaTeX output. diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index d3e1bd99e..993d48962 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -22,7 +22,7 @@ except ImportError: from docutils import nodes from sphinx.errors import SphinxError -from sphinx.util import ensuredir, ENOENT +from sphinx.util import ensuredir, ENOENT, EPIPE from sphinx.util.compat import Directive @@ -102,6 +102,10 @@ def render_dot(self, code, options, format, prefix='graphviz'): ensuredir(path.dirname(outfn)) + # graphviz expects UTF-8 by default + if isinstance(code, unicode): + code = code.encode('utf-8') + dot_args = [self.builder.config.graphviz_dot] dot_args.extend(self.builder.config.graphviz_dot_args) dot_args.extend(options) @@ -118,10 +122,17 @@ def render_dot(self, code, options, format, prefix='graphviz'): self.builder.config.graphviz_dot) self.builder._graphviz_warned_dot = True return None, None - # graphviz expects UTF-8 by default - if isinstance(code, unicode): - code = code.encode('utf-8') - stdout, stderr = p.communicate(code) + try: + # Graphviz may close standard input when an error occurs, + # resulting in a broken pipe on communicate() + stdout, stderr = p.communicate(code) + except OSError, err: + if err.errno != EPIPE: + raise + # in this case, read the standard output and standard error streams + # directly, to get the error message(s) + stdout, stderr = p.stdout.read(), p.stderr.read() + p.wait() if p.returncode != 0: raise GraphvizError('dot exited with error:\n[stderr]\n%s\n' '[stdout]\n%s' % (stderr, stdout)) @@ -131,7 +142,7 @@ def render_dot(self, code, options, format, prefix='graphviz'): def render_dot_html(self, node, code, options, prefix='graphviz', imgcls=None, alt=None): try: - fname, outfn = render_dot(self, code, options, 'png', prefix) + fname, outfn = render_dot(self, code, options, 'pnf', prefix) except GraphvizError, exc: self.builder.warn('dot code %r: ' % code + str(exc)) raise nodes.SkipNode diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 0b9a1ace0..5745907f4 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -29,6 +29,7 @@ import sphinx # Errnos that we need. EEXIST = getattr(errno, 'EEXIST', 0) ENOENT = getattr(errno, 'ENOENT', 0) +EPIPE = getattr(errno, 'EPIPE', 0) # Generally useful regular expressions. ws_re = re.compile(r'\s+') From a9235ebc238db493076367d605b2f5c65eba7d3a Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 09:57:57 +0000 Subject: [PATCH 07/17] #314: fix typo in autosummary template. --- sphinx/ext/autosummary/templates/autosummary/module.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/ext/autosummary/templates/autosummary/module.rst b/sphinx/ext/autosummary/templates/autosummary/module.rst index cc76c9e00..c14456ba1 100644 --- a/sphinx/ext/autosummary/templates/autosummary/module.rst +++ b/sphinx/ext/autosummary/templates/autosummary/module.rst @@ -30,7 +30,7 @@ .. rubric:: Exceptions .. autosummary:: - {% for item in classes %} + {% for item in exceptions %} {{ item }} {%- endfor %} {% endif %} From 43d08313a0ecb0b331179c4875cf83728b4d9665 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 10:45:38 +0000 Subject: [PATCH 08/17] Improve the handling of non-Unicode strings in the configuration: warn about non-ascii bytestrings, and give nicer messages if unicode errors occur. --- CHANGES | 2 ++ sphinx/application.py | 1 + sphinx/builders/html.py | 9 ++++++++- sphinx/builders/latex.py | 8 +++++++- sphinx/config.py | 20 +++++++++++++++++++- sphinx/errors.py | 4 ++++ tests/test_config.py | 19 ++++++++++++++++++- 7 files changed, 59 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 119950f22..6bb149feb 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ Release 0.6.4 (in development) ============================== +* Improve the handling of non-Unicode strings in the configuration. + * #316: Catch OSErrors occurring when calling graphviz with arguments it doesn't understand. diff --git a/sphinx/application.py b/sphinx/application.py index 581e0fc6e..7d5c54392 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -92,6 +92,7 @@ class Sphinx(object): # read config self.tags = Tags(tags) self.config = Config(confdir, CONFIG_FILENAME, confoverrides, self.tags) + self.config.check_unicode(self.warn) # load all extension modules for extension in self.config.extensions: diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 6eff890cf..04f070707 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -656,7 +656,14 @@ class StandaloneHTMLBuilder(Builder): self.app.emit('html-page-context', pagename, templatename, ctx, event_arg) - output = self.templates.render(templatename, ctx) + try: + output = self.templates.render(templatename, ctx) + except UnicodeError: + self.warn("a Unicode error occurred when rendering the page %s. " + "Please make sure all config values that contain " + "non-ASCII content are Unicode strings." % pagename) + return + if not outfilename: outfilename = self.get_outfilename(pagename) # outfilename's path is in general different from self.outdir diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py index 0db30d553..eed4787d5 100644 --- a/sphinx/builders/latex.py +++ b/sphinx/builders/latex.py @@ -102,7 +102,13 @@ class LaTeXBuilder(Builder): doctree.settings.title = title doctree.settings.docname = docname doctree.settings.docclass = docclass - docwriter.write(doctree, destination) + try: + docwriter.write(doctree, destination) + except UnicodeError: + self.warn("a Unicode error occurred when writing the output. " + "Please make sure all config values that contain " + "non-ASCII content are Unicode strings." % pagename) + return self.info("done") def assemble_doctree(self, indexfile, toctree_only, appendices): diff --git a/sphinx/config.py b/sphinx/config.py index ee1bfb5fa..990849c93 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -10,9 +10,13 @@ """ import os +import re from os import path from sphinx.util import make_filename +from sphinx.errors import ConfigError + +nonascii_re = re.compile(r'[\x80-\xff]') class Config(object): @@ -112,20 +116,34 @@ class Config(object): self.values = Config.config_values.copy() config = {} if dirname is not None: - config['__file__'] = path.join(dirname, filename) + config_file = path.join(dirname, filename) + config['__file__'] = config_file config['tags'] = tags olddir = os.getcwd() try: os.chdir(dirname) execfile(config['__file__'], config) + except SyntaxError, err: + raise ConfigError('There is a syntax error in your ' + 'configuration file: ' + str(err)) finally: os.chdir(olddir) + self._raw_config = config # these two must be preinitialized because extensions can add their # own config values self.setup = config.get('setup', None) self.extensions = config.get('extensions', []) + def check_unicode(self, warn): + # check all string values for non-ASCII characters in + # bytestrings, since that can + for name, value in self._raw_config.iteritems(): + if isinstance(value, str) and nonascii_re.search(value): + warn('the config value %r is set to a string with non-ASCII ' + 'characters; this can lead to Unicode errors occurring. ' + 'Please use Unicode strings, e.g. u"Content".' % name) + def init_values(self): config = self._raw_config for valname, value in self.overrides.iteritems(): diff --git a/sphinx/errors.py b/sphinx/errors.py index 684101c68..4e62b1af1 100644 --- a/sphinx/errors.py +++ b/sphinx/errors.py @@ -44,5 +44,9 @@ class ExtensionError(SphinxError): return parent_str +class ConfigError(SphinxError): + category = 'Configuration error' + + class ThemeError(SphinxError): category = 'Theme error' diff --git a/tests/test_config.py b/tests/test_config.py index 76f7920b6..346e66c9a 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -12,7 +12,8 @@ from util import * -from sphinx.application import ExtensionError +from sphinx.config import Config +from sphinx.errors import ExtensionError, ConfigError @with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True', @@ -77,3 +78,19 @@ def test_extension_values(app): 'html_title', 'x', True) raises_msg(ExtensionError, 'already present', app.add_config_value, 'value_from_ext', 'x', True) + + +@with_tempdir +def test_errors_warnings(dir): + # test the error for syntax errors in the config file + write_file(dir / 'conf.py', 'project = \n') + raises_msg(ConfigError, 'conf.py', Config, dir, 'conf.py', {}, None) + + # test the warning for bytestrings with non-ascii content + write_file(dir / 'conf.py', '# -*- coding: latin-1\nproject = "foo\xe4"\n') + cfg = Config(dir, 'conf.py', {}, None) + warned = [False] + def warn(msg): + warned[0] = True + cfg.check_unicode(warn) + assert warned[0] From 1b725c3acf24474b4b05daac88f45203eec578ad Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 10:47:05 +0000 Subject: [PATCH 09/17] Fix typo. --- sphinx/ext/graphviz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 993d48962..b7cf93d24 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -142,7 +142,7 @@ def render_dot(self, code, options, format, prefix='graphviz'): def render_dot_html(self, node, code, options, prefix='graphviz', imgcls=None, alt=None): try: - fname, outfn = render_dot(self, code, options, 'pnf', prefix) + fname, outfn = render_dot(self, code, options, 'png', prefix) except GraphvizError, exc: self.builder.warn('dot code %r: ' % code + str(exc)) raise nodes.SkipNode From c2379f7c2105d3ea1460e1c5214ae8b426bd83d9 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 20:53:43 +0000 Subject: [PATCH 10/17] Remove Python 2.5ism and undefined local access. --- sphinx/builders/latex.py | 2 +- sphinx/config.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py index eed4787d5..751bf28cd 100644 --- a/sphinx/builders/latex.py +++ b/sphinx/builders/latex.py @@ -107,7 +107,7 @@ class LaTeXBuilder(Builder): except UnicodeError: self.warn("a Unicode error occurred when writing the output. " "Please make sure all config values that contain " - "non-ASCII content are Unicode strings." % pagename) + "non-ASCII content are Unicode strings.") return self.info("done") diff --git a/sphinx/config.py b/sphinx/config.py index 990849c93..4cd514921 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -121,11 +121,12 @@ class Config(object): config['tags'] = tags olddir = os.getcwd() try: - os.chdir(dirname) - execfile(config['__file__'], config) - except SyntaxError, err: - raise ConfigError('There is a syntax error in your ' - 'configuration file: ' + str(err)) + try: + os.chdir(dirname) + execfile(config['__file__'], config) + except SyntaxError, err: + raise ConfigError('There is a syntax error in your ' + 'configuration file: ' + str(err)) finally: os.chdir(olddir) From 872062f93b6ba2adebe369e4f38e6b45c3979101 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 20:55:59 +0000 Subject: [PATCH 11/17] Prepare for release 0.6.4. --- CHANGES | 4 ++-- sphinx/__init__.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 6bb149feb..5e8d41ea6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ -Release 0.6.4 (in development) -============================== +Release 0.6.4 (Jan 12, 2010) +============================ * Improve the handling of non-Unicode strings in the configuration. diff --git a/sphinx/__init__.py b/sphinx/__init__.py index bbf83e58a..6a55c9b85 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -12,8 +12,8 @@ import sys from os import path -__version__ = '0.6.3+' -__released__ = '0.6.3' # used when Sphinx builds its own docs +__version__ = '0.6.4' +__released__ = '0.6.4' # used when Sphinx builds its own docs package_dir = path.abspath(path.dirname(__file__)) From 59a7070e7ecc81592ede641c317b60383cfa00c4 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 21:01:49 +0000 Subject: [PATCH 12/17] Update long_description a bit. --- setup.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 981270c88..aedfb8e78 100644 --- a/setup.py +++ b/setup.py @@ -21,19 +21,20 @@ Sphinx uses reStructuredText as its markup language, and many of its strengths come from the power and straightforwardness of reStructuredText and its parsing and translating suite, the Docutils. -Although it is still under constant development, the following features -are already present, work fine and can be seen "in action" in the Python docs: +Among its features are the following: -* Output formats: HTML (including Windows HTML Help), plain text and LaTeX, - for printable PDF versions +* Output formats: HTML (including derivative formats such as HTML Help, Epub + and Qt Help), plain text and LaTeX or direct PDF output using rst2pdf * Extensive cross-references: semantic markup and automatic links for functions, classes, glossary terms and similar pieces of information * Hierarchical structure: easy definition of a document tree, with automatic links to siblings, parents and children * Automatic indices: general index as well as a module index * Code handling: automatic highlighting using the Pygments highlighter +* Flexible HTML output using the Jinja 2 templating engine * Various extensions are available, e.g. for automatic testing of snippets - and inclusion of appropriately formatted docstrings. + and inclusion of appropriately formatted docstrings +* Setuptools integration A development egg can be found `here `_. From fa00d30daf77fe195d2d6fd7902f06b124646af4 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 12 Jan 2010 21:11:20 +0000 Subject: [PATCH 14/17] Add link to rst2pdf generated version. --- doc/_templates/index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/_templates/index.html b/doc/_templates/index.html index 0f4d4c641..a68a62514 100644 --- a/doc/_templates/index.html +++ b/doc/_templates/index.html @@ -46,8 +46,10 @@

The Python documentation and this page are different examples of Sphinx in use. - You can also download a PDF version - of the Sphinx documentation, generated from the LaTeX Sphinx produces. + You can also download PDF versions of the Sphinx documentation: + a version generated from + the LaTeX Sphinx produces, and a + version generated by rst2pdf.

For examples of how Sphinx source files look, use the “Show source” From 8b5ae5c13180a39213bade387eb94f65854f533e Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 16 Jan 2010 19:54:37 +0100 Subject: [PATCH 15/17] Remove bad tags. --- utils/check_sources.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/check_sources.py b/utils/check_sources.py index ec7695d57..6f78c26e0 100755 --- a/utils/check_sources.py +++ b/utils/check_sources.py @@ -154,8 +154,7 @@ def check_whitespace_and_spelling(fn, lines): yield lno+1, '"%s" used' % word -bad_tags = ('', '', '' - '

', '', '', '', '', '', '
', ' Date: Sun, 17 Jan 2010 12:18:21 +0100 Subject: [PATCH 16/17] #288: fix bottom margin of paragraphs in admonitions. --- sphinx/themes/default/static/default.css_t | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sphinx/themes/default/static/default.css_t b/sphinx/themes/default/static/default.css_t index 3bee8c8a5..b465da3fa 100644 --- a/sphinx/themes/default/static/default.css_t +++ b/sphinx/themes/default/static/default.css_t @@ -199,6 +199,18 @@ div.admonition p.admonition-title + p { display: inline; } +div.admonition p { + margin-bottom: 5px; +} + +div.admonition pre { + margin-bottom: 5px; +} + +div.admonition ul, div.admonition ol { + margin-bottom: 5px; +} + div.note { background-color: #eee; border: 1px solid #ccc; From 8fc4896801e9a887d0004d17005ffdf5e21db1ed Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 17 Jan 2010 14:17:23 +0100 Subject: [PATCH 17/17] #321: Fix link generation in the LaTeX builder -- target names need to be escaped in references as well as definitions. --- CHANGES | 6 ++++++ sphinx/writers/latex.py | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 5e8d41ea6..66aee2446 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +Release 0.6.5 (in development) +============================== + +* #321: Fix link generation in the LaTeX builder. + + Release 0.6.4 (Jan 12, 2010) ============================ diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 8e1a6a80b..981c2eb8f 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1038,13 +1038,15 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append('\\href{%s}{' % self.encode_uri(uri)) self.context.append('}') elif uri.startswith('#'): - self.body.append('\\hyperlink{%s}{' % uri[1:]) + # references to labels + self.body.append('\\hyperlink{%s}{' % self.idescape(uri[1:])) self.context.append('}') elif uri.startswith('%'): + # references to documents or labels inside documents hashindex = uri.find('#') targetname = (hashindex == -1) and '--doc-' + uri[1:] \ or uri[hashindex+1:] - self.body.append('\\hyperlink{%s}{' % targetname) + self.body.append('\\hyperlink{%s}{' % self.idescape(targetname)) self.context.append('}') elif uri.startswith('@token'): if self.in_production_list: