sarj-python-lint 0.81.16__tar.gz → 0.81.18__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 (129) hide show
  1. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/PKG-INFO +1 -1
  2. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/pyproject.toml +6 -1
  3. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +2 -2
  4. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +12 -8
  5. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/.gitignore +0 -0
  6. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/LICENSE +0 -0
  7. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/README.md +0 -0
  8. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/__init__.py +0 -0
  9. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/__main__.py +0 -0
  10. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/_analysis_session.py +0 -0
  11. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/_filesystem.py +0 -0
  12. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/_python_target.py +0 -0
  13. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  14. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/_secret_names.py +0 -0
  15. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/_version.py +0 -0
  16. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/py.typed +0 -0
  17. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/ratchet.py +0 -0
  18. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rule_base.py +0 -0
  19. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/__init__.py +0 -0
  20. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_ast_index.py +0 -0
  21. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_comments.py +0 -0
  22. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  23. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  24. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_first_party.py +0 -0
  25. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
  26. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_imports.py +0 -0
  27. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_logging.py +0 -0
  28. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_paths.py +0 -0
  29. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_project_index.py +0 -0
  30. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  31. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_pytest.py +0 -0
  32. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_registry.py +0 -0
  33. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_sql.py +0 -0
  34. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  35. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  36. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
  37. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
  38. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  39. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  40. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
  41. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  42. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  43. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  44. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  45. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  46. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  47. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
  48. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  49. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  50. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  51. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  52. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_deleted_only_override_parameter.py +0 -0
  53. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
  54. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  55. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  56. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
  57. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  58. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
  59. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  60. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  61. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  62. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  63. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
  64. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
  65. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  66. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
  67. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
  68. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  69. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
  70. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  71. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  72. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  73. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  74. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  75. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
  76. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  77. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  78. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  79. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  80. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  81. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  82. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
  83. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  84. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  85. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  86. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  87. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  88. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
  89. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
  90. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  91. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  92. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  93. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
  94. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  95. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  96. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
  97. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  98. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  99. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  100. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  101. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  102. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  103. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  104. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  105. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  106. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  107. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  108. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/pydantic_at_boundaries.py +0 -0
  109. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  110. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  111. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  112. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  113. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
  114. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  115. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
  116. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
  117. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  118. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  119. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  120. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  121. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/stepdown.py +0 -0
  122. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
  123. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  124. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  125. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  126. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
  127. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  128. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
  129. {sarj_python_lint-0.81.16 → sarj_python_lint-0.81.18}/src/sarj_python_lint/rules/unused_test_factory_option.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sarj-python-lint
3
- Version: 0.81.16
3
+ Version: 0.81.18
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 = "0.81.16"
3
+ version = "0.81.18"
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" }]
@@ -64,3 +64,8 @@ markers = [
64
64
  # Dogfooding: linted/formatted by this repo's own published config (root-synced).
65
65
  [tool.ruff]
66
66
  extend = "../../.ruff-strict.toml"
67
+
68
+ [tool.deptry.per_rule_ignores]
69
+ # Ruff is invoked at runtime through `sys.executable -m ruff`, which Deptry's
70
+ # import analysis cannot observe.
71
+ DEP002 = ["ruff"]
@@ -436,7 +436,7 @@ def _two_arm_ast_projection_findings(
436
436
  line=first.lineno,
437
437
  col=first.col_offset + 1,
438
438
  code=code,
439
- severity=Severity.WARNING,
439
+ severity=Severity.ERROR,
440
440
  message=(
441
441
  f"two-arm ast.Name/ast.Attribute projection on '{subject}' — use one match/case "
442
442
  "statement so the structural alternatives are explicit."
@@ -581,7 +581,7 @@ def _diagnostic(path: Path, code: str, node: ast.If, dispatch: _Dispatch, shape:
581
581
  line=node.lineno,
582
582
  col=node.col_offset + 1,
583
583
  code=code,
584
- severity=Severity.WARNING,
584
+ severity=Severity.ERROR,
585
585
  message=(
586
586
  f"{dispatch.branch_count}-branch {shape} on '{dispatch.subject}' — use match/case class patterns "
587
587
  "so the mutually exclusive runtime type dispatch is explicit."
@@ -50,14 +50,16 @@ class PreferWalrusAwaitedNoneGuard(Rule):
50
50
  remediation=(
51
51
  "Rewrite `value = await lookup(); if value is None: return` as "
52
52
  "`if (value := await lookup()) is None: return`. Preserve `is not None` when the terminal branch "
53
- "returns or raises with the bound value. Keep two statements when the assignment is an intentional "
54
- "debugging or tracing boundary."
53
+ "returns or raises with the bound value. A short message assignment may remain inside the guard before "
54
+ "the terminal statement. Keep two statements when the awaited assignment is an intentional debugging "
55
+ "or tracing boundary."
55
56
  ),
56
57
  category=RuleCategory.STYLE,
57
58
  autofix=AutofixPolicy.NONE,
58
59
  limitations=(
59
- "Only one-line awaited calls followed immediately by an exact `is None` or `is not None` guard containing one return or raise are checked.",
60
- "A negative guard requires a later use on the surviving path; a positive guard must consume the binding in its terminal statement and leave no later use before rebinding.",
60
+ "Only one-line awaited calls followed immediately by an exact `is None` or `is not None` guard ending in return or raise are checked.",
61
+ "Statements before the terminal operation must be simple assignments; expressions and compound control flow are excluded.",
62
+ "An `is None` guard requires a later use on the surviving path and must not use or rebind the name inside the guard; an `is not None` guard must consume the binding inside the terminal branch and leave no later use before rebinding.",
61
63
  "The combined condition must fit 120 columns; comments, else branches, ambiguous name flow, generated files, and broader assignment-expression preferences are excluded.",
62
64
  ),
63
65
  examples=(
@@ -167,17 +169,19 @@ def _candidate(
167
169
  and guard.col_offset == assignment.col_offset
168
170
  and guard.test.end_lineno == guard.lineno
169
171
  and not guard.orelse
170
- and len(guard.body) == 1
171
- and isinstance(guard.body[0], (ast.Return, ast.Raise))
172
+ and guard.body
173
+ and all(isinstance(statement, (ast.Assign, ast.AnnAssign)) for statement in guard.body[:-1])
174
+ and isinstance(guard.body[-1], (ast.Return, ast.Raise))
172
175
  ):
173
176
  return None
174
177
  name = assignment.targets[0].id
175
178
  is_not_none = _none_guard_kind(guard.test, name)
176
179
  if is_not_none is None or _loads_name(assignment.value, name):
177
180
  return None
178
- terminal = guard.body[0]
181
+ terminal = guard.body[-1]
179
182
  usage = _NameUsage(name)
180
- usage.visit(terminal)
183
+ for statement in guard.body:
184
+ usage.visit(statement)
181
185
  if usage.rebound or (is_not_none != usage.loaded):
182
186
  return None
183
187
  terminal_end = terminal.end_lineno or terminal.lineno