sphinx-codeautolink 0.17.5__tar.gz → 0.18.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 (186) hide show
  1. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/PKG-INFO +2 -1
  2. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/about.rst +22 -0
  3. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/release_notes.rst +9 -0
  4. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/pyproject.toml +1 -0
  5. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/__init__.py +1 -1
  6. sphinx_codeautolink-0.18.0/src/sphinx_codeautolink/extension/resolve.py +307 -0
  7. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/parse.py +14 -3
  8. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink.egg-info/PKG-INFO +2 -1
  9. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink.egg-info/SOURCES.txt +7 -0
  10. sphinx_codeautolink-0.18.0/tests/extension/ref/ref_for_loop.txt +26 -0
  11. sphinx_codeautolink-0.18.0/tests/extension/ref/ref_module_attribute.txt +13 -0
  12. sphinx_codeautolink-0.18.0/tests/extension/ref/ref_module_attribute_builtin.txt +13 -0
  13. sphinx_codeautolink-0.18.0/tests/extension/ref/ref_module_attribute_class.txt +13 -0
  14. sphinx_codeautolink-0.18.0/tests/extension/ref/ref_type_checking_gated.txt +15 -0
  15. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/src/test_project/__init__.py +23 -0
  16. sphinx_codeautolink-0.18.0/tests/extension/src/type_checking/__init__.py +19 -0
  17. sphinx_codeautolink-0.18.0/tests/extension/src/type_checking/foo.py +4 -0
  18. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/parse/assign.py +25 -1
  19. sphinx_codeautolink-0.17.5/src/sphinx_codeautolink/extension/resolve.py +0 -178
  20. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/LICENSE +0 -0
  21. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/MANIFEST.in +0 -0
  22. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/contributing.rst +0 -0
  23. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/requirements.txt +0 -0
  24. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/404.rst +0 -0
  25. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/conf.py +0 -0
  26. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/example_library.rst +0 -0
  27. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/examples.rst +0 -0
  28. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/index.rst +0 -0
  29. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/lib.py +0 -0
  30. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/reference.rst +0 -0
  31. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/docs/src/static/custom.css +0 -0
  32. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/readme_pypi.rst +0 -0
  33. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/requirements/build +0 -0
  34. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/requirements/dev +0 -0
  35. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/requirements/docs +0 -0
  36. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/requirements/extras +0 -0
  37. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/requirements/tests +0 -0
  38. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/setup.cfg +0 -0
  39. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/extension/__init__.py +0 -0
  40. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/extension/backref.py +0 -0
  41. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/extension/block.py +0 -0
  42. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/extension/cache.py +0 -0
  43. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/extension/directive.py +0 -0
  44. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/extension/translation.py +0 -0
  45. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/de/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  46. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/de/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  47. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/es/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  48. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/es/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  49. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/fi/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  50. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/fi/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  51. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/fr/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  52. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/fr/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  53. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/it/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  54. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/it/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  55. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/nl/LC_MESSAGES/sphinx-codeautolink.mo +0 -0
  56. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/nl/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  57. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/ru/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  58. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/sphinx-codeautolink.pot +0 -0
  59. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/locale/uk/LC_MESSAGES/sphinx-codeautolink.po +0 -0
  60. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/static/sphinx-codeautolink.css +0 -0
  61. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink/warn.py +0 -0
  62. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink.egg-info/dependency_links.txt +0 -0
  63. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink.egg-info/requires.txt +0 -0
  64. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/src/sphinx_codeautolink.egg-info/top_level.txt +0 -0
  65. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/__init__.py +0 -0
  66. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/__init__.py +0 -0
  67. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/_check.py +0 -0
  68. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/concat_invalid.txt +0 -0
  69. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/custom_block_import_invalid.txt +0 -0
  70. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/custom_block_syntax_error.txt +0 -0
  71. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/failed_resolve_invalid_location.txt +0 -0
  72. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/failed_resolve_no_module.txt +0 -0
  73. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/failed_resolve_return_type.txt +0 -0
  74. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/match_block_warning.txt +0 -0
  75. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/missing_inventory.txt +0 -0
  76. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/no_backreference.txt +0 -0
  77. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/no_module_docs.txt +0 -0
  78. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/preface_invalid_arg.txt +0 -0
  79. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/ref_import_star_invalid.txt +0 -0
  80. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/ref_invalid_block_type.txt +0 -0
  81. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/ref_invalid_syntax.txt +0 -0
  82. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/ref_invalid_syntax_complex.txt +0 -0
  83. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/ref_ipython_non-python.txt +0 -0
  84. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/fail/skip_invalid.txt +0 -0
  85. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/class_mro_fix.txt +0 -0
  86. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/concat_default.txt +0 -0
  87. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/concat_off.txt +0 -0
  88. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/concat_on_across_sections.txt +0 -0
  89. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/concat_on_breaks.txt +0 -0
  90. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/concat_section_breaks.txt +0 -0
  91. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/concat_section_returns_to_global.txt +0 -0
  92. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/custom_block.txt +0 -0
  93. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/custom_block_imported.txt +0 -0
  94. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/empty_project.txt +0 -0
  95. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/inventory_map_is_needed.txt +0 -0
  96. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/inventory_map_not_needed.txt +0 -0
  97. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_Python.txt +0 -0
  98. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_bazel.txt +0 -0
  99. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_default.txt +0 -0
  100. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_default_fail.txt +0 -0
  101. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_doctest.txt +0 -0
  102. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_doctest_empty_input.txt +0 -0
  103. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_extdoctest_doctest.txt +0 -0
  104. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_extdoctest_setup.txt +0 -0
  105. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_extdoctest_setup_wrong.txt +0 -0
  106. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_extdoctest_testcode.txt +0 -0
  107. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_highlight_language.txt +0 -0
  108. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_highlight_none.txt +0 -0
  109. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_ipython.txt +0 -0
  110. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_ipython3.txt +0 -0
  111. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_ipython_directive.txt +0 -0
  112. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_ipython_directive_comment.txt +0 -0
  113. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_ipython_syntax.txt +0 -0
  114. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_literal.txt +0 -0
  115. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_non_python_block.txt +0 -0
  116. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_py.txt +0 -0
  117. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_py3.txt +0 -0
  118. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_pycon.txt +0 -0
  119. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_pycon_implicit.txt +0 -0
  120. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_pyi.txt +0 -0
  121. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_python3.txt +0 -0
  122. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_sage.txt +0 -0
  123. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/lexer_starlark.txt +0 -0
  124. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/line_numbers.txt +0 -0
  125. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_concatenated.txt +0 -0
  126. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_consumed_non_python.txt +0 -0
  127. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_document.txt +0 -0
  128. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_global.txt +0 -0
  129. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_global_multiline.txt +0 -0
  130. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_global_overwritten.txt +0 -0
  131. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_multiline.txt +0 -0
  132. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_multiline_and_arg.txt +0 -0
  133. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_multiple.txt +0 -0
  134. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/preface_single.txt +0 -0
  135. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_assign_targets.txt +0 -0
  136. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_builtins.txt +0 -0
  137. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_chain.txt +0 -0
  138. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_chain_call.txt +0 -0
  139. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_class_attr.txt +0 -0
  140. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_class_meth_returns_self.txt +0 -0
  141. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_class_type_attr.txt +0 -0
  142. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_decorator.txt +0 -0
  143. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_fluent_attrs.txt +0 -0
  144. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_fluent_call.txt +0 -0
  145. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_func_args.txt +0 -0
  146. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_func_no_module.txt +0 -0
  147. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_import_as.txt +0 -0
  148. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_import_from.txt +0 -0
  149. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_import_from_complex.txt +0 -0
  150. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_import_multiple.txt +0 -0
  151. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_import_multiple_libs.txt +0 -0
  152. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_import_star.txt +0 -0
  153. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_import_submodule.txt +0 -0
  154. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_imported_func.txt +0 -0
  155. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_imported_func_relocated.txt +0 -0
  156. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_inherited.txt +0 -0
  157. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_intersphinx_only.txt +0 -0
  158. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_invalid_func.txt +0 -0
  159. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_invalid_typehint.txt +0 -0
  160. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_optional.txt +0 -0
  161. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_optional_future.txt +0 -0
  162. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_shadow_builtin.txt +0 -0
  163. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/ref_simple.txt +0 -0
  164. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/search_css_duplicates_removed.txt +0 -0
  165. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/skip_file.txt +0 -0
  166. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/skip_next.txt +0 -0
  167. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/skip_next_consumed_non_python.txt +0 -0
  168. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/skip_off.txt +0 -0
  169. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/ref/skip_section.txt +0 -0
  170. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/src/class_mro_fix.py +0 -0
  171. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/src/future_project.py +0 -0
  172. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/src/parser_func.py +0 -0
  173. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/src/test_project/sub.py +0 -0
  174. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/table/tab_autodoc_empty.txt +0 -0
  175. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/table/tab_autodoc_links.txt +0 -0
  176. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/table/tab_manual_collapse.txt +0 -0
  177. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/table/tab_manual_empty.txt +0 -0
  178. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/table/tab_manual_links.txt +0 -0
  179. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/table/tab_manual_links_subsection.txt +0 -0
  180. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/extension/table/tab_no_table.txt +0 -0
  181. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/parse/__init__.py +0 -0
  182. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/parse/_util.py +0 -0
  183. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/parse/chain.py +0 -0
  184. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/parse/match.py +0 -0
  185. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tests/parse/scope.py +0 -0
  186. {sphinx_codeautolink-0.17.5 → sphinx_codeautolink-0.18.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sphinx-codeautolink
3
- Version: 0.17.5
3
+ Version: 0.18.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>
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
22
23
  Classifier: Topic :: Documentation
23
24
  Classifier: Topic :: Documentation :: Sphinx
24
25
  Classifier: Topic :: Software Development :: Documentation
@@ -85,6 +85,28 @@ The extension parses code blocks in the ``doctree-read`` Sphinx event.
85
85
  The priority is set to 490 to catch nodes removed by ``sphinx.ext.doctest``
86
86
  (priority 500). In other cases the priority of the extension is default.
87
87
 
88
+ Type checking blocks
89
+ ********************
90
+ To resolve annotations that reference names imported under
91
+ ``if TYPE_CHECKING:``, the extension re-executes the bodies of those gated
92
+ blocks in the importing module's own namespace the first time it inspects
93
+ that module. Without this step, ``typing.get_type_hints`` would fail with
94
+ ``NameError`` because, at runtime, ``TYPE_CHECKING`` is ``False`` and the
95
+ gated names are never bound.
96
+
97
+ A few things to be aware of:
98
+
99
+ - Only top-level ``if`` blocks whose condition is ``TYPE_CHECKING`` or
100
+ ``MYPY`` (as a bare name or attribute access, e.g. ``typing.TYPE_CHECKING``)
101
+ are recognised. The condition is matched by AST shape, not evaluated.
102
+ - The original module objects are mutated in place:
103
+ names that would normally only exist for type checkers become real
104
+ attributes on the module.
105
+ - Bodies are executed with the equivalent of ``exec`` in the module's
106
+ globals. If execution fails, for example due to a cyclic import or
107
+ a missing optional dependency, that block is silently skipped and the rest
108
+ of the module continues to work.
109
+
88
110
  Copying code blocks
89
111
  -------------------
90
112
  If you feel like code links make copying code a bit more difficult,
@@ -8,6 +8,15 @@ These release notes are based on
8
8
  sphinx-codeautolink adheres to
9
9
  `Semantic Versioning <https://semver.org>`_.
10
10
 
11
+ 0.18.0 (2026-04-25)
12
+ -------------------
13
+ - Support module attributes and class aliases (:issue:`65`)
14
+ - Resolve for-loop iterables into targets. ``for target in lib.iterable():``
15
+ now links ``target.method()`` in the loop body (:issue:`196`)
16
+ - Resolve return annotations that reference names imported inside
17
+ ``if TYPE_CHECKING:`` and similar blocks (:issue:`197`)
18
+ - Support Python 3.14 officially (:issue:`198`)
19
+
11
20
  0.17.5 (2025-07-09)
12
21
  -------------------
13
22
  - Add ``Python`` to default lexers (:issue:`194`)
@@ -30,6 +30,7 @@ classifiers = [
30
30
  "Programming Language :: Python :: 3.11",
31
31
  "Programming Language :: Python :: 3.12",
32
32
  "Programming Language :: Python :: 3.13",
33
+ "Programming Language :: Python :: 3.14",
33
34
  "Topic :: Documentation",
34
35
  "Topic :: Documentation :: Sphinx",
35
36
  "Topic :: Software Development :: Documentation",
@@ -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.17.5"
11
+ __version__ = "0.18.0"
12
12
 
13
13
 
14
14
  def setup(app: Sphinx):
@@ -0,0 +1,307 @@
1
+ """Resolve import locations and type hints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ast
6
+ import inspect
7
+ from collections import abc
8
+ from collections.abc import Callable
9
+ from contextlib import suppress
10
+ from dataclasses import dataclass
11
+ from functools import cache
12
+ from importlib import import_module
13
+ from inspect import isclass, ismodule, isroutine
14
+ from types import ModuleType, UnionType
15
+ from typing import Any, Union, get_type_hints
16
+
17
+ from sphinx_codeautolink.parse import Name, NameBreak
18
+
19
+ # Containers whose first generic argument is the element type produced
20
+ # by iteration. ``tuple`` only fits ``tuple[T, ...]``; for mixed tuples
21
+ # like ``tuple[int, str]`` we pick the first arg, which may be wrong.
22
+ ITERABLE_ORIGINS = frozenset(
23
+ {
24
+ abc.Iterable,
25
+ abc.Iterator,
26
+ abc.Generator,
27
+ abc.AsyncIterable,
28
+ abc.AsyncIterator,
29
+ abc.AsyncGenerator,
30
+ abc.Collection,
31
+ abc.Sequence,
32
+ abc.MutableSequence,
33
+ abc.Set,
34
+ abc.MutableSet,
35
+ abc.Mapping,
36
+ abc.MutableMapping,
37
+ list,
38
+ set,
39
+ frozenset,
40
+ tuple,
41
+ dict,
42
+ }
43
+ )
44
+
45
+
46
+ def resolve_location(chain: Name, inventory) -> str:
47
+ """Find the final type that a name refers to."""
48
+ segments: list[tuple[list[str], NameBreak | None]] = []
49
+ current: list[str] = []
50
+ for comp in chain.import_components:
51
+ if comp in (NameBreak.call, NameBreak.for_iter):
52
+ segments.append((current, NameBreak(comp)))
53
+ current = []
54
+ else:
55
+ current.append(comp)
56
+ segments.append((current, None))
57
+
58
+ cursor = None
59
+ last = len(segments) - 1
60
+ for i, (segment, terminator) in enumerate(segments):
61
+ comps = segment
62
+ if cursor is None:
63
+ try:
64
+ comps, cursor = make_cursor(comps)
65
+ except CouldNotResolve:
66
+ if i == last:
67
+ # Last ditch effort to locate based on the string only
68
+ return ".".join(comps)
69
+ raise
70
+ cursor = locate_type(cursor, tuple(comps), inventory)
71
+ if terminator == NameBreak.call:
72
+ call_value(cursor)
73
+ elif terminator == NameBreak.for_iter:
74
+ iter_value(cursor)
75
+ return cursor.location if cursor is not None else None
76
+
77
+
78
+ class CouldNotResolve(Exception): # noqa: N818
79
+ """Could not resolve type to inventory."""
80
+
81
+
82
+ @dataclass
83
+ class Cursor:
84
+ """Cursor to follow a component path to the final type."""
85
+
86
+ location: str
87
+ value: Any
88
+ instance: bool
89
+ annotation: Any = None
90
+
91
+
92
+ def make_cursor(components: list[str]) -> tuple[list[str], Cursor]:
93
+ """Divide components into module and rest, create cursor for following the rest."""
94
+ value, index = closest_module(tuple(components))
95
+ location = ".".join(components[:index])
96
+ return components[index:], Cursor(location, value, instance=False)
97
+
98
+
99
+ def locate_type(cursor: Cursor, components: tuple[str, ...], inventory) -> Cursor:
100
+ """Find type hint and resolve to new location."""
101
+ previous = cursor
102
+ for i, component in enumerate(components):
103
+ previous = cursor
104
+
105
+ # When descending through an instance or alias
106
+ # try to normalise to the original type if possible
107
+ if previous.value is not None and not (
108
+ isclass(previous.value)
109
+ or ismodule(previous.value)
110
+ or isroutine(previous.value)
111
+ ):
112
+ with suppress(AttributeError, TypeError):
113
+ previous.value = type(previous.value)
114
+ previous.location = fully_qualified_name(previous.value)
115
+
116
+ annotation = None
117
+ with suppress(NameError, TypeError):
118
+ annotation = get_type_hints(previous.value).get(component)
119
+ cursor = Cursor(
120
+ previous.location + "." + component,
121
+ getattr(previous.value, component, None),
122
+ previous.instance,
123
+ annotation=annotation,
124
+ )
125
+
126
+ if cursor.value is None:
127
+ msg = f"{cursor.location} does not exist."
128
+ raise CouldNotResolve(msg)
129
+
130
+ if isclass(cursor.value):
131
+ cursor.instance = False
132
+
133
+ if isclass(cursor.value) or (
134
+ isroutine(cursor.value) and cursor.location not in inventory
135
+ ):
136
+ # Normalise location of type or imported function
137
+ # If odd construct encountered: don't try to be clever but continue
138
+ with suppress(AttributeError, TypeError):
139
+ cursor.location = fully_qualified_name(cursor.value)
140
+
141
+ # Check bases if member not found in current class
142
+ if isclass(previous.value) and cursor.location not in inventory:
143
+ for val in previous.value.__mro__[1:]:
144
+ name = fully_qualified_name(val)
145
+ if name + "." + component in inventory:
146
+ previous.location = name
147
+ return locate_type(previous, components[i:], inventory)
148
+
149
+ return cursor
150
+
151
+
152
+ def call_value(cursor: Cursor) -> None:
153
+ """Call class, instance or function."""
154
+ if isclass(cursor.value) and not cursor.instance:
155
+ # class definition: "instantiate" class
156
+ cursor.instance = True
157
+ return
158
+
159
+ if callable(cursor.value) and not isroutine(cursor.value):
160
+ # callable class instance
161
+ cursor.value = cursor.value.__call__
162
+ elif not isroutine(cursor.value):
163
+ raise CouldNotResolve # not a function either
164
+
165
+ annotation = get_return_annotation(cursor.value)
166
+ type_ = origin_type(annotation)
167
+ if not isinstance(type_, type):
168
+ msg = f"Unable to follow return annotation of {annotation!r}."
169
+ raise CouldNotResolve(msg)
170
+ cursor.value = type_
171
+ cursor.location = fully_qualified_name(type_)
172
+ cursor.instance = True
173
+ cursor.annotation = annotation
174
+
175
+
176
+ def iter_value(cursor: Cursor) -> None:
177
+ """Unwrap the iterable cursor points to into its element type."""
178
+ element = unwrap_iterable(strip_optional(cursor.annotation))
179
+ if not isinstance(element, type):
180
+ msg = (
181
+ f"Unable to unwrap iterable element type of"
182
+ f" {get_name_for_debugging(cursor.value)}."
183
+ )
184
+ raise CouldNotResolve(msg)
185
+ cursor.value = element
186
+ cursor.location = fully_qualified_name(element)
187
+ cursor.instance = True
188
+ cursor.annotation = None
189
+
190
+
191
+ def strip_optional(annotation: Any) -> Any:
192
+ """Reduce ``Optional[T]`` / ``T | None`` to ``T``; otherwise return as-is."""
193
+ origin = getattr(annotation, "__origin__", None)
194
+ args = getattr(annotation, "__args__", None)
195
+ if (origin is Union or isinstance(annotation, UnionType)) and args:
196
+ non_none = [a for a in args if a is not type(None)]
197
+ if len(non_none) == 1:
198
+ return non_none[0]
199
+ return annotation
200
+
201
+
202
+ def origin_type(annotation: Any) -> Any:
203
+ """Return underlying type of an annotation (e.g. ``list`` from ``list[Foo]``)."""
204
+ return getattr(annotation, "__origin__", None) or annotation
205
+
206
+
207
+ def unwrap_iterable(annotation: Any) -> type | None:
208
+ """Return the element type of an iterable annotation, or None."""
209
+ origin = getattr(annotation, "__origin__", None)
210
+ args = getattr(annotation, "__args__", None)
211
+ if origin in ITERABLE_ORIGINS and args:
212
+ return args[0]
213
+ return None
214
+
215
+
216
+ def get_return_annotation(func: Callable) -> Any:
217
+ """Determine the target of a function return type hint."""
218
+ try:
219
+ annotation = get_type_hints(func).get("return")
220
+ except (NameError, TypeError) as e:
221
+ msg = f"Unable to follow return annotation of {get_name_for_debugging(func)}."
222
+ raise CouldNotResolve(msg) from e
223
+ if not annotation:
224
+ msg = f"No return annotation on {get_name_for_debugging(func)}."
225
+ raise CouldNotResolve(msg)
226
+ return strip_optional(annotation)
227
+
228
+
229
+ def fully_qualified_name(thing: type | Callable) -> str:
230
+ """Construct the fully qualified name of a type."""
231
+ return thing.__module__ + "." + thing.__qualname__
232
+
233
+
234
+ def get_name_for_debugging(thing: type | Callable) -> str:
235
+ """Construct the fully qualified name or some readable information of a type."""
236
+ try:
237
+ return fully_qualified_name(thing)
238
+ except (AttributeError, TypeError):
239
+ return repr(thing)
240
+
241
+
242
+ @cache
243
+ def closest_module(components: tuple[str, ...]) -> tuple[Any, int]:
244
+ """Find closest importable module."""
245
+ try:
246
+ mod = import_module(components[0])
247
+ except ImportError as e:
248
+ msg = f"Could not import {components[0]}."
249
+ raise CouldNotResolve(msg) from e
250
+ populate_type_checking(mod)
251
+
252
+ for i in range(1, len(components)):
253
+ try:
254
+ mod = import_module(".".join(components[: i + 1]))
255
+ except ImportError:
256
+ # import failed, exclude previously added item
257
+ return mod, i
258
+ populate_type_checking(mod)
259
+ # imports succeeded, include all items
260
+ return mod, len(components)
261
+
262
+
263
+ populated_modules: set[int] = set()
264
+
265
+
266
+ def populate_type_checking(mod: ModuleType) -> None:
267
+ """
268
+ Execute top-level TYPE_CHECKING blocks into ``mod.__dict__``.
269
+
270
+ At runtime TYPE_CHECKING is False, so names imported under such gates
271
+ are never bound on the module. ``get_type_hints`` then fails to resolve
272
+ annotations that reference them. Re-execute the gated bodies in the
273
+ module's own namespace so those names become available.
274
+ """
275
+ if id(mod) in populated_modules:
276
+ return
277
+ populated_modules.add(id(mod))
278
+
279
+ try:
280
+ source = inspect.getsource(mod)
281
+ except (OSError, TypeError):
282
+ return
283
+
284
+ tree = ast.parse(source)
285
+
286
+ filename = getattr(mod, "__file__", None) or "<type_checking>"
287
+ for node in tree.body:
288
+ if not isinstance(node, ast.If) or not is_type_checking_test(node.test):
289
+ continue
290
+ body = ast.Module(body=node.body, type_ignores=[])
291
+ # Catch e.g. optional deps and cyclic imports
292
+ with suppress(Exception):
293
+ exec(compile(body, filename, "exec"), mod.__dict__) # noqa: S102
294
+
295
+
296
+ def is_type_checking_test(expr: ast.expr) -> bool:
297
+ """
298
+ Determine if expr is a test for type checking.
299
+
300
+ Mirror mypy's ``infer_condition_value``: match a bare name or any
301
+ attribute access regardless of qualifier.
302
+ """
303
+ if isinstance(expr, ast.Name):
304
+ return expr.id in ("TYPE_CHECKING", "MYPY")
305
+ if isinstance(expr, ast.Attribute):
306
+ return expr.attr in ("TYPE_CHECKING", "MYPY")
307
+ return False
@@ -94,6 +94,7 @@ class NameBreak(str, Enum):
94
94
  call = "()"
95
95
  namedexpr = ":="
96
96
  import_from = ">"
97
+ for_iter = "<>"
97
98
 
98
99
 
99
100
  class LinkContext(str, Enum):
@@ -499,9 +500,19 @@ class ImportTrackerVisitor(ast.NodeVisitor):
499
500
  self.visit_For(node)
500
501
 
501
502
  def visit_For(self, node: ast.For | ast.AsyncFor) -> None:
502
- """Swap node order."""
503
- self.visit(node.iter)
504
- self.visit(node.target)
503
+ """Swap node order and resolve iterators."""
504
+ iter_pending = self.visit(node.iter)
505
+
506
+ if (
507
+ isinstance(iter_pending, PendingAccess)
508
+ and iter_pending.components
509
+ and isinstance(node.target, ast.Name)
510
+ ):
511
+ marker = Component(NameBreak.for_iter.value, *linenos(node), "load")
512
+ self.assign_name(node.target.id, [*iter_pending.components, marker])
513
+ else:
514
+ self.visit(node.target)
515
+
505
516
  for n in node.body:
506
517
  self.visit(n)
507
518
  for n in node.orelse:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sphinx-codeautolink
3
- Version: 0.17.5
3
+ Version: 0.18.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>
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
22
23
  Classifier: Topic :: Documentation
23
24
  Classifier: Topic :: Documentation :: Sphinx
24
25
  Classifier: Topic :: Software Development :: Documentation
@@ -131,6 +131,7 @@ tests/extension/ref/ref_class_type_attr.txt
131
131
  tests/extension/ref/ref_decorator.txt
132
132
  tests/extension/ref/ref_fluent_attrs.txt
133
133
  tests/extension/ref/ref_fluent_call.txt
134
+ tests/extension/ref/ref_for_loop.txt
134
135
  tests/extension/ref/ref_func_args.txt
135
136
  tests/extension/ref/ref_func_no_module.txt
136
137
  tests/extension/ref/ref_import_as.txt
@@ -146,10 +147,14 @@ tests/extension/ref/ref_inherited.txt
146
147
  tests/extension/ref/ref_intersphinx_only.txt
147
148
  tests/extension/ref/ref_invalid_func.txt
148
149
  tests/extension/ref/ref_invalid_typehint.txt
150
+ tests/extension/ref/ref_module_attribute.txt
151
+ tests/extension/ref/ref_module_attribute_builtin.txt
152
+ tests/extension/ref/ref_module_attribute_class.txt
149
153
  tests/extension/ref/ref_optional.txt
150
154
  tests/extension/ref/ref_optional_future.txt
151
155
  tests/extension/ref/ref_shadow_builtin.txt
152
156
  tests/extension/ref/ref_simple.txt
157
+ tests/extension/ref/ref_type_checking_gated.txt
153
158
  tests/extension/ref/search_css_duplicates_removed.txt
154
159
  tests/extension/ref/skip_file.txt
155
160
  tests/extension/ref/skip_next.txt
@@ -161,6 +166,8 @@ tests/extension/src/future_project.py
161
166
  tests/extension/src/parser_func.py
162
167
  tests/extension/src/test_project/__init__.py
163
168
  tests/extension/src/test_project/sub.py
169
+ tests/extension/src/type_checking/__init__.py
170
+ tests/extension/src/type_checking/foo.py
164
171
  tests/extension/table/tab_autodoc_empty.txt
165
172
  tests/extension/table/tab_autodoc_links.txt
166
173
  tests/extension/table/tab_manual_collapse.txt
@@ -0,0 +1,26 @@
1
+ test_project
2
+ test_project.mod_list
3
+ a.meth
4
+ test_project.mod_typing_list
5
+ b.meth
6
+ test_project.iter_foos
7
+ c.meth
8
+ # split
9
+ # split
10
+ Test project
11
+ ============
12
+
13
+ .. code:: python
14
+
15
+ import test_project
16
+
17
+ for a in test_project.mod_list:
18
+ a.meth()
19
+
20
+ for b in test_project.mod_typing_list:
21
+ b.meth()
22
+
23
+ for c in test_project.iter_foos():
24
+ c.meth()
25
+
26
+ .. automodule:: test_project
@@ -0,0 +1,13 @@
1
+ test_project
2
+ test_project.mod_attr.attr
3
+ # split
4
+ # split
5
+ Test project
6
+ ============
7
+
8
+ .. code:: python
9
+
10
+ import test_project
11
+ test_project.mod_attr.attr
12
+
13
+ .. automodule:: test_project
@@ -0,0 +1,13 @@
1
+ test_project
2
+ # split
3
+ codeautolink_warn_on_missing_inventory = False
4
+ # split
5
+ Test project
6
+ ============
7
+
8
+ .. code:: python
9
+
10
+ import test_project
11
+ test_project.mod_int.bit_length()
12
+
13
+ .. automodule:: test_project
@@ -0,0 +1,13 @@
1
+ test_project
2
+ test_project.mod_type.attr
3
+ # split
4
+ # split
5
+ Test project
6
+ ============
7
+
8
+ .. code:: python
9
+
10
+ import test_project
11
+ test_project.mod_type.attr
12
+
13
+ .. automodule:: test_project
@@ -0,0 +1,15 @@
1
+ type_checking
2
+ type_checking.pick
3
+ attr
4
+ # split
5
+ # split
6
+ Test project
7
+ ============
8
+
9
+ .. code:: python
10
+
11
+ import type_checking
12
+ type_checking.pick(["a"]).attr
13
+
14
+ .. automodule:: type_checking
15
+ .. automodule:: type_checking.foo
@@ -1,5 +1,8 @@
1
1
  """Docstring."""
2
2
 
3
+ from collections.abc import Iterator
4
+ from typing import List # noqa: UP035
5
+
3
6
  from .sub import SubBar, subfoo # noqa: F401
4
7
 
5
8
 
@@ -25,10 +28,30 @@ class Foo:
25
28
  """Test call."""
26
29
 
27
30
 
31
+ mod_attr: Foo = Foo()
32
+ """Module attribute."""
33
+
34
+ mod_int: int = 0
35
+ """Module attribute with a builtin type."""
36
+
37
+ mod_type = Foo
38
+ """Module attribute whose value is a class, not an instance."""
39
+
40
+ mod_list: list[Foo] = []
41
+ """Module list attribute."""
42
+
43
+ mod_typing_list: List[Foo] = [] # noqa: UP006
44
+ """Typing module list attribute."""
45
+
46
+
28
47
  def bar() -> Foo:
29
48
  """Bar test function."""
30
49
 
31
50
 
51
+ def iter_foos() -> "Iterator[Foo]":
52
+ """Return an iterator of Foos."""
53
+
54
+
32
55
  def optional() -> Foo | None:
33
56
  """Return optional type."""
34
57
 
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from collections.abc import Collection
8
+
9
+ if typing.TYPE_CHECKING:
10
+ from .foo import Foo
11
+
12
+ if False:
13
+ pass
14
+
15
+
16
+ def pick(items: Collection[str]) -> Foo:
17
+ """Return value whose annotation references a name guarded by
18
+ ``if TYPE_CHECKING: ...``
19
+ """
@@ -0,0 +1,4 @@
1
+ class Foo:
2
+ """Foo test class."""
3
+
4
+ attr: str = "test"
@@ -298,7 +298,7 @@ class TestAssignLike:
298
298
  return s, refs
299
299
 
300
300
  @refs_equal
301
- def test_for_uses_imported(self):
301
+ def test_for_uses_imported_but_target_unused(self):
302
302
  s = "import a\nfor b in a:\n a"
303
303
  refs = [("a", "a"), ("a", "a"), ("a", "a")]
304
304
  return s, refs
@@ -312,6 +312,30 @@ class TestAssignLike:
312
312
  @refs_equal
313
313
  def test_for_uses_and_overwrites_imported(self):
314
314
  s = "import a\nfor a in a:\n a"
315
+ refs = [("a", "a"), ("a", "a"), ("a.<>", "a")]
316
+ return s, refs
317
+
318
+ @refs_equal
319
+ def test_for_target_bound_to_iter_name_element(self):
320
+ s = "import a\nfor b in a:\n b"
321
+ refs = [("a", "a"), ("a", "a"), ("a.<>", "b")]
322
+ return s, refs
323
+
324
+ @refs_equal
325
+ def test_for_target_bound_to_iter_call_element(self):
326
+ s = "import a\nfor b in a():\n b"
327
+ refs = [("a", "a"), ("a", "a"), ("a.().<>", "b")]
328
+ return s, refs
329
+
330
+ @refs_equal
331
+ def test_for_target_bound_to_iter_attribute_element(self):
332
+ s = "import a\nfor b in a.x:\n b"
333
+ refs = [("a", "a"), ("a.x", "a.x"), ("a.x.<>", "b")]
334
+ return s, refs
335
+
336
+ @refs_equal
337
+ def test_for_tuple_target_not_bound(self):
338
+ s = "import a\nfor b, c in a():\n b"
315
339
  refs = [("a", "a"), ("a", "a")]
316
340
  return s, refs
317
341