From 2a09c8033690279c6afbbd5164d768561b854cac Mon Sep 17 00:00:00 2001 From: Joseph Martinot-Lagarde Date: Sat, 3 Jun 2023 20:21:26 +0200 Subject: [PATCH 1/8] Always use __dict__ and ignore __slots__ on classes --- sphinx_automodapi/automodsumm.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/sphinx_automodapi/automodsumm.py b/sphinx_automodapi/automodsumm.py index ec99ce8..1677ba9 100644 --- a/sphinx_automodapi/automodsumm.py +++ b/sphinx_automodapi/automodsumm.py @@ -555,25 +555,11 @@ def get_members_class(obj, typ, include_public=[], items = [] # using dir gets all of the attributes, including the elements - # from the base class, otherwise use __slots__ or __dict__ + # from the base class, otherwise use __dict__ if include_base: names = dir(obj) else: - # Classes deriving from an ABC using the `abc` module will - # have an empty `__slots__` attribute in Python 3, unless - # other slots were declared along the inheritance chain. If - # the ABC-derived class has empty slots, we'll use the - # class `__dict__` instead. - declares_slots = ( - hasattr(obj, '__slots__') and - not (issubclass(type(obj), abc.ABCMeta) and - len(obj.__slots__) == 0) - ) - - if declares_slots: - names = tuple(getattr(obj, '__slots__')) - else: - names = getattr(obj, '__dict__').keys() + names = getattr(obj, '__dict__').keys() for name in names: try: From d5ae502fd904af3dbe92206ce9f08f014d9c896d Mon Sep 17 00:00:00 2001 From: Joseph Martinot-Lagarde Date: Sat, 3 Jun 2023 21:22:38 +0200 Subject: [PATCH 2/8] abc module unused --- sphinx_automodapi/automodsumm.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sphinx_automodapi/automodsumm.py b/sphinx_automodapi/automodsumm.py index 1677ba9..ecdd3fe 100644 --- a/sphinx_automodapi/automodsumm.py +++ b/sphinx_automodapi/automodsumm.py @@ -83,7 +83,6 @@ class members that are inherited from a base class. This value can be .. _sphinx.ext.inheritance_diagram: http://sphinx-doc.org/latest/ext/inheritance.html """ -import abc import inspect import os import re From 29ed8b48409f24d147784e7426d9f148fdd29a1d Mon Sep 17 00:00:00 2001 From: Kyle D Fawcett Date: Tue, 19 Dec 2023 10:33:00 -0500 Subject: [PATCH 3/8] TST: test classes that use __slots__ --- sphinx_automodapi/tests/cases/slots/README.md | 1 + .../tests/cases/slots/input/index.rst | 1 + ...ests.example_module.slots.DerivedParam.rst | 17 ++++ ....example_module.slots.DerivedSlotParam.rst | 27 ++++++ ...pi.tests.example_module.slots.SlotDict.rst | 27 ++++++ .../cases/slots/output/index.rst.automodapi | 19 ++++ .../cases/slots/output/index.rst.automodsumm | 8 ++ .../tests/example_module/slots.py | 91 +++++++++++++++++++ 8 files changed, 191 insertions(+) create mode 100644 sphinx_automodapi/tests/cases/slots/README.md create mode 100644 sphinx_automodapi/tests/cases/slots/input/index.rst create mode 100644 sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedParam.rst create mode 100644 sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedSlotParam.rst create mode 100644 sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.SlotDict.rst create mode 100644 sphinx_automodapi/tests/cases/slots/output/index.rst.automodapi create mode 100644 sphinx_automodapi/tests/cases/slots/output/index.rst.automodsumm create mode 100644 sphinx_automodapi/tests/example_module/slots.py diff --git a/sphinx_automodapi/tests/cases/slots/README.md b/sphinx_automodapi/tests/cases/slots/README.md new file mode 100644 index 0000000..1b95d31 --- /dev/null +++ b/sphinx_automodapi/tests/cases/slots/README.md @@ -0,0 +1 @@ +Test classes that put attributes in `__slots__`. \ No newline at end of file diff --git a/sphinx_automodapi/tests/cases/slots/input/index.rst b/sphinx_automodapi/tests/cases/slots/input/index.rst new file mode 100644 index 0000000..fdf9586 --- /dev/null +++ b/sphinx_automodapi/tests/cases/slots/input/index.rst @@ -0,0 +1 @@ +.. automodapi:: sphinx_automodapi.tests.example_module.slots diff --git a/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedParam.rst b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedParam.rst new file mode 100644 index 0000000..bf65bf4 --- /dev/null +++ b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedParam.rst @@ -0,0 +1,17 @@ +DerivedParam +============ + +.. currentmodule:: sphinx_automodapi.tests.example_module.slots + +.. autoclass:: DerivedParam + :show-inheritance: + + .. rubric:: Methods Summary + + .. autosummary:: + + ~DerivedParam.derived_from_slot_class_method + + .. rubric:: Methods Documentation + + .. automethod:: derived_from_slot_class_method diff --git a/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedSlotParam.rst b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedSlotParam.rst new file mode 100644 index 0000000..cfe6df9 --- /dev/null +++ b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedSlotParam.rst @@ -0,0 +1,27 @@ +DerivedSlotParam +================ + +.. currentmodule:: sphinx_automodapi.tests.example_module.slots + +.. autoclass:: DerivedSlotParam + :show-inheritance: + + .. rubric:: Attributes Summary + + .. autosummary:: + + ~DerivedSlotParam.extra_param + + .. rubric:: Methods Summary + + .. autosummary:: + + ~DerivedSlotParam.derived_from_slot_class_method + + .. rubric:: Attributes Documentation + + .. autoattribute:: extra_param + + .. rubric:: Methods Documentation + + .. automethod:: derived_from_slot_class_method diff --git a/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.SlotDict.rst b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.SlotDict.rst new file mode 100644 index 0000000..4db68a8 --- /dev/null +++ b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.SlotDict.rst @@ -0,0 +1,27 @@ +SlotDict +======== + +.. currentmodule:: sphinx_automodapi.tests.example_module.slots + +.. autoclass:: SlotDict + :show-inheritance: + + .. rubric:: Attributes Summary + + .. autosummary:: + + ~SlotDict.param + + .. rubric:: Methods Summary + + .. autosummary:: + + ~SlotDict.my_method + + .. rubric:: Attributes Documentation + + .. autoattribute:: param + + .. rubric:: Methods Documentation + + .. automethod:: my_method diff --git a/sphinx_automodapi/tests/cases/slots/output/index.rst.automodapi b/sphinx_automodapi/tests/cases/slots/output/index.rst.automodapi new file mode 100644 index 0000000..487ab9f --- /dev/null +++ b/sphinx_automodapi/tests/cases/slots/output/index.rst.automodapi @@ -0,0 +1,19 @@ + +sphinx_automodapi.tests.example_module.slots Module +--------------------------------------------------- + +.. automodule:: sphinx_automodapi.tests.example_module.slots + +Classes +^^^^^^^ + +.. automodsumm:: sphinx_automodapi.tests.example_module.slots + :classes-only: + :toctree: api + +Class Inheritance Diagram +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automod-diagram:: sphinx_automodapi.tests.example_module.slots + :private-bases: + :parts: 1 diff --git a/sphinx_automodapi/tests/cases/slots/output/index.rst.automodsumm b/sphinx_automodapi/tests/cases/slots/output/index.rst.automodsumm new file mode 100644 index 0000000..83b7aa7 --- /dev/null +++ b/sphinx_automodapi/tests/cases/slots/output/index.rst.automodsumm @@ -0,0 +1,8 @@ +.. currentmodule:: sphinx_automodapi.tests.example_module.slots + +.. autosummary:: + :toctree: api + + SlotDict + DerivedParam + DerivedSlotParam diff --git a/sphinx_automodapi/tests/example_module/slots.py b/sphinx_automodapi/tests/example_module/slots.py new file mode 100644 index 0000000..8e6e95a --- /dev/null +++ b/sphinx_automodapi/tests/example_module/slots.py @@ -0,0 +1,91 @@ +"""Test classes containing slots""" +from __future__ import annotations + +__all__ = ['SlotDict', 'DerivedParam', 'DerivedSlotParam',] + + +class SlotDict(object): + """ + A class that uses __slots__ and __dict__ for its attribute namespace. + """ + __slots__ = ('param', '__dict__',) + + def __init__(self, param: str, other_param: str): + """ + Initializes a SlotDict object. + + Parameters + ---------- + my_param : str + My parameter + """ + self.param = param + self.other_param = other_param + + def my_method(self): + """ + Prints the class's parameters. + """ + print(f"param: {self.param}") + print(f"other_param: {self.other_param}") + + +class DerivedParam(SlotDict): + """ + Extends SlotDict by adding an extra parameter + """ + def __init__(self, param: str, other_param: str, extra_param: str): + """ + Initializes a DerivedParam object. + + Parameters + ---------- + param : str + A parameter + other_param : str + Another parameter + extra_param : str + An extra parameter + """ + super(DerivedParam, self).__init__(param, other_param) + self.extra_param = extra_param + + def derived_from_slot_class_method(self): + """ + Prints the DerivedParam parameters. + """ + print(f"param: {self.param}") + print(f"other_param: {self.other_param}") + print(f"dict_param: {self.extra_param}") + + +class DerivedSlotParam(SlotDict): + """ + Extends SlotDict by adding a slot parameter + """ + + __slots__ = ('extra_param',) + + def __init__(self, param: str, other_param: str, extra_param: str): + """ + Initializes a DerivedParam object. + + Parameters + ---------- + param : str + A parameter + other_param : str + Another parameter + extra_param : str + An extra parameter + """ + super(DerivedSlotParam, self).__init__(param, other_param) + self.extra_param = extra_param + + def derived_from_slot_class_method(self): + """ + Prints the DerivedParam parameters. + """ + print(f"param: {self.param}") + print(f"other_param: {self.other_param}") + print(f"extra_param: {self.extra_param}") From 472cd4a36ebea845fc37c36e286de01ee6a08ee6 Mon Sep 17 00:00:00 2001 From: Kyle D Fawcett Date: Tue, 19 Dec 2023 13:05:43 -0500 Subject: [PATCH 4/8] update change log --- CHANGES.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index f8bb685..86a0ec7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,8 @@ Changes in sphinx-automodapi 0.17.0 (unreleased) ------------------- +- Fixes fixes issue where ``__slots__`` hides class variables [#168] + - Minimum supported Python version is now 3.8. [#177] 0.16.0 (2023-08-17) From e00be6f0d64d23f1176fcd075ef35141b21d5181 Mon Sep 17 00:00:00 2001 From: kylefawcett <45832007+kylefawcett@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:55:29 -0500 Subject: [PATCH 5/8] Update CHANGES.rst Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com> --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 86a0ec7..a7a3e75 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,7 @@ Changes in sphinx-automodapi 0.17.0 (unreleased) ------------------- -- Fixes fixes issue where ``__slots__`` hides class variables [#168] +- Fixes fixes issue where ``__slots__`` hides class variables [#181] - Minimum supported Python version is now 3.8. [#177] From fc31e65cb7ac1def2269690487fc1def3734d6af Mon Sep 17 00:00:00 2001 From: Kyle D Fawcett Date: Thu, 21 Dec 2023 14:31:42 -0500 Subject: [PATCH 6/8] make slots example more consistent with python nomenclature --- ....example_module.slots.DerivedSlotParam.rst | 4 +- ...pi.tests.example_module.slots.SlotDict.rst | 6 +- .../tests/example_module/slots.py | 65 +++++++++++++------ 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedSlotParam.rst b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedSlotParam.rst index cfe6df9..3a2438c 100644 --- a/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedSlotParam.rst +++ b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.DerivedSlotParam.rst @@ -10,7 +10,7 @@ DerivedSlotParam .. autosummary:: - ~DerivedSlotParam.extra_param + ~DerivedSlotParam.extra_attr .. rubric:: Methods Summary @@ -20,7 +20,7 @@ DerivedSlotParam .. rubric:: Attributes Documentation - .. autoattribute:: extra_param + .. autoattribute:: extra_attr .. rubric:: Methods Documentation diff --git a/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.SlotDict.rst b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.SlotDict.rst index 4db68a8..ccdf348 100644 --- a/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.SlotDict.rst +++ b/sphinx_automodapi/tests/cases/slots/output/api/sphinx_automodapi.tests.example_module.slots.SlotDict.rst @@ -10,7 +10,8 @@ SlotDict .. autosummary:: - ~SlotDict.param + ~SlotDict.class_attr + ~SlotDict.instance_attr .. rubric:: Methods Summary @@ -20,7 +21,8 @@ SlotDict .. rubric:: Attributes Documentation - .. autoattribute:: param + .. autoattribute:: class_attr + .. autoattribute:: instance_attr .. rubric:: Methods Documentation diff --git a/sphinx_automodapi/tests/example_module/slots.py b/sphinx_automodapi/tests/example_module/slots.py index 8e6e95a..ee9e0fd 100644 --- a/sphinx_automodapi/tests/example_module/slots.py +++ b/sphinx_automodapi/tests/example_module/slots.py @@ -1,4 +1,12 @@ -"""Test classes containing slots""" +"""Test classes containing __slots__ + +Instance attributes named in ``__slots__`` can be introspected and are listed +in the Attributes section of the class documentation. Class attributes are +listed in the same section of the generated docs so docstrings should be used +to distinguish class attributes vs instance attributes. Regular instance +attributes are dynamically inserted into ``__dict__`` and cannot be reliably +introspected so they're not included in the documentation. +""" from __future__ import annotations __all__ = ['SlotDict', 'DerivedParam', 'DerivedSlotParam',] @@ -8,7 +16,13 @@ class SlotDict(object): """ A class that uses __slots__ and __dict__ for its attribute namespace. """ - __slots__ = ('param', '__dict__',) + __slots__ = { + "instance_attr": "instance attribute docstring can be added here", + "__dict__": None, # Allows additional instance attributes to be added + } + + class_attr = "class attribute value" + """(class attr) this is a class attribute.""" def __init__(self, param: str, other_param: str): """ @@ -16,18 +30,29 @@ def __init__(self, param: str, other_param: str): Parameters ---------- - my_param : str - My parameter + param : str + A parameter + other_param : str + Another parameter """ - self.param = param - self.other_param = other_param + + self.instance_attr = param + """Instance attributes declared in slots can also define their docstring + here + """ + + if other_param is not None: + self.other_attr = other_param + """This instance attribute is dynamic (not declared in a slot) so + it's not included in the docs + """ def my_method(self): """ - Prints the class's parameters. + Prints the SlotDict parameters. """ - print(f"param: {self.param}") - print(f"other_param: {self.other_param}") + print(f"instance_attr: {self.instance_attr}") + print(f"other_attr: {self.other_attr}") class DerivedParam(SlotDict): @@ -48,15 +73,15 @@ def __init__(self, param: str, other_param: str, extra_param: str): An extra parameter """ super(DerivedParam, self).__init__(param, other_param) - self.extra_param = extra_param + self.extra_attr = extra_param def derived_from_slot_class_method(self): """ Prints the DerivedParam parameters. """ - print(f"param: {self.param}") - print(f"other_param: {self.other_param}") - print(f"dict_param: {self.extra_param}") + print(f"instance_attr: {self.instance_attr}") + print(f"other_attr: {self.other_attr}") + print(f"extra_attr: {self.extra_attr}") class DerivedSlotParam(SlotDict): @@ -64,11 +89,11 @@ class DerivedSlotParam(SlotDict): Extends SlotDict by adding a slot parameter """ - __slots__ = ('extra_param',) + __slots__ = ('extra_attr',) def __init__(self, param: str, other_param: str, extra_param: str): """ - Initializes a DerivedParam object. + Initializes a DerivedSlotParam object. Parameters ---------- @@ -80,12 +105,12 @@ def __init__(self, param: str, other_param: str, extra_param: str): An extra parameter """ super(DerivedSlotParam, self).__init__(param, other_param) - self.extra_param = extra_param + self.extra_attr = extra_param def derived_from_slot_class_method(self): """ - Prints the DerivedParam parameters. + Prints the DerivedSlotParam parameters. """ - print(f"param: {self.param}") - print(f"other_param: {self.other_param}") - print(f"extra_param: {self.extra_param}") + print(f"instance_attr: {self.instance_attr}") + print(f"other_attr: {self.other_attr}") + print(f"extra_attr: {self.extra_attr}") From d58f35ff6d8f083aa07cfc656768bd3f24de7636 Mon Sep 17 00:00:00 2001 From: Kyle D Fawcett Date: Thu, 21 Dec 2023 14:33:13 -0500 Subject: [PATCH 7/8] TST: add basic coverage test for slots example --- sphinx_automodapi/tests/test_cases.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sphinx_automodapi/tests/test_cases.py b/sphinx_automodapi/tests/test_cases.py index 63b0171..0ffa4c8 100644 --- a/sphinx_automodapi/tests/test_cases.py +++ b/sphinx_automodapi/tests/test_cases.py @@ -140,3 +140,13 @@ def test_duplicated_warning(tmpdir): os.chdir(start_dir) assert status == 0 + + +def test_slots_example(): + """Basic tests for slots example module""" + from sphinx_automodapi.tests.example_module.slots import ( + SlotDict, DerivedParam, DerivedSlotParam + ) + SlotDict('param', 'other_param').my_method() + DerivedParam('param', 'other_param', 'extra_param').derived_from_slot_class_method() + DerivedSlotParam('param', 'other_param', 'extra_param').derived_from_slot_class_method() From 5904a172dd457b113b8067902a29d44a768f68f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brigitta=20Sip=C5=91cz?= Date: Fri, 26 Jan 2024 19:52:38 -0800 Subject: [PATCH 8/8] DOC: fixup changelog --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index a7a3e75..0e98011 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,7 @@ Changes in sphinx-automodapi 0.17.0 (unreleased) ------------------- -- Fixes fixes issue where ``__slots__`` hides class variables [#181] +- Fixes issue where ``__slots__`` hides class variables. [#181] - Minimum supported Python version is now 3.8. [#177]