sarj-python-lint 1.12.0__tar.gz → 1.13.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 (169) hide show
  1. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/PKG-INFO +1 -1
  2. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/pyproject.toml +1 -1
  3. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/unused_test_factory_option.py +94 -11
  4. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/.gitignore +0 -0
  5. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/LICENSE +0 -0
  6. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/README.md +0 -0
  7. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/__init__.py +0 -0
  8. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/__main__.py +0 -0
  9. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/_analysis_session.py +0 -0
  10. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/_file_context.py +0 -0
  11. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/_filesystem.py +0 -0
  12. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/_python_target.py +0 -0
  13. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  14. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/_secret_names.py +0 -0
  15. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/_version.py +0 -0
  16. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/benchmark.py +0 -0
  17. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/json_boundary.py +0 -0
  18. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/py.typed +0 -0
  19. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/ratchet.py +0 -0
  20. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rule_base.py +0 -0
  21. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/__init__.py +0 -0
  22. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
  23. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_ast_index.py +0 -0
  24. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_ast_position.py +0 -0
  25. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_comments.py +0 -0
  26. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
  27. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
  28. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  29. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  30. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_first_party.py +0 -0
  31. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
  32. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_imports.py +0 -0
  33. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_logging.py +0 -0
  34. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
  35. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_paths.py +0 -0
  36. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_project_index.py +0 -0
  37. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  38. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_pytest.py +0 -0
  39. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_registry.py +0 -0
  40. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_resource_provenance.py +0 -0
  41. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_set_fields.py +0 -0
  42. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_sql.py +0 -0
  43. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  44. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  45. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/_test_composition.py +0 -0
  46. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
  47. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
  48. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
  49. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
  50. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/discourage_nullable_constructor_parameters.py +0 -0
  51. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  52. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  53. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
  54. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  55. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
  56. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  57. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  58. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  59. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  60. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
  61. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  62. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
  63. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
  64. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  65. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  66. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  67. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  68. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
  69. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
  70. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
  71. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  72. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
  73. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  74. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
  75. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  76. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
  77. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
  78. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  79. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  80. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
  81. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
  82. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  83. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
  84. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  85. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
  86. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
  87. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  88. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
  89. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
  90. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  91. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
  92. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  93. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  94. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  95. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  96. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  97. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
  98. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
  99. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  100. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
  101. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  102. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  103. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  104. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  105. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
  106. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  107. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
  108. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  109. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  110. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  111. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  112. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  113. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
  114. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
  115. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  116. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
  117. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  118. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  119. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
  120. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
  121. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
  122. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  123. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
  124. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
  125. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  126. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
  127. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  128. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  129. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
  130. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
  131. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  132. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  133. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  134. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  135. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  136. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
  137. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  138. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  139. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  140. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  141. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  142. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  143. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  144. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  145. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
  146. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  147. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
  148. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
  149. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
  150. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
  151. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
  152. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
  153. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  154. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
  155. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
  156. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  157. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
  158. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  159. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  160. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
  161. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/stepdown.py +0 -0
  162. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
  163. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  164. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
  165. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  166. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  167. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
  168. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  169. {sarj_python_lint-1.12.0 → sarj_python_lint-1.13.0}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sarj-python-lint
3
- Version: 1.12.0
3
+ Version: 1.13.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.12.0"
3
+ version = "1.13.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" }]
@@ -38,14 +38,15 @@ class UnusedTestFactoryOption(Rule):
38
38
  code = "SARJ443"
39
39
  documentation: ClassVar[RuleDocumentation | None] = RuleDocumentation(
40
40
  default_level=Severity.WARNING,
41
- summary="A private test factory exposes a literal option that visible callers never vary.",
41
+ summary="A private test factory exposes an option that visible callers never vary.",
42
42
  rationale="Unused customization obscures the values that actually distinguish test scenarios.",
43
43
  remediation="Keep the value in the factory's construction instead of exposing an unused option; retain it if external callers need it.",
44
44
  category=RuleCategory.TESTING,
45
45
  autofix=AutofixPolicy.NONE,
46
46
  limitations=(
47
47
  "Only module-level private _make_ and _build_ helpers with straight-line local assignments ending in a construction return are considered; control flow and standalone side effects are excluded.",
48
- "Only literal defaults with direct, unambiguous calls in this file are reported. Explicit options require at least two calls with the same effective literal value. Decorators, rebinding, callable escapes, reflection, and argument unpacking exclude the helper.",
48
+ "Literal defaults and stable earlier module-local function defaults are considered. Callable options are reported only when every direct caller omits them; explicit literal options require at least two calls with the same effective value.",
49
+ "Decorators, rebinding, shadowing, callable escapes, reflection, argument unpacking, and ambiguous provider mutation or patch targets exclude the affected helper or callable option.",
49
50
  "Cross-module callers cannot be proven absent. Shared helpers require an exact suppression; this advisory never autofixes signatures or changes default evaluation timing.",
50
51
  ),
51
52
  examples=(
@@ -77,6 +78,36 @@ class UnusedTestFactoryOption(Rule):
77
78
  expected_count=0,
78
79
  public=True,
79
80
  ),
81
+ RuleExample(
82
+ example_id="unused-callable-option",
83
+ scenario="callable-default",
84
+ title="Use an unexercised local dependency directly",
85
+ outcome=ExampleOutcome.MATCH,
86
+ files=(
87
+ ExampleFile.python(
88
+ "tests/test_widget.py",
89
+ "def _read():\n return 'value'\n\ndef _make_widget(*, read=_read):\n return Widget(read=read)\n\n_make_widget()\n",
90
+ ),
91
+ ),
92
+ focus_path=PurePosixPath("tests/test_widget.py"),
93
+ expected_count=1,
94
+ public=True,
95
+ ),
96
+ RuleExample(
97
+ example_id="exercised-callable-option",
98
+ scenario="callable-default",
99
+ title="Keep a dependency that a caller replaces",
100
+ outcome=ExampleOutcome.NO_MATCH,
101
+ files=(
102
+ ExampleFile.python(
103
+ "tests/test_widget.py",
104
+ "def _read():\n return 'value'\n\ndef _make_widget(*, read=_read):\n return Widget(read=read)\n\n_make_widget(read=other)\n",
105
+ ),
106
+ ),
107
+ focus_path=PurePosixPath("tests/test_widget.py"),
108
+ expected_count=0,
109
+ public=True,
110
+ ),
80
111
  ),
