sarj-python-lint 1.72.0__tar.gz → 1.74.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 (254) hide show
  1. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/PKG-INFO +1 -1
  2. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/pyproject.toml +1 -1
  3. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_parallel.py +2 -1
  4. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_redundant_local_alias.py +100 -8
  5. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/.gitignore +0 -0
  6. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/LICENSE +0 -0
  7. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/README.md +0 -0
  8. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/__init__.py +0 -0
  9. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/__main__.py +0 -0
  10. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_analysis_session.py +0 -0
  11. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_file_context.py +0 -0
  12. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_filesystem.py +0 -0
  13. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_fixes.py +0 -0
  14. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_python_target.py +0 -0
  15. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  16. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_secret_names.py +0 -0
  17. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_source.py +0 -0
  18. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/_version.py +0 -0
  19. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/benchmark.py +0 -0
  20. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/cast_access.py +0 -0
  21. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/interpreter_argv.py +0 -0
  22. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/json_boundary.py +0 -0
  23. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/py.typed +0 -0
  24. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/ratchet.py +0 -0
  25. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rule_base.py +0 -0
  26. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/__init__.py +0 -0
  27. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_annotation_origins.py +0 -0
  28. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
  29. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_ast_index.py +0 -0
  30. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_ast_names.py +0 -0
  31. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_ast_position.py +0 -0
  32. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_closed_helpers.py +0 -0
  33. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_comments.py +0 -0
  34. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
  35. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_copy_on_write.py +0 -0
  36. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_data_union_discriminator.py +0 -0
  37. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_declared_contracts.py +0 -0
  38. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
  39. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  40. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_exports.py +0 -0
  41. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  42. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_first_party.py +0 -0
  43. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
  44. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_imports.py +0 -0
  45. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_inert_model_annotation.py +0 -0
  46. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_inherited_contract.py +0 -0
  47. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_local_alias_fix.py +0 -0
  48. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_local_source.py +0 -0
  49. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_logging.py +0 -0
  50. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_mapping_shape_callbacks.py +0 -0
  51. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_namespace_access.py +0 -0
  52. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_native_namespace_capability.py +0 -0
  53. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
  54. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_paths.py +0 -0
  55. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_project_index.py +0 -0
  56. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  57. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_pydantic_field_contract.py +0 -0
  58. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_pytest.py +0 -0
  59. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_registry.py +0 -0
  60. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_resolved_operation_signature.py +0 -0
  61. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_resource_provenance.py +0 -0
  62. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_route_shapes.py +0 -0
  63. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_runtime_bindings.py +0 -0
  64. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_set_fields.py +0 -0
  65. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_sql.py +0 -0
  66. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_static_json_alias.py +0 -0
  67. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_store_writes.py +0 -0
  68. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  69. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  70. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_test_composition.py +0 -0
  71. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
  72. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/_type_guard_symbols.py +0 -0
  73. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
  74. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
  75. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
  76. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
  77. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/delete_route_returns_no_content.py +0 -0
  78. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  79. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  80. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/duplicate_adjacent_exception_handler.py +0 -0
  81. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/duplicate_closed_pure_helper.py +0 -0
  82. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/duplicate_pytest_fixture_params.py +0 -0
  83. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
  84. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  85. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
  86. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  87. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  88. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  89. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  90. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
  91. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  92. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
  93. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
  94. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_async_function_cache.py +0 -0
  95. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
  96. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_blanket_suppression.py +0 -0
  97. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
  98. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  99. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_conflicting_pydantic_alias_validation.py +0 -0
  100. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  101. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_contradictory_type_guard.py +0 -0
  102. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  103. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  104. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_create_verb_in_post_path.py +0 -0
  105. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
  106. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_defaulted_environment_setting.py +0 -0
  107. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
  108. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_discarded_validation_result.py +0 -0
  109. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_dual_shape_model_field_reader.py +0 -0
  110. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
  111. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  112. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_duplicate_field_validator_body.py +0 -0
  113. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_exception_text_in_500_detail.py +0 -0
  114. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
  115. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  116. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
  117. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  118. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
  119. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_fixed_sleep_in_loop.py +0 -0
  120. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_folded_bad_request_not_found.py +0 -0
  121. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
  122. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  123. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_hasattr.py +0 -0
  124. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  125. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_impossible_pydantic_field_bounds.py +0 -0
  126. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
  127. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
  128. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +0 -0
  129. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
  130. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_invalid_pydantic_bypass.py +0 -0
  131. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_invalid_pydantic_validator_return.py +0 -0
  132. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_loguru_exc_info.py +0 -0
  133. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_loguru_printf_format.py +0 -0
  134. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
  135. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_mutating_container_transform.py +0 -0
  136. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  137. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
  138. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  139. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_partial_type_is.py +0 -0
  140. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
  141. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
  142. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  143. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
  144. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
  145. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  146. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
  147. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  148. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  149. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  150. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  151. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  152. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
  153. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
  154. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_shallow_record_type_guard.py +0 -0
  155. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_slash_collection_root_under_prefix.py +0 -0
  156. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  157. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
  158. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  159. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
  160. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  161. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  162. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_unknown_pydantic_validator_field.py +0 -0
  163. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  164. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
  165. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
  166. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
  167. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  168. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
  169. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/no_work_verb_get_route.py +0 -0
  170. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  171. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  172. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  173. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
  174. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_bulk_upsert.py +0 -0
  175. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  176. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  177. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
  178. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_declarative_batch_validation.py +0 -0
  179. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_direct_import_module.py +0 -0
  180. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_discriminated_model_union.py +0 -0
  181. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
  182. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  183. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
  184. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  185. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  186. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
  187. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
  188. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
  189. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  190. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
  191. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
  192. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  193. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_native_string_check.py +0 -0
  194. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
  195. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  196. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  197. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_precise_object_contract.py +0 -0
  198. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_psycopg_executemany.py +0 -0
  199. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
  200. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_pydantic_model_assertion.py +0 -0
  201. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_pytest_dependency_fixtures.py +0 -0
  202. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
  203. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
  204. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
  205. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  206. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  207. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  208. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  209. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  210. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_typed_settings_field.py +0 -0
  211. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
  212. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  213. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  214. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  215. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  216. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  217. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/pytest_fixture_returns_closed_resource.py +0 -0
  218. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  219. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  220. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  221. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/redundant_test_constructor_forwarder.py +0 -0
  222. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
  223. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  224. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
  225. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/repeated_unimplemented_test_contract.py +0 -0
  226. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_exp_on_jwt_decode.py +0 -0
  227. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
  228. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
  229. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
  230. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_injectable_retry_sleep.py +0 -0
  231. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
  232. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
  233. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  234. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
  235. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
  236. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  237. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_pydantic_for_mapping_shape.py +0 -0
  238. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
  239. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  240. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  241. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
  242. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/stepdown.py +0 -0
  243. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/store_field_update_reuses_upsert.py +0 -0
  244. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
  245. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  246. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
  247. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/test_without_explicit_oracle.py +0 -0
  248. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  249. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  250. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
  251. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  252. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
  253. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/src/sarj_python_lint/rules/unused_test_factory_option.py +0 -0
  254. {sarj_python_lint-1.72.0 → sarj_python_lint-1.74.0}/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.72.0
