sarj-python-lint 1.25.7__tar.gz → 1.26.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/PKG-INFO +1 -1
  2. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/pyproject.toml +1 -1
  3. sarj_python_lint-1.26.2/src/sarj_python_lint/interpreter_argv.py +381 -0
  4. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_registry.py +2 -0
  5. sarj_python_lint-1.26.2/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +281 -0
  6. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/.gitignore +0 -0
  7. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/LICENSE +0 -0
  8. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/README.md +0 -0
  9. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/__init__.py +0 -0
  10. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/__main__.py +0 -0
  11. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_analysis_session.py +0 -0
  12. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_file_context.py +0 -0
  13. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_filesystem.py +0 -0
  14. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_python_target.py +0 -0
  15. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  16. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_secret_names.py +0 -0
  17. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_source.py +0 -0
  18. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_version.py +0 -0
  19. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/benchmark.py +0 -0
  20. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/json_boundary.py +0 -0
  21. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/py.typed +0 -0
  22. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/ratchet.py +0 -0
  23. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rule_base.py +0 -0
  24. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/__init__.py +0 -0
  25. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
  26. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_ast_index.py +0 -0
  27. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_ast_position.py +0 -0
  28. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_comments.py +0 -0
  29. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
  30. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_copy_on_write.py +0 -0
  31. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
  32. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  33. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  34. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_first_party.py +0 -0
  35. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
  36. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_imports.py +0 -0
  37. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_local_source.py +0 -0
  38. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_logging.py +0 -0
  39. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
  40. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_paths.py +0 -0
  41. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_project_index.py +0 -0
  42. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  43. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_pytest.py +0 -0
  44. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_resource_provenance.py +0 -0
  45. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_set_fields.py +0 -0
  46. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_sql.py +0 -0
  47. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  48. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  49. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_test_composition.py +0 -0
  50. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
  51. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
  52. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
  53. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
  54. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
  55. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  56. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  57. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
  58. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  59. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
  60. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  61. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  62. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  63. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  64. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
  65. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  66. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
  67. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
  68. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
  69. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
  70. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  71. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  72. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  73. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  74. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
  75. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
  76. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
  77. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  78. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
  79. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  80. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
  81. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  82. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
  83. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
  84. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  85. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  86. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
  87. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
  88. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
  89. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
  90. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  91. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
  92. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  93. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
  94. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
  95. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  96. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
  97. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
  98. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  99. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
  100. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  101. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  102. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  103. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  104. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  105. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
  106. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
  107. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  108. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
  109. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  110. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
  111. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  112. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  113. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  114. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
  115. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
  116. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
  117. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  118. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
  119. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  120. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  121. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  122. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
  123. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  124. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  125. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
  126. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
  127. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  128. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
  129. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  130. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  131. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
  132. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
  133. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
  134. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  135. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
  136. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
  137. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  138. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_native_string_check.py +0 -0
  139. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
  140. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  141. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  142. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
  143. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
  144. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
  145. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
  146. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  147. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  148. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  149. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  150. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  151. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
  152. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  153. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  154. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  155. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  156. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  157. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  158. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  159. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  160. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
  161. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  162. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
  163. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
  164. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
  165. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
  166. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
  167. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
  168. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  169. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
  170. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
  171. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  172. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
  173. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  174. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  175. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
  176. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/stepdown.py +0 -0
  177. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
  178. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  179. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
  180. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  181. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  182. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
  183. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  184. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
  185. {sarj_python_lint-1.25.7 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/unused_test_factory_option.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sarj-python-lint
3
- Version: 1.25.7
3
+ Version: 1.26.2
4
4
  Summary: Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults
5
5
  Project-URL: Homepage, https://code-standards.sarj.ai/rules/python/
6
6
  Project-URL: Documentation, https://code-standards.sarj.ai/rules/python/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sarj-python-lint"
3
- version = "1.25.7"
3
+ version = "1.26.2"
4
4
  description = "Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "sarj-ai" }]
@@ -0,0 +1,381 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import PurePosixPath
5
+ import re
6
+ from types import MappingProxyType
7
+ from typing import TYPE_CHECKING, Literal
8
+
9
+
10
+ if TYPE_CHECKING:
11
+ from collections.abc import Sequence
12
+
13
+
14
+ _SHORT_ATTACHED_LENGTH = 2
15
+
16
+
17
+ ProgramKind = Literal["external", "inline", "shell", "stdin", "other", "unknown"]
18
+
19
+
20
+ @dataclass(frozen=True, slots=True)
21
+ class InterpreterInvocation:
22
+ kind: ProgramKind
23
+ payload: str | None = None
24
+ forwarded: tuple[str, ...] = ()
25
+
26
+
27
+ @dataclass(frozen=True, slots=True)
28
+ class ParsedOption:
29
+ invocation: InterpreterInvocation | None = None
30
+ consumed: int = 1
31
+
32
+
33
+ _SHELLS = frozenset({"sh", "bash", "dash", "zsh", "ksh"})
34
+ _NODE_VALUE_FLAGS = frozenset(
35
+ {
36
+ "--require",
37
+ "--import",
38
+ "--loader",
39
+ "--experimental-loader",
40
+ "--input-type",
41
+ "--conditions",
42
+ "--inspect-port",
43
+ "--openssl-config",
44
+ "--icu-data-dir",
45
+ "--title",
46
+ }
47
+ )
48
+ _JQ_VALUE_FLAGS = MappingProxyType(
49
+ {"--arg": 2, "--argjson": 2, "--slurpfile": 2, "--rawfile": 2, "--indent": 1, "-L": 1}
50
+ )
51
+ _RUBY_VALUE_FLAGS = frozenset({"I", "r", "C", "X", "E"})
52
+ _RUBY_LONG_VALUE_FLAGS = frozenset(
53
+ {"--encoding", "--external-encoding", "--internal-encoding", "--backtrace-limit", "--enable", "--disable"}
54
+ )
55
+ _WRAPPER_VALUES = MappingProxyType(
56
+ {
57
+ "env": frozenset({"-u", "--unset", "-C", "--chdir"}),
58
+ "sudo": frozenset(
59
+ {
60
+ "-u",
61
+ "--user",
62
+ "-g",
63
+ "--group",
64
+ "-h",
65
+ "--host",
66
+ "-p",
67
+ "--prompt",
68
+ "-C",
69
+ "--close-from",
70
+ "-T",
71
+ "--command-timeout",
72
+ "-R",
73
+ "--chroot",
74
+ "-D",
75
+ "--chdir",
76
+ }
77
+ ),
78
+ "timeout": frozenset({"-s", "--signal", "-k", "--kill-after"}),
79
+ }
80
+ )
81
+ _MAX_WRAPPERS = 8
82
+
83
+
84
+ class UnprovableCommandError(ValueError):
85
+ """A wrapper executable position cannot be established safely."""
86
+
87
+
88
+ def unwrap_command(argv: Sequence[str]) -> tuple[str, ...]:
89
+ current = tuple(argv)
90
+ for _ in range(_MAX_WRAPPERS):
91
+ if not current:
92
+ return ()
93
+ command = PurePosixPath(current[0]).name
94
+ if command in {"exec", "command"}:
95
+ if command == "command" and any(argument in {"-v", "-V"} for argument in current[1:2]):
96
+ return current
97
+ current = current[_command_wrapper_index(current, command) :]
98
+ continue
99
+ if command not in _WRAPPER_VALUES:
100
+ return current
101
+ current = current[_value_wrapper_index(current, command) :]
102
+ msg = "command wrapper nesting exceeds analysis bound"
103
+ raise UnprovableCommandError(msg)
104
+
105
+
106
+ def _command_wrapper_index(arguments: Sequence[str], command: str) -> int:
107
+ index = 1
108
+ while index < len(arguments) and arguments[index].startswith("-"):
109
+ argument = arguments[index]
110
+ if argument == "--":
111
+ return index + 1
112
+ if command == "exec" and argument == "-a":
113
+ index += 2
114
+ continue
115
+ if argument not in {"-p", "-c", "-l"}:
116
+ msg = "unsupported command wrapper option"
117
+ raise UnprovableCommandError(msg)
118
+ index += 1
119
+ return index
120
+
121
+
122
+ def _value_wrapper_index(arguments: Sequence[str], command: str) -> int:
123
+ index = 1
124
+ while index < len(arguments):
125
+ argument = arguments[index]
126
+ if argument == "--":
127
+ index += 1
128
+ break
129
+ if command == "env" and re.match(r"^[A-Za-z_][A-Za-z0-9_]*=", argument):
130
+ index += 1
131
+ continue
132
+ if not argument.startswith("-") or argument == "-":
133
+ break
134
+ if command == "env" and argument in {"-S", "--split-string"}:
135
+ msg = "env split-string has a separate unproven quoting grammar"
136
+ raise UnprovableCommandError(msg)
137
+ index += 2 if argument in _WRAPPER_VALUES[command] else 1
138
+ # Timeout's positional duration precedes its executable.
139
+ return index + int(command == "timeout")
140
+
141
+
142
+ def is_python_executable(executable: str) -> bool:
143
+ return re.fullmatch(r"python(?:[23](?:\.\d+)?)?", PurePosixPath(executable).name) is not None
144
+
145
+
146
+ def classify_interpreter(argv: Sequence[str]) -> InterpreterInvocation:
147
+ try:
148
+ arguments = unwrap_command(argv)
149
+ except UnprovableCommandError:
150
+ return InterpreterInvocation("unknown")
151
+ if not arguments:
152
+ return InterpreterInvocation("other")
153
+ executable = PurePosixPath(arguments[0]).name
154
+ if is_python_executable(executable):
155
+ return _python(arguments[1:])
156
+ if executable in _SHELLS:
157
+ return _short_options(arguments[1:], source="c", values=frozenset({"o", "O"}), shell_mode=True)
158
+ if executable in {"node", "nodejs"}:
159
+ return _node(arguments[1:])
160
+ if executable == "jq":
161
+ return _jq(arguments[1:])
162
+ if executable in {"awk", "gawk", "mawk", "nawk"}:
163
+ return _awk(arguments[1:])
164
+ if executable == "ruby":
165
+ return _ruby(arguments[1:])
166
+ if executable in {"perl", "php"}:
167
+ return _short_options(arguments[1:], source={"perl": "eE", "php": "r"}[executable], values=frozenset({"I"}))
168
+ return InterpreterInvocation("other")
169
+
170
+
171
+ def _python(arguments: Sequence[str]) -> InterpreterInvocation:
172
+ index = 0
173
+ while index < len(arguments):
174
+ boundary = _external_boundary(arguments, index)
175
+ if boundary is not None:
176
+ return boundary
177
+ argument = arguments[index]
178
+ if argument.startswith("--"):
179
+ return InterpreterInvocation(
180
+ "external"
181
+ if argument in {"--help", "--version", "--help-env", "--help-xoptions", "--help-all"}
182
+ else "unknown"
183
+ )
184
+ parsed = _python_short_option(argument, _following_operand(arguments, index))
185
+ if parsed.invocation is not None:
186
+ return parsed.invocation
187
+ index += parsed.consumed
188
+ return InterpreterInvocation("stdin")
189
+
190
+
191
+ def _python_short_option(argument: str, following: str | None) -> ParsedOption:
192
+ for cursor, flag in enumerate(argument[1:], 1):
193
+ if flag in {"h", "V"}:
194
+ return ParsedOption(InterpreterInvocation("external"))
195
+ if flag in {"c", "m", "W", "X"}:
196
+ attached = argument[cursor + 1 :]
197
+ operand = attached or following
198
+ if operand is None:
199
+ return ParsedOption(InterpreterInvocation("unknown"))
200
+ if flag == "c":
201
+ return ParsedOption(InterpreterInvocation("inline", operand))
202
+ if flag == "m":
203
+ return ParsedOption(InterpreterInvocation("external", operand))
204
+ return ParsedOption(consumed=1 + int(not attached))
205
+ if flag not in "bBdEhiIOPqRsSuvVx":
206
+ return ParsedOption(InterpreterInvocation("unknown"))
207
+ return ParsedOption()
208
+
209
+
210
+ def _ruby(arguments: Sequence[str]) -> InterpreterInvocation:
211
+ index = 0
212
+ while index < len(arguments):
213
+ boundary = _external_boundary(arguments, index)
214
+ if boundary is not None:
215
+ return boundary
216
+ parsed = _ruby_option(arguments, index)
217
+ if parsed.invocation is not None:
218
+ return parsed.invocation
219
+ index += parsed.consumed
220
+ return InterpreterInvocation("stdin")
221
+
222
+
223
+ def _ruby_option(arguments: Sequence[str], index: int) -> ParsedOption:
224
+ argument = arguments[index]
225
+ if argument.startswith("--"):
226
+ return _ruby_long_option(argument, _following_operand(arguments, index))
227
+ if re.fullmatch(r"-(?:0[0-7]{0,3}|W[0-2]?)", argument):
228
+ return ParsedOption()
229
+ for cursor, flag in enumerate(argument[1:], 1):
230
+ if flag == "h":
231
+ return ParsedOption(InterpreterInvocation("external"))
232
+ if flag in "Fix":
233
+ # These operands are attached only and consume the rest of this word.
234
+ return ParsedOption()
235
+ if flag == "e" or flag in _RUBY_VALUE_FLAGS:
236
+ if cursor + 1 == len(argument) and _following_operand(arguments, index) is None:
237
+ return ParsedOption(InterpreterInvocation("unknown"))
238
+ return _short_option(arguments, index, source="e", values=_RUBY_VALUE_FLAGS, shell_mode=False)
239
+ if flag not in "acdlnpsSvwU":
240
+ return ParsedOption(InterpreterInvocation("unknown"))
241
+ return ParsedOption()
242
+
243
+
244
+ def _ruby_long_option(argument: str, following: str | None) -> ParsedOption:
245
+ if argument in {"--help", "--version"}:
246
+ return ParsedOption(InterpreterInvocation("external"))
247
+ if argument in {"--debug", "--verbose", "--copyright"}:
248
+ return ParsedOption()
249
+ name, separator, _operand = argument.partition("=")
250
+ if name in _RUBY_LONG_VALUE_FLAGS and (separator or following is not None):
251
+ return ParsedOption(consumed=1 + int(not separator))
252
+ return ParsedOption(InterpreterInvocation("unknown"))
253
+
254
+
255
+ def _short_options(
256
+ arguments: Sequence[str], *, source: str, values: frozenset[str], shell_mode: bool = False
257
+ ) -> InterpreterInvocation:
258
+ index = 0
259
+ while index < len(arguments):
260
+ boundary = _external_boundary(arguments, index, plus_options=True)
261
+ if boundary is not None:
262
+ return boundary
263
+ argument = arguments[index]
264
+ if argument.startswith("--"):
265
+ index += 2 if shell_mode and argument in {"--rcfile", "--init-file"} else 1
266
+ continue
267
+ parsed = _short_option(arguments, index, source=source, values=values, shell_mode=shell_mode)
268
+ if parsed.invocation is not None:
269
+ return parsed.invocation
270
+ index += parsed.consumed
271
+ return InterpreterInvocation("stdin")
272
+
273
+
274
+ def _short_option(
275
+ arguments: Sequence[str], index: int, *, source: str, values: frozenset[str], shell_mode: bool
276
+ ) -> ParsedOption:
277
+ argument = arguments[index]
278
+ for cursor, flag in enumerate(argument[1:], 1):
279
+ if flag in source:
280
+ # Shell -c always consumes the next word, including inside -ceu.
281
+ attached = "" if shell_mode else argument[cursor + 1 :]
282
+ operand = attached or _following_operand(arguments, index)
283
+ forwarded = tuple(arguments[index + 3 :]) if shell_mode else ()
284
+ return ParsedOption(InterpreterInvocation("shell" if shell_mode else "inline", operand, forwarded))
285
+ if flag in values:
286
+ return ParsedOption(consumed=1 + int(cursor + 1 == len(argument)))
287
+ return ParsedOption()
288
+
289
+
290
+ def _node(arguments: Sequence[str]) -> InterpreterInvocation:
291
+ index = 0
292
+ while index < len(arguments):
293
+ boundary = _external_boundary(arguments, index)
294
+ if boundary is not None:
295
+ return boundary
296
+ argument = arguments[index]
297
+ inline = _node_source_option(argument, _following_operand(arguments, index))
298
+ if inline is not None:
299
+ return inline
300
+ index += 2 if argument in _NODE_VALUE_FLAGS or argument in {"-r", "-C"} else 1
301
+ return InterpreterInvocation("stdin")
302
+
303
+
304
+ def _node_source_option(argument: str, following: str | None) -> InterpreterInvocation | None:
305
+ if argument.split("=", 1)[0] in {"--eval", "--print"}:
306
+ operand = argument.split("=", 1)[1] if "=" in argument else following
307
+ return InterpreterInvocation("inline", operand)
308
+ if argument.startswith("--"):
309
+ return None
310
+ for flag in argument[1:]:
311
+ if flag in "ep":
312
+ return InterpreterInvocation("inline")
313
+ if flag in "rC":
314
+ break
315
+ return None
316
+
317
+
318
+ def _external_boundary(
319
+ arguments: Sequence[str], index: int, *, plus_options: bool = False
320
+ ) -> InterpreterInvocation | None:
321
+ argument = arguments[index]
322
+ if argument == "--":
323
+ return InterpreterInvocation("external" if index + 1 < len(arguments) else "stdin")
324
+ if argument == "-":
325
+ return InterpreterInvocation("stdin")
326
+ prefixes = ("-", "+") if plus_options else ("-",)
327
+ return None if argument.startswith(prefixes) else InterpreterInvocation("external")
328
+
329
+
330
+ def _following_operand(arguments: Sequence[str], index: int) -> str | None:
331
+ return arguments[index + 1] if index + 1 < len(arguments) else None
332
+
333
+
334
+ def _jq(arguments: Sequence[str]) -> InterpreterInvocation:
335
+ index = 0
336
+ while index < len(arguments):
337
+ argument = arguments[index]
338
+ if (
339
+ argument in {"-f", "--from-file"}
340
+ or argument.startswith("--from-file=")
341
+ or (argument.startswith("-f") and len(argument) > _SHORT_ATTACHED_LENGTH)
342
+ ):
343
+ return InterpreterInvocation("external")
344
+ if argument.startswith("-") and not argument.startswith("--") and "f" in argument[1:]:
345
+ return InterpreterInvocation("external")
346
+ if argument == "--":
347
+ return InterpreterInvocation("inline" if index + 1 < len(arguments) else "other")
348
+ if not argument.startswith("-"):
349
+ return InterpreterInvocation("inline", argument)
350
+ index += 1 + _JQ_VALUE_FLAGS.get(argument, 0)
351
+ return InterpreterInvocation("other")
352
+
353
+
354
+ def _awk(arguments: Sequence[str]) -> InterpreterInvocation:
355
+ index = 0
356
+ external = False
357
+ while index < len(arguments):
358
+ argument = arguments[index]
359
+ if argument in {"-f", "--file", "-E", "--exec"}:
360
+ external = True
361
+ index += 2
362
+ continue
363
+ if argument.startswith(("--file=", "--exec=")) or (
364
+ argument.startswith(("-f", "-E")) and len(argument) > _SHORT_ATTACHED_LENGTH
365
+ ):
366
+ external = True
367
+ elif (
368
+ argument in {"-e", "--source"}
369
+ or argument.startswith("--source=")
370
+ or (argument.startswith("-e") and len(argument) > _SHORT_ATTACHED_LENGTH)
371
+ ):
372
+ return InterpreterInvocation("inline")
373
+ elif argument in {"-F", "-v", "--field-separator", "--assign"}:
374
+ index += 2
375
+ continue
376
+ elif argument == "--":
377
+ return InterpreterInvocation("external" if external else "inline")
378
+ elif not argument.startswith("-"):
379
+ return InterpreterInvocation("external" if external else "inline", argument)
380
+ index += 1
381
+ return InterpreterInvocation("external" if external else "other")
@@ -62,6 +62,7 @@ from sarj_python_lint.rules.no_hidden_constructor_fallback import (
62
62
  )
63
63
  from sarj_python_lint.rules.no_injected_module_loader import NoInjectedModuleLoader
64
64
  from sarj_python_lint.rules.no_input_model_mutation import NoInputModelMutation
65
+ from sarj_python_lint.rules.no_interpreter_source_arguments import NoInterpreterSourceArguments
65
66
  from sarj_python_lint.rules.no_invalid_argument_name_suppression import NoInvalidArgumentNameSuppression
66
67
  from sarj_python_lint.rules.no_mocked_pydantic_value_object import NoMockedPydanticValueObject
67
68
  from sarj_python_lint.rules.no_nested_pydantic_field_validator import NoNestedPydanticFieldValidator
@@ -207,6 +208,7 @@ if TYPE_CHECKING:
207
208
 
208
209
  REGISTRY: Mapping[str, type[Rule]] = MappingProxyType(
209
210
  {
211
+ NoInterpreterSourceArguments.id: NoInterpreterSourceArguments,
210
212
  NoUnusedCopyResult.id: NoUnusedCopyResult,
211
213
  NoBeforeValidatorInputMutation.id: NoBeforeValidatorInputMutation,
212
214
  NoInputModelMutation.id: NoInputModelMutation,