sarj-python-lint 1.100.0__tar.gz → 1.101.1__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.100.0 → sarj_python_lint-1.101.1}/PKG-INFO +2 -2
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/pyproject.toml +2 -2
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix.py +41 -9
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_parallel.py +12 -7
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_copy_on_write.py +6 -8
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_namespace_access.py +1 -1
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_opaque_contracts.py +12 -5
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_project_index.py +19 -3
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_delete_statement.py +2 -2
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_direct_import_module.py +3 -2
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_precise_object_contract.py +5 -2
- sarj_python_lint-1.101.1/src/sarj_python_lint/rules/prefer_typed_mapping_get.py +378 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +1 -1
- sarj_python_lint-1.100.0/src/sarj_python_lint/rules/prefer_typed_mapping_get.py +0 -189
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/.gitignore +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/LICENSE +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/README.md +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/__main__.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_analysis_session.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_aliases.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_annotations.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_comments.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_declared_contracts.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_declared_tests.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_docs.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_enums.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_exhaustiveness.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_inert.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_parameters.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_repeated.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_security.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_sql_projection.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_autofix_tests.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_file_context.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_filesystem.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_fixes.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_prepared_sources.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_python_target.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_rule_descriptors.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_source.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/application_logging.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/autofix.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/benchmark.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/cast_access.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/interpreter_argv.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/json_boundary.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rule_metadata.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_annotation_origins.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_annotation_semantics.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_ast_names.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_ast_position.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_async_lifecycle.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_binding_inventory.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_closed_helpers.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_comment_narration.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_comments.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_data_union_discriminator.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_declared_contracts.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_docstrings.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_exports.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_fastapi.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_imports.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_inert_model_annotation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_inherited_contract.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_local_alias_fix.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_local_source.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_mapping_shape_callbacks.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_native_namespace_capability.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_native_object_contracts.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_numeric_proof.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_postgres.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_pydantic_field_contract.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_registry.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_resolved_operation_signature.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_resource_provenance.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_route_shapes.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_runtime_bindings.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_runtime_registry.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_service_http_callbacks.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_set_fields.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_sql_aggregate_identity.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_sql_explain.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_sql_policy_source.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_static_json_alias.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_store_sql.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_store_writes.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_test_composition.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_transactional_sql.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_type_guard_symbols.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/async_executor_shutdown.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/async_subprocess_cancellation_cleanup.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/cancel_owned_task_without_join.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/delete_route_returns_no_content.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/duplicate_adjacent_exception_handler.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/duplicate_closed_pure_helper.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/duplicate_pytest_fixture_params.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/failed_probe_zero_threshold.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/nan_hidden_by_builtin_min.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_async_client_in_constructor.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_async_function_cache.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_blanket_suppression.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_conflicting_pydantic_alias_validation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_contradictory_type_guard.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_create_verb_in_post_path.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_custom_control_flow_exception.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_defaulted_environment_setting.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_discarded_tagged_outcome.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_discarded_validation_result.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_dual_shape_model_field_reader.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_duplicate_field_validator_body.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_exception_text_in_500_detail.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_fixed_sleep_in_loop.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_folded_bad_request_not_found.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_generic_json_parser.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_hasattr.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_impossible_pydantic_field_bounds.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_invalid_pydantic_bypass.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_invalid_pydantic_validator_return.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_loguru_exc_info.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_loguru_printf_format.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_mutating_container_transform.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_mutating_input_with_result.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_partial_type_is.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_recording_store.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_redundant_attribute_unpacking.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_redundant_local_alias.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_redundant_sql_alias.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_shallow_record_type_guard.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_slash_collection_root_under_prefix.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_test_comments.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_unknown_pydantic_validator_field.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/no_work_verb_get_route.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_application_model_joins.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_bulk_upsert.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_declarative_batch_validation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_discriminated_model_union.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_grouped_settings.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_native_string_check.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_optional_composite.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_psycopg_executemany.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_pydantic_model_assertion.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_pytest_dependency_fixtures.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_pytest_fixture_contract.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_runtime_validation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_typed_cli.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_typed_settings_field.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/pytest_fixture_returns_closed_resource.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/redundant_test_constructor_forwarder.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/repeated_unimplemented_test_contract.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_constrained_api_integer.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_exp_on_jwt_decode.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_injectable_retry_sleep.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_pydantic_for_mapping_shape.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/service_singleton_delegates_to_bulk.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/stepdown.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/store_field_update_reuses_upsert.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/store_insert_requires_explicit_conflict_policy.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/store_mutation_command_fanout.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/test_without_explicit_oracle.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/unused_test_factory_option.py +0 -0
- {sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/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.101.1
|
|
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/
|
|
@@ -19,7 +19,7 @@ Classifier: Topic :: Software Development :: Quality Assurance
|
|
|
19
19
|
Requires-Python: >=3.14
|
|
20
20
|
Requires-Dist: packaging==26.3
|
|
21
21
|
Requires-Dist: ruff>=0.17.2
|
|
22
|
-
Requires-Dist: sarj-rule-contracts==0.
|
|
22
|
+
Requires-Dist: sarj-rule-contracts==0.6.0
|
|
23
23
|
Requires-Dist: sqlglot==30.24.0
|
|
24
24
|
Requires-Dist: typer==0.27.3
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sarj-python-lint"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.101.1"
|
|
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" }]
|
|
@@ -15,7 +15,7 @@ classifiers = [
|
|
|
15
15
|
"Programming Language :: Python :: 3.14",
|
|
16
16
|
"Topic :: Software Development :: Quality Assurance",
|
|
17
17
|
]
|
|
18
|
-
dependencies = ["sarj-rule-contracts==0.
|
|
18
|
+
dependencies = ["sarj-rule-contracts==0.6.0", "packaging==26.3", "ruff>=0.17.2", "sqlglot==30.24.0", "typer==0.27.3"]
|
|
19
19
|
|
|
20
20
|
[project.scripts]
|
|
21
21
|
sarj-python-lint = "sarj_python_lint.__main__:main"
|
|
@@ -2,13 +2,14 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import ast
|
|
4
4
|
from bisect import bisect_left, insort
|
|
5
|
+
from dataclasses import dataclass
|
|
5
6
|
from functools import cached_property
|
|
6
7
|
from hashlib import sha256
|
|
7
8
|
from io import StringIO
|
|
8
9
|
from itertools import pairwise
|
|
9
10
|
import re
|
|
10
11
|
import tokenize
|
|
11
|
-
from typing import TYPE_CHECKING, Final, NamedTuple
|
|
12
|
+
from typing import TYPE_CHECKING, Final, Literal, NamedTuple
|
|
12
13
|
from unicodedata import normalize
|
|
13
14
|
|
|
14
15
|
from sarj_rule_contracts import TextEdit, apply_edits
|
|
@@ -80,6 +81,8 @@ _WALRUS_CODES = frozenset({"SARJ081", "SARJ432"})
|
|
|
80
81
|
_JWT_POSITIONAL_PREFIX_ARGUMENTS = 3
|
|
81
82
|
_STREAM_MIN_BODY_LENGTH = 3
|
|
82
83
|
_CONSTANT_TRUE_DEPTH_LIMIT = 32
|
|
84
|
+
# Bound accepted revisions; each rule still owns its work and replacement size.
|
|
85
|
+
_MAX_FIX_PASSES: Final = 256
|
|
83
86
|
_PURE_STRING_TRANSFORMS: Final[dict[str, str]] = {
|
|
84
87
|
"strip": "stripped_value",
|
|
85
88
|
"lower": "lowered_value",
|
|
@@ -1360,6 +1363,18 @@ _BUILDERS: Final[dict[str, Callable[[_Source, Diagnostic], list[TextEdit]]]] = {
|
|
|
1360
1363
|
}
|
|
1361
1364
|
|
|
1362
1365
|
|
|
1366
|
+
@dataclass(frozen=True, slots=True)
|
|
1367
|
+
class _FixCandidate:
|
|
1368
|
+
code: str
|
|
1369
|
+
edits: tuple[TextEdit, ...]
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
@dataclass(frozen=True, slots=True)
|
|
1373
|
+
class _FixPass:
|
|
1374
|
+
edits: tuple[TextEdit, ...]
|
|
1375
|
+
codes: tuple[str, ...]
|
|
1376
|
+
|
|
1377
|
+
|
|
1363
1378
|
def fix_source(path: Path, source: str, *, rule_ids: Sequence[str] | None = None) -> str:
|
|
1364
1379
|
from sarj_python_lint.__main__ import check_source # ruff: ignore[import-outside-top-level] -- the CLI imports this entry point lazily.
|
|
1365
1380
|
|
|
@@ -1371,6 +1386,8 @@ def fix_source(path: Path, source: str, *, rule_ids: Sequence[str] | None = None
|
|
|
1371
1386
|
# Only the closed alias builder owns aligned physical-line buffers and token coordinates here.
|
|
1372
1387
|
rules = [rule for rule in rules if rule.code == "SARJ531"]
|
|
1373
1388
|
seen: set[bytes] = set()
|
|
1389
|
+
applied_codes: set[str] = set()
|
|
1390
|
+
passes = 0
|
|
1374
1391
|
current = source
|
|
1375
1392
|
while (fingerprint := sha256(current.encode("utf-8")).digest()) not in seen:
|
|
1376
1393
|
seen.add(fingerprint)
|
|
@@ -1380,30 +1397,43 @@ def fix_source(path: Path, source: str, *, rule_ids: Sequence[str] | None = None
|
|
|
1380
1397
|
if not candidates:
|
|
1381
1398
|
return current
|
|
1382
1399
|
# Batch independent candidates; overlapping candidates get fresh offsets on the next pass.
|
|
1383
|
-
|
|
1400
|
+
selected_pass = _coherent_edits(candidates)
|
|
1401
|
+
updated = apply_edits(current, selected_pass.edits)
|
|
1384
1402
|
compile(updated, str(path), "exec", dont_inherit=True)
|
|
1385
1403
|
if updated == current:
|
|
1386
1404
|
return current
|
|
1405
|
+
if passes == _MAX_FIX_PASSES:
|
|
1406
|
+
raise _convergence_error(path, reason="pass budget exhausted", passes=passes, codes=applied_codes)
|
|
1407
|
+
passes += 1
|
|
1408
|
+
applied_codes.update(selected_pass.codes)
|
|
1387
1409
|
current = updated
|
|
1388
|
-
|
|
1389
|
-
|
|
1410
|
+
raise _convergence_error(path, reason="source cycle", passes=passes, codes=applied_codes)
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
def _convergence_error(
|
|
1414
|
+
path: Path, *, reason: Literal["pass budget exhausted", "source cycle"], passes: int, codes: set[str]
|
|
1415
|
+
) -> ValueError:
|
|
1416
|
+
participants = ", ".join(sorted(codes)) or "none"
|
|
1417
|
+
msg = f"Python autofixes did not converge: {path} ({reason}; passes={passes}; rules={participants})"
|
|
1418
|
+
return ValueError(msg)
|
|
1390
1419
|
|
|
1391
1420
|
|
|
1392
|
-
def _candidate_edits(context: PythonFileContext, diagnostics: Sequence[Diagnostic]) -> list[
|
|
1421
|
+
def _candidate_edits(context: PythonFileContext, diagnostics: Sequence[Diagnostic]) -> list[_FixCandidate]:
|
|
1393
1422
|
view = _Source(context, diagnostics)
|
|
1394
1423
|
return [
|
|
1395
|
-
edits
|
|
1424
|
+
_FixCandidate(diagnostic.code, tuple(edits))
|
|
1396
1425
|
for diagnostic in diagnostics
|
|
1397
1426
|
if (builder := _BUILDERS.get(diagnostic.code)) is not None
|
|
1398
1427
|
if (edits := builder(view, diagnostic))
|
|
1399
1428
|
]
|
|
1400
1429
|
|
|
1401
1430
|
|
|
1402
|
-
def _coherent_edits(candidates: list[
|
|
1431
|
+
def _coherent_edits(candidates: list[_FixCandidate]) -> _FixPass:
|
|
1403
1432
|
accepted: list[TextEdit] = []
|
|
1433
|
+
codes: list[str] = []
|
|
1404
1434
|
known: set[TextEdit] = set()
|
|
1405
1435
|
for candidate in candidates:
|
|
1406
|
-
additions = sorted(set(candidate) - known)
|
|
1436
|
+
additions = sorted(set(candidate.edits) - known)
|
|
1407
1437
|
if any(map(_overlap, additions, additions[1:], strict=False)):
|
|
1408
1438
|
continue
|
|
1409
1439
|
for edit in additions:
|
|
@@ -1416,7 +1446,9 @@ def _coherent_edits(candidates: list[list[TextEdit]]) -> list[TextEdit]:
|
|
|
1416
1446
|
for edit in additions:
|
|
1417
1447
|
insort(accepted, edit)
|
|
1418
1448
|
known.update(additions)
|
|
1419
|
-
|
|
1449
|
+
if additions:
|
|
1450
|
+
codes.append(candidate.code)
|
|
1451
|
+
return _FixPass(tuple(accepted), tuple(dict.fromkeys(codes)))
|
|
1420
1452
|
|
|
1421
1453
|
|
|
1422
1454
|
def _overlap(first: TextEdit, second: TextEdit) -> bool:
|
|
@@ -143,19 +143,24 @@ def check_parallel(
|
|
|
143
143
|
for path, source in loaded.items()
|
|
144
144
|
)
|
|
145
145
|
for result in pool.map(_check_file, items, chunksize=1, buffersize=workers * 4):
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
needs_serial = True
|
|
146
|
+
# Drain actual results after either replay signal so a later worker
|
|
147
|
+
# failure cannot be disguised as a clean serial replay.
|
|
148
|
+
if needs_serial:
|
|
150
149
|
continue
|
|
151
150
|
resolutions.update(result.resolutions)
|
|
152
151
|
modules.update(result.modules)
|
|
153
152
|
# A worker cannot hit either order-dependent limit when the whole
|
|
154
153
|
# union stays strictly below it. At the boundary, discard all output.
|
|
155
|
-
if
|
|
156
|
-
|
|
154
|
+
if (
|
|
155
|
+
result.needs_serial
|
|
156
|
+
or len(resolutions) >= LOCAL_SOURCE_CACHE_LIMIT
|
|
157
|
+
or len(modules) >= LOCAL_SOURCE_CACHE_LIMIT
|
|
157
158
|
):
|
|
158
|
-
|
|
159
|
+
needs_serial = True
|
|
160
|
+
diagnostics.clear()
|
|
161
|
+
resolutions.clear()
|
|
162
|
+
modules.clear()
|
|
163
|
+
continue
|
|
159
164
|
diagnostics.extend(result.diagnostics)
|
|
160
165
|
return None if needs_serial else diagnostics
|
|
161
166
|
finally:
|
{sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_copy_on_write.py
RENAMED
|
@@ -973,10 +973,8 @@ class CopyOnWriteAnalysis:
|
|
|
973
973
|
summaries[key] = _summary_value(_OwnershipSummary(alternatives))
|
|
974
974
|
bindings[name] = summaries[key]
|
|
975
975
|
|
|
976
|
-
def _scan(self, statements: list[ast.stmt], bindings: dict[str, _Value]) ->
|
|
977
|
-
for statement in statements
|
|
978
|
-
if self._statement(statement, bindings):
|
|
979
|
-
return
|
|
976
|
+
def _scan(self, statements: list[ast.stmt], bindings: dict[str, _Value]) -> bool:
|
|
977
|
+
return any(self._statement(statement, bindings) for statement in statements)
|
|
980
978
|
|
|
981
979
|
def _statement(self, statement: ast.stmt, bindings: dict[str, _Value]) -> bool:
|
|
982
980
|
match statement:
|
|
@@ -991,7 +989,7 @@ class CopyOnWriteAnalysis:
|
|
|
991
989
|
self._write(target, bindings)
|
|
992
990
|
self._bind(target, None, bindings)
|
|
993
991
|
case ast.If():
|
|
994
|
-
self._branches(statement, bindings)
|
|
992
|
+
return self._branches(statement, bindings)
|
|
995
993
|
case ast.For() | ast.AsyncFor():
|
|
996
994
|
self._for(statement, bindings)
|
|
997
995
|
case ast.Expr(value=ast.Call() as call):
|
|
@@ -1026,16 +1024,16 @@ class CopyOnWriteAnalysis:
|
|
|
1026
1024
|
self._write(target, bindings)
|
|
1027
1025
|
self._bind(target, value, bindings)
|
|
1028
1026
|
|
|
1029
|
-
def _branches(self, statement: ast.If, bindings: dict[str, _Value]) ->
|
|
1027
|
+
def _branches(self, statement: ast.If, bindings: dict[str, _Value]) -> bool:
|
|
1030
1028
|
self._expression(statement.test, bindings)
|
|
1031
1029
|
branches: list[dict[str, _Value]] = []
|
|
1032
1030
|
for positive, block in ((True, statement.body), (False, statement.orelse)):
|
|
1033
1031
|
branch = dict(bindings)
|
|
1034
1032
|
self._refine(statement.test, branch, positive=positive)
|
|
1035
|
-
self._scan(block, branch)
|
|
1036
|
-
if not block or not isinstance(block[-1], (ast.Return, ast.Raise)):
|
|
1033
|
+
if not self._scan(block, branch):
|
|
1037
1034
|
branches.append(branch)
|
|
1038
1035
|
self._join(branches, bindings)
|
|
1036
|
+
return not branches
|
|
1039
1037
|
|
|
1040
1038
|
def _for(self, statement: ast.For | ast.AsyncFor, bindings: dict[str, _Value]) -> None:
|
|
1041
1039
|
self._expression(statement.iter, bindings)
|
|
@@ -48,7 +48,7 @@ def dynamic_namespace_access(
|
|
|
48
48
|
def _namespace_api_aliases(nodes: Iterable[ast.AST]) -> set[str]:
|
|
49
49
|
aliases = set(_NAMESPACE_APIS) | {"__builtins__"}
|
|
50
50
|
for node in nodes:
|
|
51
|
-
if not isinstance(node, ast.ImportFrom) or node.module not in _MODULE_APIS:
|
|
51
|
+
if not isinstance(node, ast.ImportFrom) or node.level != 0 or node.module not in _MODULE_APIS:
|
|
52
52
|
continue
|
|
53
53
|
members = _MODULE_APIS[node.module]
|
|
54
54
|
aliases.update(alias.asname or alias.name for alias in node.names if alias.name in members)
|
|
@@ -16,6 +16,7 @@ if TYPE_CHECKING:
|
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
|
|
18
18
|
from sarj_python_lint._file_context import PythonFileContext
|
|
19
|
+
from sarj_python_lint.rules._local_source import LocalSourceFacts
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
type _Function = ast.FunctionDef | ast.AsyncFunctionDef
|
|
@@ -111,11 +112,13 @@ class OpaqueContractFacts:
|
|
|
111
112
|
context: PythonFileContext,
|
|
112
113
|
facts: MappingShapeFacts,
|
|
113
114
|
*,
|
|
115
|
+
local_source: LocalSourceFacts,
|
|
114
116
|
modules: dict[Path, OpaqueContractFacts] | None = None,
|
|
115
117
|
budget: _ProofBudget | None = None,
|
|
116
118
|
) -> None:
|
|
117
119
|
self.context = context
|
|
118
120
|
self.facts = facts
|
|
121
|
+
self.local_source = local_source
|
|
119
122
|
self.native = NativeObjectContracts(context, facts)
|
|
120
123
|
self.guards: dict[str, _Refinement | None] = {}
|
|
121
124
|
self.checked: dict[_Function, frozenset[ast.arg]] = {}
|
|
@@ -712,20 +715,24 @@ class OpaqueContractFacts:
|
|
|
712
715
|
|
|
713
716
|
def _imported_source(self, qualified: str) -> tuple[OpaqueContractFacts, ast.FunctionDef] | None:
|
|
714
717
|
module, _, name = qualified.rpartition(".")
|
|
715
|
-
path = self.context.session.
|
|
716
|
-
self.context.path, module, 0, facts=self.context.session.first_party
|
|
717
|
-
)
|
|
718
|
+
path = self.local_source.resolve_module(self.context.path, module, 0, facts=self.context.session.first_party)
|
|
718
719
|
if path is not None and (owner := self.modules.get(path.resolve())) is not None:
|
|
719
720
|
return owner.export(name)
|
|
720
721
|
if len(self.modules) >= _MAX_GUARDS:
|
|
721
722
|
return None
|
|
722
|
-
loaded = self.
|
|
723
|
+
loaded = self.local_source.read_module(path) if path is not None else None
|
|
723
724
|
if loaded is None:
|
|
724
725
|
return None
|
|
725
726
|
from sarj_python_lint._file_context import PythonFileContext # ruff: ignore[import-outside-top-level] -- source loading runs after AnalysisSession initialization.
|
|
726
727
|
|
|
727
728
|
context = PythonFileContext(loaded.path, loaded.source, self.context.session)
|
|
728
|
-
owner = OpaqueContractFacts(
|
|
729
|
+
owner = OpaqueContractFacts(
|
|
730
|
+
context,
|
|
731
|
+
MappingShapeFacts(context),
|
|
732
|
+
local_source=self.local_source,
|
|
733
|
+
modules=self.modules,
|
|
734
|
+
budget=self.budget,
|
|
735
|
+
)
|
|
729
736
|
return owner.export(name)
|
|
730
737
|
|
|
731
738
|
def export(self, name: str) -> tuple[OpaqueContractFacts, ast.FunctionDef] | None:
|
{sarj_python_lint-1.100.0 → sarj_python_lint-1.101.1}/src/sarj_python_lint/rules/_project_index.py
RENAMED
|
@@ -156,6 +156,11 @@ class SourceUnit:
|
|
|
156
156
|
captured: CapturedSource | None = None
|
|
157
157
|
|
|
158
158
|
|
|
159
|
+
@dataclass(frozen=True, slots=True)
|
|
160
|
+
class _AmbiguousModuleSources:
|
|
161
|
+
paths: tuple[Path, ...]
|
|
162
|
+
|
|
163
|
+
|
|
159
164
|
@dataclass(frozen=True, slots=True)
|
|
160
165
|
class LoadedSource:
|
|
161
166
|
path: Path
|
|
@@ -276,8 +281,18 @@ class ProjectIndexSet:
|
|
|
276
281
|
self._bound_value_prefixes: dict[str, bool] = {}
|
|
277
282
|
self._value_origins_incomplete = False
|
|
278
283
|
self.import_namespace_mutations = ImportNamespaceMutations(WeakMethod(self._namespace_write_inventory))
|
|
279
|
-
by_module
|
|
280
|
-
|
|
284
|
+
by_module: dict[str, dict[Path, SourceUnit]] = {}
|
|
285
|
+
for unit in units.values():
|
|
286
|
+
if unit.module is not None:
|
|
287
|
+
by_module.setdefault(unit.module, {})[unit.path] = unit
|
|
288
|
+
self._by_module = MappingProxyType(
|
|
289
|
+
{
|
|
290
|
+
module: next(iter(candidates.values()))
|
|
291
|
+
if len(candidates) == 1
|
|
292
|
+
else _AmbiguousModuleSources(tuple(candidates))
|
|
293
|
+
for module, candidates in by_module.items()
|
|
294
|
+
}
|
|
295
|
+
)
|
|
281
296
|
classes: dict[SymbolRef, ClassSummary] = {}
|
|
282
297
|
nominals: dict[str, set[SymbolRef]] = {}
|
|
283
298
|
_collect_unit_symbols(units, classes, nominals)
|
|
@@ -429,7 +444,8 @@ class ProjectIndexSet:
|
|
|
429
444
|
return False
|
|
430
445
|
|
|
431
446
|
def source_unit(self, module: str) -> SourceUnit | None:
|
|
432
|
-
|
|
447
|
+
source = self._by_module.get(module)
|
|
448
|
+
return source if isinstance(source, SourceUnit) else None
|
|
433
449
|
|
|
434
450
|
def _namespace_write_inventory(self) -> Mapping[str, _ImportNamespaceWrites]:
|
|
435
451
|
def resolve(origin: SymbolRef) -> tuple[SymbolRef, ...] | None:
|
|
@@ -136,6 +136,6 @@ class NoDeleteStatement(Rule):
|
|
|
136
136
|
"immutably, or add an exact SARJ442 suppression explaining why deletion is required."
|
|
137
137
|
),
|
|
138
138
|
)
|
|
139
|
-
for node in context.nodes(ast.
|
|
140
|
-
if
|
|
139
|
+
for node in context.nodes(ast.Delete)
|
|
140
|
+
if not is_suppressed(source_lines, node.lineno, self.code)
|
|
141
141
|
]
|
|
@@ -71,10 +71,11 @@ class PreferDirectImportModule(Rule):
|
|
|
71
71
|
def check_context(self, context: PythonFileContext) -> list[Diagnostic]:
|
|
72
72
|
if context.generated or context.tree is None or "import_module" not in context.symbol_source:
|
|
73
73
|
return []
|
|
74
|
+
provenance = context.resource_provenance
|
|
74
75
|
loader_references = {
|
|
75
76
|
reference
|
|
76
77
|
for call in context.nodes(ast.Call)
|
|
77
|
-
if
|
|
78
|
+
if provenance.runtime_import_name(call.func) == "importlib.import_module"
|
|
78
79
|
for reference in ast.walk(call.func)
|
|
79
80
|
}
|
|
80
81
|
if dynamic_namespace_access(
|
|
@@ -96,7 +97,7 @@ class PreferDirectImportModule(Rule):
|
|
|
96
97
|
if isinstance(statement, ast.Assign | ast.AnnAssign | ast.Expr)
|
|
97
98
|
and isinstance(node := statement.value, ast.Call)
|
|
98
99
|
and (module := _literal_module(node)) is not None
|
|
99
|
-
and
|
|
100
|
+
and provenance.runtime_import_name(node.func) == "importlib.import_module"
|
|
100
101
|
]
|
|
101
102
|
|
|
102
103
|
|
|
@@ -15,6 +15,7 @@ from sarj_python_lint.rule_base import (
|
|
|
15
15
|
RuleExample,
|
|
16
16
|
Severity,
|
|
17
17
|
)
|
|
18
|
+
from sarj_python_lint.rules._local_source import LocalSourceFacts
|
|
18
19
|
from sarj_python_lint.rules._native_object_contracts import builtin_object, builtin_symbol
|
|
19
20
|
from sarj_python_lint.rules._opaque_contracts import REFINEMENT_TYPES, OpaqueContractFacts
|
|
20
21
|
from sarj_python_lint.rules.require_pydantic_for_mapping_shape import MappingShapeFacts
|
|
@@ -48,7 +49,7 @@ class PreferPreciseObjectContract(Rule):
|
|
|
48
49
|
"Safe fixes narrow only a bare builtin object return annotation to builtin str for a closed private nested synchronous helper returning one exact string literal, with every call used directly as an if test and all containing return contracts explicit. Existing inert/metadata/binding proofs must hold; public/domain/container/parameter/model contracts and other result uses remain review-only.",
|
|
49
50
|
"Checks builtin object in function signatures and class field annotations, including supported containers, callables, optional unions and quoted annotations. Local opaque values, object() sentinels, Literal/Annotated metadata, framework hooks, proven override signatures, and registered raw Pydantic callbacks are excluded. Functions that directly validate an object parameter through a source-visible BaseModel, BaseSettings or RootModel model_validate call, positionally or with obj=, retain that raw boundary. JSON text inputs still require a text or byte contract. Aliases must resolve to their source declaration and their bodies use definition scope. Alias graphs are bounded and shared branches reuse their facts. Imported or shadowed application types named object are preserved. Genuine opaque public contracts can use an explained exact-code exception; narrowing outside the exact private truthiness-only subset remains manual.",
|
|
50
51
|
"An import-proven TypeGuard or TypeIs retains bare object on its guarded positional parameter and unchecked object slots in its declared refinement result; other object parameters remain checked. Guard correctness belongs to the type-guard rules. Universal type[object] class contracts and the return of a canonical module-level PEP 562 __getattr__ hook retain their opaque runtime contracts.",
|
|
51
|
-
"Ordinary raw validators retain object inputs tied to builtin isinstance, exact builtin type comparisons or an actual source-resolved TypeGuard/TypeIs through rejecting branches, actual type/refinement assertions, accepting terminal branches with a rejecting fallback, or conditional expressions. Stable projections from containers with unchecked value slots retain their raw root contract when those values are validated. Source-visible local and imported validators may delegate those inputs and raw results; precise result narrowing does not justify a bare object output. Related unchecked mapping projections and transforms retain unknown values; import-proven native parsers and JSONDecoder preserve raw outputs. Universal builtin and stdlib interoperation may retain raw inputs. Independent object parameters, domain constructors and unproven parser names remain checked. Source resolution and dataflow
|
|
52
|
+
"Ordinary raw validators retain object inputs tied to builtin isinstance, exact builtin type comparisons or an actual source-resolved TypeGuard/TypeIs through rejecting branches, actual type/refinement assertions, accepting terminal branches with a rejecting fallback, or conditional expressions. Stable projections from containers with unchecked value slots retain their raw root contract when those values are validated. Source-visible local and imported validators may delegate those inputs and raw results; precise result narrowing does not justify a bare object output. Related unchecked mapping projections and transforms retain unknown values; import-proven native parsers and JSONDecoder preserve raw outputs. Universal builtin and stdlib interoperation may retain raw inputs. Independent object parameters, domain constructors and unproven parser names remain checked. Source resolution and dataflow use a bounded per-file proof cache, captured source inputs and cycle guards; rebinding, decorators and namespace mutation invalidate delegated proof.",
|
|
52
53
|
"Native opaque contracts include canonical ast.Constant.value reads and captures, FunctionType invocations, identity-only inputs and sys.getrefcount. Actual exec/eval globals and locals retain unknown values only through bounded native dict construction and alias flow; unrelated dictionaries and source domain factories do not borrow that ownership. Stub property returns on an import-proven runtime_checkable Protocol retain unchecked incoming attributes. Generic callable results, ordinary Protocol methods, application properties and unused parameters remain checked.",
|
|
53
54
|
"Raw input unions may include scalar or None branches; only genuine unchecked container branches seed raw projections. Mapping consumers that inspect only keys retain uninspected value slots. Projected aliases require simple statement dominance, and precise active guards permit typed consumption after validation. Native namespace output reads require a preceding direct function-scope execution and abstain after authored mutations. Benign builtins imports do not hide builtin object contracts; explicit object shadowing and source-visible object mutations remain outside scope.",
|
|
54
55
|
"An import-proven Iterable of unchecked values retains its raw element contract when every input use is a direct synchronous iteration and every reachable element read directly enters source-proven Pydantic model_validate. Deferred closures, rebinding, other iterator/element uses, unknown model providers and JSON-text parsers do not establish that boundary.",
|
|
@@ -131,7 +132,9 @@ class PreferPreciseObjectContract(Rule):
|
|
|
131
132
|
if facts.provenance.wildcard:
|
|
132
133
|
return []
|
|
133
134
|
findings: list[Diagnostic] = []
|
|
134
|
-
opaque = OpaqueContractFacts(
|
|
135
|
+
opaque = OpaqueContractFacts(
|
|
136
|
+
context, facts, local_source=LocalSourceFacts(source_inputs=context.session.source_inputs)
|
|
137
|
+
)
|
|
135
138
|
for owner, annotation in _contracts(context):
|
|
136
139
|
if not _has_object(annotation, context, facts, at=annotation):
|
|
137
140
|
continue
|