From 97e6bcf3a7c70ce272a5f8a674eb8192d1c30c56 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Thu, 19 Aug 2021 10:50:50 +0100 Subject: [PATCH 1/3] Avoid warnings when accessing attributes on classes that may not be regular properties --- sphinx_automodapi/autodoc_enhancements.py | 9 +++++- .../class_with_property_warning/README.md | 1 + .../input/index.rst | 1 + ...le.class_with_property_warning.Camelot.rst | 19 ++++++++++++ .../output/index.rst.automodapi | 19 ++++++++++++ .../output/index.rst.automodsumm | 6 ++++ .../class_with_property_warning.py | 29 +++++++++++++++++++ sphinx_automodapi/tests/test_cases.py | 11 ++++++- 8 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 sphinx_automodapi/tests/cases/class_with_property_warning/README.md create mode 100644 sphinx_automodapi/tests/cases/class_with_property_warning/input/index.rst create mode 100644 sphinx_automodapi/tests/cases/class_with_property_warning/output/api/sphinx_automodapi.tests.example_module.class_with_property_warning.Camelot.rst create mode 100644 sphinx_automodapi/tests/cases/class_with_property_warning/output/index.rst.automodapi create mode 100644 sphinx_automodapi/tests/cases/class_with_property_warning/output/index.rst.automodsumm create mode 100644 sphinx_automodapi/tests/example_module/class_with_property_warning.py diff --git a/sphinx_automodapi/autodoc_enhancements.py b/sphinx_automodapi/autodoc_enhancements.py index 7721043..1cc53d4 100644 --- a/sphinx_automodapi/autodoc_enhancements.py +++ b/sphinx_automodapi/autodoc_enhancements.py @@ -1,6 +1,7 @@ """ Miscellaneous enhancements to help autodoc along. """ +import warnings from sphinx.ext.autodoc import AttributeDocumenter __all__ = [] @@ -58,7 +59,13 @@ def type_object_attrgetter(obj, attr, *defargs): return base.__dict__[attr] break - return getattr(obj, attr, *defargs) + # In some cases, getting attributes with getattr can lead to warnings, e.g. + # deprecation warnings (this is not normally the case with methods and + # regular properties since we don't execute them but using getattr does run + # the code inside those properties, so we filter out any warnings. + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + return getattr(obj, attr, *defargs) def setup(app): diff --git a/sphinx_automodapi/tests/cases/class_with_property_warning/README.md b/sphinx_automodapi/tests/cases/class_with_property_warning/README.md new file mode 100644 index 0000000..a942693 --- /dev/null +++ b/sphinx_automodapi/tests/cases/class_with_property_warning/README.md @@ -0,0 +1 @@ +Documenting a module with a class that has a non-standard property that emits a warning diff --git a/sphinx_automodapi/tests/cases/class_with_property_warning/input/index.rst b/sphinx_automodapi/tests/cases/class_with_property_warning/input/index.rst new file mode 100644 index 0000000..955b233 --- /dev/null +++ b/sphinx_automodapi/tests/cases/class_with_property_warning/input/index.rst @@ -0,0 +1 @@ +.. automodapi:: sphinx_automodapi.tests.example_module.class_with_property_warning diff --git a/sphinx_automodapi/tests/cases/class_with_property_warning/output/api/sphinx_automodapi.tests.example_module.class_with_property_warning.Camelot.rst b/sphinx_automodapi/tests/cases/class_with_property_warning/output/api/sphinx_automodapi.tests.example_module.class_with_property_warning.Camelot.rst new file mode 100644 index 0000000..a053905 --- /dev/null +++ b/sphinx_automodapi/tests/cases/class_with_property_warning/output/api/sphinx_automodapi.tests.example_module.class_with_property_warning.Camelot.rst @@ -0,0 +1,19 @@ +Camelot +======= + +.. currentmodule:: sphinx_automodapi.tests.example_module.class_with_property_warning + +.. autoclass:: Camelot + :show-inheritance: + + .. rubric:: Attributes Summary + + .. autosummary:: + + ~Camelot.place + ~Camelot.silly + + .. rubric:: Attributes Documentation + + .. autoattribute:: place + .. autoattribute:: silly diff --git a/sphinx_automodapi/tests/cases/class_with_property_warning/output/index.rst.automodapi b/sphinx_automodapi/tests/cases/class_with_property_warning/output/index.rst.automodapi new file mode 100644 index 0000000..0df1c3d --- /dev/null +++ b/sphinx_automodapi/tests/cases/class_with_property_warning/output/index.rst.automodapi @@ -0,0 +1,19 @@ + +sphinx_automodapi.tests.example_module.class_with_property_warning Module +------------------------------------------------------------------------- + +.. automodule:: sphinx_automodapi.tests.example_module.class_with_property_warning + +Classes +^^^^^^^ + +.. automodsumm:: sphinx_automodapi.tests.example_module.class_with_property_warning + :classes-only: + :toctree: api + +Class Inheritance Diagram +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automod-diagram:: sphinx_automodapi.tests.example_module.class_with_property_warning + :private-bases: + :parts: 1 diff --git a/sphinx_automodapi/tests/cases/class_with_property_warning/output/index.rst.automodsumm b/sphinx_automodapi/tests/cases/class_with_property_warning/output/index.rst.automodsumm new file mode 100644 index 0000000..cb956df --- /dev/null +++ b/sphinx_automodapi/tests/cases/class_with_property_warning/output/index.rst.automodsumm @@ -0,0 +1,6 @@ +.. currentmodule:: sphinx_automodapi.tests.example_module.class_with_property_warning + +.. autosummary:: + :toctree: api + + Camelot diff --git a/sphinx_automodapi/tests/example_module/class_with_property_warning.py b/sphinx_automodapi/tests/example_module/class_with_property_warning.py new file mode 100644 index 0000000..15b1d4d --- /dev/null +++ b/sphinx_automodapi/tests/example_module/class_with_property_warning.py @@ -0,0 +1,29 @@ +import warnings + +__all__ = ['Camelot'] + + +class customproperty: + def __init__(self, getter): + self.getter = getter + + def __get__(self, instance, owner): + return self.getter(owner) + + + +class Camelot(object): + """ + A class where a property emits a warning + """ + + @customproperty + def silly(cls): + warnings.warn("It is VERY silly", UserWarning) + + @property + def place(self): + """ + Indeed. + """ + pass diff --git a/sphinx_automodapi/tests/test_cases.py b/sphinx_automodapi/tests/test_cases.py index 72f6140..a705111 100644 --- a/sphinx_automodapi/tests/test_cases.py +++ b/sphinx_automodapi/tests/test_cases.py @@ -99,12 +99,21 @@ def test_run_full_case(tmpdir, case_dir, parallel): try: os.chdir(docs_dir) - status = build_main(argv=argv) + with pytest.warns(None) as record: + status = build_main(argv=argv) finally: os.chdir(start_dir) assert status == 0 + # Make sure there are no warnings - if there are we print them out for debugging + if len(record) > 0: + print('Build emitted the following unexpected warnings:') + for warning in record: + print(' ' + str(warning)) + + assert len(record) == 0 + # Check that all expected output files are there and match the reference files for root, dirnames, filenames in os.walk(output_dir): for filename in filenames: From 9f4fdcef1d3553181c4917314f098545c1f88abf Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Thu, 19 Aug 2021 22:52:29 +0100 Subject: [PATCH 2/3] Fix test --- sphinx_automodapi/autodoc_enhancements.py | 2 +- sphinx_automodapi/automodsumm.py | 13 +++++++++++-- sphinx_automodapi/tests/test_cases.py | 14 +++++--------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/sphinx_automodapi/autodoc_enhancements.py b/sphinx_automodapi/autodoc_enhancements.py index 1cc53d4..2ae4b24 100644 --- a/sphinx_automodapi/autodoc_enhancements.py +++ b/sphinx_automodapi/autodoc_enhancements.py @@ -63,7 +63,7 @@ def type_object_attrgetter(obj, attr, *defargs): # deprecation warnings (this is not normally the case with methods and # regular properties since we don't execute them but using getattr does run # the code inside those properties, so we filter out any warnings. - with warnings.catch_warnings(): + with warnings.catch_warnings(record=False): warnings.simplefilter('ignore') return getattr(obj, attr, *defargs) diff --git a/sphinx_automodapi/automodsumm.py b/sphinx_automodapi/automodsumm.py index 70e611b..1f61201 100644 --- a/sphinx_automodapi/automodsumm.py +++ b/sphinx_automodapi/automodsumm.py @@ -88,6 +88,7 @@ class members that are inherited from a base class. This value can be import os import re import io +import warnings from sphinx.util import logging from sphinx.ext.autosummary import Autosummary @@ -201,7 +202,12 @@ def get_items(self, names): self.bridge.genopt['imported-members'] = True except AttributeError: # Sphinx < 4.0 self.genopt['imported-members'] = True - return Autosummary.get_items(self, names) + # Autosummary.get_items relies on getattr to get attributes from classes. + # In some cases, getting attributes with getattr can lead to warnings, e.g. + # deprecation warnings, so we filter out any warnings. + with warnings.catch_warnings(record=False): + warnings.simplefilter('ignore') + return Autosummary.get_items(self, names) # <-------------------automod-diagram stuff-----------------------------------> @@ -469,7 +475,10 @@ def generate_automodsumm_docs(lines, srcfn, app=None, suffix='.rst', ensuredir(path) try: - import_by_name_values = import_by_name(name) + import warnings + with warnings.catch_warnings(record=False): + warnings.simplefilter('ignore') + import_by_name_values = import_by_name(name) except ImportError as e: logger.warning('[automodsumm] failed to import %r: %s' % (name, e)) continue diff --git a/sphinx_automodapi/tests/test_cases.py b/sphinx_automodapi/tests/test_cases.py index a705111..64f3de0 100644 --- a/sphinx_automodapi/tests/test_cases.py +++ b/sphinx_automodapi/tests/test_cases.py @@ -8,6 +8,7 @@ import sys import glob import shutil +import warnings from itertools import product import pytest @@ -99,21 +100,16 @@ def test_run_full_case(tmpdir, case_dir, parallel): try: os.chdir(docs_dir) - with pytest.warns(None) as record: + # Make sure there are no warnings - this is needed to catch warnings that + # Sphinx might not capture. + with warnings.catch_warnings(record=True) as record: + warnings.simplefilter('error') status = build_main(argv=argv) finally: os.chdir(start_dir) assert status == 0 - # Make sure there are no warnings - if there are we print them out for debugging - if len(record) > 0: - print('Build emitted the following unexpected warnings:') - for warning in record: - print(' ' + str(warning)) - - assert len(record) == 0 - # Check that all expected output files are there and match the reference files for root, dirnames, filenames in os.walk(output_dir): for filename in filenames: From a8025b8fb85e03ea64363795a63d215215904127 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Thu, 19 Aug 2021 23:02:17 +0100 Subject: [PATCH 3/3] Pin jinja2 to <3 to avoid deprecation warning with most Sphinx versions --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 8395008..5183ccd 100644 --- a/tox.ini +++ b/tox.ini @@ -6,6 +6,7 @@ requires = pip >= 18.0 [testenv] changedir = .tmp/{envname} deps = + jinja2<3 # to avoid a deprecation warning with old versions of sphinx sphinx17: sphinx==1.7.* sphinx18: sphinx==1.8.* sphinx20: sphinx==2.0.*