sphinx-codeautolink 0.19.0__tar.gz → 0.20.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/PKG-INFO +3 -3
  2. sphinx_codeautolink-0.20.0/docs/requirements.txt +6 -0
  3. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/about.rst +4 -1
  4. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/release_notes.rst +15 -0
  5. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/pyproject.toml +2 -2
  6. sphinx_codeautolink-0.20.0/requirements/tests +4 -0
  7. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/__init__.py +3 -2
  8. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/__init__.py +22 -18
  9. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/block.py +8 -9
  10. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/resolve.py +21 -13
  11. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/parse.py +29 -11
  12. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/PKG-INFO +3 -3
  13. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/SOURCES.txt +7 -0
  14. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/__init__.py +41 -0
  15. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_builtins.txt +5 -0
  16. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_comprehension_target.txt +25 -0
  17. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_comprehension_unpack.txt +17 -0
  18. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_lazy_import.txt +19 -0
  19. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_type_alias.txt +22 -0
  20. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_type_param_defaults.txt +22 -0
  21. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_type_params.txt +23 -0
  22. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_union_return.txt +20 -0
  23. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/self_type.py +1 -4
  24. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/parse/_util.py +0 -11
  25. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/parse/match.py +1 -2
  26. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/parse/scope.py +1 -2
  27. sphinx_codeautolink-0.19.0/docs/requirements.txt +0 -6
  28. sphinx_codeautolink-0.19.0/requirements/tests +0 -5
  29. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/LICENSE +0 -0
  30. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/MANIFEST.in +0 -0
  31. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/contributing.rst +0 -0
  32. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/404.rst +0 -0
  33. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/conf.py +0 -0
  34. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/example_library.rst +0 -0
  35. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/examples.rst +0 -0
  36. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/index.rst +0 -0
  37. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/lib.py +0 -0
  38. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/reference.rst +0 -0
  39. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/docs/src/static/custom.css +0 -0
  40. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/readme_pypi.rst +0 -0
  41. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/requirements/build +0 -0
  42. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/requirements/dev +0 -0
  43. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/requirements/docs +0 -0
  44. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/requirements/extras +0 -0
  45. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/setup.cfg +0 -0
  46. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/backref.py +0 -0
  47. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/cache.py +0 -0
  48. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/directive.py +0 -0
  49. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/translation.py +0 -0
  50. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/de/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  51. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/de/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  52. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/es/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  53. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/es/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  54. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/fi/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  55. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/fi/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  56. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/fr/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  57. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/fr/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  58. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/it/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  59. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/it/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  60. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/nl/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  61. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/nl/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  62. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/ru/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  63. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/sphinx-codeautolink.pot +0 -0
  64. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/uk/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  65. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/static/sphinx-codeautolink.css +0 -0
  66. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/warn.py +0 -0
  67. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/dependency_links.txt +0 -0
  68. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/requires.txt +0 -0
  69. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/top_level.txt +0 -0
  70. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/__init__.py +0 -0
  71. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/_check.py +0 -0
  72. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/concat_invalid.txt +0 -0
  73. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/custom_block_import_invalid.txt +0 -0
  74. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/custom_block_syntax_error.txt +0 -0
  75. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/failed_resolve_invalid_location.txt +0 -0
  76. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/failed_resolve_no_module.txt +0 -0
  77. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/failed_resolve_return_type.txt +0 -0
  78. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/match_block_warning.txt +0 -0
  79. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/missing_inventory.txt +0 -0
  80. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/no_backreference.txt +0 -0
  81. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/no_module_docs.txt +0 -0
  82. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/preface_invalid_arg.txt +0 -0
  83. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_import_star_invalid.txt +0 -0
  84. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_invalid_block_type.txt +0 -0
  85. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_invalid_syntax.txt +0 -0
  86. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_invalid_syntax_complex.txt +0 -0
  87. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_ipython_non-python.txt +0 -0
  88. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/fail/skip_invalid.txt +0 -0
  89. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/class_mro_fix.txt +0 -0
  90. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_default.txt +0 -0
  91. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_off.txt +0 -0
  92. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_on_across_sections.txt +0 -0
  93. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_on_breaks.txt +0 -0
  94. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_section_breaks.txt +0 -0
  95. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_section_returns_to_global.txt +0 -0
  96. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/custom_block.txt +0 -0
  97. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/custom_block_imported.txt +0 -0
  98. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/empty_project.txt +0 -0
  99. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/inventory_map_is_needed.txt +0 -0
  100. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/inventory_map_not_needed.txt +0 -0
  101. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_Python.txt +0 -0
  102. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_bazel.txt +0 -0
  103. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_default.txt +0 -0
  104. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_default_fail.txt +0 -0
  105. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_doctest.txt +0 -0
  106. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_doctest_empty_input.txt +0 -0
  107. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_extdoctest_doctest.txt +0 -0
  108. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_extdoctest_setup.txt +0 -0
  109. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_extdoctest_setup_wrong.txt +0 -0
  110. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_extdoctest_testcode.txt +0 -0
  111. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_highlight_language.txt +0 -0
  112. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_highlight_none.txt +0 -0
  113. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython.txt +0 -0
  114. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython3.txt +0 -0
  115. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython_directive.txt +0 -0
  116. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython_directive_comment.txt +0 -0
  117. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython_syntax.txt +0 -0
  118. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_literal.txt +0 -0
  119. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_non_python_block.txt +0 -0
  120. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_py.txt +0 -0
  121. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_py3.txt +0 -0
  122. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_pycon.txt +0 -0
  123. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_pycon_implicit.txt +0 -0
  124. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_pyi.txt +0 -0
  125. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_python3.txt +0 -0
  126. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_sage.txt +0 -0
  127. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_starlark.txt +0 -0
  128. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/line_numbers.txt +0 -0
  129. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_concatenated.txt +0 -0
  130. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_consumed_non_python.txt +0 -0
  131. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_document.txt +0 -0
  132. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_global.txt +0 -0
  133. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_global_multiline.txt +0 -0
  134. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_global_overwritten.txt +0 -0
  135. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_multiline.txt +0 -0
  136. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_multiline_and_arg.txt +0 -0
  137. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_multiple.txt +0 -0
  138. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_single.txt +0 -0
  139. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_assign_targets.txt +0 -0
  140. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_attribute_assignment.txt +0 -0
  141. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_chain.txt +0 -0
  142. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_chain_call.txt +0 -0
  143. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_class_attr.txt +0 -0
  144. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_class_meth_returns_self.txt +0 -0
  145. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_class_type_attr.txt +0 -0
  146. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_decorator.txt +0 -0
  147. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_fluent_attrs.txt +0 -0
  148. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_fluent_call.txt +0 -0
  149. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_for_loop.txt +0 -0
  150. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_func_args.txt +0 -0
  151. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_func_no_module.txt +0 -0
  152. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_as.txt +0 -0
  153. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_from.txt +0 -0
  154. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_from_complex.txt +0 -0
  155. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_multiple.txt +0 -0
  156. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_multiple_libs.txt +0 -0
  157. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_star.txt +0 -0
  158. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_submodule.txt +0 -0
  159. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_imported_func.txt +0 -0
  160. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_imported_func_relocated.txt +0 -0
  161. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_inherited.txt +0 -0
  162. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_intersphinx_only.txt +0 -0
  163. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_invalid_func.txt +0 -0
  164. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_invalid_typehint.txt +0 -0
  165. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_module_attribute.txt +0 -0
  166. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_module_attribute_builtin.txt +0 -0
  167. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_module_attribute_class.txt +0 -0
  168. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_optional.txt +0 -0
  169. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_optional_future.txt +0 -0
  170. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_shadow_builtin.txt +0 -0
  171. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_simple.txt +0 -0
  172. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_type_checking_aliased.txt +0 -0
  173. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_type_checking_gated.txt +0 -0
  174. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/search_css_duplicates_removed.txt +0 -0
  175. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/self_type.txt +0 -0
  176. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_file.txt +0 -0
  177. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_next.txt +0 -0
  178. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_next_consumed_non_python.txt +0 -0
  179. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_off.txt +0 -0
  180. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_section.txt +0 -0
  181. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/class_mro_fix.py +0 -0
  182. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/future_project.py +0 -0
  183. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/parser_func.py +0 -0
  184. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/test_project/__init__.py +0 -0
  185. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/test_project/sub.py +0 -0
  186. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/type_checking/__init__.py +0 -0
  187. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/type_checking/foo.py +0 -0
  188. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/type_checking_aliased/__init__.py +0 -0
  189. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/src/type_checking_aliased/foo.py +0 -0
  190. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_autodoc_empty.txt +0 -0
  191. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_autodoc_links.txt +0 -0
  192. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_manual_collapse.txt +0 -0
  193. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_manual_empty.txt +0 -0
  194. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_manual_links.txt +0 -0
  195. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_manual_links_subsection.txt +0 -0
  196. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_no_table.txt +0 -0
  197. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/parse/__init__.py +0 -0
  198. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/parse/assign.py +0 -0
  199. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tests/parse/chain.py +0 -0
  200. {sphinx_codeautolink-0.19.0 → sphinx_codeautolink-0.20.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sphinx-codeautolink
3
- Version: 0.19.0
3
+ Version: 0.20.0
4
4
  Summary: Automatic links from code examples to reference documentation.
5
5
  Author-email: Felix Hildén <felix.hilden@gmail.com>
6
6
  Maintainer-email: Felix Hildén <felix.hilden@gmail.com>
@@ -15,15 +15,15 @@ Classifier: Framework :: Sphinx
15
15
  Classifier: Framework :: Sphinx :: Extension
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: 3 :: Only
18
- Classifier: Programming Language :: Python :: 3.10
19
18
  Classifier: Programming Language :: Python :: 3.11
20
19
  Classifier: Programming Language :: Python :: 3.12
21
20
  Classifier: Programming Language :: Python :: 3.13
22
21
  Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
23
23
  Classifier: Topic :: Documentation
24
24
  Classifier: Topic :: Documentation :: Sphinx
25
25
  Classifier: Topic :: Software Development :: Documentation
26
- Requires-Python: >=3.10
26
+ Requires-Python: >=3.11
27
27
  Description-Content-Type: text/x-rst
28
28
  License-File: LICENSE
29
29
  Requires-Dist: sphinx>=3.2.0
@@ -0,0 +1,6 @@
1
+ # Manually pin Sphinx + docs requirements
2
+ sphinx==9.2.0
3
+ sphinx-rtd-theme==3.1.0
4
+ docutils==0.21.2
5
+ matplotlib==3.11.2
6
+ ipython==9.18.1
@@ -10,7 +10,7 @@ That information is fed to the name resolver, which attempts to match a series
10
10
  of attributes and calls to the concrete type in question by following
11
11
  type hints and other information accessible via imports of the library.
12
12
  If a match is found, a link to the correct reference documentation entry
13
- is injected after the ordinary Sphinx build is finished.
13
+ is injected into the HTML of the page as it is written.
14
14
 
15
15
  .. _caveats:
16
16
 
@@ -44,6 +44,9 @@ Caveats
44
44
  change after the definition and impact the function.
45
45
  Encountering this should be unlikely, because it only occurs in practice
46
46
  when a variable shadows or overwrites an imported module or its part.
47
+ - Type parameters of generic functions, classes and type aliases
48
+ (``def f[T](arg: T)``) do not shadow imported names, so an imported ``T``
49
+ would be linked inside the definition.
47
50
 
48
51
  These cases are subject to change when the library matures. For more details
49
52
  on the expected failures, see our `test suite on GitHub <https://github.com
@@ -8,6 +8,21 @@ These release notes are based on
8
8
  sphinx-codeautolink adheres to
9
9
  `Semantic Versioning <https://semver.org>`_.
10
10
 
11
+ 0.20.0 (2026-11-08)
12
+ -------------------
13
+ - Inject links while each page is written, instead of rewriting the HTML
14
+ files after the build. This makes builds faster, and fixes links missing
15
+ from pages that Sphinx rewrites without their source changing, such as the
16
+ parent of a renamed toctree entry (:issue:`205`)
17
+ - Don't link names assigned from a call returning a union such as
18
+ ``Foo | Bar`` to ``typing.Union`` on Python 3.14
19
+ - Support Python 3.15 officially, and remove support for 3.10 (:issue:`206`)
20
+ - Link assignments from builtins (:issue:`207`)
21
+ - Avoid crashing in dict comprehensions with ``**`` unpacking (:issue:`208`)
22
+ - Link names in bounds and defaults of type parameters (:issue:`209`)
23
+ - Track ``type`` alias statements (:issue:`210`)
24
+ - Link comprehension targets from the iterable (:issue:`211`)
25
+
11
26
  0.19.0 (2026-07-29)
12
27
  -------------------
13
28
  - Only add a hover title to links when the resolved location of the object
@@ -9,7 +9,7 @@ readme = "readme_pypi.rst"
9
9
  license-files = ["LICENSE"]
10
10
  dynamic = ["version"]
11
11
 
12
- requires-python = ">=3.10"
12
+ requires-python = ">=3.11"
13
13
  dependencies = [
14
14
  "sphinx>=3.2.0",
15
15
  "beautifulsoup4>=4.8.1",
@@ -26,11 +26,11 @@ classifiers = [
26
26
  "Framework :: Sphinx :: Extension",
27
27
  "Programming Language :: Python :: 3",
28
28
  "Programming Language :: Python :: 3 :: Only",
29
- "Programming Language :: Python :: 3.10",
30
29
  "Programming Language :: Python :: 3.11",
31
30
  "Programming Language :: Python :: 3.12",
32
31
  "Programming Language :: Python :: 3.13",
33
32
  "Programming Language :: Python :: 3.14",
33
+ "Programming Language :: Python :: 3.15",
34
34
  "Topic :: Documentation",
35
35
  "Topic :: Documentation :: Sphinx",
36
36
  "Topic :: Software Development :: Documentation",
@@ -0,0 +1,4 @@
1
+ -r extras
2
+
3
+ pytest>=6
4
+ coverage[toml]>=5
@@ -8,7 +8,7 @@ from .extension import SphinxCodeAutoLink, backref, directive
8
8
  from .extension.block import clean_ipython, clean_pycon
9
9
  from .extension.translation import MESSAGE_CATALOG_NAME
10
10
 
11
- __version__ = "0.19.0"
11
+ __version__ = "0.20.0"
12
12
 
13
13
 
14
14
  def setup(app: Sphinx):
@@ -74,7 +74,8 @@ def setup(app: Sphinx):
74
74
  app.connect("env-purge-doc", state.purge_doc_from_environment)
75
75
  app.connect("env-updated", state.create_references)
76
76
  app.connect("doctree-resolved", state.generate_backref_tables)
77
- app.connect("build-finished", state.apply_links)
77
+ app.connect("html-page-context", state.apply_links)
78
+ app.connect("build-finished", state.write_cache)
78
79
 
79
80
  app.add_node(
80
81
  backref.DetailsNode, html=(backref.visit_details, backref.depart_details)
@@ -81,7 +81,6 @@ class SphinxCodeAutoLink:
81
81
  self.disable_link_titles = None
82
82
 
83
83
  # Populated once
84
- self.outdated_docs: set[str] = set()
85
84
  self.inventory = {}
86
85
  self.code_refs: dict[str, list[CodeExample]] = {}
87
86
 
@@ -98,7 +97,6 @@ class SphinxCodeAutoLink:
98
97
  self.cache = DataCache(app.doctreedir, app.srcdir)
99
98
  self.cache.read()
100
99
  app.env.sphinx_codeautolink_transforms = self.cache.transforms
101
- self.outdated_docs = {str(Path(d)) for d in app.builder.get_outdated_docs()}
102
100
  self.custom_blocks = app.config.codeautolink_custom_blocks
103
101
  for k, v in self.custom_blocks.items():
104
102
  if isinstance(v, str):
@@ -281,24 +279,30 @@ class SphinxCodeAutoLink:
281
279
  return None
282
280
 
283
281
  @print_exceptions()
284
- def apply_links(self, app, exception) -> None:
285
- """Apply links to HTML output and write refs file."""
286
- if self.do_nothing or exception is not None:
282
+ def apply_links(self, app, pagename, templatename, context, doctree) -> None:
283
+ """Apply links to the HTML body of a page before it is written."""
284
+ if self.do_nothing:
287
285
  return
288
286
 
289
- for doc, transforms in self.cache.transforms.items():
290
- if not transforms or str(Path(doc)) not in self.outdated_docs:
291
- continue
292
- link_html(
293
- doc,
294
- app.outdir,
295
- transforms,
296
- self.inventory,
297
- self.custom_blocks,
298
- self.search_css_classes,
299
- builder_name=app.builder.name,
300
- disable_link_titles=self.disable_link_titles,
301
- )
287
+ transforms = self.cache.transforms.get(str(Path(pagename)))
288
+ if not transforms:
289
+ return
290
+ context["body"] = link_html(
291
+ pagename,
292
+ context["body"],
293
+ transforms,
294
+ self.inventory,
295
+ self.custom_blocks,
296
+ self.search_css_classes,
297
+ builder_name=app.builder.name,
298
+ disable_link_titles=self.disable_link_titles,
299
+ )
300
+
301
+ @print_exceptions()
302
+ def write_cache(self, app, exception) -> None:
303
+ """Write refs file."""
304
+ if self.do_nothing or exception is not None:
305
+ return
302
306
 
303
307
  self.cache.write()
304
308
 
@@ -379,7 +379,7 @@ def format_title(location: str, text: str) -> str:
379
379
 
380
380
  def link_html(
381
381
  document: str,
382
- out_dir: str,
382
+ html: str,
383
383
  transforms: list[SourceTransform],
384
384
  inventory: dict,
385
385
  custom_blocks: dict,
@@ -387,15 +387,14 @@ def link_html(
387
387
  builder_name: str = "html",
388
388
  *,
389
389
  disable_link_titles: bool,
390
- ) -> None:
391
- """Inject links to code blocks on disk."""
390
+ ) -> str:
391
+ """Inject links to code blocks in the HTML of a document."""
392
392
  if builder_name == "dirhtml" and Path(document).name != "index":
393
- html_file = Path(out_dir) / document / "index.html"
393
+ html_file = Path(document) / "index.html"
394
394
  else:
395
- html_file = Path(out_dir) / (document + ".html")
395
+ html_file = Path(document + ".html")
396
396
 
397
- text = html_file.read_text("utf-8")
398
- soup = BeautifulSoup(text, "html.parser")
397
+ soup = BeautifulSoup(html, "html.parser")
399
398
 
400
399
  block_types = BUILTIN_BLOCKS.keys() | custom_blocks.keys()
401
400
  classes = [f"highlight-{t}" for t in block_types] + ["doctest"]
@@ -408,7 +407,7 @@ def link_html(
408
407
  blocks = sorted(unique_blocks, key=lambda b: b.sourceline)
409
408
  inners = [block.select("div > pre")[0] for block in blocks]
410
409
 
411
- up_lvls = len(html_file.relative_to(out_dir).parents) - 1
410
+ up_lvls = len(html_file.parents) - 1
412
411
  local_prefix = "../" * up_lvls
413
412
  link_pattern = '<a href="{link}"{title} class="sphinx-codeautolink-a">{text}</a>'
414
413
 
@@ -467,7 +466,7 @@ def link_html(
467
466
 
468
467
  inner.replace_with(BeautifulSoup("\n".join(lines), "html.parser"))
469
468
 
470
- html_file.write_text(str(soup), "utf-8")
469
+ return str(soup)
471
470
 
472
471
 
473
472
  # ---------------------------------------------------------------
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import ast
6
+ import builtins
6
7
  import inspect
7
8
  from collections import abc
8
9
  from collections.abc import Callable
@@ -12,18 +13,10 @@ from functools import cache
12
13
  from importlib import import_module
13
14
  from inspect import isclass, ismodule, isroutine
14
15
  from types import ModuleType, UnionType
15
- from typing import Any, Union, get_type_hints
16
+ from typing import Any, Self, Union, get_type_hints
16
17
 
17
18
  from sphinx_codeautolink.parse import Name, NameBreak
18
19
 
19
- try:
20
- from typing import Self # Python >= 3.11
21
- except ImportError: # pragma: no cover
22
- try:
23
- from typing_extensions import Self
24
- except ImportError:
25
- Self = None # type: ignore[assignment,misc]
26
-
27
20
  # Containers whose first generic argument is the element type produced
28
21
  # by iteration. ``tuple`` only fits ``tuple[T, ...]``; for mixed tuples
29
22
  # like ``tuple[int, str]`` we pick the first arg, which may be wrong.
@@ -80,7 +73,9 @@ def resolve_location(chain: Name, inventory) -> str:
80
73
  call_value(cursor)
81
74
  elif terminator == NameBreak.for_iter:
82
75
  iter_value(cursor)
83
- return cursor.location if cursor is not None else None
76
+ if cursor is None:
77
+ return None
78
+ return cursor.location.removeprefix(builtins.__name__ + ".")
84
79
 
85
80
 
86
81
  class CouldNotResolve(Exception): # noqa: N818
@@ -106,7 +101,14 @@ class Cursor:
106
101
 
107
102
  def make_cursor(components: list[str]) -> tuple[list[str], Cursor]:
108
103
  """Divide components into module and rest, create cursor for following the rest."""
109
- value, index = closest_module(tuple(components))
104
+ try:
105
+ value, index = closest_module(tuple(components))
106
+ except CouldNotResolve:
107
+ if not hasattr(builtins, components[0]):
108
+ raise
109
+ # Builtins are documented without a module prefix, so start from
110
+ # the module itself and let the prefix be stripped on resolution
111
+ return components, Cursor(builtins.__name__, builtins, instance=False)
110
112
  location = ".".join(components[:index])
111
113
  return components[index:], Cursor(location, value, instance=False)
112
114
 
@@ -232,7 +234,11 @@ def strip_optional(annotation: Any) -> Any:
232
234
 
233
235
  def origin_type(annotation: Any) -> Any:
234
236
  """Return underlying type of an annotation (e.g. ``list`` from ``list[Foo]``)."""
235
- return getattr(annotation, "__origin__", None) or annotation
237
+ origin = getattr(annotation, "__origin__", None)
238
+ # on 3.14+ the origin of ``X | Y`` is typing.Union, which is a class
239
+ if origin is Union:
240
+ return None
241
+ return origin or annotation
236
242
 
237
243
 
238
244
  def unwrap_iterable(annotation: Any) -> type | None:
@@ -258,7 +264,9 @@ def get_return_annotation(func: Callable) -> Any:
258
264
 
259
265
 
260
266
  def fully_qualified_name(thing: type | Callable) -> str:
261
- """Construct the fully qualified name of a type."""
267
+ """Construct the fully qualified name of a type, omitting the builtins module."""
268
+ if thing.__module__ == builtins.__name__:
269
+ return thing.__qualname__
262
270
  return thing.__module__ + "." + thing.__qualname__
263
271
 
264
272
 
@@ -6,7 +6,7 @@ import ast
6
6
  import builtins
7
7
  import sys
8
8
  from dataclasses import dataclass
9
- from enum import Enum
9
+ from enum import StrEnum
10
10
  from importlib import import_module
11
11
 
12
12
  from .warn import logger, warn_type
@@ -83,7 +83,7 @@ class Assignment:
83
83
  value: PendingAccess | None
84
84
 
85
85
 
86
- class NameBreak(str, Enum):
86
+ class NameBreak(StrEnum):
87
87
  """
88
88
  Elements that break name access chains.
89
89
 
@@ -97,7 +97,7 @@ class NameBreak(str, Enum):
97
97
  for_iter = "<>"
98
98
 
99
99
 
100
- class LinkContext(str, Enum):
100
+ class LinkContext(StrEnum):
101
101
  """Context in which a link appears to help HTML matching."""
102
102
 
103
103
  none = "none"
@@ -438,6 +438,18 @@ class ImportTrackerVisitor(ast.NodeVisitor):
438
438
  target = self.visit(node.target)
439
439
  return Assignment([target], value)
440
440
 
441
+ def visit_type_params(self, node: ast.AST) -> None:
442
+ """Visit bounds and defaults of type parameters."""
443
+ for param in getattr(node, "type_params", []):
444
+ self.visit(param)
445
+
446
+ def visit_TypeAlias(self, node: ast.AST) -> Assignment:
447
+ """Visit a type alias statement like an assignment."""
448
+ value = self.visit(node.value)
449
+ self.visit_type_params(node)
450
+ target = self.visit(node.name)
451
+ return Assignment([target], value)
452
+
441
453
  def visit_AugAssign(self, node: ast.AugAssign) -> None:
442
454
  """Visit an AugAssign node."""
443
455
  self.visit(node.value)
@@ -501,8 +513,8 @@ class ImportTrackerVisitor(ast.NodeVisitor):
501
513
  """Delegate to sync for."""
502
514
  self.visit_For(node)
503
515
 
504
- def visit_For(self, node: ast.For | ast.AsyncFor) -> None:
505
- """Swap node order and resolve iterators."""
516
+ def bind_iter_target(self, node: ast.For | ast.AsyncFor | ast.comprehension):
517
+ """Visit iterator and bind a simple name target to its element."""
506
518
  iter_pending = self.visit(node.iter)
507
519
 
508
520
  if (
@@ -510,11 +522,15 @@ class ImportTrackerVisitor(ast.NodeVisitor):
510
522
  and iter_pending.components
511
523
  and isinstance(node.target, ast.Name)
512
524
  ):
513
- marker = Component(NameBreak.for_iter.value, *linenos(node), "load")
525
+ marker = Component(NameBreak.for_iter.value, *linenos(node.target), "load")
514
526
  self.assign_name(node.target.id, [*iter_pending.components, marker])
515
527
  else:
516
528
  self.visit(node.target)
517
529
 
530
+ def visit_For(self, node: ast.For | ast.AsyncFor) -> None:
531
+ """Swap node order and resolve iterators."""
532
+ self.bind_iter_target(node)
533
+
518
534
  for n in node.body:
519
535
  self.visit(n)
520
536
  for n in node.orelse:
@@ -528,6 +544,7 @@ class ImportTrackerVisitor(ast.NodeVisitor):
528
544
  self.visit(base)
529
545
  for kw in node.keywords:
530
546
  self.visit(kw)
547
+ self.visit_type_params(node)
531
548
 
532
549
  self.overwrite_name(node.name)
533
550
  self.pseudo_scopes_stack.append(self.pseudo_scopes_stack[0].copy())
@@ -552,6 +569,7 @@ class ImportTrackerVisitor(ast.NodeVisitor):
552
569
  if d is None:
553
570
  continue
554
571
  self.visit(d)
572
+ self.visit_type_params(node)
555
573
  args = self._get_args(node.args)
556
574
  args += [node.args.vararg, node.args.kwarg]
557
575
 
@@ -610,17 +628,17 @@ class ImportTrackerVisitor(ast.NodeVisitor):
610
628
  self.visit_generic_comp([node.elt], node.generators)
611
629
 
612
630
  def visit_DictComp(self, node: ast.DictComp) -> None:
613
- """Delegate to generic comp."""
614
- self.visit_generic_comp([node.key, node.value], node.generators)
631
+ """Delegate to generic comp, key is None when unpacking with ``**``."""
632
+ values = [v for v in (node.key, node.value) if v is not None]
633
+ self.visit_generic_comp(values, node.generators)
615
634
 
616
635
  def visit_GeneratorExp(self, node: ast.GeneratorExp) -> None:
617
636
  """Delegate to generic comp."""
618
637
  self.visit_generic_comp([node.elt], node.generators)
619
638
 
620
639
  def visit_comprehension(self, node: ast.comprehension) -> None:
621
- """Swap node order."""
622
- self.visit(node.iter)
623
- self.visit(node.target)
640
+ """Swap node order and resolve iterators."""
641
+ self.bind_iter_target(node)
624
642
  for f in node.ifs:
625
643
  self.visit(f)
626
644
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sphinx-codeautolink
3
- Version: 0.19.0
3
+ Version: 0.20.0
4
4
  Summary: Automatic links from code examples to reference documentation.
5
5
  Author-email: Felix Hildén <felix.hilden@gmail.com>
6
6
  Maintainer-email: Felix Hildén <felix.hilden@gmail.com>
@@ -15,15 +15,15 @@ Classifier: Framework :: Sphinx
15
15
  Classifier: Framework :: Sphinx :: Extension
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: 3 :: Only
18
- Classifier: Programming Language :: Python :: 3.10
19
18
  Classifier: Programming Language :: Python :: 3.11
20
19
  Classifier: Programming Language :: Python :: 3.12
21
20
  Classifier: Programming Language :: Python :: 3.13
22
21
  Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
23
23
  Classifier: Topic :: Documentation
24
24
  Classifier: Topic :: Documentation :: Sphinx
25
25
  Classifier: Topic :: Software Development :: Documentation
26
- Requires-Python: >=3.10
26
+ Requires-Python: >=3.11
27
27
  Description-Content-Type: text/x-rst
28
28
  License-File: LICENSE
29
29
  Requires-Dist: sphinx>=3.2.0
@@ -129,6 +129,8 @@ tests/extension/ref/ref_chain_call.txt
129
129
  tests/extension/ref/ref_class_attr.txt
130
130
  tests/extension/ref/ref_class_meth_returns_self.txt
131
131
  tests/extension/ref/ref_class_type_attr.txt
132
+ tests/extension/ref/ref_comprehension_target.txt
133
+ tests/extension/ref/ref_comprehension_unpack.txt
132
134
  tests/extension/ref/ref_decorator.txt
133
135
  tests/extension/ref/ref_fluent_attrs.txt
134
136
  tests/extension/ref/ref_fluent_call.txt
@@ -148,6 +150,7 @@ tests/extension/ref/ref_inherited.txt
148
150
  tests/extension/ref/ref_intersphinx_only.txt
149
151
  tests/extension/ref/ref_invalid_func.txt
150
152
  tests/extension/ref/ref_invalid_typehint.txt
153
+ tests/extension/ref/ref_lazy_import.txt
151
154
  tests/extension/ref/ref_module_attribute.txt
152
155
  tests/extension/ref/ref_module_attribute_builtin.txt
153
156
  tests/extension/ref/ref_module_attribute_class.txt
@@ -155,8 +158,12 @@ tests/extension/ref/ref_optional.txt
155
158
  tests/extension/ref/ref_optional_future.txt
156
159
  tests/extension/ref/ref_shadow_builtin.txt
157
160
  tests/extension/ref/ref_simple.txt
161
+ tests/extension/ref/ref_type_alias.txt
158
162
  tests/extension/ref/ref_type_checking_aliased.txt
159
163
  tests/extension/ref/ref_type_checking_gated.txt
164
+ tests/extension/ref/ref_type_param_defaults.txt
165
+ tests/extension/ref/ref_type_params.txt
166
+ tests/extension/ref/ref_union_return.txt
160
167
  tests/extension/ref/search_css_duplicates_removed.txt
161
168
  tests/extension/ref/self_type.txt
162
169
  tests/extension/ref/skip_file.txt
@@ -32,6 +32,13 @@ codeautolink_warn_on_no_backreference = False
32
32
  any_whitespace = re.compile(r"\s*")
33
33
  ref_tests = [(p.name, p) for p in Path(__file__).with_name("ref").glob("*.txt")]
34
34
  ref_xfails = {}
35
+ ref_min_python = {
36
+ "ref_type_alias.txt": (3, 12),
37
+ "ref_type_params.txt": (3, 12),
38
+ "ref_type_param_defaults.txt": (3, 13),
39
+ "ref_comprehension_unpack.txt": (3, 15),
40
+ "ref_lazy_import.txt": (3, 15),
41
+ }
35
42
 
36
43
 
37
44
  def assert_links(file: Path, links: list):
@@ -63,6 +70,8 @@ def test_references(name: str, file: Path, tmp_path: Path):
63
70
  """
64
71
  if ref_xfails.get(file.name, False):
65
72
  pytest.xfail("Expected to fail.")
73
+ if sys.version_info < ref_min_python.get(file.name, (0,)):
74
+ pytest.skip("Requires a newer Python version.")
66
75
 
67
76
  links, conf, index = file.read_text("utf-8").split("# split")
68
77
  links = links.strip().split("\n")
@@ -191,6 +200,38 @@ But edited.
191
200
  _sphinx_build(tmp_path, "html", {"another.rst": another2})
192
201
 
193
202
 
203
+ def test_build_twice_and_rename_toctree_entry(tmp_path: Path):
204
+ index = """
205
+ Test project
206
+ ------------
207
+
208
+ .. code:: python
209
+
210
+ import test_project
211
+ test_project.bar()
212
+
213
+ .. automodule:: test_project
214
+
215
+ .. toctree::
216
+
217
+ another
218
+ """
219
+ another = """
220
+ Another
221
+ -------
222
+ """
223
+ another2 = """
224
+ Renamed
225
+ -------
226
+ """
227
+ files = {"conf.py": default_conf, "index.rst": index, "another.rst": another}
228
+ _sphinx_build(tmp_path, "html", files)
229
+ # index is unchanged but rewritten, because its toctree changed
230
+ result_dir = _sphinx_build(tmp_path, "html", {"another.rst": another2})
231
+ assert "Renamed" in (result_dir / "index.html").read_text("utf-8")
232
+ assert_links(result_dir / "index.html", ["test_project", "test_project.bar"])
233
+
234
+
194
235
  def test_build_twice_and_delete_one_file(tmp_path: Path):
195
236
  conf = default_conf + "\nsuppress_warnings = ['toc.not_readable']"
196
237
  index = """
@@ -1,5 +1,8 @@
1
1
  print
2
2
  RuntimeError
3
+ number
4
+ int
5
+ number.bit_length
3
6
  # split
4
7
  extensions = [
5
8
  "sphinx.ext.intersphinx",
@@ -14,3 +17,5 @@ Test project
14
17
 
15
18
  print("Hi")
16
19
  raise RuntimeError("Bye")
20
+ number = int("1")
21
+ number.bit_length()
@@ -0,0 +1,25 @@
1
+ test_project
2
+ a.meth
3
+ test_project.mod_list
4
+ b.meth
5
+ test_project.mod_typing_list
6
+ c.meth
7
+ test_project.iter_foos
8
+ d.attr
9
+ test_project.mod_list
10
+ d.meth
11
+ # split
12
+ # split
13
+ Test project
14
+ ============
15
+
16
+ .. code:: python
17
+
18
+ import test_project
19
+
20
+ [a.meth() for a in test_project.mod_list]
21
+ {b.meth() for b in test_project.mod_typing_list}
22
+ (c.meth() for c in test_project.iter_foos())
23
+ {d.attr: 1 for d in test_project.mod_list for e in d.meth()}
24
+
25
+ .. automodule:: test_project
@@ -0,0 +1,17 @@
1
+ test_project
2
+ test_project.mod_list
3
+ test_project.mod_list
4
+ d
5
+ test_project.mod_list
6
+ # split
7
+ # split
8
+ Test project
9
+ ============
10
+
11
+ .. code:: python
12
+
13
+ import test_project
14
+ [*test_project.mod_list for _ in test_project.mod_list]
15
+ {**d for d in test_project.mod_list}
16
+
17
+ .. automodule:: test_project
@@ -0,0 +1,19 @@
1
+ test_project
2
+ test_project
3
+ Foo
4
+ test_project.Foo
5
+ Foo
6
+ # split
7
+ # split
8
+ Test project
9
+ ============
10
+
11
+ .. code:: python
12
+
13
+ lazy import test_project
14
+ lazy from test_project import Foo
15
+
16
+ test_project.Foo
17
+ Foo
18
+
19
+ .. automodule:: test_project
@@ -0,0 +1,22 @@
1
+ test_project
2
+ Alias
3
+ test_project.Foo
4
+ Alias.attr
5
+ test_project.Foo
6
+ test_project.Foo
7
+ # split
8
+ # split
9
+ Test project
10
+ ============
11
+
12
+ .. code:: python
13
+
14
+ import test_project
15
+
16
+ type Alias = test_project.Foo
17
+ Alias.attr
18
+
19
+ type Union = test_project.Foo | None
20
+ type Generic[T] = T | test_project.Foo
21
+
22
+ .. automodule:: test_project
@@ -0,0 +1,22 @@
1
+ test_project
2
+ test_project.Foo
3
+ test_project.Foo
4
+ test_project.Foo
5
+ # split
6
+ # split
7
+ Test project
8
+ ============
9
+
10
+ .. code:: python
11
+
12
+ import test_project
13
+
14
+ def f[T = test_project.Foo](arg: T):
15
+ pass
16
+
17
+ class C[T = test_project.Foo]:
18
+ pass
19
+
20
+ type Alias[T = test_project.Foo] = T
21
+
22
+ .. automodule:: test_project