From 72ca2bdffc2947d818b1cd36484debe577a25dbc Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Wed, 8 Jul 2020 16:45:07 +1000 Subject: [PATCH 1/8] Add autosummary_filename_map config to avoid clashes --- doc/usage/extensions/autosummary.rst | 9 ++++++ sphinx/ext/autosummary/__init__.py | 1 + sphinx/ext/autosummary/generate.py | 12 ++++++-- tests/roots/test-autosummary/sphinx.rst | 39 ++++++++----------------- tests/test_ext_autosummary.py | 16 ++++++++++ 5 files changed, 48 insertions(+), 29 deletions(-) diff --git a/doc/usage/extensions/autosummary.rst b/doc/usage/extensions/autosummary.rst index 38d18361ed6..c1f59170b38 100644 --- a/doc/usage/extensions/autosummary.rst +++ b/doc/usage/extensions/autosummary.rst @@ -195,6 +195,15 @@ also use these config values: .. versionadded:: 2.1 +.. confval:: autosummary_filename_map + + A dict mapping object names to filenames. This is necessary to avoid + filename conflicts where multiple objects have names that are + indistinguishable when case is ignored, on file systems where filenames + are case-insensitive. + + .. versionadded:: 3.2 + Customizing templates --------------------- diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 0984377c565..ece16c15bc5 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -790,5 +790,6 @@ def setup(app: Sphinx) -> Dict[str, Any]: app.add_config_value('autosummary_mock_imports', lambda config: config.autodoc_mock_imports, 'env') app.add_config_value('autosummary_imported_members', [], False, [bool]) + app.add_config_value('autosummary_filename_map', {}, 'html') return {'version': sphinx.__display_version__, 'parallel_read_safe': True} diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index d908e208822..2693c90083b 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -28,7 +28,7 @@ import warnings from gettext import NullTranslations from os import path -from typing import Any, Callable, Dict, List, NamedTuple, Set, Tuple, Union +from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Set, Tuple, Type, Union from jinja2 import TemplateNotFound from jinja2.sandbox import SandboxedEnvironment @@ -393,6 +393,14 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None, # keep track of new files new_files = [] + if app: + filename_map = app.config.autosummary_filename_map + if not isinstance(filename_map, Mapping): + raise TypeError('autosummary_filename_map should be a mapping from ' + 'strings to strings') + else: + filename_map = {} + # write for entry in sorted(set(items), key=str): if entry.path is None: @@ -418,7 +426,7 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None, imported_members, app, entry.recursive, context, modname, qualname) - filename = os.path.join(path, name + suffix) + filename = os.path.join(path, filename_map.get(name, name) + suffix) if os.path.isfile(filename): with open(filename, encoding=encoding) as f: old_content = f.read() diff --git a/tests/roots/test-autosummary/sphinx.rst b/tests/roots/test-autosummary/sphinx.rst index fc1a35a0edc..7b47b2c0e97 100644 --- a/tests/roots/test-autosummary/sphinx.rst +++ b/tests/roots/test-autosummary/sphinx.rst @@ -1,31 +1,16 @@ -Autosummary test -================ +sphinx +====== -.. autosummary:: - :toctree: generated +.. automodule:: sphinx - sphinx.application.Sphinx + + + -.. currentmodule:: sphinx.application + + + -.. autoclass:: TemplateBridge - - Basic test - - .. autosummary:: - - render -- some ignored stuff goes here - render_string More ignored stuff - - Test with tildes - - .. autosummary:: - - ~TemplateBridge.render - ~TemplateBridge.render_string - - Methods: - - .. automethod:: render - - .. automethod:: render_string + + + \ No newline at end of file diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 3dd90b8ce60..fe16092dd75 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -386,6 +386,22 @@ def test_autosummary_recursive(app, status, warning): assert 'package.package.module' in content +@pytest.mark.sphinx('dummy', testroot='ext-autosummary-recursive', + confoverrides={'autosummary_filename_map': + {"package": "package_mangled", + "package.package": "package_package_mangled"}}) +def test_autosummary_filename_map(app, status, warning): + app.build() + + assert (app.srcdir / 'generated' / 'package_mangled.rst').exists() + assert not (app.srcdir / 'generated' / 'package.rst').exists() + assert (app.srcdir / 'generated' / 'package.module.rst').exists() + assert (app.srcdir / 'generated' / 'package.module_importfail.rst').exists() is False + assert (app.srcdir / 'generated' / 'package_package_mangled.rst').exists() + assert not (app.srcdir / 'generated' / 'package.package.rst').exists() + assert (app.srcdir / 'generated' / 'package.package.module.rst').exists() + + @pytest.mark.sphinx('latex', **default_kw) def test_autosummary_latex_table_colspec(app, status, warning): app.builder.build_all() From d4010540e551f4d34946b605aae700db660ab69e Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Wed, 8 Jul 2020 20:29:17 +1000 Subject: [PATCH 2/8] Flake8 --- sphinx/ext/autosummary/generate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 2693c90083b..7c5a6e0a4cd 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -28,7 +28,7 @@ import warnings from gettext import NullTranslations from os import path -from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Set, Tuple, Type, Union +from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Set, Tuple, Union from jinja2 import TemplateNotFound from jinja2.sandbox import SandboxedEnvironment From 4e0ff5cac2a47fab136955a4aab4da75b599c5c9 Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Wed, 8 Jul 2020 22:36:40 +1000 Subject: [PATCH 3/8] Fix attempt with new test root --- sphinx/ext/autosummary/generate.py | 1 + .../autosummary_dummy_module.py | 41 +++++++++++++++++++ .../autosummary_importfail.py | 4 ++ .../test-ext-autosummary-filename-map/conf.py | 10 +++++ .../index.rst | 15 +++++++ tests/test_ext_autosummary.py | 18 ++++---- 6 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 tests/roots/test-ext-autosummary-filename-map/autosummary_dummy_module.py create mode 100644 tests/roots/test-ext-autosummary-filename-map/autosummary_importfail.py create mode 100644 tests/roots/test-ext-autosummary-filename-map/conf.py create mode 100644 tests/roots/test-ext-autosummary-filename-map/index.rst diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 7c5a6e0a4cd..4454e47fce5 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -74,6 +74,7 @@ def __init__(self, translator: NullTranslations) -> None: self.warningiserror = False self.config.add('autosummary_context', {}, True, None) + self.config.add('autosummary_filename_map', {}, True, None) self.config.init_values() def emit_firstresult(self, *args: Any) -> None: diff --git a/tests/roots/test-ext-autosummary-filename-map/autosummary_dummy_module.py b/tests/roots/test-ext-autosummary-filename-map/autosummary_dummy_module.py new file mode 100644 index 00000000000..85981a0f865 --- /dev/null +++ b/tests/roots/test-ext-autosummary-filename-map/autosummary_dummy_module.py @@ -0,0 +1,41 @@ +from os import path # NOQA +from typing import Union + + +class Foo: + class Bar: + pass + + def __init__(self): + pass + + def bar(self): + pass + + @property + def baz(self): + pass + + +class _Baz: + pass + + +def bar(x: Union[int, str], y: int = 1) -> None: + pass + + +def _quux(): + pass + + +class Exc(Exception): + pass + + +class _Exc(Exception): + pass + + +#: a module-level attribute +qux = 2 diff --git a/tests/roots/test-ext-autosummary-filename-map/autosummary_importfail.py b/tests/roots/test-ext-autosummary-filename-map/autosummary_importfail.py new file mode 100644 index 00000000000..9e3f9f19509 --- /dev/null +++ b/tests/roots/test-ext-autosummary-filename-map/autosummary_importfail.py @@ -0,0 +1,4 @@ +import sys + +# Fail module import in a catastrophic way +sys.exit(1) diff --git a/tests/roots/test-ext-autosummary-filename-map/conf.py b/tests/roots/test-ext-autosummary-filename-map/conf.py new file mode 100644 index 00000000000..55c769c6f54 --- /dev/null +++ b/tests/roots/test-ext-autosummary-filename-map/conf.py @@ -0,0 +1,10 @@ +import os +import sys + +sys.path.insert(0, os.path.abspath('.')) + +extensions = ['sphinx.ext.autosummary'] +autosummary_generate = True + +# The suffix of source filenames. +source_suffix = '.rst' diff --git a/tests/roots/test-ext-autosummary-filename-map/index.rst b/tests/roots/test-ext-autosummary-filename-map/index.rst new file mode 100644 index 00000000000..9f657bb736d --- /dev/null +++ b/tests/roots/test-ext-autosummary-filename-map/index.rst @@ -0,0 +1,15 @@ + +:autolink:`autosummary_dummy_module.Foo` + +:autolink:`autosummary_importfail` + +.. autosummary:: + :toctree: generated + :caption: An autosummary + + autosummary_dummy_module + autosummary_dummy_module.Foo + autosummary_dummy_module.Foo.Bar + autosummary_dummy_module.bar + autosummary_dummy_module.qux + autosummary_importfail diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index fe16092dd75..7a35d7c901f 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -386,20 +386,18 @@ def test_autosummary_recursive(app, status, warning): assert 'package.package.module' in content -@pytest.mark.sphinx('dummy', testroot='ext-autosummary-recursive', +@pytest.mark.sphinx('dummy', testroot='ext-autosummary-filename-map', confoverrides={'autosummary_filename_map': - {"package": "package_mangled", - "package.package": "package_package_mangled"}}) + {"autosummary_dummy_module": "module_mangled", + "autosummary_dummy_module.bar": "bar"}}) def test_autosummary_filename_map(app, status, warning): app.build() - assert (app.srcdir / 'generated' / 'package_mangled.rst').exists() - assert not (app.srcdir / 'generated' / 'package.rst').exists() - assert (app.srcdir / 'generated' / 'package.module.rst').exists() - assert (app.srcdir / 'generated' / 'package.module_importfail.rst').exists() is False - assert (app.srcdir / 'generated' / 'package_package_mangled.rst').exists() - assert not (app.srcdir / 'generated' / 'package.package.rst').exists() - assert (app.srcdir / 'generated' / 'package.package.module.rst').exists() + assert (app.srcdir / 'generated' / 'module_mangled.rst').exists() + assert not (app.srcdir / 'generated' / 'autosummary_dummy_module.rst').exists() + assert (app.srcdir / 'generated' / 'bar.rst').exists() + assert not (app.srcdir / 'generated' / 'autosummary_dummy_module.bar.rst').exists() + assert (app.srcdir / 'generated' / 'autosummary_dummy_module.Foo.rst').exists() @pytest.mark.sphinx('latex', **default_kw) From 52c173bdb9fa804c14c3852ae339781a50035e67 Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Fri, 10 Jul 2020 11:30:06 +1000 Subject: [PATCH 4/8] Responding to comments --- tests/roots/test-autosummary/sphinx.rst | 39 +++++++++++++------ .../autosummary_importfail.py | 4 -- .../test-ext-autosummary-filename-map/conf.py | 7 ++-- .../index.rst | 1 - tests/test_ext_autosummary.py | 5 +-- 5 files changed, 32 insertions(+), 24 deletions(-) delete mode 100644 tests/roots/test-ext-autosummary-filename-map/autosummary_importfail.py diff --git a/tests/roots/test-autosummary/sphinx.rst b/tests/roots/test-autosummary/sphinx.rst index 7b47b2c0e97..fc1a35a0edc 100644 --- a/tests/roots/test-autosummary/sphinx.rst +++ b/tests/roots/test-autosummary/sphinx.rst @@ -1,16 +1,31 @@ -sphinx -====== +Autosummary test +================ -.. automodule:: sphinx +.. autosummary:: + :toctree: generated - - - + sphinx.application.Sphinx - - - +.. currentmodule:: sphinx.application - - - \ No newline at end of file +.. autoclass:: TemplateBridge + + Basic test + + .. autosummary:: + + render -- some ignored stuff goes here + render_string More ignored stuff + + Test with tildes + + .. autosummary:: + + ~TemplateBridge.render + ~TemplateBridge.render_string + + Methods: + + .. automethod:: render + + .. automethod:: render_string diff --git a/tests/roots/test-ext-autosummary-filename-map/autosummary_importfail.py b/tests/roots/test-ext-autosummary-filename-map/autosummary_importfail.py deleted file mode 100644 index 9e3f9f19509..00000000000 --- a/tests/roots/test-ext-autosummary-filename-map/autosummary_importfail.py +++ /dev/null @@ -1,4 +0,0 @@ -import sys - -# Fail module import in a catastrophic way -sys.exit(1) diff --git a/tests/roots/test-ext-autosummary-filename-map/conf.py b/tests/roots/test-ext-autosummary-filename-map/conf.py index 55c769c6f54..17e2fa44565 100644 --- a/tests/roots/test-ext-autosummary-filename-map/conf.py +++ b/tests/roots/test-ext-autosummary-filename-map/conf.py @@ -5,6 +5,7 @@ extensions = ['sphinx.ext.autosummary'] autosummary_generate = True - -# The suffix of source filenames. -source_suffix = '.rst' +autosummary_filename_map = { + "autosummary_dummy_module": "module_mangled", + "autosummary_dummy_module.bar": "bar" +} diff --git a/tests/roots/test-ext-autosummary-filename-map/index.rst b/tests/roots/test-ext-autosummary-filename-map/index.rst index 9f657bb736d..ef27d9d19e0 100644 --- a/tests/roots/test-ext-autosummary-filename-map/index.rst +++ b/tests/roots/test-ext-autosummary-filename-map/index.rst @@ -12,4 +12,3 @@ autosummary_dummy_module.Foo.Bar autosummary_dummy_module.bar autosummary_dummy_module.qux - autosummary_importfail diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 7a35d7c901f..62fe4cc5684 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -386,10 +386,7 @@ def test_autosummary_recursive(app, status, warning): assert 'package.package.module' in content -@pytest.mark.sphinx('dummy', testroot='ext-autosummary-filename-map', - confoverrides={'autosummary_filename_map': - {"autosummary_dummy_module": "module_mangled", - "autosummary_dummy_module.bar": "bar"}}) +@pytest.mark.sphinx('dummy', testroot='ext-autosummary-filename-map') def test_autosummary_filename_map(app, status, warning): app.build() From 71d1b37f8ad9b470c1779d0b74a8581b1e131353 Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Fri, 10 Jul 2020 11:31:27 +1000 Subject: [PATCH 5/8] Simplify dummy module --- .../autosummary_dummy_module.py | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/tests/roots/test-ext-autosummary-filename-map/autosummary_dummy_module.py b/tests/roots/test-ext-autosummary-filename-map/autosummary_dummy_module.py index 85981a0f865..1f57eeb256c 100644 --- a/tests/roots/test-ext-autosummary-filename-map/autosummary_dummy_module.py +++ b/tests/roots/test-ext-autosummary-filename-map/autosummary_dummy_module.py @@ -17,25 +17,5 @@ def baz(self): pass -class _Baz: - pass - - def bar(x: Union[int, str], y: int = 1) -> None: pass - - -def _quux(): - pass - - -class Exc(Exception): - pass - - -class _Exc(Exception): - pass - - -#: a module-level attribute -qux = 2 From aae8ce8efa64963c6c5f73f318da6762499c705e Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Wed, 15 Jul 2020 18:46:51 +1000 Subject: [PATCH 6/8] Fix toctree generation --- sphinx/ext/autosummary/__init__.py | 4 +++- sphinx/ext/autosummary/generate.py | 3 --- tests/roots/test-ext-autosummary-filename-map/index.rst | 3 +-- tests/test_ext_autosummary.py | 3 +++ 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index ece16c15bc5..350604387b0 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -252,7 +252,9 @@ def run(self) -> List[Node]: tree_prefix = self.options['toctree'].strip() docnames = [] excluded = Matcher(self.config.exclude_patterns) + filename_map = self.config.autosummary_filename_map for name, sig, summary, real_name in items: + real_name = filename_map.get(real_name, real_name) docname = posixpath.join(tree_prefix, real_name) docname = posixpath.normpath(posixpath.join(dirname, docname)) if docname not in self.env.found_docs: @@ -785,11 +787,11 @@ def setup(app: Sphinx) -> Dict[str, Any]: app.add_role('autolink', AutoLink()) app.connect('builder-inited', process_generate_options) app.add_config_value('autosummary_context', {}, True) + app.add_config_value('autosummary_filename_map', {}, 'html') app.add_config_value('autosummary_generate', [], True, [bool]) app.add_config_value('autosummary_generate_overwrite', True, False) app.add_config_value('autosummary_mock_imports', lambda config: config.autodoc_mock_imports, 'env') app.add_config_value('autosummary_imported_members', [], False, [bool]) - app.add_config_value('autosummary_filename_map', {}, 'html') return {'version': sphinx.__display_version__, 'parallel_read_safe': True} diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 4454e47fce5..98e2a047a1e 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -396,9 +396,6 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None, if app: filename_map = app.config.autosummary_filename_map - if not isinstance(filename_map, Mapping): - raise TypeError('autosummary_filename_map should be a mapping from ' - 'strings to strings') else: filename_map = {} diff --git a/tests/roots/test-ext-autosummary-filename-map/index.rst b/tests/roots/test-ext-autosummary-filename-map/index.rst index ef27d9d19e0..e85389395a4 100644 --- a/tests/roots/test-ext-autosummary-filename-map/index.rst +++ b/tests/roots/test-ext-autosummary-filename-map/index.rst @@ -9,6 +9,5 @@ autosummary_dummy_module autosummary_dummy_module.Foo - autosummary_dummy_module.Foo.Bar + autosummary_dummy_module.Foo.bar autosummary_dummy_module.bar - autosummary_dummy_module.qux diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 62fe4cc5684..462a93954d7 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -396,6 +396,9 @@ def test_autosummary_filename_map(app, status, warning): assert not (app.srcdir / 'generated' / 'autosummary_dummy_module.bar.rst').exists() assert (app.srcdir / 'generated' / 'autosummary_dummy_module.Foo.rst').exists() + html_warnings = app._warning.getvalue() + assert html_warnings == '' + @pytest.mark.sphinx('latex', **default_kw) def test_autosummary_latex_table_colspec(app, status, warning): From 2b843dd856ab54d7e0a9769fe0e507ac7671b263 Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Wed, 15 Jul 2020 20:49:05 +1000 Subject: [PATCH 7/8] Rm unused import --- sphinx/ext/autosummary/generate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 98e2a047a1e..c1b50de577a 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -28,7 +28,7 @@ import warnings from gettext import NullTranslations from os import path -from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Set, Tuple, Union +from typing import Any, Callable, Dict, List, NamedTuple, Set, Tuple, Union from jinja2 import TemplateNotFound from jinja2.sandbox import SandboxedEnvironment From 144f18a5284f1df792bd1ba217d6d35a7a20d8dc Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Thu, 23 Jul 2020 17:27:57 +1000 Subject: [PATCH 8/8] Remove irrelevant test RST --- tests/roots/test-ext-autosummary-filename-map/index.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/roots/test-ext-autosummary-filename-map/index.rst b/tests/roots/test-ext-autosummary-filename-map/index.rst index e85389395a4..57d902b6aba 100644 --- a/tests/roots/test-ext-autosummary-filename-map/index.rst +++ b/tests/roots/test-ext-autosummary-filename-map/index.rst @@ -1,8 +1,4 @@ -:autolink:`autosummary_dummy_module.Foo` - -:autolink:`autosummary_importfail` - .. autosummary:: :toctree: generated :caption: An autosummary