sarj-python-lint 1.74.0__tar.gz → 1.74.2__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 (254) hide show
  1. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/PKG-INFO +1 -1
  2. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/pyproject.toml +1 -1
  3. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_local_alias_fix.py +4 -9
  4. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_resource_provenance.py +3 -3
  5. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_redundant_local_alias.py +7 -15
  6. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/.gitignore +0 -0
  7. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/LICENSE +0 -0
  8. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/README.md +0 -0
  9. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/__init__.py +0 -0
  10. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/__main__.py +0 -0
  11. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_analysis_session.py +0 -0
  12. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_file_context.py +0 -0
  13. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_filesystem.py +0 -0
  14. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_fixes.py +0 -0
  15. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_parallel.py +0 -0
  16. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_python_target.py +0 -0
  17. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  18. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_secret_names.py +0 -0
  19. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_source.py +0 -0
  20. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/_version.py +0 -0
  21. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/benchmark.py +0 -0
  22. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/cast_access.py +0 -0
  23. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/interpreter_argv.py +0 -0
  24. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/json_boundary.py +0 -0
  25. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/py.typed +0 -0
  26. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/ratchet.py +0 -0
  27. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rule_base.py +0 -0
  28. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/__init__.py +0 -0
  29. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_annotation_origins.py +0 -0
  30. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
  31. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_ast_index.py +0 -0
  32. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_ast_names.py +0 -0
  33. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_ast_position.py +0 -0
  34. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_closed_helpers.py +0 -0
  35. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_comments.py +0 -0
  36. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
  37. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_copy_on_write.py +0 -0
  38. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_data_union_discriminator.py +0 -0
  39. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_declared_contracts.py +0 -0
  40. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
  41. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  42. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_exports.py +0 -0
  43. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  44. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_first_party.py +0 -0
  45. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
  46. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_imports.py +0 -0
  47. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_inert_model_annotation.py +0 -0
  48. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_inherited_contract.py +0 -0
  49. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_local_source.py +0 -0
  50. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_logging.py +0 -0
  51. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_mapping_shape_callbacks.py +0 -0
  52. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_namespace_access.py +0 -0
  53. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_native_namespace_capability.py +0 -0
  54. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
  55. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_paths.py +0 -0
  56. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_project_index.py +0 -0
  57. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  58. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_pydantic_field_contract.py +0 -0
  59. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_pytest.py +0 -0
  60. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_registry.py +0 -0
  61. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_resolved_operation_signature.py +0 -0
  62. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_route_shapes.py +0 -0
  63. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_runtime_bindings.py +0 -0
  64. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_set_fields.py +0 -0
  65. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_sql.py +0 -0
  66. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_static_json_alias.py +0 -0
  67. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_store_writes.py +0 -0
  68. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  69. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  70. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_test_composition.py +0 -0
  71. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
  72. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/_type_guard_symbols.py +0 -0
  73. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
  74. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
  75. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
  76. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
  77. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/delete_route_returns_no_content.py +0 -0
  78. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  79. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  80. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/duplicate_adjacent_exception_handler.py +0 -0
  81. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/duplicate_closed_pure_helper.py +0 -0
  82. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/duplicate_pytest_fixture_params.py +0 -0
  83. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
  84. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  85. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
  86. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  87. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  88. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  89. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  90. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
  91. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  92. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
  93. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
  94. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_async_function_cache.py +0 -0
  95. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
  96. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_blanket_suppression.py +0 -0
  97. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
  98. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  99. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_conflicting_pydantic_alias_validation.py +0 -0
  100. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  101. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_contradictory_type_guard.py +0 -0
  102. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  103. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  104. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_create_verb_in_post_path.py +0 -0
  105. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
  106. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_defaulted_environment_setting.py +0 -0
  107. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
  108. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_discarded_validation_result.py +0 -0
  109. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_dual_shape_model_field_reader.py +0 -0
  110. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
  111. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  112. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_duplicate_field_validator_body.py +0 -0
  113. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_exception_text_in_500_detail.py +0 -0
  114. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
  115. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  116. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
  117. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  118. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
  119. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_fixed_sleep_in_loop.py +0 -0
  120. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_folded_bad_request_not_found.py +0 -0
  121. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
  122. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  123. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_hasattr.py +0 -0
  124. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  125. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_impossible_pydantic_field_bounds.py +0 -0
  126. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
  127. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
  128. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +0 -0
  129. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
  130. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_invalid_pydantic_bypass.py +0 -0
  131. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_invalid_pydantic_validator_return.py +0 -0
  132. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_loguru_exc_info.py +0 -0
  133. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_loguru_printf_format.py +0 -0
  134. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
  135. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_mutating_container_transform.py +0 -0
  136. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  137. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
  138. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  139. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_partial_type_is.py +0 -0
  140. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
  141. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
  142. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  143. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
  144. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
  145. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  146. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
  147. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  148. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  149. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  150. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  151. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  152. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
  153. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
  154. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_shallow_record_type_guard.py +0 -0
  155. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_slash_collection_root_under_prefix.py +0 -0
  156. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  157. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
  158. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  159. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
  160. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  161. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  162. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_unknown_pydantic_validator_field.py +0 -0
  163. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  164. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
  165. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
  166. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
  167. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  168. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
  169. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/no_work_verb_get_route.py +0 -0
  170. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  171. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  172. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  173. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
  174. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_bulk_upsert.py +0 -0
  175. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  176. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  177. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
  178. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_declarative_batch_validation.py +0 -0
  179. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_direct_import_module.py +0 -0
  180. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_discriminated_model_union.py +0 -0
  181. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
  182. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  183. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
  184. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  185. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  186. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
  187. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
  188. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
  189. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  190. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
  191. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
  192. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  193. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_native_string_check.py +0 -0
  194. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
  195. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  196. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  197. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_precise_object_contract.py +0 -0
  198. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_psycopg_executemany.py +0 -0
  199. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
  200. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_pydantic_model_assertion.py +0 -0
  201. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_pytest_dependency_fixtures.py +0 -0
  202. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
  203. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
  204. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
  205. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  206. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  207. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  208. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  209. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  210. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_typed_settings_field.py +0 -0
  211. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
  212. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  213. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  214. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  215. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  216. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  217. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/pytest_fixture_returns_closed_resource.py +0 -0
  218. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  219. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  220. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  221. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/redundant_test_constructor_forwarder.py +0 -0
  222. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
  223. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  224. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
  225. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/repeated_unimplemented_test_contract.py +0 -0
  226. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_exp_on_jwt_decode.py +0 -0
  227. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
  228. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
  229. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
  230. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_injectable_retry_sleep.py +0 -0
  231. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
  232. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
  233. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  234. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
  235. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
  236. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  237. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_pydantic_for_mapping_shape.py +0 -0
  238. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
  239. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  240. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  241. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
  242. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/stepdown.py +0 -0
  243. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/store_field_update_reuses_upsert.py +0 -0
  244. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
  245. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  246. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
  247. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/test_without_explicit_oracle.py +0 -0
  248. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  249. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  250. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
  251. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  252. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
  253. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/rules/unused_test_factory_option.py +0 -0
  254. {sarj_python_lint-1.74.0 → sarj_python_lint-1.74.2}/src/sarj_python_lint/suppression_policy.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sarj-python-lint
