From 13be8e03ba7c52e2b471caa053c381cd3ea37f56 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 31 Jul 2017 22:35:56 +0900 Subject: [PATCH 1/2] Fix #3969: private instance attributes causes AttributeError --- CHANGES | 1 + sphinx/ext/autodoc.py | 14 ++++++++++---- tests/test_autodoc.py | 5 ++++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 32e945ec3..a8cd32a16 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,7 @@ Bugs fixed * #3946: Typo in sphinx.sty (this was a bug with no effect in default context) * :pep: and :rfc: does not supports ``default-role`` directive (refs: #3960) * #3960: default_role = 'guilabel' not functioning +* #3969: private instance attributes causes AttributeError Testing -------- diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index 91feb6a2a..bb5f78332 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -962,14 +962,20 @@ class Documenter(object): self.options.special_members is not ALL and \ membername in self.options.special_members: keep = has_doc or self.options.undoc_members + elif (namespace, membername) in attr_docs: + if want_all and membername.startswith('_'): + # ignore members whose name starts with _ by default + keep = self.options.private_members and \ + (has_doc or self.options.undoc_members) + else: + # keep documented attributes + keep = True + isattr = True + print(membername, keep) elif want_all and membername.startswith('_'): # ignore members whose name starts with _ by default keep = self.options.private_members and \ (has_doc or self.options.undoc_members) - elif (namespace, membername) in attr_docs: - # keep documented attributes - keep = True - isattr = True else: # ignore undocumented members if :undoc-members: is not given keep = has_doc or self.options.undoc_members diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index e04e38bb3..6eb087567 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -107,7 +107,7 @@ def process_signature(app, what, name, obj, options, args, retann): def skip_member(app, what, name, obj, skip, options): if name in ('__special1__', '__special2__'): return skip - if name.startswith('_'): + if name.startswith('__'): return True if name == 'skipmeth': return True @@ -756,6 +756,7 @@ def test_generate(): # test autodoc_member_order == 'source' directive.env.ref_context['py:module'] = 'test_autodoc' + options.private_members = True if PY3: roger_line = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)' else: @@ -773,6 +774,7 @@ def test_generate(): ' .. py:classmethod:: Class.moore(a, e, f) -> happiness', ' .. py:attribute:: Class.inst_attr_comment', ' .. py:attribute:: Class.inst_attr_string', + ' .. py:attribute:: Class._private_inst_attr', ' .. py:method:: Class.inheritedmeth()', ], 'class', 'Class', member_order='bysource', all_members=True) @@ -989,6 +991,7 @@ class Class(Base): self.inst_attr_comment = None self.inst_attr_string = None """a documented instance attribute""" + self._private_inst_attr = None #: a private instance attribute def __special1__(self): """documented special method""" From c96b5b67b15386e2b59d1b1bd3412fadcda90dc0 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 10 Aug 2017 10:36:19 +0900 Subject: [PATCH 2/2] Fix flake8 violation --- tests/test_environment_toctree.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_environment_toctree.py b/tests/test_environment_toctree.py index 5fef9218a..f7a24d1fc 100644 --- a/tests/test_environment_toctree.py +++ b/tests/test_environment_toctree.py @@ -275,7 +275,8 @@ def test_get_toctree_for_collapse(app): @pytest.mark.test_params(shared_result='test_environment_toctree_basic') def test_get_toctree_for_maxdepth(app): app.build() - toctree = TocTree(app.env).get_toctree_for('index', app.builder, collapse=False, maxdepth=3) + toctree = TocTree(app.env).get_toctree_for('index', app.builder, + collapse=False, maxdepth=3) assert_node(toctree, [compact_paragraph, ([caption, "Table of Contents"], bullet_list,