sphinx-codeautolink 0.18.1__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 (199) hide show
  1. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/PKG-INFO +3 -3
  2. sphinx_codeautolink-0.20.0/docs/requirements.txt +6 -0
  3. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/about.rst +4 -1
  4. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/reference.rst +9 -0
  5. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/release_notes.rst +27 -0
  6. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/pyproject.toml +4 -2
  7. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/__init__.py +6 -2
  8. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/__init__.py +24 -17
  9. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/block.py +25 -14
  10. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/resolve.py +44 -5
  11. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/parse.py +39 -19
  12. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/PKG-INFO +3 -3
  13. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/SOURCES.txt +10 -0
  14. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/__init__.py +98 -0
  15. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_attribute_assignment.txt +17 -0
  16. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_builtins.txt +5 -0
  17. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_comprehension_target.txt +25 -0
  18. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_comprehension_unpack.txt +17 -0
  19. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_lazy_import.txt +19 -0
  20. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_type_alias.txt +22 -0
  21. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_type_param_defaults.txt +22 -0
  22. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_type_params.txt +23 -0
  23. sphinx_codeautolink-0.20.0/tests/extension/ref/ref_union_return.txt +20 -0
  24. sphinx_codeautolink-0.20.0/tests/extension/ref/self_type.txt +17 -0
  25. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/future_project.py +1 -1
  26. sphinx_codeautolink-0.20.0/tests/extension/src/self_type.py +20 -0
  27. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/test_project/__init__.py +1 -1
  28. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/parse/_util.py +0 -11
  29. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/parse/assign.py +42 -0
  30. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/parse/match.py +1 -2
  31. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/parse/scope.py +1 -2
  32. sphinx_codeautolink-0.18.1/docs/requirements.txt +0 -6
  33. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/LICENSE +0 -0
  34. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/MANIFEST.in +0 -0
  35. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/contributing.rst +0 -0
  36. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/404.rst +0 -0
  37. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/conf.py +0 -0
  38. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/example_library.rst +0 -0
  39. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/examples.rst +0 -0
  40. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/index.rst +0 -0
  41. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/lib.py +0 -0
  42. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/docs/src/static/custom.css +0 -0
  43. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/readme_pypi.rst +0 -0
  44. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/requirements/build +0 -0
  45. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/requirements/dev +0 -0
  46. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/requirements/docs +0 -0
  47. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/requirements/extras +0 -0
  48. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/requirements/tests +0 -0
  49. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/setup.cfg +0 -0
  50. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/backref.py +0 -0
  51. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/cache.py +0 -0
  52. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/directive.py +0 -0
  53. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/extension/translation.py +0 -0
  54. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/de/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  55. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/de/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  56. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/es/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  57. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/es/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  58. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/fi/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  59. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/fi/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  60. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/fr/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  61. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/fr/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  62. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/it/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  63. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/it/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  64. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/nl/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  65. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/nl/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  66. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/ru/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  67. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/sphinx-codeautolink.pot +0 -0
  68. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/locale/uk/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  69. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/static/sphinx-codeautolink.css +0 -0
  70. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink/warn.py +0 -0
  71. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/dependency_links.txt +0 -0
  72. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/requires.txt +0 -0
  73. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/src/sphinx_codeautolink.egg-info/top_level.txt +0 -0
  74. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/__init__.py +0 -0
  75. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/_check.py +0 -0
  76. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/concat_invalid.txt +0 -0
  77. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/custom_block_import_invalid.txt +0 -0
  78. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/custom_block_syntax_error.txt +0 -0
  79. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/failed_resolve_invalid_location.txt +0 -0
  80. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/failed_resolve_no_module.txt +0 -0
  81. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/failed_resolve_return_type.txt +0 -0
  82. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/match_block_warning.txt +0 -0
  83. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/missing_inventory.txt +0 -0
  84. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/no_backreference.txt +0 -0
  85. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/no_module_docs.txt +0 -0
  86. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/preface_invalid_arg.txt +0 -0
  87. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_import_star_invalid.txt +0 -0
  88. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_invalid_block_type.txt +0 -0
  89. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_invalid_syntax.txt +0 -0
  90. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_invalid_syntax_complex.txt +0 -0
  91. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/ref_ipython_non-python.txt +0 -0
  92. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/fail/skip_invalid.txt +0 -0
  93. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/class_mro_fix.txt +0 -0
  94. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_default.txt +0 -0
  95. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_off.txt +0 -0
  96. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_on_across_sections.txt +0 -0
  97. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_on_breaks.txt +0 -0
  98. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_section_breaks.txt +0 -0
  99. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/concat_section_returns_to_global.txt +0 -0
  100. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/custom_block.txt +0 -0
  101. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/custom_block_imported.txt +0 -0
  102. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/empty_project.txt +0 -0
  103. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/inventory_map_is_needed.txt +0 -0
  104. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/inventory_map_not_needed.txt +0 -0
  105. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_Python.txt +0 -0
  106. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_bazel.txt +0 -0
  107. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_default.txt +0 -0
  108. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_default_fail.txt +0 -0
  109. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_doctest.txt +0 -0
  110. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_doctest_empty_input.txt +0 -0
  111. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_extdoctest_doctest.txt +0 -0
  112. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_extdoctest_setup.txt +0 -0
  113. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_extdoctest_setup_wrong.txt +0 -0
  114. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_extdoctest_testcode.txt +0 -0
  115. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_highlight_language.txt +0 -0
  116. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_highlight_none.txt +0 -0
  117. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython.txt +0 -0
  118. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython3.txt +0 -0
  119. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython_directive.txt +0 -0
  120. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython_directive_comment.txt +0 -0
  121. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_ipython_syntax.txt +0 -0
  122. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_literal.txt +0 -0
  123. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_non_python_block.txt +0 -0
  124. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_py.txt +0 -0
  125. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_py3.txt +0 -0
  126. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_pycon.txt +0 -0
  127. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_pycon_implicit.txt +0 -0
  128. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_pyi.txt +0 -0
  129. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_python3.txt +0 -0
  130. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_sage.txt +0 -0
  131. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/lexer_starlark.txt +0 -0
  132. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/line_numbers.txt +0 -0
  133. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_concatenated.txt +0 -0
  134. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_consumed_non_python.txt +0 -0
  135. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_document.txt +0 -0
  136. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_global.txt +0 -0
  137. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_global_multiline.txt +0 -0
  138. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_global_overwritten.txt +0 -0
  139. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_multiline.txt +0 -0
  140. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_multiline_and_arg.txt +0 -0
  141. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_multiple.txt +0 -0
  142. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/preface_single.txt +0 -0
  143. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_assign_targets.txt +0 -0
  144. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_chain.txt +0 -0
  145. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_chain_call.txt +0 -0
  146. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_class_attr.txt +0 -0
  147. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_class_meth_returns_self.txt +0 -0
  148. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_class_type_attr.txt +0 -0
  149. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_decorator.txt +0 -0
  150. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_fluent_attrs.txt +0 -0
  151. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_fluent_call.txt +0 -0
  152. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_for_loop.txt +0 -0
  153. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_func_args.txt +0 -0
  154. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_func_no_module.txt +0 -0
  155. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_as.txt +0 -0
  156. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_from.txt +0 -0
  157. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_from_complex.txt +0 -0
  158. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_multiple.txt +0 -0
  159. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_multiple_libs.txt +0 -0
  160. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_star.txt +0 -0
  161. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_import_submodule.txt +0 -0
  162. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_imported_func.txt +0 -0
  163. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_imported_func_relocated.txt +0 -0
  164. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_inherited.txt +0 -0
  165. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_intersphinx_only.txt +0 -0
  166. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_invalid_func.txt +0 -0
  167. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_invalid_typehint.txt +0 -0
  168. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_module_attribute.txt +0 -0
  169. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_module_attribute_builtin.txt +0 -0
  170. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_module_attribute_class.txt +0 -0
  171. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_optional.txt +0 -0
  172. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_optional_future.txt +0 -0
  173. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_shadow_builtin.txt +0 -0
  174. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_simple.txt +0 -0
  175. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_type_checking_aliased.txt +0 -0
  176. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/ref_type_checking_gated.txt +0 -0
  177. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/search_css_duplicates_removed.txt +0 -0
  178. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_file.txt +0 -0
  179. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_next.txt +0 -0
  180. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_next_consumed_non_python.txt +0 -0
  181. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_off.txt +0 -0
  182. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/ref/skip_section.txt +0 -0
  183. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/class_mro_fix.py +0 -0
  184. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/parser_func.py +0 -0
  185. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/test_project/sub.py +0 -0
  186. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/type_checking/__init__.py +0 -0
  187. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/type_checking/foo.py +0 -0
  188. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/type_checking_aliased/__init__.py +0 -0
  189. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/src/type_checking_aliased/foo.py +0 -0
  190. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_autodoc_empty.txt +0 -0
  191. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_autodoc_links.txt +0 -0
  192. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_manual_collapse.txt +0 -0
  193. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_manual_empty.txt +0 -0
  194. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_manual_links.txt +0 -0
  195. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_manual_links_subsection.txt +0 -0
  196. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/extension/table/tab_no_table.txt +0 -0
  197. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/parse/__init__.py +0 -0
  198. {sphinx_codeautolink-0.18.1 → sphinx_codeautolink-0.20.0}/tests/parse/chain.py +0 -0
  199. {sphinx_codeautolink-0.18.1 → 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.18.1
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
@@ -55,6 +55,15 @@ Configuration
55
55
  Useful when objects are imported and documented somewhere else than their
56
56
  original location as advertised by ``__module__``.
57
57
 
58
+ .. confval:: codeautolink_disable_link_titles
59
+
60
+ Type: ``bool``. Don't add a ``title`` attribute, shown as a tooltip on
61
+ hover, to code links. By default the title contains the resolved location
62
+ of the linked object, but only when it differs from the code that is being
63
+ linked: hovering over ``instance.method()`` shows ``module.Class.method``,
64
+ while hovering over ``module.Class`` adds no tooltip.
65
+ Defaults to :code:`False`.
66
+
58
67
  .. confval:: codeautolink_warn_on_missing_inventory
59
68
 
60
69
  Type: ``bool``. Warn when an object cannot be found in
@@ -8,6 +8,33 @@ 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
+
26
+ 0.19.0 (2026-07-29)
27
+ -------------------
28
+ - Only add a hover title to links when the resolved location of the object
29
+ differs from the linked code, and add
30
+ :confval:`codeautolink_disable_link_titles`
31
+ to disable the titles altogether (:issue:`200`)
32
+ - Fix "Could not match transformation" warnings for assignments to
33
+ attributes such as ``thing.attr = 1`` (:issue:`201`)
34
+ - Resolve ``typing.Self`` return annotations, respecting inheritance so a
35
+ ``Self``-returning method accessed through a subclass or mixin resolves to
36
+ the accessing class rather than the class it's defined on (:issue:`147`)
37
+
11
38
  0.18.1 (2026-04-30)
12
39
  -------------------
13
40
  - Recognize aliased ``TYPE_CHECKING`` imports such as
@@ -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",
@@ -72,6 +72,7 @@ ignore = [
72
72
  extend-ignore = [
73
73
  "ARG001", # unused args needed in interfaces
74
74
  "ARG002", # unused args needed in interfaces
75
+ "CPY001", # no copyright notices needed
75
76
  "D107", # docstring missing is fine
76
77
  "D203", # recommended by ruff format
77
78
  "D212", # docstring format clash
@@ -80,6 +81,7 @@ extend-ignore = [
80
81
  "ISC001", # recommended by ruff format
81
82
  "PLR0913", # many arguments is fine
82
83
  "PLR0915", # many statements is fine
84
+ "PLR0917", # many arguments is fine
83
85
  ]
84
86
  extend-unsafe-fixes = ["F401"]
85
87
  isort.split-on-trailing-comma = false
@@ -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.18.1"
11
+ __version__ = "0.20.0"
12
12
 
13
13
 
14
14
  def setup(app: Sphinx):
@@ -34,6 +34,9 @@ def setup(app: Sphinx):
34
34
  app.add_config_value(
35
35
  "codeautolink_inventory_map", default={}, rebuild="html", types=[dict]
36
36
  )
37
+ app.add_config_value(
38
+ "codeautolink_disable_link_titles", default=False, rebuild="html", types=[bool]
39
+ )
37
40
  app.add_config_value(
38
41
  "codeautolink_warn_on_missing_inventory",
39
42
  default=False,
@@ -71,7 +74,8 @@ def setup(app: Sphinx):
71
74
  app.connect("env-purge-doc", state.purge_doc_from_environment)
72
75
  app.connect("env-updated", state.create_references)
73
76
  app.connect("doctree-resolved", state.generate_backref_tables)
74
- app.connect("build-finished", state.apply_links)
77
+ app.connect("html-page-context", state.apply_links)
78
+ app.connect("build-finished", state.write_cache)
75
79
 
76
80
  app.add_node(
77
81
  backref.DetailsNode, html=(backref.visit_details, backref.depart_details)
@@ -78,9 +78,9 @@ class SphinxCodeAutoLink:
78
78
  self.warn_no_backreference = None
79
79
  self.warn_default_parse_fail = None
80
80
  self.highlight_lang = None
81
+ self.disable_link_titles = None
81
82
 
82
83
  # Populated once
83
- self.outdated_docs: set[str] = set()
84
84
  self.inventory = {}
85
85
  self.code_refs: dict[str, list[CodeExample]] = {}
86
86
 
@@ -97,7 +97,6 @@ class SphinxCodeAutoLink:
97
97
  self.cache = DataCache(app.doctreedir, app.srcdir)
98
98
  self.cache.read()
99
99
  app.env.sphinx_codeautolink_transforms = self.cache.transforms
100
- self.outdated_docs = {str(Path(d)) for d in app.builder.get_outdated_docs()}
101
100
  self.custom_blocks = app.config.codeautolink_custom_blocks
102
101
  for k, v in self.custom_blocks.items():
103
102
  if isinstance(v, str):
@@ -112,6 +111,7 @@ class SphinxCodeAutoLink:
112
111
  app.config.codeautolink_warn_on_default_parse_fail
113
112
  )
114
113
  self.highlight_lang = app.config.highlight_language
114
+ self.disable_link_titles = app.config.codeautolink_disable_link_titles
115
115
 
116
116
  # Append static resources path so references in setup() are valid
117
117
  app.config.html_static_path.append(
@@ -279,23 +279,30 @@ class SphinxCodeAutoLink:
279
279
  return None
280
280
 
281
281
  @print_exceptions()
282
- def apply_links(self, app, exception) -> None:
283
- """Apply links to HTML output and write refs file."""
284
- 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:
285
285
  return
286
286
 
287
- for doc, transforms in self.cache.transforms.items():
288
- if not transforms or str(Path(doc)) not in self.outdated_docs:
289
- continue
290
- link_html(
291
- doc,
292
- app.outdir,
293
- transforms,
294
- self.inventory,
295
- self.custom_blocks,
296
- self.search_css_classes,
297
- builder_name=app.builder.name,
298
- )
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
299
306
 
300
307
  self.cache.write()
301
308
 
@@ -369,23 +369,32 @@ class CodeBlockAnalyser(nodes.SparseNodeVisitor):
369
369
  )
370
370
 
371
371
 
372
+ def format_title(location: str, text: str) -> str:
373
+ """Format the title attribute of a link, empty if it wouldn't add information."""
374
+ code = re.sub(r"\s+", "", BeautifulSoup(text, "html.parser").get_text())
375
+ if code == location:
376
+ return ""
377
+ return f' title="{location}"'
378
+
379
+
372
380
  def link_html(
373
381
  document: str,
374
- out_dir: str,
382
+ html: str,
375
383
  transforms: list[SourceTransform],
376
384
  inventory: dict,
377
385
  custom_blocks: dict,
378
386
  search_css_classes: list,
379
387
  builder_name: str = "html",
380
- ) -> None:
381
- """Inject links to code blocks on disk."""
388
+ *,
389
+ disable_link_titles: bool,
390
+ ) -> str:
391
+ """Inject links to code blocks in the HTML of a document."""
382
392
  if builder_name == "dirhtml" and Path(document).name != "index":
383
- html_file = Path(out_dir) / document / "index.html"
393
+ html_file = Path(document) / "index.html"
384
394
  else:
385
- html_file = Path(out_dir) / (document + ".html")
395
+ html_file = Path(document + ".html")
386
396
 
387
- text = html_file.read_text("utf-8")
388
- soup = BeautifulSoup(text, "html.parser")
397
+ soup = BeautifulSoup(html, "html.parser")
389
398
 
390
399
  block_types = BUILTIN_BLOCKS.keys() | custom_blocks.keys()
391
400
  classes = [f"highlight-{t}" for t in block_types] + ["doctest"]
@@ -398,11 +407,9 @@ def link_html(
398
407
  blocks = sorted(unique_blocks, key=lambda b: b.sourceline)
399
408
  inners = [block.select("div > pre")[0] for block in blocks]
400
409
 
401
- up_lvls = len(html_file.relative_to(out_dir).parents) - 1
410
+ up_lvls = len(html_file.parents) - 1
402
411
  local_prefix = "../" * up_lvls
403
- link_pattern = (
404
- '<a href="{link}" title="{title}" class="sphinx-codeautolink-a">{text}</a>'
405
- )
412
+ link_pattern = '<a href="{link}"{title} class="sphinx-codeautolink-a">{text}</a>'
406
413
 
407
414
  for trans in transforms:
408
415
  for ix in range(len(inners)):
@@ -447,15 +454,19 @@ def link_html(
447
454
  location = inventory[name.resolved_location]
448
455
  if not any(location.startswith(s) for s in ("http://", "https://")):
449
456
  location = local_prefix + location
450
- link = link_pattern.format(
451
- link=location, title=name.resolved_location, text=selection[start:end]
457
+ text = selection[start:end]
458
+ title = (
459
+ ""
460
+ if disable_link_titles
461
+ else format_title(name.resolved_location, text)
452
462
  )
463
+ link = link_pattern.format(link=location, title=title, text=text)
453
464
  transformed = selection[:start] + link + selection[end:]
454
465
  lines[begin_line : end_line + 1] = transformed.split("\n")
455
466
 
456
467
  inner.replace_with(BeautifulSoup("\n".join(lines), "html.parser"))
457
468
 
458
- html_file.write_text(str(soup), "utf-8")
469
+ return str(soup)
459
470
 
460
471
 
461
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,7 +13,7 @@ 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
 
@@ -72,7 +73,9 @@ def resolve_location(chain: Name, inventory) -> str:
72
73
  call_value(cursor)
73
74
  elif terminator == NameBreak.for_iter:
74
75
  iter_value(cursor)
75
- 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__ + ".")
76
79
 
77
80
 
78
81
  class CouldNotResolve(Exception): # noqa: N818
@@ -87,11 +90,25 @@ class Cursor:
87
90
  value: Any
88
91
  instance: bool
89
92
  annotation: Any = None
93
+ # The live object/class this cursor's value was accessed on, e.g. the
94
+ # receiver of a bound method. Used to resolve `Self` return annotations
95
+ # to the accessing class rather than the (possibly different, e.g. a
96
+ # mixin) class the method happens to be defined on. Unlike `location`,
97
+ # this is never rewritten by the MRO fallback below, so it reflects the
98
+ # true runtime receiver even when the naive `location` doesn't resolve.
99
+ receiver: Any = None
90
100
 
91
101
 
92
102
  def make_cursor(components: list[str]) -> tuple[list[str], Cursor]:
93
103
  """Divide components into module and rest, create cursor for following the rest."""
94
- 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)
95
112
  location = ".".join(components[:index])
96
113
  return components[index:], Cursor(location, value, instance=False)
97
114
 
@@ -121,6 +138,7 @@ def locate_type(cursor: Cursor, components: tuple[str, ...], inventory) -> Curso
121
138
  getattr(previous.value, component, None),
122
139
  previous.instance,
123
140
  annotation=annotation,
141
+ receiver=previous.value,
124
142
  )
125
143
 
126
144
  if cursor.value is None:
@@ -163,6 +181,21 @@ def call_value(cursor: Cursor) -> None:
163
181
  raise CouldNotResolve # not a function either
164
182
 
165
183
  annotation = get_return_annotation(cursor.value)
184
+ if Self is not None and annotation is Self and cursor.receiver is not None:
185
+ # `Self` refers to whichever class/instance the method was accessed
186
+ # on, which is not necessarily the class it's defined on (e.g. a
187
+ # mixin). Use the receiver rather than re-deriving the owner from
188
+ # `cursor.location`, since that string may have been rewritten to
189
+ # the *defining* class by the MRO fallback above.
190
+ owner_value = cursor.receiver
191
+ if not isclass(owner_value):
192
+ owner_value = type(owner_value)
193
+ cursor.value = owner_value
194
+ cursor.location = fully_qualified_name(owner_value)
195
+ cursor.instance = True
196
+ cursor.annotation = annotation
197
+ return
198
+
166
199
  type_ = origin_type(annotation)
167
200
  if not isinstance(type_, type):
168
201
  msg = f"Unable to follow return annotation of {annotation!r}."
@@ -201,7 +234,11 @@ def strip_optional(annotation: Any) -> Any:
201
234
 
202
235
  def origin_type(annotation: Any) -> Any:
203
236
  """Return underlying type of an annotation (e.g. ``list`` from ``list[Foo]``)."""
204
- 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
205
242
 
206
243
 
207
244
  def unwrap_iterable(annotation: Any) -> type | None:
@@ -227,7 +264,9 @@ def get_return_annotation(func: Callable) -> Any:
227
264
 
228
265
 
229
266
  def fully_qualified_name(thing: type | Callable) -> str:
230
- """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__
231
270
  return thing.__module__ + "." + thing.__qualname__
232
271
 
233
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"
@@ -286,15 +286,17 @@ class ImportTrackerVisitor(ast.NodeVisitor):
286
286
  if target is None:
287
287
  return
288
288
 
289
- if len(target.components) == 1:
290
- comp = target.components[0]
291
- if value is None:
292
- self.overwrite_name(comp.name)
293
- else:
294
- self.assign_name(comp.name, value.components)
295
- self._create_access(target.components)
289
+ if len(target.components) != 1:
290
+ # Dotted targets don't assign to the current scope, and their access
291
+ # was already resolved when the access chain was visited.
292
+ return
293
+
294
+ comp = target.components[0]
295
+ if value is None:
296
+ self.overwrite_name(comp.name)
296
297
  else:
297
- self.resolve_pending_access(target)
298
+ self.assign_name(comp.name, value.components)
299
+ self._create_access(target.components)
298
300
 
299
301
  def create_simple_access(self, name: str, lineno: int) -> None:
300
302
  """Create single-component access to scope."""
@@ -436,6 +438,18 @@ class ImportTrackerVisitor(ast.NodeVisitor):
436
438
  target = self.visit(node.target)
437
439
  return Assignment([target], value)
438
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
+
439
453
  def visit_AugAssign(self, node: ast.AugAssign) -> None:
440
454
  """Visit an AugAssign node."""
441
455
  self.visit(node.value)
@@ -499,8 +513,8 @@ class ImportTrackerVisitor(ast.NodeVisitor):
499
513
  """Delegate to sync for."""
500
514
  self.visit_For(node)
501
515
 
502
- def visit_For(self, node: ast.For | ast.AsyncFor) -> None:
503
- """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."""
504
518
  iter_pending = self.visit(node.iter)
505
519
 
506
520
  if (
@@ -508,11 +522,15 @@ class ImportTrackerVisitor(ast.NodeVisitor):
508
522
  and iter_pending.components
509
523
  and isinstance(node.target, ast.Name)
510
524
  ):
511
- marker = Component(NameBreak.for_iter.value, *linenos(node), "load")
525
+ marker = Component(NameBreak.for_iter.value, *linenos(node.target), "load")
512
526
  self.assign_name(node.target.id, [*iter_pending.components, marker])
513
527
  else:
514
528
  self.visit(node.target)
515
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
+
516
534
  for n in node.body:
517
535
  self.visit(n)
518
536
  for n in node.orelse:
@@ -526,6 +544,7 @@ class ImportTrackerVisitor(ast.NodeVisitor):
526
544
  self.visit(base)
527
545
  for kw in node.keywords:
528
546
  self.visit(kw)
547
+ self.visit_type_params(node)
529
548
 
530
549
  self.overwrite_name(node.name)
531
550
  self.pseudo_scopes_stack.append(self.pseudo_scopes_stack[0].copy())
@@ -550,6 +569,7 @@ class ImportTrackerVisitor(ast.NodeVisitor):
550
569
  if d is None:
551
570
  continue
552
571
  self.visit(d)
572
+ self.visit_type_params(node)
553
573
  args = self._get_args(node.args)
554
574
  args += [node.args.vararg, node.args.kwarg]
555
575
 
@@ -608,17 +628,17 @@ class ImportTrackerVisitor(ast.NodeVisitor):
608
628
  self.visit_generic_comp([node.elt], node.generators)
609
629
 
610
630
  def visit_DictComp(self, node: ast.DictComp) -> None:
611
- """Delegate to generic comp."""
612
- 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)
613
634
 
614
635
  def visit_GeneratorExp(self, node: ast.GeneratorExp) -> None:
615
636
  """Delegate to generic comp."""
616
637
  self.visit_generic_comp([node.elt], node.generators)
617
638
 
618
639
  def visit_comprehension(self, node: ast.comprehension) -> None:
619
- """Swap node order."""
620
- self.visit(node.iter)
621
- self.visit(node.target)
640
+ """Swap node order and resolve iterators."""
641
+ self.bind_iter_target(node)
622
642
  for f in node.ifs:
623
643
  self.visit(f)
624
644
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sphinx-codeautolink
3
- Version: 0.18.1
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
@@ -122,12 +122,15 @@ tests/extension/ref/preface_multiline_and_arg.txt
122
122
  tests/extension/ref/preface_multiple.txt
123
123
  tests/extension/ref/preface_single.txt
124
124
  tests/extension/ref/ref_assign_targets.txt
125
+ tests/extension/ref/ref_attribute_assignment.txt
125
126
  tests/extension/ref/ref_builtins.txt
126
127
  tests/extension/ref/ref_chain.txt
127
128
  tests/extension/ref/ref_chain_call.txt
128
129
  tests/extension/ref/ref_class_attr.txt
129
130
  tests/extension/ref/ref_class_meth_returns_self.txt
130
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
131
134
  tests/extension/ref/ref_decorator.txt
132
135
  tests/extension/ref/ref_fluent_attrs.txt
133
136
  tests/extension/ref/ref_fluent_call.txt
@@ -147,6 +150,7 @@ tests/extension/ref/ref_inherited.txt
147
150
  tests/extension/ref/ref_intersphinx_only.txt
148
151
  tests/extension/ref/ref_invalid_func.txt
149
152
  tests/extension/ref/ref_invalid_typehint.txt
153
+ tests/extension/ref/ref_lazy_import.txt
150
154
  tests/extension/ref/ref_module_attribute.txt
151
155
  tests/extension/ref/ref_module_attribute_builtin.txt
152
156
  tests/extension/ref/ref_module_attribute_class.txt
@@ -154,9 +158,14 @@ tests/extension/ref/ref_optional.txt
154
158
  tests/extension/ref/ref_optional_future.txt
155
159
  tests/extension/ref/ref_shadow_builtin.txt
156
160
  tests/extension/ref/ref_simple.txt
161
+ tests/extension/ref/ref_type_alias.txt
157
162
  tests/extension/ref/ref_type_checking_aliased.txt
158
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
159
167
  tests/extension/ref/search_css_duplicates_removed.txt
168
+ tests/extension/ref/self_type.txt
160
169
  tests/extension/ref/skip_file.txt
161
170
  tests/extension/ref/skip_next.txt
162
171
  tests/extension/ref/skip_next_consumed_non_python.txt
@@ -165,6 +174,7 @@ tests/extension/ref/skip_section.txt
165
174
  tests/extension/src/class_mro_fix.py
166
175
  tests/extension/src/future_project.py
167
176
  tests/extension/src/parser_func.py
177
+ tests/extension/src/self_type.py
168
178
  tests/extension/src/test_project/__init__.py
169
179
  tests/extension/src/test_project/sub.py
170
180
  tests/extension/src/type_checking/__init__.py