81
112
  )
82
113
  description = documentation.summary
@@ -173,6 +204,27 @@ def _factory_findings(
173
204
  ),
174
205
  )
175
206
  )
207
+ for argument, default in _factory_options(function):
208
+ if (
209
+ argument.arg in supplied
210
+ or not isinstance(default, ast.Name)
211
+ or not _is_stable_local_callable(tree, function, default.id, node_index=node_index)
212
+ or is_suppressed(lines, argument.lineno, code)
213
+ ):
214
+ continue
215
+ findings.append(
216
+ Diagnostic(
217
+ path=path,
218
+ line=argument.lineno,
219
+ col=argument.col_offset + 1,
220
+ code=code,
221
+ severity=Severity.WARNING,
222
+ message=(
223
+ f"No direct caller in this file supplies `{function.name}.{argument.arg}`; use the stable local "
224
+ f"callable `{default.id}` in the factory instead of exposing an unused option. Retain it if external callers need it."
225
+ ),
226
+ )
227
+ )
176
228
  return findings
177
229
 
178
230
 
@@ -258,18 +310,49 @@ def _factory_argument_is_invariant(argument: ast.arg, default: ast.Constant, bou
258
310
  )
259
311
 
260
312
 
261
- def _literal_factory_options(function: ast.FunctionDef) -> list[tuple[ast.arg, ast.Constant]]:
262
- options: list[tuple[ast.arg, ast.Constant]] = []
313
+ def _factory_options(function: ast.FunctionDef) -> list[tuple[ast.arg, ast.expr]]:
263
314
  positional = [*function.args.posonlyargs, *function.args.args]
264
315
  defaults = [
265
316
  *zip(positional[len(positional) - len(function.args.defaults) :], function.args.defaults, strict=True),
266
317
  *zip(function.args.kwonlyargs, function.args.kw_defaults, strict=True),
267
318
  ]
268
319
  used = {node.id for node in nodes(function, ast.Name) if isinstance(node.ctx, ast.Load)}
269
- for argument, default in defaults:
270
- if argument.arg not in used or not isinstance(default, ast.Constant):
271
- continue
272
- if default.value is not None and not isinstance(default.value, (str, bytes, int, float)):
273
- continue
274
- options.append((argument, default))
275
- return options
320
+ return [(argument, default) for argument, default in defaults if argument.arg in used and default is not None]
321
+
322
+
323
+ def _literal_factory_options(function: ast.FunctionDef) -> list[tuple[ast.arg, ast.Constant]]:
324
+ return [
325
+ (argument, default)
326
+ for argument, default in _factory_options(function)
327
+ if isinstance(default, ast.Constant)
328
+ and (default.value is None or isinstance(default.value, (str, bytes, int, float)))
329
+ ]
330
+
331
+
332
+ def _is_stable_local_callable(
333
+ tree: ast.Module,
334
+ factory: ast.FunctionDef,
335
+ name: str,
336
+ *,
337
+ node_index: NodeIndex | None = None,
338
+ ) -> bool:
339
+ if not any(
340
+ isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
341
+ and node.name == name
342
+ and node.lineno < factory.lineno
343
+ and not node.decorator_list
344
+ for node in tree.body
345
+ ) or not _has_unambiguous_factory_name(tree, name, node_index=node_index):
346
+ return False
347
+ return not (
348
+ any(node.id == name and not isinstance(node.ctx, ast.Load) for node in nodes(tree, ast.Name, index=node_index))
349
+ or any(
350
+ not isinstance(node.ctx, ast.Load) and any(child.id == name for child in nodes(node.value, ast.Name))
351
+ for node in nodes(tree, ast.Attribute, index=node_index)
352
+ )
353
+ or any(
354
+ isinstance(node.value, str)
355
+ and (node.value.rsplit(".", 1)[-1] == name or factory.name in node.value.split("."))
356
+ for node in nodes(tree, ast.Constant, index=node_index)
357
+ )
358
+ )