sarj-python-lint 1.83.1__tar.gz → 1.85.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.83.1 → sarj_python_lint-1.85.0}/PKG-INFO +1 -1
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/pyproject.toml +1 -1
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/__main__.py +3 -2
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix.py +9 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_file_context.py +2 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_annotation_origins.py +43 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_annotation_semantics.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_copy_on_write.py +29 -20
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_docstrings.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_fastapi.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_imports.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_mapping_shape_callbacks.py +18 -12
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_native_object_contracts.py +25 -16
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_opaque_contracts.py +22 -15
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/_postgres.py +17 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_project_index.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_prose_budget.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_registry.py +24 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_resource_provenance.py +7 -6
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/_store_sql.py +245 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_store_writes.py +8 -5
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_test_composition.py +17 -14
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +95 -44
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +14 -8
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/duplicate_closed_pure_helper.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +7 -4
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/no_custom_control_flow_exception.py +237 -0
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/no_discarded_tagged_outcome.py +469 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +48 -37
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_invalid_pydantic_bypass.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +16 -10
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +119 -58
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +15 -9
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/no_recording_store.py +276 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_redundant_local_alias.py +7 -4
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/no_redundant_sql_alias.py +164 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_repeated_string_literal.py +8 -7
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +18 -8
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_tautological_expect.py +29 -17
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +23 -20
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/over_mocked_test.py +7 -6
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/prefer_application_model_joins.py +138 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_class_row.py +14 -10
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +17 -11
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_declarative_batch_validation.py +14 -8
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_discriminated_model_union.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_library_fake.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +276 -9
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_monkeypatch_for_process_state_in_test.py +9 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_native_string_check.py +14 -8
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +14 -11
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/prefer_optional_composite.py +297 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_or_pattern.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_pydantic_model_assertion.py +13 -10
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/prefer_runtime_validation.py +97 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_str_enum.py +45 -30
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/prefer_typed_cli.py +219 -0
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/prefer_typed_mapping_get.py +189 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +9 -6
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +22 -19
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/redundant_docstring.py +8 -7
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +8 -5
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +30 -21
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_port_for_service.py +23 -16
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +16 -10
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_pydantic_for_mapping_shape.py +18 -20
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +8 -5
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/restated_test_docstring.py +16 -12
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/stepdown.py +8 -5
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +29 -17
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/store_insert_requires_explicit_conflict_policy.py +105 -0
- sarj_python_lint-1.85.0/src/sarj_python_lint/rules/store_mutation_command_fanout.py +172 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +30 -24
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/unused_mock_setup.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/.gitignore +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/LICENSE +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/README.md +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_analysis_session.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_aliases.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_annotations.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_comments.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_declared_contracts.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_declared_tests.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_docs.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_enums.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_exhaustiveness.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_inert.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_parameters.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_repeated.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_security.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_sql_projection.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_autofix_tests.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_filesystem.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_fixes.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_parallel.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_python_target.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_source.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/application_logging.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/autofix.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/benchmark.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/cast_access.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/interpreter_argv.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/json_boundary.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_ast_names.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_ast_position.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_async_lifecycle.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_binding_inventory.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_closed_helpers.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_comment_narration.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_comments.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_data_union_discriminator.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_declared_contracts.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_exports.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_inert_model_annotation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_inherited_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_local_alias_fix.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_local_source.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_namespace_access.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_native_namespace_capability.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_numeric_proof.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_pydantic_field_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_resolved_operation_signature.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_route_shapes.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_runtime_bindings.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_service_http_callbacks.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_set_fields.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_sql_aggregate_identity.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_sql_explain.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_sql_policy_source.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_static_json_alias.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_transactional_sql.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_type_guard_symbols.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/async_executor_shutdown.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/async_mock_call_without_await_assertion.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/async_subprocess_cancellation_cleanup.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/cancel_owned_task_without_join.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/delete_route_returns_no_content.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/duplicate_adjacent_exception_handler.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/duplicate_pytest_fixture_params.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/failed_probe_zero_threshold.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/nan_hidden_by_builtin_min.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_async_function_cache.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_blanket_suppression.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_conflicting_pydantic_alias_validation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_contradictory_type_guard.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_create_verb_in_post_path.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_defaulted_environment_setting.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_discarded_validation_result.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_dual_shape_model_field_reader.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_duplicate_field_validator_body.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_exception_text_in_500_detail.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_fixed_sleep_in_loop.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_folded_bad_request_not_found.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_hasattr.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_impossible_pydantic_field_bounds.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_invalid_pydantic_validator_return.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_loguru_exc_info.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_loguru_printf_format.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_mutating_container_transform.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_partial_type_is.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_shallow_record_type_guard.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_slash_collection_root_under_prefix.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_unknown_pydantic_validator_field.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/no_work_verb_get_route.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_bulk_upsert.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_direct_import_module.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_grouped_settings.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_precise_object_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_psycopg_executemany.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_pytest_dependency_fixtures.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_typed_settings_field.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/pytest_fixture_returns_closed_resource.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/redundant_test_constructor_forwarder.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/repeated_unimplemented_test_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_exp_on_jwt_decode.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_injectable_retry_sleep.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/store_field_update_reuses_upsert.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/test_without_explicit_oracle.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/unused_test_factory_option.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.85.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.85.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/
|
|
@@ -187,12 +187,13 @@ _DIAGNOSTIC_PRECEDENCE = MappingProxyType(
|
|
|
187
187
|
# A proven external or nested request boundary already requires schema
|
|
188
188
|
# validation at this field read. Retain standalone shape advice when
|
|
189
189
|
# that more specific rule is unselected or locally suppressed.
|
|
190
|
-
"SARJ411": frozenset({"SARJ521"}),
|
|
190
|
+
"SARJ411": frozenset({"SARJ521", "SARJ535"}),
|
|
191
191
|
# Any-valued mappings are the stronger correctness failure. SARJ008
|
|
192
192
|
# still owns every fixed dictionary return when selected alone, while
|
|
193
193
|
# an all-rules run emits one actionable diagnostic for this overlap.
|
|
194
194
|
"SARJ447": frozenset({"SARJ008"}),
|
|
195
|
-
"SARJ450": frozenset({"SARJ521"}),
|
|
195
|
+
"SARJ450": frozenset({"SARJ521", "SARJ535"}),
|
|
196
|
+
"SARJ521": frozenset({"SARJ535"}),
|
|
196
197
|
"SARJ457": frozenset({"SARJ045"}),
|
|
197
198
|
"SARJ465": frozenset({"SARJ071"}),
|
|
198
199
|
"SARJ491": frozenset({"SARJ400"}),
|
|
@@ -759,6 +759,8 @@ def _primitive_set(node: ast.expr) -> bool:
|
|
|
759
759
|
|
|
760
760
|
|
|
761
761
|
def _dispatch_fix(source: _Source, diagnostic: Diagnostic) -> list[TextEdit]:
|
|
762
|
+
if diagnostic.code == "SARJ080" and diagnostic.severity is not Severity.ERROR:
|
|
763
|
+
return []
|
|
762
764
|
for root in source.context.nodes(ast.If):
|
|
763
765
|
if not _at(root, diagnostic) or source.comments_between(root.lineno, _last_line(root)):
|
|
764
766
|
continue
|
|
@@ -993,10 +995,13 @@ def _jwt_required_sequence(required: ast.expr) -> ast.expr | None:
|
|
|
993
995
|
):
|
|
994
996
|
return None
|
|
995
997
|
elements = [*required.elts, ast.Constant(value="exp")]
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
998
|
+
match required:
|
|
999
|
+
case ast.List():
|
|
1000
|
+
return ast.List(elts=elements, ctx=ast.Load())
|
|
1001
|
+
case ast.Tuple():
|
|
1002
|
+
return ast.Tuple(elts=elements, ctx=ast.Load())
|
|
1003
|
+
case _:
|
|
1004
|
+
pass
|
|
1000
1005
|
return ast.Set(elts=elements)
|
|
1001
1006
|
|
|
1002
1007
|
|
|
@@ -22,6 +22,7 @@ if TYPE_CHECKING:
|
|
|
22
22
|
|
|
23
23
|
from sarj_python_lint.rules._copy_on_write import CopyOnWriteAnalysis
|
|
24
24
|
from sarj_python_lint.rules._resource_provenance import ResourceProvenance
|
|
25
|
+
from sarj_python_lint.rules._store_sql import StoreQuery
|
|
25
26
|
from sarj_python_lint.rules._test_provenance import TestProvenance
|
|
26
27
|
|
|
27
28
|
|
|
@@ -31,6 +32,7 @@ class PythonFileContext:
|
|
|
31
32
|
self.path = path
|
|
32
33
|
self.source = source
|
|
33
34
|
self.session = session if session is not None else AnalysisSession()
|
|
35
|
+
self.store_queries: tuple[StoreQuery, ...] | None = None
|
|
34
36
|
|
|
35
37
|
@cached_property
|
|
36
38
|
def symbol_source(self) -> str:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import ast
|
|
4
|
+
from dataclasses import dataclass
|
|
4
5
|
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
from sarj_python_lint.rules._imports import ImportIndex
|
|
@@ -10,6 +11,15 @@ if TYPE_CHECKING:
|
|
|
10
11
|
from sarj_python_lint._file_context import PythonFileContext
|
|
11
12
|
|
|
12
13
|
|
|
14
|
+
_MAX_ALIAS_DEPTH = 32
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True, slots=True)
|
|
18
|
+
class ResolvedAnnotation:
|
|
19
|
+
expression: ast.expr
|
|
20
|
+
at: ast.expr
|
|
21
|
+
|
|
22
|
+
|
|
13
23
|
class AnnotationOrigins:
|
|
14
24
|
def __init__(self, context: PythonFileContext) -> None:
|
|
15
25
|
self.context = context
|
|
@@ -19,6 +29,39 @@ class AnnotationOrigins:
|
|
|
19
29
|
for node in context.nodes(ast.Import, ast.ImportFrom)
|
|
20
30
|
}
|
|
21
31
|
|
|
32
|
+
def alias_value(self, node: ast.Name, at: ast.AST) -> ast.expr | None:
|
|
33
|
+
value = self.context.annotation_semantics.aliases.get(node.id)
|
|
34
|
+
if value is None:
|
|
35
|
+
return None
|
|
36
|
+
binding = self.provenance.binding(node.id, at)
|
|
37
|
+
if not isinstance(binding, ast.Name):
|
|
38
|
+
return None
|
|
39
|
+
parent = self.context.parents.get(binding)
|
|
40
|
+
if isinstance(parent, ast.TypeAlias | ast.AnnAssign) and parent.value is value:
|
|
41
|
+
return value
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
def resolve_annotation(self, node: ast.expr, *, at: ast.expr | None = None) -> ResolvedAnnotation | None:
|
|
45
|
+
current = node
|
|
46
|
+
scope = node if at is None else at
|
|
47
|
+
seen: set[str] = set()
|
|
48
|
+
for _ in range(_MAX_ALIAS_DEPTH):
|
|
49
|
+
parsed = self.context.annotation_semantics.parse(current)
|
|
50
|
+
if parsed is None:
|
|
51
|
+
return None
|
|
52
|
+
if isinstance(parsed, ast.Name):
|
|
53
|
+
if self.shadowed(parsed.id, scope):
|
|
54
|
+
return None
|
|
55
|
+
value = self.alias_value(parsed, scope)
|
|
56
|
+
if value is not None:
|
|
57
|
+
if parsed.id in seen:
|
|
58
|
+
return None
|
|
59
|
+
seen.add(parsed.id)
|
|
60
|
+
current = scope = value
|
|
61
|
+
continue
|
|
62
|
+
return ResolvedAnnotation(parsed, scope)
|
|
63
|
+
return None
|
|
64
|
+
|
|
22
65
|
def shadowed(self, name: str, at: ast.AST) -> bool:
|
|
23
66
|
return type_parameter_shadow(name, at, self.context)
|
|
24
67
|
|
|
@@ -158,10 +158,13 @@ def _bound_names(statement: ast.stmt) -> set[str]:
|
|
|
158
158
|
|
|
159
159
|
|
|
160
160
|
def _target_names(node: ast.expr) -> set[str]:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
match node:
|
|
162
|
+
case ast.Name():
|
|
163
|
+
return {node.id}
|
|
164
|
+
case ast.List() | ast.Tuple():
|
|
165
|
+
return {name for item in node.elts for name in _target_names(item)}
|
|
166
|
+
case _:
|
|
167
|
+
pass
|
|
165
168
|
return set()
|
|
166
169
|
|
|
167
170
|
|
{sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_copy_on_write.py
RENAMED
|
@@ -659,28 +659,37 @@ class CopyOnWriteAnalysis:
|
|
|
659
659
|
return _Value(_Shape("dict", element=element), shared_children=shared, fields=tuple(fields.items()))
|
|
660
660
|
|
|
661
661
|
def _write(self, target: ast.expr, bindings: Mapping[str, _Value]) -> None:
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
662
|
+
match target:
|
|
663
|
+
case ast.Tuple() | ast.List():
|
|
664
|
+
for item in target.elts:
|
|
665
|
+
self._write(item, bindings)
|
|
666
|
+
case ast.Attribute() | ast.Subscript():
|
|
667
|
+
owner = self._value(target.value, bindings)
|
|
668
|
+
if (
|
|
669
|
+
owner is not None
|
|
670
|
+
and owner.borrowed
|
|
671
|
+
and (
|
|
672
|
+
isinstance(target, ast.Subscript)
|
|
673
|
+
or (
|
|
674
|
+
owner.shape.model is not None
|
|
675
|
+
and self.models.field(owner.shape.model, target.attr) is not None
|
|
676
|
+
)
|
|
677
|
+
)
|
|
678
|
+
):
|
|
679
|
+
self.mutations.append(Mutation(target, self._before))
|
|
680
|
+
case _:
|
|
681
|
+
pass
|
|
676
682
|
|
|
677
683
|
def _expression(self, node: ast.AST, bindings: dict[str, _Value]) -> None:
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
+
match node:
|
|
685
|
+
case ast.Lambda() | ast.FunctionDef() | ast.AsyncFunctionDef() | ast.ClassDef():
|
|
686
|
+
return
|
|
687
|
+
case ast.NamedExpr():
|
|
688
|
+
self._expression(node.value, bindings)
|
|
689
|
+
self._bind(node.target, self._value(node.value, bindings), bindings)
|
|
690
|
+
return
|
|
691
|
+
case _:
|
|
692
|
+
pass
|
|
684
693
|
if isinstance(node, ast.Call) and self._mutator_call(node, bindings):
|
|
685
694
|
self.mutations.append(Mutation(node, self._before))
|
|
686
695
|
if isinstance(node, (ast.ListComp, ast.SetComp, ast.GeneratorExp, ast.DictComp)):
|
{sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_docstrings.py
RENAMED
|
@@ -305,10 +305,13 @@ def base_names(node: ast.ClassDef) -> set[str]:
|
|
|
305
305
|
names: set[str] = set()
|
|
306
306
|
for base in node.bases:
|
|
307
307
|
target = base.value if isinstance(base, ast.Subscript) else base
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
308
|
+
match target:
|
|
309
|
+
case ast.Attribute():
|
|
310
|
+
names.add(target.attr)
|
|
311
|
+
case ast.Name():
|
|
312
|
+
names.add(target.id)
|
|
313
|
+
case _:
|
|
314
|
+
pass
|
|
312
315
|
return names
|
|
313
316
|
|
|
314
317
|
|
|
@@ -241,10 +241,13 @@ class FastapiIndex:
|
|
|
241
241
|
for node in walk_ast(tree):
|
|
242
242
|
if self._node_scopes[id(node)] != 0:
|
|
243
243
|
continue
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
match node:
|
|
245
|
+
case ast.Import():
|
|
246
|
+
self._read_import(node)
|
|
247
|
+
case ast.ImportFrom():
|
|
248
|
+
self._read_import_from(node)
|
|
249
|
+
case _:
|
|
250
|
+
pass
|
|
248
251
|
|
|
249
252
|
def _read_import(self, node: ast.Import) -> None:
|
|
250
253
|
for alias in node.names:
|
|
@@ -141,10 +141,13 @@ def _module_non_import_bindings(tree: ast.Module) -> set[str]:
|
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
def _target_names(node: ast.expr) -> set[str]:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
match node:
|
|
145
|
+
case ast.Name():
|
|
146
|
+
return {node.id}
|
|
147
|
+
case ast.Tuple() | ast.List():
|
|
148
|
+
return {name for element in node.elts for name in _target_names(element)}
|
|
149
|
+
case _:
|
|
150
|
+
pass
|
|
148
151
|
return set()
|
|
149
152
|
|
|
150
153
|
|
|
@@ -59,14 +59,17 @@ class RawMappingCallbacks:
|
|
|
59
59
|
def callback(self, node: ast.expr, *, seen: frozenset[ast.AST] = frozenset()) -> _Function | None:
|
|
60
60
|
if len(seen) >= _MAX_DEPTH:
|
|
61
61
|
return None
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
match node:
|
|
63
|
+
case ast.Call():
|
|
64
|
+
return (
|
|
65
|
+
self._partial(node, seen)
|
|
66
|
+
if self.qualified(node.func, node) == "functools.partial"
|
|
67
|
+
else self._method(node, "__call__", seen)
|
|
68
|
+
)
|
|
69
|
+
case ast.Attribute():
|
|
70
|
+
return self._method(node.value, node.attr, seen)
|
|
71
|
+
case _:
|
|
72
|
+
pass
|
|
70
73
|
if not isinstance(node, ast.Name) or not self._stable(node.id) or self.shadowed(node.id, node):
|
|
71
74
|
return None
|
|
72
75
|
binding = self.provenance.binding(node.id, node)
|
|
@@ -144,10 +147,13 @@ class RawMappingCallbacks:
|
|
|
144
147
|
def _function(self, node: ast.AST) -> _Function | None:
|
|
145
148
|
current = self.context.parents.get(node)
|
|
146
149
|
while current is not None:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
match current:
|
|
151
|
+
case ast.FunctionDef() | ast.AsyncFunctionDef():
|
|
152
|
+
return current
|
|
153
|
+
case ast.ClassDef() | ast.Lambda():
|
|
154
|
+
return None
|
|
155
|
+
case _:
|
|
156
|
+
pass
|
|
151
157
|
current = self.context.parents.get(current)
|
|
152
158
|
return None
|
|
153
159
|
|
|
@@ -406,11 +406,14 @@ class _NamespaceFlow:
|
|
|
406
406
|
def plain_dict(self, value: ast.expr, *, depth: int = 0) -> bool:
|
|
407
407
|
if depth >= _MAX_DEPTH:
|
|
408
408
|
return False
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
409
|
+
match value:
|
|
410
|
+
case ast.Name():
|
|
411
|
+
assigned = self.assigned(value)
|
|
412
|
+
return assigned is not None and self.plain_dict(assigned, depth=depth + 1)
|
|
413
|
+
case ast.IfExp():
|
|
414
|
+
return self.plain_dict(value.body, depth=depth + 1) and self.plain_dict(value.orelse, depth=depth + 1)
|
|
415
|
+
case _:
|
|
416
|
+
pass
|
|
414
417
|
return isinstance(value, ast.Dict) or (isinstance(value, ast.Call) and self.native.dict_call(value))
|
|
415
418
|
|
|
416
419
|
def _collect(self, value: ast.expr, *, execution: ast.Call, depth: int = 0) -> None:
|
|
@@ -436,10 +439,13 @@ class _NamespaceFlow:
|
|
|
436
439
|
def _input(self, value: ast.expr, *, depth: int = 0) -> set[ast.arg]:
|
|
437
440
|
if depth >= _MAX_DEPTH:
|
|
438
441
|
return set()
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
442
|
+
match value:
|
|
443
|
+
case ast.Name():
|
|
444
|
+
return self._name_input(value, depth)
|
|
445
|
+
case ast.Dict():
|
|
446
|
+
return self._dictionary_inputs(value, depth)
|
|
447
|
+
case _:
|
|
448
|
+
pass
|
|
443
449
|
if isinstance(value, ast.Call) and self.native.dict_call(value):
|
|
444
450
|
return self._constructor_inputs(value, depth)
|
|
445
451
|
found: set[ast.arg] = set()
|
|
@@ -652,13 +658,16 @@ class _NamespaceEscapes:
|
|
|
652
658
|
return None
|
|
653
659
|
binding = self.flow.binding(value)
|
|
654
660
|
found: set[ast.AST] = {binding} if binding is not None else set()
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
661
|
+
match value:
|
|
662
|
+
case ast.Name():
|
|
663
|
+
assigned = self.flow.assigned(value)
|
|
664
|
+
if isinstance(assigned, ast.Name | ast.Subscript):
|
|
665
|
+
previous = self._carrier_roots(assigned, depth=depth + 1)
|
|
666
|
+
return None if previous is None else found | previous
|
|
667
|
+
case ast.Subscript():
|
|
668
|
+
return self._carrier_roots(value.value, depth=depth + 1)
|
|
669
|
+
case _:
|
|
670
|
+
pass
|
|
662
671
|
return found
|
|
663
672
|
|
|
664
673
|
|
{sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_opaque_contracts.py
RENAMED
|
@@ -427,10 +427,13 @@ class OpaqueContractFacts:
|
|
|
427
427
|
|
|
428
428
|
def _enclosing_assertion(self, node: ast.AST) -> ast.Assert | None:
|
|
429
429
|
while (parent := self.context.parents.get(node)) is not None:
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
430
|
+
match parent:
|
|
431
|
+
case ast.Assert():
|
|
432
|
+
return parent
|
|
433
|
+
case ast.FunctionDef() | ast.AsyncFunctionDef() | ast.Lambda():
|
|
434
|
+
return None
|
|
435
|
+
case _:
|
|
436
|
+
pass
|
|
434
437
|
node = parent
|
|
435
438
|
return None
|
|
436
439
|
|
|
@@ -534,11 +537,14 @@ class OpaqueContractFacts:
|
|
|
534
537
|
return None
|
|
535
538
|
if isinstance(node, ast.Name):
|
|
536
539
|
binding = self.facts.provenance.runtime_binding(node.id, node)
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
540
|
+
match binding:
|
|
541
|
+
case ast.arg():
|
|
542
|
+
return binding
|
|
543
|
+
case ast.Name():
|
|
544
|
+
value = self.assigned(binding, node)
|
|
545
|
+
return self.parameter(value, depth=depth + 1) if value is not None else None
|
|
546
|
+
case _:
|
|
547
|
+
pass
|
|
542
548
|
receiver = _projection_receiver(node)
|
|
543
549
|
parameter = self.parameter(receiver, depth=depth + 1) if receiver is not None else None
|
|
544
550
|
return parameter if self._raw_annotation(parameter) else None
|
|
@@ -993,12 +999,13 @@ def _projection_receiver(node: ast.expr) -> ast.expr | None:
|
|
|
993
999
|
|
|
994
1000
|
|
|
995
1001
|
def _control_condition(node: ast.AST, parent: ast.AST) -> tuple[ast.expr, bool] | None:
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
+
match parent:
|
|
1003
|
+
case ast.IfExp():
|
|
1004
|
+
accepted, rejected = node is parent.body, node is parent.orelse
|
|
1005
|
+
case ast.If():
|
|
1006
|
+
accepted, rejected = node in parent.body, node in parent.orelse
|
|
1007
|
+
case _:
|
|
1008
|
+
return None
|
|
1002
1009
|
return (parent.test, accepted) if accepted or rejected else None
|
|
1003
1010
|
|
|
1004
1011
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import override
|
|
4
|
+
|
|
5
|
+
from sqlglot import exp, parse
|
|
6
|
+
from sqlglot.dialects.postgres import Postgres
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def parse_postgres(source: str) -> list[exp.Expr | None]:
|
|
10
|
+
return parse(source, read=_PostgresForLint)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _PostgresForLint(Postgres):
|
|
14
|
+
class Parser(Postgres.Parser):
|
|
15
|
+
@override
|
|
16
|
+
def _warn_unsupported(self) -> None:
|
|
17
|
+
"""Unsupported input must not copy private SQL into dependency logs."""
|
{sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_project_index.py
RENAMED
|
@@ -1271,10 +1271,13 @@ def _module_constructor_declarations(statement: ast.stmt) -> frozenset[str]:
|
|
|
1271
1271
|
|
|
1272
1272
|
|
|
1273
1273
|
def _direct_functions(owner: ast.stmt) -> tuple[ast.FunctionDef | ast.AsyncFunctionDef, ...]:
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1274
|
+
match owner:
|
|
1275
|
+
case ast.FunctionDef() | ast.AsyncFunctionDef():
|
|
1276
|
+
return (owner,)
|
|
1277
|
+
case ast.ClassDef():
|
|
1278
|
+
return tuple(item for item in owner.body if isinstance(item, ast.FunctionDef | ast.AsyncFunctionDef))
|
|
1279
|
+
case _:
|
|
1280
|
+
pass
|
|
1278
1281
|
return ()
|
|
1279
1282
|
|
|
1280
1283
|
|
{sarj_python_lint-1.83.1 → sarj_python_lint-1.85.0}/src/sarj_python_lint/rules/_prose_budget.py
RENAMED
|
@@ -228,10 +228,13 @@ def _decorator_terminal_names(node: ast.FunctionDef | ast.AsyncFunctionDef | ast
|
|
|
228
228
|
names: set[str] = set()
|
|
229
229
|
for decorator in node.decorator_list:
|
|
230
230
|
target = decorator.func if isinstance(decorator, ast.Call) else decorator
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
231
|
+
match target:
|
|
232
|
+
case ast.Name():
|
|
233
|
+
names.add(target.id.casefold())
|
|
234
|
+
case ast.Attribute():
|
|
235
|
+
names.add(target.attr.casefold())
|
|
236
|
+
case _:
|
|
237
|
+
pass
|
|
235
238
|
return frozenset(names)
|
|
236
239
|
|
|
237
240
|
|
|
@@ -228,7 +228,9 @@ from sarj_python_lint.rules.nan_hidden_by_builtin_min import NanHiddenByBuiltinM
|
|
|
228
228
|
from sarj_python_lint.rules.no_conflicting_pydantic_alias_validation import NoConflictingPydanticAliasValidation
|
|
229
229
|
from sarj_python_lint.rules.no_contradictory_type_guard import NoContradictoryTypeGuard
|
|
230
230
|
from sarj_python_lint.rules.no_create_verb_in_post_path import NoCreateVerbInPostPath
|
|
231
|
+
from sarj_python_lint.rules.no_custom_control_flow_exception import NoCustomControlFlowException
|
|
231
232
|
from sarj_python_lint.rules.no_defaulted_environment_setting import NoDefaultedEnvironmentSetting
|
|
233
|
+
from sarj_python_lint.rules.no_discarded_tagged_outcome import NoDiscardedTaggedOutcome
|
|
232
234
|
from sarj_python_lint.rules.no_duplicate_field_validator_body import NoDuplicateFieldValidatorBody
|
|
233
235
|
from sarj_python_lint.rules.no_exception_text_in_500_detail import NoExceptionTextIn500Detail
|
|
234
236
|
from sarj_python_lint.rules.no_folded_bad_request_not_found import NoFoldedBadRequestNotFound
|
|
@@ -237,35 +239,57 @@ from sarj_python_lint.rules.no_impossible_pydantic_field_bounds import NoImpossi
|
|
|
237
239
|
from sarj_python_lint.rules.no_invalid_pydantic_bypass import NoInvalidPydanticBypass
|
|
238
240
|
from sarj_python_lint.rules.no_invalid_pydantic_validator_return import NoInvalidPydanticValidatorReturn
|
|
239
241
|
from sarj_python_lint.rules.no_partial_type_is import NoPartialTypeIs
|
|
242
|
+
from sarj_python_lint.rules.no_recording_store import NoRecordingStore
|
|
240
243
|
from sarj_python_lint.rules.no_redundant_local_alias import NoRedundantLocalAlias
|
|
244
|
+
from sarj_python_lint.rules.no_redundant_sql_alias import NoRedundantSqlAlias
|
|
241
245
|
from sarj_python_lint.rules.no_shallow_record_type_guard import NoShallowRecordTypeGuard
|
|
242
246
|
from sarj_python_lint.rules.no_slash_collection_root_under_prefix import NoSlashCollectionRootUnderPrefix
|
|
243
247
|
from sarj_python_lint.rules.no_unknown_pydantic_validator_field import NoUnknownPydanticValidatorField
|
|
244
248
|
from sarj_python_lint.rules.no_work_verb_get_route import NoWorkVerbGetRoute
|
|
249
|
+
from sarj_python_lint.rules.prefer_application_model_joins import PreferApplicationModelJoins
|
|
245
250
|
from sarj_python_lint.rules.prefer_bulk_upsert import PreferBulkUpsert
|
|
246
251
|
from sarj_python_lint.rules.prefer_direct_import_module import PreferDirectImportModule
|
|
247
252
|
from sarj_python_lint.rules.prefer_discriminated_model_union import PreferDiscriminatedModelUnion
|
|
248
253
|
from sarj_python_lint.rules.prefer_grouped_settings import PreferGroupedSettings
|
|
254
|
+
from sarj_python_lint.rules.prefer_optional_composite import PreferOptionalComposite
|
|
249
255
|
from sarj_python_lint.rules.prefer_precise_object_contract import PreferPreciseObjectContract
|
|
250
256
|
from sarj_python_lint.rules.prefer_psycopg_executemany import PreferPsycopgExecutemany
|
|
251
257
|
from sarj_python_lint.rules.prefer_pydantic_model_assertion import PreferPydanticModelAssertion
|
|
252
258
|
from sarj_python_lint.rules.prefer_pytest_dependency_fixtures import PreferPytestDependencyFixtures
|
|
259
|
+
from sarj_python_lint.rules.prefer_runtime_validation import PreferRuntimeValidation
|
|
260
|
+
from sarj_python_lint.rules.prefer_typed_cli import PreferTypedCli
|
|
261
|
+
from sarj_python_lint.rules.prefer_typed_mapping_get import PreferTypedMappingGet
|
|
253
262
|
from sarj_python_lint.rules.prefer_typed_settings_field import PreferTypedSettingsField
|
|
254
263
|
from sarj_python_lint.rules.pytest_fixture_returns_closed_resource import PytestFixtureReturnsClosedResource
|
|
255
264
|
from sarj_python_lint.rules.redundant_test_constructor_forwarder import RedundantTestConstructorForwarder
|
|
256
265
|
from sarj_python_lint.rules.repeated_unimplemented_test_contract import RepeatedUnimplementedTestContract
|
|
257
266
|
from sarj_python_lint.rules.require_exp_on_jwt_decode import RequireExpOnJwtDecode
|
|
258
267
|
from sarj_python_lint.rules.store_field_update_reuses_upsert import StoreFieldUpdateReusesUpsert
|
|
268
|
+
from sarj_python_lint.rules.store_insert_requires_explicit_conflict_policy import (
|
|
269
|
+
StoreInsertRequiresExplicitConflictPolicy,
|
|
270
|
+
)
|
|
271
|
+
from sarj_python_lint.rules.store_mutation_command_fanout import StoreMutationCommandFanout
|
|
259
272
|
from sarj_python_lint.rules.test_without_explicit_oracle import NoExplicitTestOracle
|
|
260
273
|
|
|
261
274
|
|
|
262
275
|
REGISTRY: Mapping[str, type[Rule]] = MappingProxyType(
|
|
263
276
|
{
|
|
277
|
+
NoDiscardedTaggedOutcome.id: NoDiscardedTaggedOutcome,
|
|
278
|
+
StoreInsertRequiresExplicitConflictPolicy.id: StoreInsertRequiresExplicitConflictPolicy,
|
|
279
|
+
StoreMutationCommandFanout.id: StoreMutationCommandFanout,
|
|
280
|
+
PreferApplicationModelJoins.id: PreferApplicationModelJoins,
|
|
281
|
+
NoRecordingStore.id: NoRecordingStore,
|
|
282
|
+
NoRedundantSqlAlias.id: NoRedundantSqlAlias,
|
|
283
|
+
NoCustomControlFlowException.id: NoCustomControlFlowException,
|
|
284
|
+
PreferOptionalComposite.id: PreferOptionalComposite,
|
|
264
285
|
AsyncSubprocessCancellationCleanup.id: AsyncSubprocessCancellationCleanup,
|
|
265
286
|
CancelOwnedTaskWithoutJoin.id: CancelOwnedTaskWithoutJoin,
|
|
266
287
|
AsyncExecutorShutdown.id: AsyncExecutorShutdown,
|
|
267
288
|
NanHiddenByBuiltinMin.id: NanHiddenByBuiltinMin,
|
|
268
289
|
FailedProbeZeroThreshold.id: FailedProbeZeroThreshold,
|
|
290
|
+
PreferTypedMappingGet.id: PreferTypedMappingGet,
|
|
291
|
+
PreferRuntimeValidation.id: PreferRuntimeValidation,
|
|
292
|
+
PreferTypedCli.id: PreferTypedCli,
|
|
269
293
|
PreferGroupedSettings.id: PreferGroupedSettings,
|
|
270
294
|
NoRedundantLocalAlias.id: NoRedundantLocalAlias,
|
|
271
295
|
PytestFixtureReturnsClosedResource.id: PytestFixtureReturnsClosedResource,
|
|
@@ -225,12 +225,13 @@ class ResourceProvenance:
|
|
|
225
225
|
if not isinstance(node, ast.alias):
|
|
226
226
|
return False
|
|
227
227
|
parent = self.parents.get(node)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
228
|
+
match parent:
|
|
229
|
+
case ast.Import():
|
|
230
|
+
targets.add(("import", None, 0, node.name))
|
|
231
|
+
case ast.ImportFrom():
|
|
232
|
+
targets.add(("from", parent.module, parent.level, node.name))
|
|
233
|
+
case _:
|
|
234
|
+
return False
|
|
234
235
|
return len(targets) == 1
|
|
235
236
|
|
|
236
237
|
def imported(self, node: ast.expr, qualified: str) -> bool:
|