diff options
Diffstat (limited to 'sphinx/ext')
| -rw-r--r-- | sphinx/ext/autodoc.py | 162 | ||||
| -rw-r--r-- | sphinx/ext/autosummary/__init__.py | 22 | ||||
| -rw-r--r-- | sphinx/ext/autosummary/generate.py | 13 | ||||
| -rw-r--r-- | sphinx/ext/coverage.py | 5 | ||||
| -rw-r--r-- | sphinx/ext/doctest.py | 6 | ||||
| -rw-r--r-- | sphinx/ext/graphviz.py | 38 | ||||
| -rw-r--r-- | sphinx/ext/inheritance_diagram.py | 16 | ||||
| -rw-r--r-- | sphinx/ext/intersphinx.py | 26 | ||||
| -rw-r--r-- | sphinx/ext/oldcmarkup.py | 1 | ||||
| -rw-r--r-- | sphinx/ext/pngmath.py | 6 | ||||
| -rw-r--r-- | sphinx/ext/viewcode.py | 8 |
11 files changed, 175 insertions, 128 deletions
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index adf08bcd..3a2476a6 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -14,7 +14,7 @@ import re import sys import inspect -from types import FunctionType, BuiltinFunctionType, MethodType, ClassType +from types import FunctionType, BuiltinFunctionType, MethodType from docutils import nodes from docutils.utils import assemble_option_dict @@ -27,15 +27,10 @@ from sphinx.application import ExtensionError from sphinx.util.nodes import nested_parse_with_titles from sphinx.util.compat import Directive from sphinx.util.inspect import isdescriptor, safe_getmembers, safe_getattr +from sphinx.util.pycompat import base_exception, class_types from sphinx.util.docstrings import prepare_docstring -try: - base_exception = BaseException -except NameError: - base_exception = Exception - - #: extended signature RE: with explicit module name separated by :: py_ext_sig_re = re.compile( r'''^ ([\w.]+::)? # explicit module name @@ -90,7 +85,8 @@ def members_set_option(arg): def bool_option(arg): """Used to convert flag options to auto directives. (Instead of - directives.flag(), which returns None.)""" + directives.flag(), which returns None). + """ return True @@ -138,8 +134,7 @@ class AutodocReporter(object): # Some useful event listener factories for autodoc-process-docstring. def cut_lines(pre, post=0, what=None): - """ - Return a listener that removes the first *pre* and last *post* + """Return a listener that removes the first *pre* and last *post* lines of every docstring. If *what* is a sequence of strings, only docstrings of a type in *what* will be processed. @@ -165,9 +160,8 @@ def cut_lines(pre, post=0, what=None): return process def between(marker, what=None, keepempty=False, exclude=False): - """ - Return a listener that either keeps, or if *exclude* is True excludes, lines - between lines that match the *marker* regular expression. If no line + """Return a listener that either keeps, or if *exclude* is True excludes, + lines between lines that match the *marker* regular expression. If no line matches, the resulting docstring would be empty, so no change will be made unless *keepempty* is true. @@ -256,6 +250,9 @@ class Documenter(object): self.retann = None # the object to document (set after import_object succeeds) self.object = None + self.object_name = None + # the parent/owner of the object to document + self.parent = None # the module analyzer to get at attribute docs, or None self.analyzer = None @@ -264,8 +261,7 @@ class Documenter(object): self.directive.result.append(self.indent + line, source, *lineno) def resolve_name(self, modname, parents, path, base): - """ - Resolve the module and name of the object to document given by the + """Resolve the module and name of the object to document given by the arguments and the current module/class. Must return a pair of the module name and a chain of attributes; for @@ -275,8 +271,7 @@ class Documenter(object): raise NotImplementedError('must be implemented in subclasses') def parse_name(self): - """ - Determine what module to import and what attribute to document. + """Determine what module to import and what attribute to document. Returns True and sets *self.modname*, *self.objpath*, *self.fullname*, *self.args* and *self.retann* if parsing and resolving was successful. @@ -313,17 +308,20 @@ class Documenter(object): return True def import_object(self): - """ - Import the object given by *self.modname* and *self.objpath* and sets + """Import the object given by *self.modname* and *self.objpath* and set it as *self.object*. Returns True if successful, False if an error occurred. """ try: __import__(self.modname) + parent = None obj = self.module = sys.modules[self.modname] for part in self.objpath: + parent = obj obj = self.get_attr(obj, part) + self.object_name = part + self.parent = parent self.object = obj return True # this used to only catch SyntaxError, ImportError and AttributeError, @@ -336,15 +334,15 @@ class Documenter(object): return False def get_real_modname(self): - """ - Get the real module name of an object to document. (It can differ - from the name of the module through which the object was imported.) + """Get the real module name of an object to document. + + It can differ from the name of the module through which the object was + imported. """ return self.get_attr(self.object, '__module__', None) or self.modname def check_module(self): - """ - Check if *self.object* is really defined in the module given by + """Check if *self.object* is really defined in the module given by *self.modname*. """ modname = self.get_attr(self.object, '__module__', None) @@ -353,25 +351,26 @@ class Documenter(object): return True def format_args(self): - """ - Format the argument signature of *self.object*. Should return None if - the object does not have a signature. + """Format the argument signature of *self.object*. + + Should return None if the object does not have a signature. """ return None def format_name(self): - """ - Format the name of *self.object*. This normally should be something - that can be parsed by the generated directive, but doesn't need to be - (Sphinx will display it unparsed then). + """Format the name of *self.object*. + + This normally should be something that can be parsed by the generated + directive, but doesn't need to be (Sphinx will display it unparsed + then). """ # normally the name doesn't contain the module (except for module # directives of course) return '.'.join(self.objpath) or self.modname def format_signature(self): - """ - Format the signature (arguments and return annotation) of the object. + """Format the signature (arguments and return annotation) of the object. + Let the user process it via the ``autodoc-process-signature`` event. """ if self.args is not None: @@ -416,9 +415,11 @@ class Documenter(object): def get_doc(self, encoding=None): """Decode and return lines of the docstring(s) for the object.""" docstring = self.get_attr(self.object, '__doc__', None) - if docstring: - # make sure we have Unicode docstrings, then sanitize and split - # into lines + # make sure we have Unicode docstrings, then sanitize and split + # into lines + if isinstance(docstring, unicode): + return [prepare_docstring(docstring)] + elif docstring: return [prepare_docstring(force_decode(docstring, encoding))] return [] @@ -438,8 +439,11 @@ class Documenter(object): # set sourcename and add content from attribute documentation if self.analyzer: # prevent encoding errors when the file name is non-ASCII - filename = unicode(self.analyzer.srcname, - sys.getfilesystemencoding(), 'replace') + if not isinstance(self.analyzer.srcname, unicode): + filename = unicode(self.analyzer.srcname, + sys.getfilesystemencoding(), 'replace') + else: + filename = self.analyzer.srcname sourcename = u'%s:docstring of %s' % (filename, self.fullname) attr_docs = self.analyzer.find_attr_docs() @@ -466,8 +470,7 @@ class Documenter(object): self.add_line(line, src[0], src[1]) def get_object_members(self, want_all): - """ - Return `(members_check_module, members)` where `members` is a + """Return `(members_check_module, members)` where `members` is a list of `(membername, member)` pairs of the members of *self.object*. If *want_all* is True, return all members. Else, only return those @@ -511,8 +514,9 @@ class Documenter(object): return False, sorted(members) def filter_members(self, members, want_all): - """ - Filter the given member list: members are skipped if + """Filter the given member list. + + Members are skipped if - they are private (except if given explicitly) - they are undocumented (except if undoc-members is given) @@ -565,9 +569,10 @@ class Documenter(object): return ret def document_members(self, all_members=False): - """ - Generate reST for member documentation. If *all_members* is True, - do all members, else those given by *self.options.members*. + """Generate reST for member documentation. + + If *all_members* is True, do all members, else those given by + *self.options.members*. """ # set current namespace for finding members self.env.temp_data['autodoc:module'] = self.modname @@ -625,8 +630,8 @@ class Documenter(object): def generate(self, more_content=None, real_modname=None, check_module=False, all_members=False): - """ - Generate reST for the object given by *self.name*, and possibly members. + """Generate reST for the object given by *self.name*, and possibly for + its members. If *more_content* is given, include that content. If *real_modname* is given, use that module name to find attribute docs. If *check_module* is @@ -866,7 +871,7 @@ class ClassDocumenter(ModuleLevelDocumenter): @classmethod def can_document_member(cls, member, membername, isattr, parent): - return isinstance(member, (type, ClassType)) + return isinstance(member, class_types) def import_object(self): ret = ModuleLevelDocumenter.import_object(self) @@ -939,9 +944,12 @@ class ClassDocumenter(ModuleLevelDocumenter): docstrings = [initdocstring] else: docstrings.append(initdocstring) - - return [prepare_docstring(force_decode(docstring, encoding)) - for docstring in docstrings] + doc = [] + for docstring in docstrings: + if not isinstance(docstring, unicode): + docstring = force_decode(docstring, encoding) + doc.append(prepare_docstring(docstring)) + return doc def add_content(self, more_content, no_docstring=False): if self.doc_as_attr: @@ -972,7 +980,7 @@ class ExceptionDocumenter(ClassDocumenter): @classmethod def can_document_member(cls, member, membername, isattr, parent): - return isinstance(member, (type, ClassType)) and \ + return isinstance(member, class_types) and \ issubclass(member, base_exception) @@ -1004,24 +1012,38 @@ class MethodDocumenter(ClassLevelDocumenter): return inspect.isroutine(member) and \ not isinstance(parent, ModuleDocumenter) - def import_object(self): - ret = ClassLevelDocumenter.import_object(self) - if isinstance(self.object, classmethod) or \ - (isinstance(self.object, MethodType) and - self.object.im_self is not None): - self.directivetype = 'classmethod' - # document class and static members before ordinary ones - self.member_order = self.member_order - 1 - elif isinstance(self.object, FunctionType) or \ - (isinstance(self.object, BuiltinFunctionType) and - hasattr(self.object, '__self__') and - self.object.__self__ is not None): - self.directivetype = 'staticmethod' - # document class and static members before ordinary ones - self.member_order = self.member_order - 1 - else: - self.directivetype = 'method' - return ret + if sys.version_info >= (3, 0): + def import_object(self): + ret = ClassLevelDocumenter.import_object(self) + obj_from_parent = self.parent.__dict__.get(self.object_name) + if isinstance(obj_from_parent, classmethod): + self.directivetype = 'classmethod' + self.member_order = self.member_order - 1 + elif isinstance(obj_from_parent, staticmethod): + self.directivetype = 'staticmethod' + self.member_order = self.member_order - 1 + else: + self.directivetype = 'method' + return ret + else: + def import_object(self): + ret = ClassLevelDocumenter.import_object(self) + if isinstance(self.object, classmethod) or \ + (isinstance(self.object, MethodType) and + self.object.im_self is not None): + self.directivetype = 'classmethod' + # document class and static members before ordinary ones + self.member_order = self.member_order - 1 + elif isinstance(self.object, FunctionType) or \ + (isinstance(self.object, BuiltinFunctionType) and + hasattr(self.object, '__self__') and + self.object.__self__ is not None): + self.directivetype = 'staticmethod' + # document class and static members before ordinary ones + self.member_order = self.member_order - 1 + else: + self.directivetype = 'method' + return ret def format_args(self): if inspect.isbuiltin(self.object) or \ diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index cf67c7fb..8186a2e5 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -73,8 +73,7 @@ class autosummary_toc(nodes.comment): pass def process_autosummary_toc(app, doctree): - """ - Insert items described in autosummary:: to the TOC tree, but do + """Insert items described in autosummary:: to the TOC tree, but do not generate the toctree:: list. """ env = app.builder.env @@ -135,8 +134,8 @@ except AttributeError: isgetsetdescriptor = ismemberdescriptor def get_documenter(obj): - """ - Get an autodoc.Documenter class suitable for documenting the given object + """Get an autodoc.Documenter class suitable for documenting the given + object. """ import sphinx.ext.autodoc as autodoc @@ -218,8 +217,7 @@ class Autosummary(Directive): return self.warnings + nodes def get_items(self, names): - """ - Try to import the given names, and return a list of + """Try to import the given names, and return a list of ``[(name, signature, summary_string, real_name), ...]``. """ env = self.state.document.settings.env @@ -287,8 +285,7 @@ class Autosummary(Directive): return items def get_table(self, items): - """ - Generate a proper list of table nodes for autosummary:: directive. + """Generate a proper list of table nodes for autosummary:: directive. *items* is a list produced by :meth:`get_items`. """ @@ -351,8 +348,7 @@ def mangle_signature(sig, max_chars=30): return u"(%s)" % sig def limited_join(sep, items, max_chars=30, overflow_marker="..."): - """ - Join a number of strings to one, limiting the length to *max_chars*. + """Join a number of strings to one, limiting the length to *max_chars*. If the string overflows this limit, replace the last fitting item by *overflow_marker*. @@ -377,8 +373,7 @@ def limited_join(sep, items, max_chars=30, overflow_marker="..."): # -- Importing items ----------------------------------------------------------- def import_by_name(name, prefixes=[None]): - """ - Import a Python object that has the given *name*, under one of the + """Import a Python object that has the given *name*, under one of the *prefixes*. The first name that succeeds is used. """ tried = [] @@ -435,8 +430,7 @@ def _import_by_name(name): def autolink_role(typ, rawtext, etext, lineno, inliner, options={}, content=[]): - """ - Smart linking role. + """Smart linking role. Expands to ':obj:`text`' if `text` is an object that can be imported; otherwise expands to '*text*'. diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 66a124d2..4b6348b5 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -17,6 +17,7 @@ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ + import os import re import sys @@ -193,8 +194,8 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', # -- Finding documented entries in files --------------------------------------- def find_autosummary_in_files(filenames): - """ - Find out what items are documented in source/*.rst. + """Find out what items are documented in source/*.rst. + See `find_autosummary_in_lines`. """ documented = [] @@ -206,8 +207,8 @@ def find_autosummary_in_files(filenames): return documented def find_autosummary_in_docstring(name, module=None, filename=None): - """ - Find out what items are documented in the given object's docstring. + """Find out what items are documented in the given object's docstring. + See `find_autosummary_in_lines`. """ try: @@ -221,8 +222,8 @@ def find_autosummary_in_docstring(name, module=None, filename=None): return [] def find_autosummary_in_lines(lines, module=None, filename=None): - """ - Find out what items appear in autosummary:: directives in the given lines. + """Find out what items appear in autosummary:: directives in the + given lines. Returns a list of (name, toctree, template) where *name* is a name of an object and *toctree* the :toctree: path of the corresponding diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py index 4924d30b..f41820e2 100644 --- a/sphinx/ext/coverage.py +++ b/sphinx/ext/coverage.py @@ -173,8 +173,11 @@ class CoverageBuilder(Builder): attrs = [] + for attr_name in dir(obj): + attr = getattr(obj, attr_name) for attr_name, attr in inspect.getmembers( - obj, inspect.ismethod): + obj, lambda x: inspect.ismethod(x) or \ + inspect.isfunction(x)): if attr_name[0] == '_': # starts with an underscore, ignore it continue diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index 9d681f90..62fbfdff 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -149,14 +149,14 @@ class TestCode(object): class SphinxDocTestRunner(doctest.DocTestRunner): def summarize(self, out, verbose=None): - io = StringIO.StringIO() + string_io = StringIO.StringIO() old_stdout = sys.stdout - sys.stdout = io + sys.stdout = string_io try: res = doctest.DocTestRunner.summarize(self, verbose) finally: sys.stdout = old_stdout - out(io.getvalue()) + out(string_io.getvalue()) return res def _DocTestRunner__patched_linecache_getlines(self, filename, diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 106de7a6..19dcd951 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -11,6 +11,7 @@ """ import re +import codecs import posixpath from os import path from math import ceil @@ -46,18 +47,38 @@ class Graphviz(Directive): """ has_content = True required_arguments = 0 - optional_arguments = 0 + optional_arguments = 1 final_argument_whitespace = False option_spec = { 'alt': directives.unchanged, } def run(self): - dotcode = '\n'.join(self.content) - if not dotcode.strip(): - return [self.state_machine.reporter.warning( - 'Ignoring "graphviz" directive without content.', - line=self.lineno)] + if self.arguments: + document = self.state.document + if self.content: + return [document.reporter.warning( + 'Graphviz directive cannot have both content and ' + 'a filename argument', line=self.lineno)] + env = self.state.document.settings.env + rel_filename, filename = env.relfn2path(self.arguments[0]) + env.note_dependency(rel_filename) + try: + fp = codecs.open(filename, 'r', 'utf-8') + try: + dotcode = fp.read() + finally: + fp.close() + except (IOError, OSError): + return [document.reporter.warning( + 'External Graphviz file %r not found or reading ' + 'it failed' % filename, line=self.lineno)] + else: + dotcode = '\n'.join(self.content) + if not dotcode.strip(): + return [self.state_machine.reporter.warning( + 'Ignoring "graphviz" directive without content.', + line=self.lineno)] node = graphviz() node['code'] = dotcode node['options'] = [] @@ -89,10 +110,9 @@ class GraphvizSimple(Directive): def render_dot(self, code, options, format, prefix='graphviz'): - """ - Render graphviz code into a PNG or PDF output file. - """ + """Render graphviz code into a PNG or PDF output file.""" hashkey = code.encode('utf-8') + str(options) + \ + str(self.builder.config.graphviz_dot) + \ str(self.builder.config.graphviz_dot_args) fname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), format) if hasattr(self.builder, 'imgpath'): diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index 22c0e20f..3f6f0b4d 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -67,8 +67,7 @@ class InheritanceGraph(object): graphviz dot graph from them. """ def __init__(self, class_names, currmodule, show_builtins=False, parts=0): - """ - *class_names* is a list of child classes to show bases from. + """*class_names* is a list of child classes to show bases from. If *show_builtins* is True, then Python builtins will be shown in the graph. @@ -81,9 +80,7 @@ class InheritanceGraph(object): 'inheritance diagram') def _import_class_or_module(self, name, currmodule): - """ - Import a class using its fully-qualified *name*. - """ + """Import a class using its fully-qualified *name*.""" try: path, base = class_sig_re.match(name).groups() except ValueError: @@ -182,9 +179,7 @@ class InheritanceGraph(object): return '.'.join(name_parts[-parts:]) def get_all_class_names(self): - """ - Get all of the class names involved in the graph. - """ + """Get all of the class names involved in the graph.""" return [fullname for (_, fullname, _) in self.class_info] # These are the default attrs for graphviz @@ -213,9 +208,8 @@ class InheritanceGraph(object): def generate_dot(self, name, urls={}, env=None, graph_attrs={}, node_attrs={}, edge_attrs={}): - """ - Generate a graphviz dot graph from the classes that - were passed in to __init__. + """Generate a graphviz dot graph from the classes that were passed in + to __init__. *name* is the name of the graph. diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index 10015fc1..442617e1 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -26,6 +26,7 @@ import time import zlib +import codecs import urllib2 import posixpath from os import path @@ -33,19 +34,26 @@ from os import path from docutils import nodes from sphinx.builders.html import INVENTORY_FILENAME +from sphinx.util.pycompat import b + handlers = [urllib2.ProxyHandler(), urllib2.HTTPRedirectHandler(), urllib2.HTTPHandler()] -if hasattr(urllib2, 'HTTPSHandler'): +try: handlers.append(urllib2.HTTPSHandler) +except NameError: + pass urllib2.install_opener(urllib2.build_opener(*handlers)) +UTF8StreamReader = codecs.lookup('utf-8')[2] + def read_inventory_v1(f, uri, join): + f = UTF8StreamReader(f) invdata = {} line = f.next() - projname = line.rstrip()[11:].decode('utf-8') + projname = line.rstrip()[11:] line = f.next() version = line.rstrip()[11:] for line in f: @@ -68,25 +76,25 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024): projname = line.rstrip()[11:].decode('utf-8') line = f.readline() version = line.rstrip()[11:].decode('utf-8') - line = f.readline() + line = f.readline().decode('utf-8') if 'zlib' not in line: raise ValueError def read_chunks(): decompressor = zlib.decompressobj() - for chunk in iter(lambda: f.read(bufsize), ''): + for chunk in iter(lambda: f.read(bufsize), b('')): yield decompressor.decompress(chunk) yield decompressor.flush() def split_lines(iter): - buf = '' + buf = b('') for chunk in iter: buf += chunk - lineend = buf.find('\n') + lineend = buf.find(b('\n')) while lineend != -1: yield buf[:lineend].decode('utf-8') buf = buf[lineend+1:] - lineend = buf.find('\n') + lineend = buf.find(b('\n')) assert not buf for line in split_lines(read_chunks()): @@ -109,13 +117,13 @@ def fetch_inventory(app, uri, inv): if inv.find('://') != -1: f = urllib2.urlopen(inv) else: - f = open(path.join(app.srcdir, inv)) + f = open(path.join(app.srcdir, inv), 'rb') except Exception, err: app.warn('intersphinx inventory %r not fetchable due to ' '%s: %s' % (inv, err.__class__, err)) return try: - line = f.readline().rstrip() + line = f.readline().rstrip().decode('utf-8') try: if line == '# Sphinx inventory version 1': invdata = read_inventory_v1(f, uri, join) diff --git a/sphinx/ext/oldcmarkup.py b/sphinx/ext/oldcmarkup.py index 00ac3749..bc921a23 100644 --- a/sphinx/ext/oldcmarkup.py +++ b/sphinx/ext/oldcmarkup.py @@ -18,6 +18,7 @@ WARNING_MSG = 'using old C markup; please migrate to new-style markup ' \ '(e.g. c:function instead of cfunction), see ' \ 'http://sphinx.pocoo.org/domains.html' + class OldCDirective(Directive): has_content = True required_arguments = 1 diff --git a/sphinx/ext/pngmath.py b/sphinx/ext/pngmath.py index 7f399754..e4e7c2d0 100644 --- a/sphinx/ext/pngmath.py +++ b/sphinx/ext/pngmath.py @@ -26,6 +26,7 @@ from docutils import nodes from sphinx.errors import SphinxError from sphinx.util.png import read_png_depth, write_png_depth from sphinx.util.osutil import ensuredir, ENOENT +from sphinx.util.pycompat import b from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath class MathExtError(SphinxError): @@ -58,11 +59,10 @@ DOC_BODY_PREVIEW = r''' \end{document} ''' -depth_re = re.compile(r'\[\d+ depth=(-?\d+)\]') +depth_re = re.compile(b(r'\[\d+ depth=(-?\d+)\]')) def render_math(self, math): - """ - Render the LaTeX math expression *math* using latex and dvipng. + """Render the LaTeX math expression *math* using latex and dvipng. Return the filename relative to the built document and the "depth", that is, the distance of image bottom and baseline in pixels, if the diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index 81881beb..b9bb9d77 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -31,7 +31,11 @@ def doctree_read(app, doctree): env._viewcode_modules[modname] = False return analyzer.find_tags() - entry = analyzer.code.decode(analyzer.encoding), analyzer.tags, {} + if not isinstance(analyzer.code, unicode): + code = analyzer.code.decode(analyzer.encoding) + else: + code = analyzer.code + entry = code, analyzer.tags, {} env._viewcode_modules[modname] = entry elif entry is False: return @@ -47,7 +51,7 @@ def doctree_read(app, doctree): for signode in objnode: if not isinstance(signode, addnodes.desc_signature): continue - modname = signode['module'] + modname = signode.get('module') if not modname: continue fullname = signode['fullname'] |
