summaryrefslogtreecommitdiff
path: root/sphinx
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2011-07-07 19:50:11 +0200
committerGeorg Brandl <georg@python.org>2011-07-07 19:50:11 +0200
commit50bbb1a5e764ad72879f1ce5a6ddbdcfba5cfe08 (patch)
tree6251a2c44945150541824f691d524d5dd7c8bef0 /sphinx
parentec2ac36d5fdec3d52009bcc24b7d3336ee3a9bef (diff)
parent09e2e6e04d81d325b9b985fdb2a4965ffde7a24c (diff)
downloadsphinx-50bbb1a5e764ad72879f1ce5a6ddbdcfba5cfe08.tar.gz
Merged in jonwaltman/sphinx-info (pull request #5)
Diffstat (limited to 'sphinx')
-rw-r--r--sphinx/builders/gettext.py43
-rw-r--r--sphinx/ext/autosummary/__init__.py91
-rw-r--r--sphinx/ext/autosummary/generate.py6
-rw-r--r--sphinx/ext/mathbase.py5
-rw-r--r--sphinx/themes/basic/static/underscore.js7
-rw-r--r--sphinx/util/nodes.py13
6 files changed, 126 insertions, 39 deletions
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index f030750e..fbe8afbb 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -43,6 +43,20 @@ msgstr ""
"""[1:]
+class Catalog(object):
+ """Catalog of translatable messages."""
+
+ def __init__(self):
+ self.messages = [] # retain insertion order, a la OrderedDict
+ self.metadata = {} # msgid -> file, line, uid
+
+ def add(self, msg, origin):
+ if msg not in self.metadata: # faster lookup in hash
+ self.messages.append(msg)
+ self.metadata[msg] = []
+ self.metadata[msg].append((origin.source, origin.line, origin.uid))
+
+
class I18nBuilder(Builder):
"""
General i18n builder.
@@ -52,7 +66,7 @@ class I18nBuilder(Builder):
def init(self):
Builder.init(self)
- self.catalogs = defaultdict(dict)
+ self.catalogs = defaultdict(Catalog)
def get_target_uri(self, docname, typ=None):
return ''
@@ -67,12 +81,7 @@ class I18nBuilder(Builder):
catalog = self.catalogs[docname.split(SEP, 1)[0]]
for node, msg in extract_messages(doctree):
- if not msg in catalog:
- catalog[msg] = []
- if node.source and node.line:
- position = {"source": node.source,
- "line": node.line}
- catalog[msg].append(position)
+ catalog.add(msg, node)
class MessageCatalogBuilder(I18nBuilder):
@@ -90,7 +99,7 @@ class MessageCatalogBuilder(I18nBuilder):
# XXX should supply tz
ctime = datetime.now().strftime('%Y-%m-%d %H:%M%z'),
)
- for section, messages in self.status_iterator(
+ for section, catalog in self.status_iterator(
self.catalogs.iteritems(), "writing message catalogs... ",
lambda (section, _):darkgreen(section), len(self.catalogs)):
@@ -98,14 +107,22 @@ class MessageCatalogBuilder(I18nBuilder):
pofile = open(pofn, 'w', encoding='utf-8')
try:
pofile.write(POHEADER % data)
- for message, positions in messages.iteritems():
+
+ for message in catalog.messages:
+ positions = catalog.metadata[message]
+
+ # generate "#: file1:line1 file2:line2 ..."
+ pofile.write(u"#: %s\n" % ", ".join("%s:%s" %
+ (path.relpath(source, self.srcdir), line)
+ for source, line, _ in positions))
+ # generate "# uuid1\n# uuid2\n ..."
+ pofile.write(u"# %s\n" % "\n# ".join(uid for _, _, uid
+ in positions))
+
# message contains *one* line of text ready for translation
message = message.replace(u'\\', ur'\\'). \
replace(u'"', ur'\"')
- for position in positions:
- source = path.relpath(position["source"], self.outdir)
- line = position["line"]
- pofile.write(u'#: %s:%d\n' % (source, line))
pofile.write(u'msgid "%s"\nmsgstr ""\n\n' % message)
+
finally:
pofile.close()
diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py
index aad8b9f6..32dcc3e4 100644
--- a/sphinx/ext/autosummary/__init__.py
+++ b/sphinx/ext/autosummary/__init__.py
@@ -125,22 +125,39 @@ def autosummary_table_visit_html(self, node):
# -- autodoc integration -------------------------------------------------------
-try:
- ismemberdescriptor = inspect.ismemberdescriptor
- isgetsetdescriptor = inspect.isgetsetdescriptor
-except AttributeError:
- def ismemberdescriptor(obj):
- return False
- isgetsetdescriptor = ismemberdescriptor
+class FakeDirective:
+ env = {}
+ genopt = {}
def get_documenter(obj, parent):
"""Get an autodoc.Documenter class suitable for documenting the given
object.
+
+ *obj* is the Python object to be documented, and *parent* is an
+ another Python object (e.g. a module or a class) to which *obj*
+ belongs to.
"""
- from sphinx.ext.autodoc import AutoDirective, DataDocumenter
+ from sphinx.ext.autodoc import AutoDirective, DataDocumenter, \
+ ModuleDocumenter
+
+ if inspect.ismodule(obj):
+ # ModuleDocumenter.can_document_member always returns False
+ return ModuleDocumenter
+ # Construct a fake documenter for *parent*
+ if parent is not None:
+ parent_doc_cls = get_documenter(parent, None)
+ else:
+ parent_doc_cls = ModuleDocumenter
+
+ if hasattr(parent, '__name__'):
+ parent_doc = parent_doc_cls(FakeDirective(), parent.__name__)
+ else:
+ parent_doc = parent_doc_cls(FakeDirective(), "")
+
+ # Get the corrent documenter class for *obj*
classes = [cls for cls in AutoDirective._registry.values()
- if cls.can_document_member(obj, '', False, parent)]
+ if cls.can_document_member(obj, '', False, parent_doc)]
if classes:
classes.sort(key=lambda cls: cls.priority)
return classes[-1]
@@ -154,7 +171,7 @@ class Autosummary(Directive):
"""
Pretty table containing short signatures and summaries of functions etc.
- autosummary also generates a (hidden) toctree:: node.
+ autosummary can also optionally generate a hidden toctree:: node.
"""
required_arguments = 0
@@ -214,10 +231,7 @@ class Autosummary(Directive):
"""
env = self.state.document.settings.env
- prefixes = ['']
- currmodule = env.temp_data.get('py:module')
- if currmodule:
- prefixes.insert(0, currmodule)
+ prefixes = get_import_prefixes_from_env(env)
items = []
@@ -322,13 +336,29 @@ class Autosummary(Directive):
def mangle_signature(sig, max_chars=30):
"""Reformat a function signature to a more compact form."""
- sig = re.sub(r"^\((.*)\)$", r"\1", sig) + ", "
- r = re.compile(r"(?P<name>[a-zA-Z0-9_*]+)(?P<default>=.*?)?, ")
- items = r.findall(sig)
+ s = re.sub(r"^\((.*)\)$", r"\1", sig).strip()
+
+ # Strip strings (which can contain things that confuse the code below)
+ s = re.sub(r"\\\\", "", s)
+ s = re.sub(r"\\'", "", s)
+ s = re.sub(r"'[^']*'", "", s)
+
+ # Parse the signature to arguments + options
+ args = []
+ opts = []
+
+ opt_re = re.compile(r"^(.*, |)([a-zA-Z0-9_*]+)=")
+ while s:
+ m = opt_re.search(s)
+ if not m:
+ # The rest are arguments
+ args = s.split(', ')
+ break
- args = [name for name, default in items if not default]
- opts = [name for name, default in items if default]
+ opts.insert(0, m.group(2))
+ s = m.group(1)[:-2]
+ # Produce a more compact signature
sig = limited_join(", ", args, max_chars=max_chars-2)
if opts:
if not sig:
@@ -364,6 +394,26 @@ def limited_join(sep, items, max_chars=30, overflow_marker="..."):
# -- Importing items -----------------------------------------------------------
+def get_import_prefixes_from_env(env):
+ """
+ Obtain current Python import prefixes (for `import_by_name`)
+ from ``document.env``
+ """
+ prefixes = [None]
+
+ currmodule = env.temp_data.get('py:module')
+ if currmodule:
+ prefixes.insert(0, currmodule)
+
+ currclass = env.temp_data.get('py:class')
+ if currclass:
+ if currmodule:
+ prefixes.insert(0, currmodule + "." + currclass)
+ else:
+ prefixes.insert(0, currclass)
+
+ return prefixes
+
def import_by_name(name, prefixes=[None]):
"""Import a Python object that has the given *name*, under one of the
*prefixes*. The first name that succeeds is used.
@@ -436,8 +486,7 @@ def autolink_role(typ, rawtext, etext, lineno, inliner,
'obj', rawtext, etext, lineno, inliner, options, content)
pnode = r[0][0]
- prefixes = [None]
- #prefixes.insert(0, inliner.document.settings.env.currmodule)
+ prefixes = get_import_prefixes_from_env(env)
try:
name, obj, parent = import_by_name(pnode['reftarget'], prefixes)
except ImportError:
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index fecb5689..089d181f 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -232,7 +232,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
*template* ``None`` if the directive does not have the
corresponding options set.
"""
- autosummary_re = re.compile(r'^\s*\.\.\s+autosummary::\s*')
+ autosummary_re = re.compile(r'^(\s*)\.\.\s+autosummary::\s*')
automodule_re = re.compile(
r'^\s*\.\.\s+automodule::\s*([A-Za-z0-9_.]+)\s*$')
module_re = re.compile(
@@ -247,6 +247,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
template = None
current_module = module
in_autosummary = False
+ base_indent = ""
for line in lines:
if in_autosummary:
@@ -277,7 +278,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
documented.append((name, toctree, template))
continue
- if not line.strip():
+ if not line.strip() or line.startswith(base_indent + " "):
continue
in_autosummary = False
@@ -285,6 +286,7 @@ def find_autosummary_in_lines(lines, module=None, filename=None):
m = autosummary_re.match(line)
if m:
in_autosummary = True
+ base_indent = m.group(1)
toctree = None
template = None
continue
diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py
index b5473449..1a2ca6af 100644
--- a/sphinx/ext/mathbase.py
+++ b/sphinx/ext/mathbase.py
@@ -56,6 +56,7 @@ class MathDirective(Directive):
final_argument_whitespace = True
option_spec = {
'label': directives.unchanged,
+ 'name': directives.unchanged,
'nowrap': directives.flag,
}
@@ -65,7 +66,9 @@ class MathDirective(Directive):
latex = self.arguments[0] + '\n\n' + latex
node = displaymath()
node['latex'] = latex
- node['label'] = self.options.get('label', None)
+ node['label'] = self.options.get('name', None)
+ if node['label'] is None:
+ node['label'] = self.options.get('label', None)
node['nowrap'] = 'nowrap' in self.options
node['docname'] = self.state.document.settings.env.docname
ret = [node]
diff --git a/sphinx/themes/basic/static/underscore.js b/sphinx/themes/basic/static/underscore.js
index 9146e086..5d899143 100644
--- a/sphinx/themes/basic/static/underscore.js
+++ b/sphinx/themes/basic/static/underscore.js
@@ -1,3 +1,10 @@
+// Underscore.js 0.5.5
+// (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the terms of the MIT license.
+// Portions of Underscore are inspired by or borrowed from Prototype.js,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore/
(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<f;e++)c.call(d,
a[e],e,a);else{var g=b.keys(a);f=g.length;for(e=0;e<f;e++)c.call(d,a[g[e]],g[e],a)}}catch(h){if(h!=m)throw h;}return a};b.map=function(a,c,d){if(a&&b.isFunction(a.map))return a.map(c,d);var e=[];b.each(a,function(f,g,h){e.push(c.call(d,f,g,h))});return e};b.reduce=function(a,c,d,e){if(a&&b.isFunction(a.reduce))return a.reduce(b.bind(d,e),c);b.each(a,function(f,g,h){c=d.call(e,c,f,g,h)});return c};b.reduceRight=function(a,c,d,e){if(a&&b.isFunction(a.reduceRight))return a.reduceRight(b.bind(d,e),c);
var f=b.clone(b.toArray(a)).reverse();b.each(f,function(g,h){c=d.call(e,c,g,h,a)});return c};b.detect=function(a,c,d){var e;b.each(a,function(f,g,h){if(c.call(d,f,g,h)){e=f;b.breakLoop()}});return e};b.select=function(a,c,d){if(a&&b.isFunction(a.filter))return a.filter(c,d);var e=[];b.each(a,function(f,g,h){c.call(d,f,g,h)&&e.push(f)});return e};b.reject=function(a,c,d){var e=[];b.each(a,function(f,g,h){!c.call(d,f,g,h)&&e.push(f)});return e};b.all=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.every))return a.every(c,
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index a241f574..682ea77b 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -22,16 +22,25 @@ from sphinx.util.pycompat import class_types
explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
caption_ref_re = explicit_title_re # b/w compat alias
-
+IGNORED_NODES = (
+ nodes.Invisible,
+ nodes.Inline,
+ nodes.literal_block,
+ nodes.doctest_block,
+ #XXX there are probably more
+)
def extract_messages(doctree):
"""Extract translatable messages from a document tree."""
for node in doctree.traverse(nodes.TextElement):
- if isinstance(node, (nodes.Invisible, nodes.Inline)):
+ if not node.source:
+ continue # built-in message
+ if isinstance(node, IGNORED_NODES):
continue
# <field_name>orphan</field_name>
# XXX ignore all metadata (== docinfo)
if isinstance(node, nodes.field_name) and node.children[0] == 'orphan':
continue
+
msg = node.rawsource.replace('\n', ' ').strip()
# XXX nodes rendering empty are likely a bug in sphinx.addnodes
if msg: