summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sphinx/ext/autodoc.py31
-rw-r--r--tests/root/autodoc.txt13
-rw-r--r--tests/test_autodoc.py45
3 files changed, 75 insertions, 14 deletions
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index 44c7ad8b..691fef7a 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -489,20 +489,26 @@ class Documenter(object):
If *want_all* is True, return all members. Else, only return those
members given by *self.options.members* (which may also be none).
"""
+ analyzed_member_names = set()
+ if self.analyzer:
+ attr_docs = self.analyzer.find_attr_docs()
+ namespace = '.'.join(self.objpath)
+ for item in attr_docs.iteritems():
+ if item[0][0] == namespace:
+ analyzed_member_names.add(item[0][1])
if not want_all:
if not self.options.members:
return False, []
# specific members given
- ret = []
+ members = []
for mname in self.options.members:
try:
- ret.append((mname, self.get_attr(self.object, mname)))
+ members.append((mname, self.get_attr(self.object, mname)))
except AttributeError:
- self.directive.warn('missing attribute %s in object %s'
- % (mname, self.fullname))
- return False, ret
-
- if self.options.inherited_members:
+ if mname not in analyzed_member_names:
+ self.directive.warn('missing attribute %s in object %s'
+ % (mname, self.fullname))
+ elif self.options.inherited_members:
# safe_getmembers() uses dir() which pulls in members from all
# base classes
members = safe_getmembers(self.object)
@@ -521,13 +527,10 @@ class Documenter(object):
for mname in obj_dict.keys()]
membernames = set(m[0] for m in members)
# add instance attributes from the analyzer
- if self.analyzer:
- attr_docs = self.analyzer.find_attr_docs()
- namespace = '.'.join(self.objpath)
- for item in attr_docs.iteritems():
- if item[0][0] == namespace:
- if item[0][1] not in membernames:
- members.append((item[0][1], INSTANCEATTR))
+ for aname in analyzed_member_names:
+ if aname not in membernames and \
+ (want_all or aname in self.options.members):
+ members.append((aname, INSTANCEATTR))
return False, sorted(members)
def filter_members(self, members, want_all):
diff --git a/tests/root/autodoc.txt b/tests/root/autodoc.txt
index 5c03f947..d4b3404c 100644
--- a/tests/root/autodoc.txt
+++ b/tests/root/autodoc.txt
@@ -32,3 +32,16 @@ Just testing a few autodoc possibilities...
:noindex:
.. autoclass:: MarkupError
+
+
+.. currentmodule:: test_autodoc
+
+.. autoclass:: InstAttCls
+ :members:
+
+ All members (5 total)
+
+.. autoclass:: InstAttCls
+ :members: ca1, ia1
+
+ Specific members (2 total)
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 6dedaad8..642b9141 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -540,6 +540,32 @@ def test_generate():
assert_result_contains(
' :annotation: = None', 'attribute', 'AttCls.a2')
+ # test explicit members with instance attributes
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ directive.env.temp_data['py:module'] = 'test_autodoc'
+ options.inherited_members = False
+ options.undoc_members = False
+ options.members = ALL
+ assert_processes([
+ ('class', 'test_autodoc.InstAttCls'),
+ ('attribute', 'test_autodoc.InstAttCls.ca1'),
+ ('attribute', 'test_autodoc.InstAttCls.ca2'),
+ ('attribute', 'test_autodoc.InstAttCls.ca3'),
+ ('attribute', 'test_autodoc.InstAttCls.ia1'),
+ ('attribute', 'test_autodoc.InstAttCls.ia2'),
+ ], 'class', 'InstAttCls')
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ options.members = ['ca1', 'ia1']
+ assert_processes([
+ ('class', 'test_autodoc.InstAttCls'),
+ ('attribute', 'test_autodoc.InstAttCls.ca1'),
+ ('attribute', 'test_autodoc.InstAttCls.ia1'),
+ ], 'class', 'InstAttCls')
+ del directive.env.temp_data['autodoc:class']
+ del directive.env.temp_data['autodoc:module']
+ del directive.env.temp_data['py:module']
# --- generate fodder ------------
@@ -680,3 +706,22 @@ class StrRepr(str):
class AttCls(object):
a1 = StrRepr('hello\nworld')
a2 = None
+
+class InstAttCls(object):
+ """Class with documented class and instance attributes."""
+
+ #: Doc comment for class attribute InstAttCls.ca1.
+ #: It can have multiple lines.
+ ca1 = 'a'
+
+ ca2 = 'b' #: Doc comment for InstAttCls.ca2. One line only.
+
+ ca3 = 'c'
+ """Docstring for class attribute InstAttCls.ca3."""
+
+ def __init__(self):
+ #: Doc comment for instance attribute InstAttCls.ia1
+ self.ia1 = 'd'
+
+ self.ia2 = 'e'
+ """Docstring for instance attribute InstAttCls.ia2."""