sarj-python-lint 1.40.0__tar.gz → 1.40.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 (206) hide show
  1. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/PKG-INFO +1 -1
  2. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/pyproject.toml +1 -1
  3. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_ast_index.py +20 -0
  4. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_resource_provenance.py +11 -2
  5. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_async_function_cache.py +2 -22
  6. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +3 -1
  7. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +20 -10
  8. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +1 -19
  9. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/.gitignore +0 -0
  10. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/LICENSE +0 -0
  11. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/README.md +0 -0
  12. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/__init__.py +0 -0
  13. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/__main__.py +0 -0
  14. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/_analysis_session.py +0 -0
  15. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/_file_context.py +0 -0
  16. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/_filesystem.py +0 -0
  17. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/_python_target.py +0 -0
  18. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  19. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/_secret_names.py +0 -0
  20. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/_source.py +0 -0
  21. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/_version.py +0 -0
  22. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/benchmark.py +0 -0
  23. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/interpreter_argv.py +0 -0
  24. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/json_boundary.py +0 -0
  25. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/py.typed +0 -0
  26. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/ratchet.py +0 -0
  27. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rule_base.py +0 -0
  28. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/__init__.py +0 -0
  29. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
  30. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_ast_position.py +0 -0
  31. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_closed_helpers.py +0 -0
  32. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_comments.py +0 -0
  33. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
  34. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_copy_on_write.py +0 -0
  35. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
  36. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  37. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_exports.py +0 -0
  38. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  39. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_first_party.py +0 -0
  40. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
  41. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_imports.py +0 -0
  42. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_inert_model_annotation.py +0 -0
  43. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_local_source.py +0 -0
  44. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_logging.py +0 -0
  45. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_namespace_access.py +0 -0
  46. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
  47. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_paths.py +0 -0
  48. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_project_index.py +0 -0
  49. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  50. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_pydantic_field_contract.py +0 -0
  51. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_pytest.py +0 -0
  52. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_registry.py +0 -0
  53. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_resolved_operation_signature.py +0 -0
  54. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_set_fields.py +0 -0
  55. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_sql.py +0 -0
  56. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_static_json_alias.py +0 -0
  57. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  58. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  59. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_test_composition.py +0 -0
  60. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
  61. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
  62. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
  63. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
  64. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
  65. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  66. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  67. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/duplicate_adjacent_exception_handler.py +0 -0
  68. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/duplicate_closed_pure_helper.py +0 -0
  69. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
  70. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  71. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
  72. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  73. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  74. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  75. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  76. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
  77. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  78. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
  79. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
  80. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
  81. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
  82. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  83. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_conflicting_pydantic_alias_validation.py +0 -0
  84. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  85. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  86. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  87. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
  88. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
  89. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
  90. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  91. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
  92. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  93. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
  94. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  95. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
  96. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_fixed_sleep_in_loop.py +0 -0
  97. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
  98. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  99. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  100. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_impossible_pydantic_field_bounds.py +0 -0
  101. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
  102. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
  103. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +0 -0
  104. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
  105. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_loguru_exc_info.py +0 -0
  106. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_loguru_printf_format.py +0 -0
  107. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
  108. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  109. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
  110. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  111. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
  112. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
  113. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  114. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
  115. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
  116. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  117. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
  118. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  119. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  120. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  121. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  122. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  123. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
  124. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
  125. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  126. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
  127. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  128. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
  129. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  130. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  131. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_unknown_pydantic_validator_field.py +0 -0
  132. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  133. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
  134. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
  135. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
  136. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  137. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
  138. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  139. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  140. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  141. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
  142. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  143. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  144. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_declarative_batch_validation.py +0 -0
  145. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
  146. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  147. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
  148. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  149. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  150. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
  151. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
  152. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
  153. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  154. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
  155. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
  156. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  157. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_native_string_check.py +0 -0
  158. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  159. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  160. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
  161. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
  162. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
  163. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  164. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  165. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  166. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  167. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  168. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
  169. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  170. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  171. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  172. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  173. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  174. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  175. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  176. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  177. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/redundant_test_constructor_forwarder.py +0 -0
  178. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
  179. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  180. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
  181. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/repeated_unimplemented_test_contract.py +0 -0
  182. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
  183. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
  184. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
  185. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_injectable_retry_sleep.py +0 -0
  186. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
  187. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
  188. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  189. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
  190. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
  191. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  192. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
  193. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  194. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  195. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
  196. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/stepdown.py +0 -0
  197. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
  198. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  199. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
  200. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/test_without_explicit_oracle.py +0 -0
  201. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  202. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  203. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
  204. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  205. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
  206. {sarj_python_lint-1.40.0 → sarj_python_lint-1.40.2}/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: 1.40.0
