sarj-python-lint 1.97.0__tar.gz → 1.100.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/PKG-INFO +1 -1
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/pyproject.toml +1 -1
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/__main__.py +1 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_rule_descriptors.py +9 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_registry.py +2 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_resource_provenance.py +2 -1
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_sql.py +9 -2
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_store_sql.py +5 -1
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +71 -38
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +4 -3
- sarj_python_lint-1.100.0/src/sarj_python_lint/rules/no_custom_control_flow_exception.py +476 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_optional_composite.py +122 -19
- sarj_python_lint-1.100.0/src/sarj_python_lint/rules/service_singleton_delegates_to_bulk.py +515 -0
- sarj_python_lint-1.97.0/src/sarj_python_lint/rules/no_custom_control_flow_exception.py +0 -251
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/.gitignore +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/LICENSE +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/README.md +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_analysis_session.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_aliases.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_annotations.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_comments.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_declared_contracts.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_declared_tests.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_docs.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_enums.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_exhaustiveness.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_inert.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_parameters.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_repeated.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_security.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_sql_projection.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_autofix_tests.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_file_context.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_filesystem.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_fixes.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_parallel.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_prepared_sources.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_python_target.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_source.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/application_logging.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/autofix.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/benchmark.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/cast_access.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/interpreter_argv.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/json_boundary.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rule_metadata.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_annotation_origins.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_ast_names.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_ast_position.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_async_lifecycle.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_binding_inventory.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_closed_helpers.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_comment_narration.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_comments.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_copy_on_write.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_data_union_discriminator.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_declared_contracts.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_docstrings.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_exports.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_fastapi.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_imports.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_inert_model_annotation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_inherited_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_local_alias_fix.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_local_source.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_mapping_shape_callbacks.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_namespace_access.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_native_namespace_capability.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_native_object_contracts.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_numeric_proof.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_opaque_contracts.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_postgres.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_project_index.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_pydantic_field_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_resolved_operation_signature.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_route_shapes.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_runtime_bindings.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_runtime_registry.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_service_http_callbacks.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_set_fields.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_sql_aggregate_identity.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_sql_explain.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_sql_policy_source.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_static_json_alias.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_store_writes.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_test_composition.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_transactional_sql.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_type_guard_symbols.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/async_executor_shutdown.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/async_subprocess_cancellation_cleanup.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/cancel_owned_task_without_join.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/delete_route_returns_no_content.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/duplicate_adjacent_exception_handler.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/duplicate_closed_pure_helper.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/duplicate_pytest_fixture_params.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/failed_probe_zero_threshold.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/nan_hidden_by_builtin_min.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_async_client_in_constructor.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_async_function_cache.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_blanket_suppression.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_conflicting_pydantic_alias_validation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_contradictory_type_guard.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_create_verb_in_post_path.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_defaulted_environment_setting.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_discarded_tagged_outcome.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_discarded_validation_result.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_dual_shape_model_field_reader.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_duplicate_field_validator_body.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_exception_text_in_500_detail.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_fixed_sleep_in_loop.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_folded_bad_request_not_found.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_generic_json_parser.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_hasattr.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_impossible_pydantic_field_bounds.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_invalid_pydantic_bypass.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_invalid_pydantic_validator_return.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_loguru_exc_info.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_loguru_printf_format.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_mutating_container_transform.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_mutating_input_with_result.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_partial_type_is.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_recording_store.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_redundant_attribute_unpacking.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_redundant_local_alias.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_redundant_sql_alias.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_shallow_record_type_guard.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_slash_collection_root_under_prefix.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_test_comments.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_unknown_pydantic_validator_field.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/no_work_verb_get_route.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_application_model_joins.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_bulk_upsert.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_declarative_batch_validation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_direct_import_module.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_discriminated_model_union.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_grouped_settings.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_native_string_check.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_precise_object_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_psycopg_executemany.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_pydantic_model_assertion.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_pytest_dependency_fixtures.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_pytest_fixture_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_runtime_validation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_typed_cli.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_typed_mapping_get.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_typed_settings_field.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/pytest_fixture_returns_closed_resource.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/redundant_test_constructor_forwarder.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/repeated_unimplemented_test_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_constrained_api_integer.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_exp_on_jwt_decode.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_injectable_retry_sleep.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_pydantic_for_mapping_shape.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/stepdown.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/store_field_update_reuses_upsert.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/store_insert_requires_explicit_conflict_policy.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/store_mutation_command_fanout.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/test_without_explicit_oracle.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/unused_test_factory_option.py +0 -0
- {sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/suppression_policy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sarj-python-lint
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.100.0
|
|
4
4
|
Summary: Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults
|
|
5
5
|
Project-URL: Homepage, https://code-standards.sarj.ai/rules/python/
|
|
6
6
|
Project-URL: Documentation, https://code-standards.sarj.ai/rules/python/
|
{sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/_rule_descriptors.py
RENAMED
|
@@ -8,6 +8,15 @@ from sarj_python_lint.rule_metadata import RuleDescriptor
|
|
|
8
8
|
|
|
9
9
|
SCHEMA_VERSION = 1
|
|
10
10
|
DESCRIPTORS: tuple[RuleDescriptor, ...] = (
|
|
11
|
+
RuleDescriptor(
|
|
12
|
+
rule_id=RuleId("service-singleton-delegates-to-bulk"),
|
|
13
|
+
module="sarj_python_lint.rules.service_singleton_delegates_to_bulk",
|
|
14
|
+
class_name="ServiceSingletonDelegatesToBulk",
|
|
15
|
+
code="SARJ556",
|
|
16
|
+
description="Service singleton CRUD operations must delegate to a bulk primitive.",
|
|
17
|
+
aliases=(),
|
|
18
|
+
enabled_by_default=True,
|
|
19
|
+
),
|
|
11
20
|
RuleDescriptor(
|
|
12
21
|
rule_id=RuleId("no-async-client-in-constructor"),
|
|
13
22
|
module="sarj_python_lint.rules.no_async_client_in_constructor",
|
{sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_registry.py
RENAMED
|
@@ -272,6 +272,7 @@ from sarj_python_lint.rules.pytest_fixture_returns_closed_resource import Pytest
|
|
|
272
272
|
from sarj_python_lint.rules.redundant_test_constructor_forwarder import RedundantTestConstructorForwarder
|
|
273
273
|
from sarj_python_lint.rules.repeated_unimplemented_test_contract import RepeatedUnimplementedTestContract
|
|
274
274
|
from sarj_python_lint.rules.require_exp_on_jwt_decode import RequireExpOnJwtDecode
|
|
275
|
+
from sarj_python_lint.rules.service_singleton_delegates_to_bulk import ServiceSingletonDelegatesToBulk
|
|
275
276
|
from sarj_python_lint.rules.store_field_update_reuses_upsert import StoreFieldUpdateReusesUpsert
|
|
276
277
|
from sarj_python_lint.rules.store_insert_requires_explicit_conflict_policy import (
|
|
277
278
|
StoreInsertRequiresExplicitConflictPolicy,
|
|
@@ -282,6 +283,7 @@ from sarj_python_lint.rules.test_without_explicit_oracle import NoExplicitTestOr
|
|
|
282
283
|
|
|
283
284
|
_AUTHORING_REGISTRY: Mapping[str, type[Rule]] = MappingProxyType(
|
|
284
285
|
{
|
|
286
|
+
ServiceSingletonDelegatesToBulk.id: ServiceSingletonDelegatesToBulk,
|
|
285
287
|
NoAsyncClientInConstructor.id: NoAsyncClientInConstructor,
|
|
286
288
|
NoDiscardedTaggedOutcome.id: NoDiscardedTaggedOutcome,
|
|
287
289
|
StoreInsertRequiresExplicitConflictPolicy.id: StoreInsertRequiresExplicitConflictPolicy,
|
|
@@ -308,7 +308,8 @@ class ResourceProvenance:
|
|
|
308
308
|
or (
|
|
309
309
|
isinstance(parent, ast.FunctionDef | ast.AsyncFunctionDef | ast.ClassDef)
|
|
310
310
|
and node in parent.decorator_list
|
|
311
|
-
and self.context.imports.resolved_qualified_name(node)
|
|
311
|
+
and self.context.imports.resolved_qualified_name(node)
|
|
312
|
+
in {"typing.final", "typing_extensions.final", "dataclasses.dataclass"}
|
|
312
313
|
)
|
|
313
314
|
)
|
|
314
315
|
|
|
@@ -27,11 +27,18 @@ def is_store_module(path: Path) -> bool:
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def sql_string_value(node: ast.expr, *, interpolation_placeholder: str = " ") -> str | None:
|
|
30
|
+
try:
|
|
31
|
+
return _sql_string_value(node, interpolation_placeholder=interpolation_placeholder)
|
|
32
|
+
except RecursionError:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _sql_string_value(node: ast.expr, *, interpolation_placeholder: str) -> str | None:
|
|
30
37
|
if isinstance(node, ast.Constant) and isinstance(node.value, str):
|
|
31
38
|
return node.value
|
|
32
39
|
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.Add):
|
|
33
|
-
left =
|
|
34
|
-
right =
|
|
40
|
+
left = _sql_string_value(node.left, interpolation_placeholder=interpolation_placeholder)
|
|
41
|
+
right = _sql_string_value(node.right, interpolation_placeholder=interpolation_placeholder)
|
|
35
42
|
if left is not None and right is not None:
|
|
36
43
|
return left + right
|
|
37
44
|
if isinstance(node, ast.JoinedStr):
|
{sarj_python_lint-1.97.0 → sarj_python_lint-1.100.0}/src/sarj_python_lint/rules/_store_sql.py
RENAMED
|
@@ -46,7 +46,11 @@ class _MethodWrites:
|
|
|
46
46
|
|
|
47
47
|
def store_queries(context: PythonFileContext) -> Iterator[StoreQuery]:
|
|
48
48
|
if context.store_queries is None:
|
|
49
|
-
|
|
49
|
+
try:
|
|
50
|
+
queries = tuple(recover_store_queries(context))
|
|
51
|
+
except RecursionError:
|
|
52
|
+
queries = ()
|
|
53
|
+
context.store_queries = queries
|
|
50
54
|
return iter(context.store_queries)
|
|
51
55
|
|
|
52
56
|
|
|
@@ -85,7 +85,11 @@ def _is_query_context(node: ast.expr, parents: Mapping[ast.AST, ast.AST], roots:
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
def _query_roots(
|
|
88
|
-
tree: ast.Module,
|
|
88
|
+
tree: ast.Module,
|
|
89
|
+
parents: Mapping[ast.AST, ast.AST],
|
|
90
|
+
*,
|
|
91
|
+
context: PythonFileContext,
|
|
92
|
+
node_index: NodeIndex | None = None,
|
|
89
93
|
) -> frozenset[int]:
|
|
90
94
|
binding_counts: dict[tuple[int, str], int] = {}
|
|
91
95
|
binding_values: dict[tuple[int, str], ast.expr] = {}
|
|
@@ -99,11 +103,12 @@ def _query_roots(
|
|
|
99
103
|
|
|
100
104
|
constructor_imports = _postgres_sql_constructors(tree, parents, node_index=node_index)
|
|
101
105
|
_query_binding_values(tree, parents, binding_values, node_index=node_index)
|
|
106
|
+
has_local_classes = bool(nodes(tree, ast.ClassDef, index=node_index))
|
|
102
107
|
|
|
103
108
|
roots: set[int] = set()
|
|
104
109
|
for call in nodes(tree, ast.Call, index=node_index):
|
|
105
110
|
argument = _query_argument(call)
|
|
106
|
-
if argument is None:
|
|
111
|
+
if argument is None or (has_local_classes and _source_local_receiver(call, context)):
|
|
107
112
|
continue
|
|
108
113
|
owner = _scope(call, parents)
|
|
109
114
|
constructors = _visible_constructors(owner, constructor_imports, parents, binding_counts, wildcard_scopes)
|
|
@@ -151,6 +156,21 @@ def _query_argument(call: ast.Call) -> ast.expr | None:
|
|
|
151
156
|
return next((keyword.value for keyword in call.keywords if keyword.arg in _QUERY_KEYWORDS), None)
|
|
152
157
|
|
|
153
158
|
|
|
159
|
+
def _source_local_receiver(call: ast.Call, context: PythonFileContext) -> bool:
|
|
160
|
+
if not isinstance(call.func, ast.Attribute) or not isinstance(call.func.value, (ast.Name, ast.Call)):
|
|
161
|
+
return False
|
|
162
|
+
provenance = context.static_resource_provenance
|
|
163
|
+
receiver: ast.expr | None = call.func.value
|
|
164
|
+
if isinstance(receiver, ast.Name):
|
|
165
|
+
binding = provenance.runtime_binding(receiver.id, call)
|
|
166
|
+
receiver = provenance.assignment_value(binding, call) if isinstance(binding, ast.Name) else None
|
|
167
|
+
return (
|
|
168
|
+
isinstance(receiver, ast.Call)
|
|
169
|
+
and isinstance(receiver.func, ast.Name)
|
|
170
|
+
and isinstance(provenance.runtime_binding(receiver.func.id, receiver), ast.ClassDef)
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
154
174
|
def _postgres_sql_constructors(
|
|
155
175
|
tree: ast.Module, parents: Mapping[ast.AST, ast.AST], *, node_index: NodeIndex | None = None
|
|
156
176
|
) -> frozenset[_ConstructorImport]:
|
|
@@ -261,13 +281,16 @@ class ComplexPostgresQueryRequiresArchitectureReview(Rule):
|
|
|
261
281
|
autofix=AutofixPolicy.NONE,
|
|
262
282
|
limitations=(
|
|
263
283
|
"Only statically recoverable SQL passed to execute, executemany, fetch, fetchrow, fetchval, or prepare in non-test modules with explicit PostgreSQL imports is analyzed, regardless of module filename.",
|
|
264
|
-
"Execution receivers use a conventional database name or import-proven Psycopg ownership. Native execution additionally follows stable module/local SQL bindings and direct same-class query-forwarding wrappers; unknown receivers abstain.",
|
|
284
|
+
"Execution receivers use a conventional database name or import-proven Psycopg ownership. Conventional names are a heuristic and can warn on unrelated objects with matching methods. Native execution additionally follows stable module/local SQL bindings and direct same-class query-forwarding wrappers; unknown receivers abstain.",
|
|
285
|
+
"Modules mixing SQLite and PostgreSQL abstain for conventional receivers; import-proven Psycopg execution remains eligible.",
|
|
286
|
+
"Stable source-local class construction abstains from conventional receiver inference, including custom delegating instances unless native recovery independently proves execution.",
|
|
265
287
|
"Conventional receivers follow one direct, unambiguous same-scope binding. Native Psycopg recovery may follow bounded stable lexical bindings, including module constants. Unexecuted constants, branch-local assignments, mutable attributes, containers and unknown dynamic composition abstain.",
|
|
266
|
-
"Review covers derived relations in every SELECT (including LATERAL, CTEs, predicates and writes), four explicit or comma joins, six query stages, three joins plus four stages, or 25 projections plus two joins. A self join over the same explicit table also merits review at 16 projected expressions.",
|
|
288
|
+
"Review covers derived relations in every SELECT (including LATERAL, CTEs, predicates and writes), four explicit or comma joins (including parenthesized joined tables), six query stages, three joins plus four stages, or 25 projections plus two joins. A self join over the same explicit table also merits review at 16 projected expressions.",
|
|
267
289
|
"Derived-relation review requires grouping, HAVING or windowing combined with joins or nested reads; expression density is not a separate trigger.",
|
|
268
|
-
"Projection width alone is accepted, and UNION branches are measured independently; execution plans and production cardinality remain authoritative.",
|
|
269
|
-
"ClickHouse and BigQuery syntax
|
|
290
|
+
"Projection width alone is accepted, and UNION branches are measured independently. Set operators do not add read stages beyond their SELECT blocks; execution plans and production cardinality remain authoritative.",
|
|
291
|
+
"Conventional receivers exclude ClickHouse and BigQuery syntax per query, including in mixed-backend modules. Import-proven Psycopg execution uses PostgreSQL parsing even when identifiers or function names overlap another dialect.",
|
|
270
292
|
"The rule does not infer optimizer behavior, materialization, performance, data-model quality, or datastore placement.",
|
|
293
|
+
"SQL parsing and static query recovery abstain on recursion limits; deeply nested source can withhold native recovery for the file.",
|
|
271
294
|
),
|
|
272
295
|
examples=(
|
|
273
296
|
RuleExample(
|
|
@@ -351,12 +374,17 @@ class ComplexPostgresQueryRequiresArchitectureReview(Rule):
|
|
|
351
374
|
tree = context.tree
|
|
352
375
|
if tree is None:
|
|
353
376
|
return []
|
|
354
|
-
|
|
377
|
+
imports = _import_names(tree, node_index=context.node_index)
|
|
378
|
+
if not _has_import_prefix(imports, _POSTGRES_IMPORT_PREFIXES):
|
|
355
379
|
return []
|
|
356
380
|
|
|
357
|
-
diagnostics =
|
|
381
|
+
diagnostics = (
|
|
382
|
+
[]
|
|
383
|
+
if _has_import_prefix(imports, _AMBIGUOUS_RELATIONAL_IMPORT_PREFIXES)
|
|
384
|
+
else _conventional_findings(context, self.code)
|
|
385
|
+
)
|
|
358
386
|
for query in store_queries(context):
|
|
359
|
-
signal = _query_architecture_signal(query.sql, path)
|
|
387
|
+
signal = _query_architecture_signal(query.sql, path, native_postgres=True)
|
|
360
388
|
if signal is None:
|
|
361
389
|
continue
|
|
362
390
|
node = query.node
|
|
@@ -372,7 +400,7 @@ def _conventional_findings(context: PythonFileContext, code: str) -> list[Diagno
|
|
|
372
400
|
tree = context.tree
|
|
373
401
|
if tree is None:
|
|
374
402
|
return []
|
|
375
|
-
query_roots = _query_roots(tree, parents, node_index=context.node_index)
|
|
403
|
+
query_roots = _query_roots(tree, parents, context=context, node_index=context.node_index)
|
|
376
404
|
diagnostics: list[Diagnostic] = []
|
|
377
405
|
consumed: set[int] = set()
|
|
378
406
|
for node in context.nodes(ast.Constant, ast.BinOp, ast.JoinedStr):
|
|
@@ -477,14 +505,13 @@ def _record_sql_constructors(
|
|
|
477
505
|
)
|
|
478
506
|
|
|
479
507
|
|
|
480
|
-
def _query_architecture_signal(text_value: str, path: Path) -> str | None:
|
|
508
|
+
def _query_architecture_signal(text_value: str, path: Path, *, native_postgres: bool = False) -> str | None:
|
|
481
509
|
sql_without_noise = strip_sql_noise(text_value)
|
|
482
|
-
if (
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
):
|
|
510
|
+
if _QUERY_SHAPE.search(sql_without_noise) is None:
|
|
511
|
+
return None
|
|
512
|
+
if not native_postgres and (_CLICKHOUSE_SQL.search(sql_without_noise) or _BIGQUERY_SQL.search(sql_without_noise)):
|
|
513
|
+
return None
|
|
514
|
+
if is_store_module(path) and analytical_signal(sql_without_noise) is not None:
|
|
488
515
|
return None
|
|
489
516
|
return _parse_signal(text_value)
|
|
490
517
|
|
|
@@ -512,8 +539,8 @@ def _architecture_signal(statement: exp.Expr) -> str | None:
|
|
|
512
539
|
maximum_joins = _maximum_query_joins(statement)
|
|
513
540
|
if maximum_joins >= _JOIN_LIMIT:
|
|
514
541
|
return f"SELECT block has {maximum_joins} JOINs (4+ explicit JOINs or comma relations)"
|
|
515
|
-
nested_queries = sum(1 for query in statement.walk() if isinstance(query,
|
|
516
|
-
nested_queries -= isinstance(statement,
|
|
542
|
+
nested_queries = sum(1 for query in statement.walk() if isinstance(query, exp.Select))
|
|
543
|
+
nested_queries -= isinstance(_derived_query(statement), exp.Select)
|
|
517
544
|
if (derived_signal := _derived_architecture_signal(statement)) is not None:
|
|
518
545
|
return derived_signal
|
|
519
546
|
if nested_queries >= _STAGE_LIMIT:
|
|
@@ -528,7 +555,7 @@ def _projection_width_signal(statement: exp.Expr) -> str | None:
|
|
|
528
555
|
|
|
529
556
|
for select in statement.find_all(exp.Select):
|
|
530
557
|
projections = tuple(_expression_args(select, "expressions"))
|
|
531
|
-
joins =
|
|
558
|
+
joins = _select_joins(select)
|
|
532
559
|
if len(projections) >= _WIDE_PROJECTION_LIMIT and len(joins) >= _WIDE_PROJECTION_JOIN_LIMIT:
|
|
533
560
|
return f"Joined query block has {len(projections)} projected expressions"
|
|
534
561
|
if len(projections) >= _WIDE_SELF_JOIN_PROJECTION_LIMIT and _self_join(select, joins):
|
|
@@ -559,7 +586,10 @@ def _self_join(select: exp.Select, joins: tuple[exp.Join, ...]) -> bool:
|
|
|
559
586
|
relations.extend(_expression_arg(join, "this") for join in joins)
|
|
560
587
|
seen: set[tuple[str, ...]] = set()
|
|
561
588
|
for relation in relations:
|
|
562
|
-
|
|
589
|
+
base = relation
|
|
590
|
+
while isinstance(base, (exp.Paren, exp.Subquery)):
|
|
591
|
+
base = _expression_arg(base, "this")
|
|
592
|
+
key = relation_key(base)
|
|
563
593
|
if key is None or any(_SQL_HOLE in name for name in key):
|
|
564
594
|
continue
|
|
565
595
|
if key in seen:
|
|
@@ -572,9 +602,7 @@ def _derived_architecture_signal(statement: exp.Expr) -> str | None:
|
|
|
572
602
|
from sqlglot import exp # ruff: ignore[import-outside-top-level] -- keep parser startup off unrelated lint runs
|
|
573
603
|
|
|
574
604
|
for select in statement.find_all(exp.Select):
|
|
575
|
-
for join in
|
|
576
|
-
if not isinstance(join, exp.Join):
|
|
577
|
-
continue
|
|
605
|
+
for join in _select_joins(select):
|
|
578
606
|
if (derived := _derived_query(_expression_arg(join, "this"))) is not None and _has_complex_body(derived):
|
|
579
607
|
return "JOIN-derived query combines grouping, HAVING or windowing with joins or nested reads"
|
|
580
608
|
from_clause = _expression_arg(select, "from_")
|
|
@@ -597,11 +625,11 @@ def _has_complex_body(query: exp.Query) -> bool:
|
|
|
597
625
|
if not isinstance(query, exp.Select):
|
|
598
626
|
return False
|
|
599
627
|
if _has_row_transform(query) and (
|
|
600
|
-
|
|
628
|
+
_select_joins(query) or any(select is not query for select in query.find_all(exp.Select))
|
|
601
629
|
):
|
|
602
630
|
return True
|
|
603
|
-
for relation in query
|
|
604
|
-
if relation.
|
|
631
|
+
for relation in (_expression_arg(query, "from_"), *_select_joins(query)):
|
|
632
|
+
if not isinstance(relation, (exp.From, exp.Join)):
|
|
605
633
|
continue
|
|
606
634
|
child = _derived_query(_expression_arg(relation, "this"))
|
|
607
635
|
if child is not None and (_has_row_transform(child) or _has_complex_body(child)):
|
|
@@ -624,14 +652,26 @@ def _maximum_query_joins(statement: exp.Expr) -> int:
|
|
|
624
652
|
from sqlglot import exp # ruff: ignore[import-outside-top-level] -- keep parser startup off unrelated lint runs
|
|
625
653
|
|
|
626
654
|
return max(
|
|
627
|
-
(
|
|
628
|
-
sum(isinstance(join, exp.Join) for join in _expression_args(select, "joins"))
|
|
629
|
-
for select in statement.find_all(exp.Select)
|
|
630
|
-
),
|
|
655
|
+
(len(_select_joins(select)) for select in statement.find_all(exp.Select)),
|
|
631
656
|
default=0,
|
|
632
657
|
)
|
|
633
658
|
|
|
634
659
|
|
|
660
|
+
def _select_joins(select: exp.Select) -> tuple[exp.Join, ...]:
|
|
661
|
+
from sqlglot import exp # ruff: ignore[import-outside-top-level] -- grouped joined tables retain their SELECT owner.
|
|
662
|
+
|
|
663
|
+
relations = (_expression_arg(select, "from_"), *_expression_args(select, "joins"))
|
|
664
|
+
return tuple(
|
|
665
|
+
node
|
|
666
|
+
for relation in relations
|
|
667
|
+
if relation is not None
|
|
668
|
+
for node in relation.walk(
|
|
669
|
+
prune=lambda node: isinstance(node, (exp.Select, exp.SetOperation, exp.Insert, exp.Update, exp.Delete))
|
|
670
|
+
)
|
|
671
|
+
if isinstance(node, exp.Join)
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
|
|
635
675
|
def _count_import_bindings(
|
|
636
676
|
tree: ast.Module,
|
|
637
677
|
parents: Mapping[ast.AST, ast.AST],
|
|
@@ -671,13 +711,6 @@ def _query_review_guidance(text_value: str) -> str:
|
|
|
671
711
|
)
|
|
672
712
|
|
|
673
713
|
|
|
674
|
-
def _is_postgres_module(tree: ast.Module, *, node_index: NodeIndex | None = None) -> bool:
|
|
675
|
-
imports = _import_names(tree, node_index=node_index)
|
|
676
|
-
return _has_import_prefix(imports, _POSTGRES_IMPORT_PREFIXES) and not _has_import_prefix(
|
|
677
|
-
imports, _AMBIGUOUS_RELATIONAL_IMPORT_PREFIXES
|
|
678
|
-
)
|
|
679
|
-
|
|
680
|
-
|
|
681
714
|
def _has_import_prefix(imports: frozenset[str], prefixes: tuple[str, ...]) -> bool:
|
|
682
715
|
return any(name == prefix or name.startswith(f"{prefix}.") for name in imports for prefix in prefixes)
|
|
683
716
|
|
|
@@ -60,15 +60,16 @@ def analytical_signal(sql: str) -> str | None:
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
def _grouped_reporting_signal(sql: str) -> str | None:
|
|
63
|
-
import sqlglot # ruff: ignore[import-outside-top-level] -- parse only aggregate-shaped SQL after cheap gates
|
|
64
63
|
from sqlglot import exp # ruff: ignore[import-outside-top-level] -- paired with lazy parser import
|
|
65
64
|
from sqlglot.errors import SqlglotError # ruff: ignore[import-outside-top-level] -- paired with lazy parser import
|
|
66
65
|
|
|
66
|
+
from sarj_python_lint.rules._postgres import parse_postgres # ruff: ignore[import-outside-top-level] -- unsupported private SQL must not enter dependency logs.
|
|
67
|
+
|
|
67
68
|
if _GROUP_BY.search(sql) is None or _COMMON_AGGREGATE.search(sql) is None:
|
|
68
69
|
return None
|
|
69
70
|
try:
|
|
70
|
-
statements =
|
|
71
|
-
except SqlglotError:
|
|
71
|
+
statements = parse_postgres(_PLACEHOLDER.sub("?", sql))
|
|
72
|
+
except SqlglotError, RecursionError:
|
|
72
73
|
return None
|
|
73
74
|
for statement in statements:
|
|
74
75
|
if not isinstance(statement, exp.Query):
|