sarj-python-lint 1.28.4__tar.gz → 1.28.5__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 (192) hide show
  1. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/PKG-INFO +1 -1
  2. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/pyproject.toml +1 -1
  3. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +4 -1
  4. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +5 -2
  5. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +4 -2
  6. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_precise_factory_signature.py +45 -14
  7. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/.gitignore +0 -0
  8. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/LICENSE +0 -0
  9. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/README.md +0 -0
  10. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/__init__.py +0 -0
  11. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/__main__.py +0 -0
  12. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/_analysis_session.py +0 -0
  13. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/_file_context.py +0 -0
  14. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/_filesystem.py +0 -0
  15. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/_python_target.py +0 -0
  16. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  17. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/_secret_names.py +0 -0
  18. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/_source.py +0 -0
  19. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/_version.py +0 -0
  20. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/benchmark.py +0 -0
  21. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/interpreter_argv.py +0 -0
  22. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/json_boundary.py +0 -0
  23. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/py.typed +0 -0
  24. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/ratchet.py +0 -0
  25. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rule_base.py +0 -0
  26. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/__init__.py +0 -0
  27. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
  28. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_ast_index.py +0 -0
  29. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_ast_position.py +0 -0
  30. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_closed_helpers.py +0 -0
  31. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_comments.py +0 -0
  32. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
  33. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_copy_on_write.py +0 -0
  34. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
  35. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  36. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  37. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_first_party.py +0 -0
  38. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
  39. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_imports.py +0 -0
  40. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_local_source.py +0 -0
  41. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_logging.py +0 -0
  42. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
  43. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_paths.py +0 -0
  44. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_project_index.py +0 -0
  45. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  46. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_pytest.py +0 -0
  47. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_registry.py +0 -0
  48. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_resource_provenance.py +0 -0
  49. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_set_fields.py +0 -0
  50. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_sql.py +0 -0
  51. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  52. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  53. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_test_composition.py +0 -0
  54. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
  55. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
  56. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
  57. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
  58. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  59. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  60. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/duplicate_adjacent_exception_handler.py +0 -0
  61. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/duplicate_closed_pure_helper.py +0 -0
  62. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
  63. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  64. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
  65. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  66. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  67. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  68. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  69. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
  70. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  71. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
  72. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
  73. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
  74. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
  75. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  76. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  77. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  78. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  79. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
  80. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
  81. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
  82. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  83. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
  84. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  85. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
  86. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  87. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
  88. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_fixed_sleep_in_loop.py +0 -0
  89. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
  90. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  91. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  92. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
  93. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
  94. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +0 -0
  95. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
  96. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
  97. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  98. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
  99. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  100. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
  101. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
  102. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  103. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
  104. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
  105. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  106. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
  107. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  108. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  109. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  110. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  111. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  112. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
  113. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
  114. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  115. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
  116. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  117. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
  118. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  119. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  120. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  121. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
  122. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
  123. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
  124. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  125. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
  126. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  127. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  128. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  129. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
  130. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  131. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  132. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
  133. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  134. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  135. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  136. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
  137. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
  138. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
  139. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  140. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
  141. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
  142. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  143. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_native_string_check.py +0 -0
  144. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
  145. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  146. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  147. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
  148. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
  149. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
  150. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
  151. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  152. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  153. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  154. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  155. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  156. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
  157. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  158. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  159. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  160. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  161. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  162. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  163. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  164. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  165. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/redundant_test_constructor_forwarder.py +0 -0
  166. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
  167. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  168. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
  169. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/repeated_unimplemented_test_contract.py +0 -0
  170. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
  171. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
  172. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
  173. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_injectable_retry_sleep.py +0 -0
  174. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
  175. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
  176. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  177. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
  178. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  179. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
  180. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  181. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  182. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
  183. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/stepdown.py +0 -0
  184. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
  185. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  186. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
  187. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  188. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  189. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
  190. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  191. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
  192. {sarj_python_lint-1.28.4 → sarj_python_lint-1.28.5}/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.28.4
3
+ Version: 1.28.5
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.28.4"
3
+ version = "1.28.5"
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,13 +64,16 @@ class DefectXfailRequiresExplicitStrict(Rule):
64
64
  ),
65
65
  remediation=(
66
66
  "Set literal `strict=True` so an unexpected pass fails. If only some parameter cases carry the defect, "
67
- "move the marker to those `pytest.param(...)` cases before making it strict."
67
+ "move the marker to those `pytest.param(...)` cases before making it strict. When the defect's exception "
68
+ "type or group shape is independently known, native `raises=...`, where supported, can narrow unrelated failures; "
69
+ "same-type failures still need an origin oracle. Keep intentional broad expected-failure policies."
68
70
  ),
69
71
  category=RuleCategory.TESTING,