3
+ Version: 1.40.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.40.0"
3
+ version = "1.40.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" }]
@@ -33,6 +33,26 @@ def comprehension_results(node: ast.ListComp | ast.SetComp | ast.DictComp | ast.
33
33
  return [child for child in children(node) if isinstance(child, ast.expr)]
34
34
 
35
35
 
36
+ def has_own_yield(function: ast.AsyncFunctionDef) -> bool:
37
+ pending: list[ast.AST] = list(function.body)
38
+ while pending:
39
+ match pending.pop():
40
+ case ast.Yield() | ast.YieldFrom():
41
+ return True
42
+ case ast.FunctionDef() | ast.AsyncFunctionDef() | ast.Lambda() as definition:
43
+ pending.extend(definition.args.defaults)
44
+ pending.extend(default for default in definition.args.kw_defaults if default is not None)
45
+ if not isinstance(definition, ast.Lambda):
46
+ pending.extend(definition.decorator_list)
47
+ case ast.ClassDef() as definition:
48
+ pending.extend(definition.bases)
49
+ pending.extend(keyword.value for keyword in definition.keywords)
50
+ pending.extend(definition.decorator_list)
51
+ case node:
52
+ pending.extend(children(node))
53
+ return False
54
+
55
+
36
56
  def walk(node: ast.AST, *, index: NodeIndex | None = None) -> Iterator[ast.AST]:
37
57
  if index is not None and index.tree is node:
38
58
  yield from index.query((ast.AST,))
@@ -6,6 +6,7 @@ from functools import cached_property
6
6
  from types import MappingProxyType
7
7
  from typing import TYPE_CHECKING, final
8
8
 
9
+ from sarj_python_lint.rules._ast_index import has_own_yield
9
10
  from sarj_python_lint.rules._namespace_access import dynamic_namespace_access
10
11
 
11
12
 
@@ -74,7 +75,7 @@ class ResourceProvenance:
74
75
  self.reads[node.id].append(node)
75
76
 
76
77
  for name in _bound_names(node):
77
- self.bindings[self.scope(node)][name].append(node)
78
+ self.bindings[self._binding_scope(node)][name].append(node)
78
79
  self.wildcard |= name == "*"
79
80
  if isinstance(node, ast.Global | ast.Nonlocal):
80
81
  self.external_bindings.update(node.names)
@@ -98,6 +99,14 @@ class ResourceProvenance:
98
99
  parent = self.context.parents.get(parent)
99
100
  return parent
100
101
 
102
+ def _binding_scope(self, node: ast.AST) -> ast.AST | None:
103
+ scope = self.scope(node)
104
+ parent = self.context.parents.get(node)
105
+ if isinstance(parent, ast.NamedExpr) and parent.target is node:
106
+ while isinstance(scope, ast.ListComp | ast.SetComp | ast.DictComp | ast.GeneratorExp):
107
+ scope = self.scope(scope)
108
+ return scope
109
+
101
110
  def binding(self, name: str, at: ast.AST) -> ast.AST | None:
102
111
  scope = self.scope(at)
103
112
  while scope is not None:
@@ -251,7 +260,7 @@ class ResourceProvenance:
251
260
  owner = self.context.parents.get(function)
252
261
  if not isinstance(owner, ast.Module | ast.FunctionDef | ast.AsyncFunctionDef):
253
262
  return None
254
- if function.decorator_list or any(isinstance(node, ast.Yield | ast.YieldFrom) for node in ast.walk(function)):
263
+ if function.decorator_list or has_own_yield(function):
255
264
  return None
256
265
  if function not in self.async_contract_cache:
257
266
  self.async_contract_cache[function] = self._async_aliases_untouched(function)
@@ -16,7 +16,7 @@ from sarj_python_lint.rule_base import (
16
16
  Severity,
17
17
  is_suppressed,
18
18
  )
19
- from sarj_python_lint.rules._ast_index import children
19
+ from sarj_python_lint.rules._ast_index import has_own_yield
20
20
 
21
21
 
22
22
  if TYPE_CHECKING:
@@ -94,7 +94,7 @@ class NoAsyncFunctionCache(Rule):
94
94
  decorator = function.decorator_list[-1]
95
95
  if (
96
96
  not _is_coroutine_cache(decorator, context.imports, shadowed)
97
- or _has_own_yield(function)
97
+ or has_own_yield(function)
98
98
  or is_suppressed(context.source_lines, decorator.lineno, self.code)
99
99
  ):
100
100
  continue
@@ -157,23 +157,3 @@ def _is_coroutine_cache(decorator: ast.expr, imports: ImportIndex, shadowed: fro
157
157
  return size > 0
158
158
  case _:
159
159
  return False
160
-
161
-
162
- def _has_own_yield(function: ast.AsyncFunctionDef) -> bool:
163
- pending: list[ast.AST] = list(function.body)
164
- while pending:
165
- match pending.pop():
166
- case ast.Yield() | ast.YieldFrom():
167
- return True
168
- case ast.FunctionDef() | ast.AsyncFunctionDef() | ast.Lambda() as definition:
169
- pending.extend(definition.args.defaults)
170
- pending.extend(default for default in definition.args.kw_defaults if default is not None)
171
- if not isinstance(definition, ast.Lambda):
172
- pending.extend(definition.decorator_list)
173
- case ast.ClassDef() as definition:
174
- pending.extend(definition.bases)
175
- pending.extend(keyword.value for keyword in definition.keywords)
176
- pending.extend(definition.decorator_list)
177
- case node:
178
- pending.extend(children(node))
179
- return False
@@ -170,7 +170,9 @@ class PreferConstantTimeSecretCompare(Rule):
170
170
  if _is_password_confirmation_pair(operands):
171
171
  continue
172
172
  scope = _enclosing_scope(comparison, parents, tree)
173
- roles = role_cache.setdefault(id(scope), _roles_for_scope(scope, environment_names))
173
+ if id(scope) not in role_cache:
174
+ role_cache[id(scope)] = _roles_for_scope(scope, environment_names)
175
+ roles = role_cache[id(scope)]
174
176
  position = (comparison.lineno, comparison.col_offset)
175
177
  dominant_roles = _dominating_walrus_roles(comparison, parents, roles, position)
176
178
  operand_roles = [_operand_role(operand, roles, position, dominant_roles) for operand in operands]
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import ast
4
+ from collections import Counter
4
5
  from dataclasses import dataclass
5
6
  from pathlib import PurePosixPath
6
7
  import re
@@ -710,7 +711,8 @@ def _unambiguous_exports(tree: ast.Module, imports: ImportIndex, facts: _TypeFac
710
711
  assignments.setdefault(assignment.target, []).append(assignment)
711
712
  # Imports are re-exports only when their binding is unambiguous; local
712
713
  # aliases must have exactly one top-level assignment and no other writes.
713
- unique = {name for name, values in assignments.items() if len(values) == 1 and _binding_count(tree, name) == 1}
714
+ bindings: Counter[str] = _binding_counts(tree) if assignments else Counter()
715
+ unique = {name for name, values in assignments.items() if len(values) == 1 and bindings.get(name, 0) == 1}
714
716
  allowed = unique | set(imports.bindings)
715
717
  return _TypeFacts(
716
718
  {name: shape for name, shape in facts.raw_aliases.items() if name in allowed},
@@ -718,15 +720,23 @@ def _unambiguous_exports(tree: ast.Module, imports: ImportIndex, facts: _TypeFac
718
720
  )
719
721
 
720
722
 
721
- def _binding_count(tree: ast.Module, name: str) -> int:
722
- return sum(
723
- 1
724
- for node in walk_ast(tree)
725
- if (isinstance(node, ast.Name) and isinstance(node.ctx, (ast.Store, ast.Del)) and node.id == name)
726
- or (isinstance(node, ast.arg) and node.arg == name)
727
- or (isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)) and node.name == name)
728
- or (isinstance(node, ast.alias) and (node.asname or node.name.partition(".")[0]) == name)
729
- )
723
+ def _binding_counts(tree: ast.Module) -> Counter[str]:
724
+ bindings: Counter[str] = Counter()
725
+ for node in walk_ast(tree):
726
+ match node:
727
+ case (
728
+ ast.Name(id=name, ctx=ast.Store() | ast.Del())
729
+ | ast.arg(arg=name)
730
+ | ast.FunctionDef(name=name)
731
+ | ast.AsyncFunctionDef(name=name)
732
+ | ast.ClassDef(name=name)
733
+ ):
734
+ bindings[name] += 1
735
+ case ast.alias(name=name, asname=alias):
736
+ bindings[alias or name.partition(".")[0]] += 1
737
+ case _:
738
+ continue
739
+ return bindings
730
740
 
731
741
 
732
742
  def _imported_facts(
@@ -96,7 +96,7 @@ class PreferRequiredConstructorParameters(Rule):
96
96
  continue
97
97
  if method.decorator_list:
98
98
  if provenance is None:
99
- provenance = _overload_provenance(context)
99
+ provenance = ResourceProvenance(context)
100
100
  if _is_overload(context, provenance, method):
101
101
  continue
102
102
  findings.extend(
@@ -134,24 +134,6 @@ def _scope(context: PythonFileContext, node: ast.AST) -> ast.AST | None:
134
134
  return parent
135
135
 
136
136
 
137
- def _overload_provenance(context: PythonFileContext) -> ResourceProvenance:
138
- provenance = ResourceProvenance(context)
139
- comprehensions = (ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp)
140
- for expression in context.nodes(ast.NamedExpr):
141
- target = expression.target
142
- original = provenance.scope(target)
143
- if not isinstance(original, comprehensions):
144
- continue
145
- # Assignment expressions in comprehensions bind in the containing
146
- # scope, unlike iteration targets, which stay comprehension-local.
147
- containing = original
148
- while isinstance(containing, comprehensions):
149
- containing = provenance.scope(containing)
150
- provenance.bindings[original][target.id].remove(target)
151
- provenance.bindings[containing][target.id].append(target)
152
- return provenance
153
-
154
-
155
137
  def _binding(provenance: ResourceProvenance, name: str, at: ast.AST) -> ast.AST | None:
156
138
  scope = provenance.scope(at)
157
139
  deferred = False