sarj-python-lint 1.16.2__tar.gz → 1.16.3__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.
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/PKG-INFO +1 -1
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/pyproject.toml +1 -1
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/unused_test_factory_option.py +124 -11
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/.gitignore +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/LICENSE +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/README.md +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/__main__.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/_analysis_session.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/_file_context.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/_filesystem.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/_python_target.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/benchmark.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/json_boundary.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_ast_position.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_comments.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_docstrings.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_fastapi.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_imports.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_local_source.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_project_index.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_registry.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_resource_provenance.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_set_fields.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_test_composition.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/discourage_nullable_constructor_parameters.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/stepdown.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
- {sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/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.16.
|
|
3
|
+
Version: 1.16.3
|
|
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/
|
|
@@ -38,15 +38,17 @@ class UnusedTestFactoryOption(Rule):
|
|
|
38
38
|
code = "SARJ443"
|
|
39
39
|
documentation: ClassVar[RuleDocumentation | None] = RuleDocumentation(
|
|
40
40
|
default_level=Severity.WARNING,
|
|
41
|
-
summary="A
|
|
41
|
+
summary="A private test factory exposes an invariant literal or unexercised local callable option.",
|
|
42
42
|
rationale="Unused customization obscures the values that actually distinguish test scenarios.",
|
|
43
|
-
remediation="Consider keeping the invariant
|
|
43
|
+
remediation="Consider keeping the invariant literal or stable local callable in the construction instead of exposing an unexercised option. Preserve intentional dependency contracts and callable default binding timing.",
|
|
44
44
|
category=RuleCategory.TESTING,
|
|
45
45
|
autofix=AutofixPolicy.NONE,
|
|
46
46
|
limitations=(
|
|
47
|
-
"
|
|
48
|
-
"
|
|
47
|
+
"Literal findings consider only private _make_ and _build_ helpers nested directly inside test functions, with at least two known direct callers and straight-line construction bodies.",
|
|
48
|
+
"Callable findings consider module-level private helpers with the same construction shape and an earlier undecorated local function default, only when at least two known direct callers all omit that option.",
|
|
49
|
+
"Conftest callable factories, explicit callable arguments, exports, decorators, escaping references, reflection, unpacking, rebinding, shadowing and ambiguous mutation or patch targets are excluded.",
|
|
49
50
|
"Same-name declarations elsewhere in the file conservatively exclude a helper. No autofix: this warning identifies unexercised customization, not an invalid callable contract.",
|
|
51
|
+
"Callable findings describe known callers in this file; cross-module and dynamic callers are not inferred. Retain intentional extension points with a reasoned exception, preserving definition-time default capture.",
|
|
50
52
|
),
|
|
51
53
|
examples=(
|
|
52
54
|
RuleExample(
|
|
@@ -63,6 +65,40 @@ class UnusedTestFactoryOption(Rule):
|
|
|
63
65
|
expected_count=1,
|
|
64
66
|
public=True,
|
|
65
67
|
),
|
|
68
|
+
RuleExample(
|
|
69
|
+
example_id="unused-local-callable-option",
|
|
70
|
+
scenario="callable-default",
|
|
71
|
+
title="Known callers do not replace a stable local dependency",
|
|
72
|
+
outcome=ExampleOutcome.MATCH,
|
|
73
|
+
files=(
|
|
74
|
+
ExampleFile.python(
|
|
75
|
+
"tests/test_widget.py",
|
|
76
|
+
"def _read():\n return 'ready'\n"
|
|
77
|
+
"def _make_widget(*, read=_read):\n return Widget(read=read)\n"
|
|
78
|
+
"_make_widget()\n_make_widget()\n",
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
focus_path=PurePosixPath("tests/test_widget.py"),
|
|
82
|
+
expected_count=1,
|
|
83
|
+
public=True,
|
|
84
|
+
),
|
|
85
|
+
RuleExample(
|
|
86
|
+
example_id="exercised-local-callable-option",
|
|
87
|
+
scenario="callable-default",
|
|
88
|
+
title="An explicit callback preserves the dependency contract",
|
|
89
|
+
outcome=ExampleOutcome.NO_MATCH,
|
|
90
|
+
files=(
|
|
91
|
+
ExampleFile.python(
|
|
92
|
+
"tests/test_widget.py",
|
|
93
|
+
"def _read():\n return 'ready'\n"
|
|
94
|
+
"def _make_widget(*, read=_read):\n return Widget(read=read)\n"
|
|
95
|
+
"_make_widget()\n_make_widget(read=_read)\n",
|
|
96
|
+
),
|
|
97
|
+
),
|
|
98
|
+
focus_path=PurePosixPath("tests/test_widget.py"),
|
|
99
|
+
expected_count=0,
|
|
100
|
+
public=True,
|
|
101
|
+
),
|
|
66
102
|
RuleExample(
|
|
67
103
|
example_id="exercised-size-option",
|
|
68
104
|
title="Keep customization that a caller exercises",
|
|
@@ -96,14 +132,15 @@ class UnusedTestFactoryOption(Rule):
|
|
|
96
132
|
lines = context.source_lines
|
|
97
133
|
findings: list[Diagnostic] = []
|
|
98
134
|
for function in context.nodes(ast.FunctionDef):
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
not _is_factory(function)
|
|
102
|
-
or not isinstance(owner, ast.FunctionDef | ast.AsyncFunctionDef)
|
|
103
|
-
or not owner.name.startswith("test_")
|
|
104
|
-
):
|
|
135
|
+
if not _is_factory(function):
|
|
105
136
|
continue
|
|
106
|
-
|
|
137
|
+
owner = context.parents.get(function)
|
|
138
|
+
if isinstance(owner, ast.FunctionDef | ast.AsyncFunctionDef) and owner.name.startswith("test_"):
|
|
139
|
+
findings.extend(
|
|
140
|
+
_factory_findings(tree, function, path, lines, self.code, node_index=context.node_index)
|
|
141
|
+
)
|
|
142
|
+
elif owner is tree and path.name != "conftest.py":
|
|
143
|
+
findings.extend(_callable_factory_findings(context, function, self.code))
|
|
107
144
|
return sorted(findings, key=lambda item: (item.line, item.col))
|
|
108
145
|
|
|
109
146
|
|
|
@@ -280,3 +317,79 @@ def _factory_options(function: ast.FunctionDef) -> list[tuple[ast.arg, ast.expr]
|
|
|
280
317
|
]
|
|
281
318
|
used = {node.id for node in nodes(function, ast.Name) if isinstance(node.ctx, ast.Load)}
|
|
282
319
|
return [(argument, default) for argument, default in defaults if argument.arg in used and default is not None]
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _callable_factory_findings(context: PythonFileContext, function: ast.FunctionDef, code: str) -> list[Diagnostic]:
|
|
323
|
+
tree = context.tree
|
|
324
|
+
if tree is None:
|
|
325
|
+
return []
|
|
326
|
+
options = [(argument, default) for argument, default in _factory_options(function) if isinstance(default, ast.Name)]
|
|
327
|
+
if not options:
|
|
328
|
+
return []
|
|
329
|
+
calls = _direct_calls(tree, function, node_index=context.node_index)
|
|
330
|
+
if len(calls) < _MIN_INVARIANT_CALLS:
|
|
331
|
+
return []
|
|
332
|
+
bound = _bound_calls(function, calls)
|
|
333
|
+
if bound is None:
|
|
334
|
+
return []
|
|
335
|
+
supplied = {name for arguments in bound for name in arguments}
|
|
336
|
+
rebound = {node.id for node in nodes(function, ast.Name) if not isinstance(node.ctx, ast.Load)}
|
|
337
|
+
findings: list[Diagnostic] = []
|
|
338
|
+
for argument, default in options:
|
|
339
|
+
if (
|
|
340
|
+
argument.arg in supplied | rebound
|
|
341
|
+
or not _is_stable_local_callable(context, function, default.id)
|
|
342
|
+
or is_suppressed(context.source_lines, argument.lineno, code)
|
|
343
|
+
):
|
|
344
|
+
continue
|
|
345
|
+
findings.append(
|
|
346
|
+
Diagnostic(
|
|
347
|
+
path=context.path,
|
|
348
|
+
line=argument.lineno,
|
|
349
|
+
col=argument.col_offset + 1,
|
|
350
|
+
code=code,
|
|
351
|
+
severity=Severity.WARNING,
|
|
352
|
+
message=(
|
|
353
|
+
f"No known direct caller in this file supplies `{function.name}.{argument.arg}`; consider "
|
|
354
|
+
f"using the stable local callable `{default.id}` internally. Preserve default binding timing "
|
|
355
|
+
"and retain the option if external callers or an intentional test contract need it."
|
|
356
|
+
),
|
|
357
|
+
)
|
|
358
|
+
)
|
|
359
|
+
return findings
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def _is_stable_local_callable(context: PythonFileContext, factory: ast.FunctionDef, name: str) -> bool:
|
|
363
|
+
tree = context.tree
|
|
364
|
+
if tree is None or not any(
|
|
365
|
+
isinstance(node, ast.FunctionDef | ast.AsyncFunctionDef)
|
|
366
|
+
and node.name == name
|
|
367
|
+
and node.lineno < factory.lineno
|
|
368
|
+
and not node.decorator_list
|
|
369
|
+
for node in tree.body
|
|
370
|
+
):
|
|
371
|
+
return False
|
|
372
|
+
if not _has_unambiguous_factory_name(tree, name, node_index=context.node_index):
|
|
373
|
+
return False
|
|
374
|
+
return not (
|
|
375
|
+
any(node.id == name and not isinstance(node.ctx, ast.Load) for node in context.nodes(ast.Name))
|
|
376
|
+
or any(
|
|
377
|
+
not isinstance(node.ctx, ast.Load) and any(child.id == name for child in nodes(node.value, ast.Name))
|
|
378
|
+
for node in context.nodes(ast.Attribute, ast.Subscript)
|
|
379
|
+
)
|
|
380
|
+
or any(
|
|
381
|
+
isinstance(node.value, str) and (name in node.value.split(".") or factory.name in node.value.split("."))
|
|
382
|
+
for node in context.nodes(ast.Constant)
|
|
383
|
+
)
|
|
384
|
+
or _provider_escapes(context, name)
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def _provider_escapes(context: PythonFileContext, name: str) -> bool:
|
|
389
|
+
for node in context.nodes(ast.Name):
|
|
390
|
+
if node.id != name or not isinstance(node.ctx, ast.Load):
|
|
391
|
+
continue
|
|
392
|
+
parent = context.parents.get(node)
|
|
393
|
+
if not (isinstance(parent, ast.arguments) or (isinstance(parent, ast.Call) and parent.func is node)):
|
|
394
|
+
return True
|
|
395
|
+
return False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/_analysis_session.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_ast_index.py
RENAMED
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_ast_position.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_dict_key_views.py
RENAMED
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_first_party.py
RENAMED
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_fixed_record.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_local_source.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_nominal_project.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_project_index.py
RENAMED
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_prose_budget.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_set_fields.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_test_assertions.py
RENAMED
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/_test_composition.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/mock_without_spec.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_comment_cruft.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_dunder_all.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_secret_in_log.py
RENAMED
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/no_select_star.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/over_mocked_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_class_row.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_or_pattern.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/prefer_str_enum.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-1.16.2 → sarj_python_lint-1.16.3}/src/sarj_python_lint/rules/unused_mock_setup.py
RENAMED
|
File without changes
|