sarj-python-lint 1.26.1__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.26.1 → sarj_python_lint-1.26.2}/PKG-INFO +1 -1
  2. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/pyproject.toml +1 -1
  3. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/interpreter_argv.py +5 -1
  4. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +95 -5
  5. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/.gitignore +0 -0
  6. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/LICENSE +0 -0
  7. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/README.md +0 -0
  8. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/__init__.py +0 -0
  9. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/__main__.py +0 -0
  10. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_analysis_session.py +0 -0
  11. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_file_context.py +0 -0
  12. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_filesystem.py +0 -0
  13. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_python_target.py +0 -0
  14. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  15. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_secret_names.py +0 -0
  16. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_source.py +0 -0
  17. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/_version.py +0 -0
  18. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/benchmark.py +0 -0
  19. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/json_boundary.py +0 -0
  20. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/py.typed +0 -0
  21. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/ratchet.py +0 -0
  22. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rule_base.py +0 -0
  23. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/__init__.py +0 -0
  24. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
  25. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_ast_index.py +0 -0
  26. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_ast_position.py +0 -0
  27. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_comments.py +0 -0
  28. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
  29. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_copy_on_write.py +0 -0
  30. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
  31. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  32. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  33. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_first_party.py +0 -0
  34. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
  35. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_imports.py +0 -0
  36. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_local_source.py +0 -0
  37. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_logging.py +0 -0
  38. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
  39. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_paths.py +0 -0
  40. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_project_index.py +0 -0
  41. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  42. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_pytest.py +0 -0
  43. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_registry.py +0 -0
  44. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_resource_provenance.py +0 -0
  45. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_set_fields.py +0 -0
  46. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_sql.py +0 -0
  47. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  48. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  49. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_test_composition.py +0 -0
  50. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
  51. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
  52. {sarj_python_lint-1.26.1 → 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.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
  55. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  56. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  57. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
  58. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  59. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
  60. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  61. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  62. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  63. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  64. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
  65. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  66. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
  68. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
  69. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
  70. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  71. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  72. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  73. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  74. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
  75. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
  76. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
  77. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  78. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
  79. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  80. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  82. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
  83. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  85. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  86. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
  87. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
  88. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
  89. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
  90. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  91. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
  92. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  93. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
  94. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  96. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
  97. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  99. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
  100. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  101. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  102. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  103. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  104. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  105. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
  106. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
  107. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  108. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
  109. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  110. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
  111. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  112. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  113. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  114. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
  115. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
  116. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
  117. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  118. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  120. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  121. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  122. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
  123. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  124. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  125. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
  126. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
  127. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  128. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
  129. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  130. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  131. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
  132. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
  133. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
  134. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  135. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
  137. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  138. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_native_string_check.py +0 -0
  139. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
  140. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  141. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  142. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
  143. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
  144. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
  145. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
  146. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  147. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  148. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  149. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  150. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  151. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
  152. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  153. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  154. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  155. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  156. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  157. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  158. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  159. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  160. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  162. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
  163. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
  164. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
  165. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
  166. {sarj_python_lint-1.26.1 → 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.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  169. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
  170. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
  171. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  172. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
  173. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  174. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  175. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
  176. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/stepdown.py +0 -0
  177. {sarj_python_lint-1.26.1 → 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.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  179. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
  180. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  181. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  182. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
  183. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  184. {sarj_python_lint-1.26.1 → sarj_python_lint-1.26.2}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
  185. {sarj_python_lint-1.26.1 → 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.26.1
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.26.1"
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" }]
@@ -139,6 +139,10 @@ def _value_wrapper_index(arguments: Sequence[str], command: str) -> int:
139
139
  return index + int(command == "timeout")
140
140
 
141
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
+
142
146
  def classify_interpreter(argv: Sequence[str]) -> InterpreterInvocation:
143
147
  try:
144
148
  arguments = unwrap_command(argv)
@@ -147,7 +151,7 @@ def classify_interpreter(argv: Sequence[str]) -> InterpreterInvocation:
147
151
  if not arguments:
148
152
  return InterpreterInvocation("other")
149
153
  executable = PurePosixPath(arguments[0]).name
150
- if re.fullmatch(r"python(?:[23](?:\.\d+)?)?", executable):
154
+ if is_python_executable(executable):
151
155
  return _python(arguments[1:])
152
156
  if executable in _SHELLS:
153
157
  return _short_options(arguments[1:], source="c", values=frozenset({"o", "O"}), shell_mode=True)
@@ -2,10 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  import ast
4
4
  from dataclasses import dataclass
5
+ import io
5
6
  from pathlib import PurePosixPath
6
7
  from typing import TYPE_CHECKING, ClassVar, final, override
7
8
 
8
- from sarj_python_lint.interpreter_argv import classify_interpreter
9
+ from sarj_python_lint.interpreter_argv import classify_interpreter, is_python_executable, unwrap_command
9
10
  from sarj_python_lint.rule_base import (
10
11
  AutofixPolicy,
11
12
  Diagnostic,
@@ -45,8 +46,8 @@ class NoInterpreterSourceArguments(ProjectRule):
45
46
  code = "SARJ484"
46
47
  documentation: ClassVar[RuleDocumentation | None] = RuleDocumentation(
47
48
  default_level=Severity.ERROR,
48
- summary="Keep interpreter programs in linted files or modules, outside process argv.",
49
- rationale="Moving deployment logic from YAML into Python still bypasses language checks when the Python wrapper passes program source through interpreter flags or jq/awk argv.",
49
+ summary="Keep interpreter programs in linted files or modules, outside process argv and literal Python stdin.",
50
+ rationale="Moving deployment logic from YAML into Python still bypasses language checks when the Python wrapper passes program source through interpreter flags, jq/awk argv, or literal Python stdin.",
50
51
  remediation="Invoke a repository-owned file or module covered by the normal language checks; pass configuration as arguments rather than interpreter source.",
51
52
  category=RuleCategory.ARCHITECTURE,
52
53
  autofix=AutofixPolicy.NONE,
@@ -54,6 +55,7 @@ class NoInterpreterSourceArguments(ProjectRule):
54
55
  "Only import-proven subprocess process APIs, asyncio.create_subprocess_exec, and os exec/spawn argv APIs with literal string vectors are checked. Import aliases are followed; shadowed or reassigned imports and methods abstain.",
55
56
  "Script/module and interpreter option boundaries use the shared dependency-free classifier, including env/sudo/timeout wrappers and jq/awk file flags.",
56
57
  "Dynamic argv, shell strings and shell=True, recursive shell payloads, receiver-based remote execution, and unknown interpreter option grammars are outside this narrow rule. A clean result does not prove those programs are linted.",
58
+ "Literal str/bytes input to subprocess.run/check_output is checked only for proven Python stdin invocations and compatible constant text/binary modes. Dynamic input, Popen.communicate, and asyncio stdin abstain.",
57
59
  "Generated/vendor sources are excluded; maintained tests are checked. Source-checker fixtures may use an exact reasoned suppression.",
58
60
  ),
59
61
  examples=(
@@ -85,6 +87,36 @@ class NoInterpreterSourceArguments(ProjectRule):
85
87
  expected_count=0,
86
88
  public=True,
87
89
  ),
90
+ RuleExample(
91
+ example_id="literal-python-stdin",
92
+ scenario="stdin",
93
+ title="Process stdin contains unchecked Python source",
94
+ outcome=ExampleOutcome.MATCH,
95
+ files=(
96
+ ExampleFile.python(
97
+ "tools/check.py",
98
+ "import subprocess\nsubprocess.run(['python3', '-'], input='print(1)', text=True)\n",
99
+ ),
100
+ ),
101
+ focus_path=PurePosixPath("tools/check.py"),
102
+ expected_count=1,
103
+ public=True,
104
+ ),
105
+ RuleExample(
106
+ example_id="external-module-stdin-data",
107
+ scenario="stdin",
108
+ title="An external module receives stdin as data",
109
+ outcome=ExampleOutcome.NO_MATCH,
110
+ files=(
111
+ ExampleFile.python(
112
+ "tools/check.py",
113
+ "import subprocess\nsubprocess.run(['python3', '-m', 'tools.verify'], input='print(1)', text=True)\n",
114
+ ),
115
+ ),
116
+ focus_path=PurePosixPath("tools/check.py"),
117
+ expected_count=0,
118
+ public=True,
119
+ ),
88
120
  ),
89
121
  )
90
122
  description = documentation.summary
@@ -106,7 +138,13 @@ class NoInterpreterSourceArguments(ProjectRule):
106
138
  if sink is None or sink in replaced or is_suppressed(context.source_lines, call.lineno, self.code):
107
139
  continue
108
140
  argv = _literal_argv(call, sink)
109
- if argv is None or classify_interpreter(argv).kind != "inline":
141
+ if argv is None:
142
+ continue
143
+ kind = classify_interpreter(argv).kind
144
+ channel = "process argv" if kind == "inline" else None
145
+ if kind == "stdin" and _literal_python_stdin(call, sink, argv):
146
+ channel = "process stdin"
147
+ if channel is None:
110
148
  continue
111
149
  findings.append(
112
150
  Diagnostic(
@@ -114,13 +152,65 @@ class NoInterpreterSourceArguments(ProjectRule):
114
152
  line=call.lineno,
115
153
  col=call.col_offset + 1,
116
154
  code=self.code,
117
- message="Interpreter source is embedded in process argv; invoke a linted repository-owned file or module instead.",
155
+ message=f"Interpreter source is embedded in {channel}; invoke a linted repository-owned file or module instead.",
118
156
  severity=Severity.ERROR,
119
157
  )
120
158
  )
121
159
  return findings
122
160
 
123
161
 
162
+ def _literal_python_stdin(call: ast.Call, sink: str, argv: tuple[str, ...]) -> bool:
163
+ if sink not in {"subprocess.run", "subprocess.check_output"}:
164
+ return False
165
+ arguments = unwrap_command(argv) # The shared classifier already proved these wrappers.
166
+ if not arguments or not is_python_executable(arguments[0]):
167
+ return False
168
+ literal = _argument(call, "input", len(call.args))
169
+ if not isinstance(literal, ast.Constant) or not isinstance(literal.value, (str, bytes)):
170
+ return False
171
+ if not _compatible_stdin(call, literal.value):
172
+ return False
173
+ try:
174
+ return bool(ast.parse(literal.value).body)
175
+ except SyntaxError, ValueError:
176
+ return True
177
+
178
+
179
+ def _compatible_stdin(call: ast.Call, payload: str | bytes) -> bool:
180
+ modes: dict[str, object] = {}
181
+ for name in ("stdin", "text", "universal_newlines", "encoding", "errors"):
182
+ option = _argument(call, name, len(call.args))
183
+ if option is not None and not isinstance(option, ast.Constant):
184
+ return False
185
+ modes[name] = option.value if isinstance(option, ast.Constant) else None
186
+ if modes["stdin"] is not None:
187
+ return False
188
+ text, universal = modes["text"], modes["universal_newlines"]
189
+ if text not in {None, True, False} or universal not in {None, True, False}:
190
+ return False
191
+ if text is not None and universal is not None and bool(text) != bool(universal):
192
+ return False
193
+ encoding, errors = modes["encoding"], modes["errors"]
194
+ if encoding is not None and not isinstance(encoding, str):
195
+ return False
196
+ if errors is not None and not isinstance(errors, str):
197
+ return False
198
+ text_mode = bool(text or universal or encoding or errors)
199
+ if isinstance(payload, str) != text_mode:
200
+ return False
201
+ return not isinstance(payload, str) or _text_input_valid(payload, encoding, errors)
202
+
203
+
204
+ def _text_input_valid(payload: str, encoding: str | None, errors: str | None) -> bool:
205
+ try:
206
+ with io.TextIOWrapper(io.BytesIO(), encoding=encoding, errors=errors) as stream:
207
+ stream.write(payload)
208
+ stream.flush()
209
+ except LookupError, UnicodeError, ValueError:
210
+ return False
211
+ return True
212
+
213
+
124
214
  def _literal_argv(call: ast.Call, sink: str) -> tuple[str, ...] | None:
125
215
  if any(keyword.arg is None for keyword in call.keywords):
126
216
  return None # Expanded options can replace the executable or enable shell=True.