3
+ Version: 1.74.0
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.72.0"
3
+ version = "1.74.0"
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" }]
@@ -87,7 +87,8 @@ def check_parallel(
87
87
  resolutions: set[_ResolutionKey] = set()
88
88
  modules: set[Path] = set()
89
89
  try:
90
- for result in pool.map(_check_file, loaded.items(), chunksize=1, buffersize=workers):
90
+ # Keep workers busy while an earlier file delays ordered results.
91
+ for result in pool.map(_check_file, loaded.items(), chunksize=1, buffersize=workers * 4):
91
92
  resolutions.update(result.resolutions)
92
93
  modules.update(result.modules)
93
94
  # A worker cannot hit either order-dependent limit when the whole
@@ -24,7 +24,7 @@ from sarj_python_lint.rules._suppression_comments import comment_lines
24
24
 
25
25
 
26
26
  if TYPE_CHECKING:
27
- from collections.abc import Mapping
27
+ from collections.abc import Iterator, Mapping
28
28
 
29
29
  from sarj_python_lint._file_context import PythonFileContext
30
30
  from sarj_python_lint.rules._resource_provenance import ResourceProvenance
@@ -32,7 +32,7 @@ if TYPE_CHECKING:
32
32
 
33
33
  _FUNCTIONS = (ast.FunctionDef, ast.AsyncFunctionDef)
34
34
  _SUITES = (*_FUNCTIONS, ast.With, ast.AsyncWith)
35
- _UNCERTAIN = (
35
+ _NESTED_SCOPES = (
36
36
  *_FUNCTIONS,
37
37
  ast.ClassDef,
38
38
  ast.Lambda,
@@ -40,6 +40,9 @@ _UNCERTAIN = (
40
40
  ast.SetComp,
41
41
  ast.DictComp,
42
42
  ast.GeneratorExp,
43
+ )
44
+ _UNCERTAIN = (
45
+ *_NESTED_SCOPES,
43
46
  ast.If,
44
47
  ast.For,
45
48
  ast.AsyncFor,
@@ -89,7 +92,8 @@ class NoRedundantLocalAlias(Rule):
89
92
  limitations=(
90
93
  "Only unannotated, single-target `alias = original` assignments with one binding and one read at `alias=alias` are checked.",
91
94
  "The original must be a parameter or an earlier initialized local with one binding; reassignment, deletion, imports, alias chains and uncertain initialization are excluded.",
92
- "Functions with if statements, loops, try statements, asserts, Boolean short-circuiting, nested scopes, global/nonlocal declarations or type aliases are excluded. Ordinary and async with bodies require ordered enclosing-suite binding evidence.",
95
+ "Completed function-body if prefixes and their Boolean tests are supported only before a fresh, uniquely initialized local and alias in that same body. Parameters, earlier source bindings and aliases nested in with bodies after such prefixes are excluded.",
96
+ "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.",
93
97
  "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.",
94
98
  "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.",
95
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.",
@@ -145,6 +149,36 @@ class NoRedundantLocalAlias(Rule):
145
149
  expected_count=0,
146
150
  public=True,
147
151
  ),
152
+ RuleExample(
153
+ example_id="completed-guard-prefix",
154
+ scenario="completed-guard",
155
+ title="Initialize the original after the completed guard",
156
+ outcome=ExampleOutcome.MATCH,
157
+ files=(
158
+ ExampleFile.python(
159
+ "case.py",
160
+ "def render(enabled):\n if not enabled:\n return None\n item = make_item()\n payload = item\n return build(payload=payload)\n",
161
+ ),
162
+ ),
163
+ focus_path=PurePosixPath("case.py"),
164
+ expected_count=1,
165
+ public=True,
166
+ ),
167
+ RuleExample(
168
+ example_id="direct-after-guard",
169
+ scenario="completed-guard",
170
+ title="Pass the fresh original directly",
171
+ outcome=ExampleOutcome.NO_MATCH,
172
+ files=(
173
+ ExampleFile.python(
174
+ "case.py",
175
+ "def render(enabled):\n if not enabled:\n return None\n item = make_item()\n return build(payload=item)\n",
176
+ ),
177
+ ),
178
+ focus_path=PurePosixPath("case.py"),
179
+ expected_count=0,
180
+ public=True,
181
+ ),
148
182
  ),
149
183
  )
150
184
  description = documentation.summary
@@ -237,12 +271,13 @@ def _local_assignments(context: PythonFileContext, names: set[str]) -> list[ast.
237
271
  if not candidates or context.has_wildcard_import:
238
272
  return []
239
273
  provenance = context.resource_provenance
240
- blocked = {provenance.scope(node) for node in context.nodes(*_UNCERTAIN)}
241
- blocked.update(
242
- provenance.scope(node) for node in context.nodes(ast.IfExp) if not _parameter_choice(node, provenance)
243
- )
274
+ boundaries = _scope_boundaries(context, provenance)
244
275
  eligible = [
245
- node for node in candidates if isinstance(scope := provenance.scope(node), _FUNCTIONS) and scope not in blocked
276
+ node
277
+ for node in candidates
278
+ if isinstance(scope := provenance.scope(node), _FUNCTIONS)
279
+ and (boundary := boundaries.get(scope, 0)) is not None
280
+ and _after_prefix(node, boundary, provenance)
246
281
  ]
247
282
  if not eligible or context.dynamic_namespace or _observes_references(context):
248
283
  return []
@@ -251,6 +286,63 @@ def _local_assignments(context: PythonFileContext, names: set[str]) -> list[ast.
251
286
  return eligible
252
287
 
253
288
 
289
+ def _scope_boundaries(context: PythonFileContext, provenance: ResourceProvenance) -> dict[ast.AST | None, int | None]:
290
+ prefixes = _prefix_bounds(context)
291
+ boundaries: dict[ast.AST | None, int | None] = {}
292
+ for node in context.nodes(*_UNCERTAIN):
293
+ scope = provenance.scope(node)
294
+ prefix = prefixes.get(node)
295
+ if prefix is None or context.parents.get(prefix) is not scope:
296
+ boundaries[scope] = None
297
+ elif (boundary := boundaries.get(scope, 0)) is not None:
298
+ boundaries[scope] = max(boundary, prefix.end_lineno or prefix.lineno)
299
+ for node in context.nodes(ast.IfExp):
300
+ if not _parameter_choice(node, provenance):
301
+ boundaries[provenance.scope(node)] = None
302
+ return boundaries
303
+
304
+
305
+ def _prefix_bounds(context: PythonFileContext) -> dict[ast.AST, ast.If]:
306
+ bounds: dict[ast.AST, ast.If] = {}
307
+ for function in context.nodes(*_FUNCTIONS):
308
+ for root in function.body:
309
+ if isinstance(root, ast.If):
310
+ for node in _prefix_conditions(root):
311
+ bounds[node] = root
312
+ return bounds
313
+
314
+
315
+ def _prefix_conditions(root: ast.If) -> Iterator[ast.AST]:
316
+ pending: list[tuple[ast.AST, bool]] = [(root, False)]
317
+ while pending:
318
+ node, inside_test = pending.pop()
319
+ if isinstance(node, _NESTED_SCOPES):
320
+ continue
321
+ if isinstance(node, ast.If) or (isinstance(node, ast.BoolOp) and inside_test):
322
+ yield node
323
+ pending.extend(
324
+ (child, inside_test or (isinstance(node, ast.If) and child is node.test)) for child in children(node)
325
+ )
326
+
327
+
328
+ def _after_prefix(assignment: ast.Assign, boundary: int, provenance: ResourceProvenance) -> bool:
329
+ if not boundary:
330
+ return True
331
+ if not isinstance(assignment.value, ast.Name):
332
+ return False
333
+ scope = provenance.scope(assignment)
334
+ bindings = provenance.bindings.get(scope, {}).get(assignment.value.id, ())
335
+ if len(bindings) != 1 or not isinstance(bindings[0], ast.Name):
336
+ return False
337
+ initializer = provenance.parents.get(bindings[0])
338
+ return (
339
+ isinstance(initializer, ast.Assign | ast.AnnAssign)
340
+ and provenance.parents.get(initializer) is scope
341
+ and provenance.parents.get(assignment) is scope
342
+ and initializer.lineno > boundary
343
+ )
344
+
345
+
254
346
  def _compiles(context: PythonFileContext) -> bool:
255
347
  if context.tree is None:
256
348
  return False