3
- Version: 1.74.0
3
+ Version: 1.74.2
4
4
  Summary: Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults
5
5
  Project-URL: Homepage, https://code-standards.sarj.ai/rules/python/
6
6
  Project-URL: Documentation, https://code-standards.sarj.ai/rules/python/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sarj-python-lint"
3
- version = "1.74.0"
3
+ version = "1.74.2"
4
4
  description = "Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "sarj-ai" }]
@@ -16,6 +16,7 @@ if TYPE_CHECKING:
16
16
  from sarj_python_lint._file_context import PythonFileContext
17
17
 
18
18
 
19
+ _ALIAS_RETURN_LENGTH = 2
19
20
  _NAMESPACE_MUTATORS = frozenset(
20
21
  {
21
22
  "setattr",
@@ -86,9 +87,9 @@ class LocalAliasFixes:
86
87
  if not isinstance(source, ast.Name) or parameters[0].arg != source.id:
87
88
  return ()
88
89
  body = owner.body[1:] if ast.get_docstring(owner) is not None else owner.body
89
- if body[:1] != [assignment] or len(body[1:]) != 1 or not isinstance(body[-1], ast.Return):
90
+ if len(body) != _ALIAS_RETURN_LENGTH or body[0] is not assignment or not isinstance(body[1], ast.Return):
90
91
  return ()
91
- call = body[-1].value
92
+ call = body[1].value
92
93
  if not isinstance(call, ast.Call) or not isinstance(call.func, ast.Name) or call.func.id != "dict":
93
94
  return ()
94
95
  if call.args or len(call.keywords) != 1 or call.keywords[0].value is not use or not self._available:
@@ -110,14 +111,8 @@ class LocalAliasFixes:
110
111
  return ()
111
112
  if assignment.end_lineno != assignment.lineno:
112
113
  return ()
113
- line = self.context.source_lines[assignment.lineno - 1]
114
114
  raw = self._lines[assignment.lineno - 1]
115
- if (
116
- raw[: assignment.col_offset].strip()
117
- or raw[assignment.end_col_offset :].strip()
118
- or ";" in line
119
- or "\\" in line
120
- ):
115
+ if raw[: assignment.col_offset].strip() or raw[assignment.end_col_offset :].strip():
121
116
  return ()
122
117
  return (
123
118
  TextEdit(assignment.lineno, 1, assignment.lineno + 1, 1, ""),
@@ -428,7 +428,7 @@ class ResourceProvenance:
428
428
  name = binding.id if isinstance(binding, ast.Name) else binding.name
429
429
  if name in self.mutated or name in self.external_bindings:
430
430
  return False
431
- for read in self._binding_reads(name, binding):
431
+ for read in self.binding_reads(name, binding):
432
432
  alias = self._function_alias(read)
433
433
  if alias is not None:
434
434
  pending.append(alias)
@@ -469,7 +469,7 @@ class ResourceProvenance:
469
469
  and any(self.imported(constructor.func, f"contextlib.{kind}") for kind in ("ExitStack", "AsyncExitStack"))
470
470
  )
471
471
 
472
- def _binding_reads(self, name: str, binding: ast.AST) -> list[ast.Name]:
472
+ def binding_reads(self, name: str, binding: ast.AST) -> list[ast.Name]:
473
473
  return self._indexed_reads(name, binding, cache=self._reads_by_binding, resolve=self.binding)
474
474
 
475
475
  def _indexed_reads(
@@ -496,7 +496,7 @@ class ResourceProvenance:
496
496
  if key not in self.escape_cache:
497
497
  self.escape_cache[key] = all(
498
498
  self._method_or_context_read(read, allow_context=allow_context)
499
- for read in self._binding_reads(name.id, binding)
499
+ for read in self.binding_reads(name.id, binding)
500
500
  )
501
501
  return self.escape_cache[key]
502
502
 
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import ast
4
- from collections import defaultdict
5
4
  from pathlib import PurePosixPath
6
5
  import re
7
6
  from typing import TYPE_CHECKING, ClassVar, final, override
@@ -96,6 +95,7 @@ class NoRedundantLocalAlias(Rule):
96
95
  "Loops, try statements, asserts, other Boolean short-circuiting, nested scopes, global/nonlocal declarations and type aliases are excluded. Ordinary and async with bodies require ordered enclosing-suite binding evidence.",
97
96
  "A conditional expression is admitted only when its test is a bare name bound once as a parameter, and neither local is read within the expression.",
98
97
  "Typed aliases, files with type comments, same-scope quoted references and conditional reads of either local are excluded. Captured bindings and module/class aliases are preserved.",
98
+ "Aliases read inside template interpolations are preserved because templates expose expression text. This conservatively also excludes reads used only in format specifications.",
99
99
  "Files with wildcard imports, Pydantic imports or references to known namespace readers, dynamic attribute getters or reference-count observers are excluded. Wildcard exports cannot establish builtin identity; computed type names can consume caller-local bindings without a Name read in the AST.",
100
100
  "Dynamic class construction and class-valued references to type are excluded. Direct, unshadowed unary type(value) queries and standard-library dataclasses remain supported.",
101
101
  "Generated source, stubs and malformed input are excluded; files must compile with normal module execution flags. Arbitrary external frame introspection is not modeled.",
@@ -193,7 +193,6 @@ class NoRedundantLocalAlias(Rule):
193
193
  return []
194
194
  provenance = context.resource_provenance
195
195
  names = {node.targets[0].id for node in candidates if isinstance(node.targets[0], ast.Name)}
196
- reads = _scope_reads(provenance, names)
197
196
  conditional_sources = _conditional_sources(context)
198
197
  quoted = _quoted_references(context, provenance, names)
199
198
  positions = {statement: i for owner in context.nodes(*_SUITES) for i, statement in enumerate(owner.body)}
@@ -206,7 +205,7 @@ class NoRedundantLocalAlias(Rule):
206
205
  continue
207
206
  if (provenance.scope(assignment), target.id) in quoted:
208
207
  continue
209
- use = _single_keyword_read(target, provenance, reads, keywords)
208
+ use = _single_keyword_read(target, provenance, keywords)
210
209
  if use is None:
211
210
  continue
212
211
  if not _dominates(assignment, use, context.parents, positions):
@@ -364,14 +363,6 @@ def _parameter_choice(node: ast.IfExp, provenance: ResourceProvenance) -> bool:
364
363
  return len(bindings) == 1 and isinstance(bindings[0], ast.arg)
365
364
 
366
365
 
367
- def _scope_reads(provenance: ResourceProvenance, names: set[str]) -> dict[tuple[ast.AST | None, str], list[ast.Name]]:
368
- reads: dict[tuple[ast.AST | None, str], list[ast.Name]] = defaultdict(list)
369
- for name in names:
370
- for read in provenance.reads.get(name, ()):
371
- reads[provenance.scope(read), name].append(read)
372
- return reads
373
-
374
-
375
366
  def _conditional_sources(context: PythonFileContext) -> set[tuple[ast.AST | None, str]]:
376
367
  provenance = context.resource_provenance
377
368
  pending: list[ast.AST] = list(context.nodes(ast.IfExp))
@@ -391,12 +382,13 @@ def _conditional_sources(context: PythonFileContext) -> set[tuple[ast.AST | None
391
382
  def _single_keyword_read(
392
383
  target: ast.Name,
393
384
  provenance: ResourceProvenance,
394
- reads: Mapping[tuple[ast.AST | None, str], list[ast.Name]],
395
385
  keywords: Mapping[ast.Name, str],
396
386
  ) -> ast.Name | None:
397
387
  scope = provenance.scope(target)
398
- uses = reads.get((scope, target.id), ())
399
- if provenance.bindings.get(scope, {}).get(target.id) != [target] or len(uses) != 1:
388
+ if provenance.bindings.get(scope, {}).get(target.id) != [target]:
389
+ return None
390
+ uses = provenance.binding_reads(target.id, target)
391
+ if len(uses) != 1:
400
392
  return None
401
393
  [use] = uses
402
394
  if keywords.get(use) != target.id or _statement(use, provenance.parents) is None:
@@ -481,7 +473,7 @@ def _plain_type_query(node: ast.AST, context: PythonFileContext) -> bool:
481
473
 
482
474
  def _statement(node: ast.AST, parents: Mapping[ast.AST, ast.AST]) -> ast.stmt | None:
483
475
  while not isinstance(node, ast.stmt):
484
- if isinstance(node, (ast.IfExp, ast.BoolOp)) or (parent := parents.get(node)) is None:
476
+ if isinstance(node, (ast.IfExp, ast.BoolOp, ast.Interpolation)) or (parent := parents.get(node)) is None:
485
477
  return None
486
478
  node = parent
487
479
  return node