70
72
  aliases=("defect-xfail-requires-strict", "xfail-requires-strict"),
71
73
  limitations=(
72
74
  "Only markers resolved through an unambiguous pytest or pytest.mark import are analyzed.",
73
75
  "Only xfail reasons that explicitly identify a defect are analyzed.",
76
+ "Exception narrowing and defect identity remain manual review; strictness or a typed marker alone does not establish failure origin.",
74
77
  "Nondeterministic, recognized Hypothesis, network, environment-gated, run=False, and statically disabled pins are excluded.",
75
78
  "Repository-level strict_xfail / xfail_strict configuration is intentionally not consulted: defect pins remain locally explicit.",
76
79
  "Default pytest test_/Test collection names are recognized; repositories with custom collection patterns may need a local suppression.",
@@ -124,13 +124,16 @@ class PreferFstringOverConcat(Rule):
124
124
  summary="Prefer f-strings for short human-readable interpolation when they make the result clearer.",
125
125
  rationale="For prose-like strings, f-strings keep interpolated values and surrounding text visible together.",
126
126
  remediation=(
127
- "Replace the interpolation with one f-string. Preserve an explicit `str(value)` conversion as `{value!s}` "
128
- "and `repr(value)` as `{value!r}` when those conversion semantics matter."
127
+ "Use one f-string when it preserves the required conversion and operator semantics. Preserve an explicit "
128
+ "`str(value)` conversion as `{value!s}` "
129
+ "and `repr(value)` as `{value!r}` when those conversion semantics matter. Retain required custom "
130
+ "concatenation or formatting behavior; a `str` annotation alone does not prove equivalence."
129
131
  ),
130
132
  category=RuleCategory.STYLE,
131
133
  autofix=AutofixPolicy.NONE,
132
134
  limitations=(
133
135
  "Runtime operands must have concrete string evidence.",
136
+ "String evidence does not prove that custom concatenation operators and `__format__` agree; this remains manual review.",
134
137
  (
135
138
  "Logging, common direct SQL and regular-expression forms, lazy strings, ORM expressions, generated files, long "
136
139
  "literals, and punctuation-oriented fragment composition are excluded."
@@ -55,7 +55,9 @@ class PreferInjectedDependencyOverMonkeypatch(Rule):
55
55
  "fake when rebuilding the fixture would add wiring without improving the boundary. Keep attribute-existence "
56
56
  "checks enabled and the tested implementation intact. Suppress SARJ445 only at that call, naming the "
57
57
  "owned instance and injection seam. For inherently global boundaries or lookup interception, explain why "
58
- "injection would invalidate the test. Do not switch to bare assignment merely to avoid this rule."
58
+ "injection would invalidate the test. Establish the binding the exercised consumer actually reads, "
59
+ "including already-bound import aliases, and show that the oracle rejects a wrong consumer. "
60
+ "Do not switch to bare assignment merely to avoid this rule."
59
61
  ),
60
62
  category=RuleCategory.TESTING,
61
63
  autofix=AutofixPolicy.NONE,
@@ -65,7 +67,7 @@ class PreferInjectedDependencyOverMonkeypatch(Rule):
65
67
  "Environment, mapping, import-path, and working-directory mutations are intentionally allowed.",
66
68
  "Untyped handles are recognized only on pytest tests or fixtures; directly parametrized values are excluded.",
67
69
  "A nested function that captures a monkeypatch handle from an outer scope is not inferred.",
68
- "Instance ownership and collaborator contracts are not inferred; justified scoped patches need a local suppression.",
70
+ "Instance ownership, collaborator contracts, and active consumer lookups are not inferred; justified scoped patches need a local suppression.",
69
71
  ),
70
72
  examples=(
71
73
  RuleExample(
@@ -35,7 +35,7 @@ class RequirePreciseFactorySignature(ProjectRule):
35
35
  documentation: ClassVar[RuleDocumentation | None] = RuleDocumentation(
36
36
  default_level=Severity.WARNING,
37
37
  summary="Keep fixed keyword factory calls behind a precise callable signature.",
38
- rationale="Callable[..., T] erases argument checking, so misspelled keywords and incompatible injected factories pass strict typing and can fail at runtime.",
38
+ rationale="Callable[..., T] and functools.partial[T] erase argument checking at injected boundaries, so misspelled keywords and incompatible factories pass strict typing and can fail at runtime.",
39
39
  remediation=(
40
40
  "If factory substitution is unnecessary, call the existing constructor directly. Otherwise reuse an "
41
41
  "existing precise callable contract; use type[T] when the dependency requires a class, accounting "
@@ -46,7 +46,7 @@ class RequirePreciseFactorySignature(ProjectRule):
46
46
  category=RuleCategory.ARCHITECTURE,
47
47
  autofix=AutofixPolicy.NONE,
48
48
  limitations=(
49
- "Only undecorated module-level functions with proven standard Callable[..., OwnedClass] parameters directly called with at least one named keyword are considered. Imported classes require scanned first-party declarations.",
49
+ "Only undecorated module-level functions with proven standard Callable[..., OwnedClass] or functools.partial[OwnedClass] parameters directly called with at least one named keyword are considered. Imported classes require scanned first-party declarations; direct partial construction and calls remain native type-checker ownership.",
50
50
  "Tests, test support, generated code, unresolved/string/generic annotations, positional-only calls, unpacking, forwarding, nested captures, rebinding and ambiguous imports are excluded. Import capture checks are conservative across the file, so an unrelated local pattern, exception or walrus binding can prevent a warning.",
51
51
  "A fixed call demonstrates signature erasure, not a current runtime defect. Genuine dynamic APIs can use a reasoned suppression. No autofix: the correct contract depends on whether classes or function factories are intended.",
52
52
  ),
@@ -65,6 +65,36 @@ class RequirePreciseFactorySignature(ProjectRule):
65
65
  expected_count=1,
66
66
  public=True,
67
67
  ),
68
+ RuleExample(
69
+ example_id="erased-partial-factory",
70
+ title="An injected partial retains its result type but loses argument checking",
71
+ outcome=ExampleOutcome.MATCH,
72
+ files=(
73
+ ExampleFile.python(
74
+ "app/service.py",
75
+ "from functools import partial\nclass Result: pass\ndef build(factory: partial[Result]):\n return factory(size=4)\n",
76
+ ),
77
+ ),
78
+ focus_path=PurePosixPath("app/service.py"),
79
+ expected_count=1,
80
+ scenario="partial-erasure",
81
+ public=True,
82
+ ),
83
+ RuleExample(
84
+ example_id="direct-partial-factory",
85
+ title="Direct partial construction keeps native argument checking",
86
+ outcome=ExampleOutcome.NO_MATCH,
87
+ files=(
88
+ ExampleFile.python(
89
+ "app/service.py",
90
+ "from functools import partial\nclass Result:\n def __init__(self, *, size: int):\n self.size = size\ndef build():\n factory = partial(Result)\n return factory(size=4)\n",
91
+ ),
92
+ ),
93
+ focus_path=PurePosixPath("app/service.py"),
94
+ expected_count=0,
95
+ scenario="partial-erasure",
96
+ public=True,
97
+ ),
68
98
  RuleExample(
69
99
  example_id="exact-factory",
70
100
  title="Factory declares its keyword contract",
@@ -113,7 +143,7 @@ class RequirePreciseFactorySignature(ProjectRule):
113
143
  col=argument.col_offset + 1,
114
144
  code=self.code,
115
145
  message=(
116
- f"`{argument.arg}` is called with fixed keywords but Callable[..., T] erases its "
146
+ f"`{argument.arg}` is called with fixed keywords but its factory annotation erases its "
117
147
  "argument contract; remove unnecessary factory indirection or reuse a precise callable "
118
148
  "contract that preserves the accepted keywords."
119
149
  ),
@@ -124,19 +154,20 @@ class RequirePreciseFactorySignature(ProjectRule):
124
154
 
125
155
 
126
156
  def _factory_result(annotation: ast.expr | None, context: PythonFileContext) -> ast.Name | ast.Attribute | None:
127
- if (
128
- not isinstance(annotation, ast.Subscript)
129
- or context.module_imports.resolved_qualified_name(annotation.value) not in _CALLABLES
130
- ):
157
+ if not isinstance(annotation, ast.Subscript):
131
158
  return None
132
- if not isinstance(annotation.slice, ast.Tuple) or len(annotation.slice.elts) != _CALLABLE_ARITY:
159
+ carrier = context.module_imports.resolved_qualified_name(annotation.value)
160
+ if carrier in _CALLABLES:
161
+ if not isinstance(annotation.slice, ast.Tuple) or len(annotation.slice.elts) != _CALLABLE_ARITY:
162
+ return None
163
+ parameters, result = annotation.slice.elts
164
+ if not isinstance(parameters, ast.Constant) or parameters.value is not Ellipsis:
165
+ return None
166
+ elif carrier == "functools.partial":
167
+ result = annotation.slice
168
+ else:
133
169
  return None
134
- parameters, result = annotation.slice.elts
135
- if (
136
- not isinstance(parameters, ast.Constant)
137
- or parameters.value is not Ellipsis
138
- or not isinstance(result, (ast.Name, ast.Attribute))
139
- ):
170
+ if not isinstance(result, (ast.Name, ast.Attribute)):
140
171
  return None
141
172
  root = _root(annotation.value)
142
173
  if (root is not None and _captured_import_root(root, context)) or any(