sarj-python-lint 1.83.1__tar.gz → 1.84.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.84.0}/PKG-INFO +1 -1
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/pyproject.toml +1 -1
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/__main__.py +3 -2
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_annotation_origins.py +43 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_annotation_semantics.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_copy_on_write.py +29 -20
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_docstrings.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_fastapi.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_imports.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_mapping_shape_callbacks.py +18 -12
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_native_object_contracts.py +25 -16
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_opaque_contracts.py +22 -15
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_project_index.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_prose_budget.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_registry.py +6 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_resource_provenance.py +7 -6
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_store_writes.py +8 -5
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_test_composition.py +17 -14
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +8 -5
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +14 -8
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/duplicate_closed_pure_helper.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_broad_keyword_capture.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +48 -37
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_invalid_pydantic_bypass.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +16 -10
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +15 -9
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_redundant_local_alias.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_repeated_string_literal.py +8 -7
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +18 -8
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_tautological_expect.py +29 -17
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +23 -20
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/over_mocked_test.py +7 -6
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_class_row.py +14 -10
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +17 -11
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_declarative_batch_validation.py +14 -8
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_discriminated_model_union.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_injected_dependency_over_monkeypatch.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_library_fake.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +151 -7
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/prefer_native_string_check.py +14 -8
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +14 -11
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_or_pattern.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_pydantic_model_assertion.py +13 -10
- sarj_python_lint-1.84.0/src/sarj_python_lint/rules/prefer_runtime_validation.py +97 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_str_enum.py +45 -30
- sarj_python_lint-1.84.0/src/sarj_python_lint/rules/prefer_typed_cli.py +219 -0
- sarj_python_lint-1.84.0/src/sarj_python_lint/rules/prefer_typed_mapping_get.py +189 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +9 -6
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +22 -19
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/redundant_docstring.py +8 -7
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/require_explicit_contract_implementation.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_explicit_psycopg_transaction.py +30 -21
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_port_for_service.py +23 -16
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +16 -10
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_pydantic_for_mapping_shape.py +18 -20
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +8 -5
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/restated_test_docstring.py +16 -12
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/stepdown.py +8 -5
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +29 -17
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +30 -24
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/unused_mock_setup.py +7 -4
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/.gitignore +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/LICENSE +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/README.md +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_analysis_session.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_aliases.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_annotations.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_comments.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_declared_contracts.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_declared_tests.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_docs.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_enums.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_exhaustiveness.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_inert.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_parameters.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_repeated.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_security.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_sql_projection.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_autofix_tests.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_file_context.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_filesystem.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_fixes.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_parallel.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_python_target.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_source.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/application_logging.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/autofix.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/benchmark.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/cast_access.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/interpreter_argv.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/json_boundary.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_ast_names.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_ast_position.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_async_lifecycle.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_binding_inventory.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_closed_helpers.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_comment_narration.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_comments.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_contract_annotation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_data_union_discriminator.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_declared_contracts.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_dict_key_views.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_exports.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_inert_model_annotation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_inherited_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_local_alias_fix.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_local_source.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_namespace_access.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_native_namespace_capability.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_nominal_project.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_numeric_proof.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_pydantic_field_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_resolved_operation_signature.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_route_shapes.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_runtime_bindings.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_service_http_callbacks.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_set_fields.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_sql_aggregate_identity.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_sql_explain.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_sql_policy_source.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_static_json_alias.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_test_provenance.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_transactional_sql.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_type_guard_symbols.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/async_cleanup_registered_synchronously.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/async_executor_shutdown.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/async_subprocess_cancellation_cleanup.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/cancel_owned_task_without_join.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/delete_route_returns_no_content.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/duplicate_adjacent_exception_handler.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/duplicate_pytest_fixture_params.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/failed_probe_zero_threshold.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/fastapi_class_router_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/named_record_at_boundaries.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/nan_hidden_by_builtin_min.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/no_any_mapping_types.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_async_function_cache.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_before_validator_input_mutation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_blanket_suppression.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_conflicting_pydantic_alias_validation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_contradictory_type_guard.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/no_database_programmability.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_defaulted_environment_setting.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_delete_statement.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_discarded_validation_result.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/no_dunder_all.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_duplicate_field_validator_body.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/no_excessive_cognitive_complexity.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_fixed_sleep_before_assert.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_fixed_sleep_in_loop.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.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.84.0}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_hasattr.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_impossible_pydantic_field_bounds.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_injected_module_loader.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_input_model_mutation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_interpreter_source_arguments.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_invalid_argument_name_suppression.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_invalid_pydantic_validator_return.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_loguru_exc_info.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_loguru_printf_format.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_mocked_pydantic_value_object.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_mutating_container_transform.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_nullable_dependency_fallback.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_partial_type_is.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_redundant_module_alias_exports.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_service_behavior_in_settings.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_shallow_container_type_guard.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_shallow_record_type_guard.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/no_swallowed_asyncio_cancellation.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_test_method_grafting.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_unknown_pydantic_validator_field.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_unused_copy_result.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_unused_underscored_keyword_parameter.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_unused_value_marker.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.0}/src/sarj_python_lint/rules/no_work_verb_get_route.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_autospec_for_callable_mock.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_bulk_upsert.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_direct_import_module.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_grouped_settings.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_match_exception_dispatch.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_match_value_dispatch.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_monotonic_for_elapsed_time.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_precise_object_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_psycopg_executemany.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_pydantic_json_value.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_pytest_dependency_fixtures.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_pytest_fixture_injection.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_regex_fullmatch.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_required_constructor_parameters.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_typed_settings_field.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/pytest_fixture_returns_closed_resource.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/redundant_test_constructor_forwarder.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/repeated_test_composition.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/repeated_unimplemented_test_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_exp_on_jwt_decode.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_explicit_service_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_injectable_retry_sleep.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.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.84.0}/src/sarj_python_lint/rules/require_precise_factory_signature.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_public_dependency_contract.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/require_pydantic_for_structured_payload.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/shared_mutable_pydantic_factory.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/store_field_update_reuses_upsert.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/subprocess_kill_without_reap.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/test_without_explicit_oracle.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/unused_test_factory_option.py +0 -0
- {sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.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"}),
|
|
@@ -993,10 +993,13 @@ def _jwt_required_sequence(required: ast.expr) -> ast.expr | None:
|
|
|
993
993
|
):
|
|
994
994
|
return None
|
|
995
995
|
elements = [*required.elts, ast.Constant(value="exp")]
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
996
|
+
match required:
|
|
997
|
+
case ast.List():
|
|
998
|
+
return ast.List(elts=elements, ctx=ast.Load())
|
|
999
|
+
case ast.Tuple():
|
|
1000
|
+
return ast.Tuple(elts=elements, ctx=ast.Load())
|
|
1001
|
+
case _:
|
|
1002
|
+
pass
|
|
1000
1003
|
return ast.Set(elts=elements)
|
|
1001
1004
|
|
|
1002
1005
|
|
|
@@ -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.84.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.84.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.84.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
|
|
{sarj_python_lint-1.83.1 → sarj_python_lint-1.84.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.84.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
|
|
|
@@ -250,6 +250,9 @@ from sarj_python_lint.rules.prefer_precise_object_contract import PreferPreciseO
|
|
|
250
250
|
from sarj_python_lint.rules.prefer_psycopg_executemany import PreferPsycopgExecutemany
|
|
251
251
|
from sarj_python_lint.rules.prefer_pydantic_model_assertion import PreferPydanticModelAssertion
|
|
252
252
|
from sarj_python_lint.rules.prefer_pytest_dependency_fixtures import PreferPytestDependencyFixtures
|
|
253
|
+
from sarj_python_lint.rules.prefer_runtime_validation import PreferRuntimeValidation
|
|
254
|
+
from sarj_python_lint.rules.prefer_typed_cli import PreferTypedCli
|
|
255
|
+
from sarj_python_lint.rules.prefer_typed_mapping_get import PreferTypedMappingGet
|
|
253
256
|
from sarj_python_lint.rules.prefer_typed_settings_field import PreferTypedSettingsField
|
|
254
257
|
from sarj_python_lint.rules.pytest_fixture_returns_closed_resource import PytestFixtureReturnsClosedResource
|
|
255
258
|
from sarj_python_lint.rules.redundant_test_constructor_forwarder import RedundantTestConstructorForwarder
|
|
@@ -266,6 +269,9 @@ REGISTRY: Mapping[str, type[Rule]] = MappingProxyType(
|
|
|
266
269
|
AsyncExecutorShutdown.id: AsyncExecutorShutdown,
|
|
267
270
|
NanHiddenByBuiltinMin.id: NanHiddenByBuiltinMin,
|
|
268
271
|
FailedProbeZeroThreshold.id: FailedProbeZeroThreshold,
|
|
272
|
+
PreferTypedMappingGet.id: PreferTypedMappingGet,
|
|
273
|
+
PreferRuntimeValidation.id: PreferRuntimeValidation,
|
|
274
|
+
PreferTypedCli.id: PreferTypedCli,
|
|
269
275
|
PreferGroupedSettings.id: PreferGroupedSettings,
|
|
270
276
|
NoRedundantLocalAlias.id: NoRedundantLocalAlias,
|
|
271
277
|
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:
|
{sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_store_writes.py
RENAMED
|
@@ -165,11 +165,14 @@ def _free_names(expression: ast.expr) -> Iterator[str]:
|
|
|
165
165
|
node, shadowed = pending.pop()
|
|
166
166
|
if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Load) and node.id not in shadowed:
|
|
167
167
|
yield node.id
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
match node:
|
|
169
|
+
case ast.FunctionDef() | ast.AsyncFunctionDef() | ast.ClassDef() | ast.Lambda():
|
|
170
|
+
continue
|
|
171
|
+
case ast.ListComp() | ast.SetComp() | ast.DictComp() | ast.GeneratorExp():
|
|
172
|
+
pending.extend(_comprehension_scopes(node, shadowed))
|
|
173
|
+
continue
|
|
174
|
+
case _:
|
|
175
|
+
pass
|
|
173
176
|
pending.extend((child, shadowed) for child in ast.iter_child_nodes(node))
|
|
174
177
|
|
|
175
178
|
|
{sarj_python_lint-1.83.1 → sarj_python_lint-1.84.0}/src/sarj_python_lint/rules/_test_composition.py
RENAMED
|
@@ -274,20 +274,23 @@ def _value_key(
|
|
|
274
274
|
scope: WiringScope,
|
|
275
275
|
seen: frozenset[str] = frozenset(),
|
|
276
276
|
) -> str | None:
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
277
|
+
match value:
|
|
278
|
+
case ast.Name():
|
|
279
|
+
if value.id in seen or value.id in scope.blocked:
|
|
280
|
+
return None
|
|
281
|
+
if value.id in scope.aliases:
|
|
282
|
+
return _value_key(
|
|
283
|
+
context,
|
|
284
|
+
project,
|
|
285
|
+
scope.aliases[value.id],
|
|
286
|
+
scope,
|
|
287
|
+
seen=seen | {value.id},
|
|
288
|
+
)
|
|
289
|
+
return f"fixture:{value.id}" if value.id in scope.parameters else None
|
|
290
|
+
case ast.Constant():
|
|
291
|
+
return ast.dump(value)
|
|
292
|
+
case _:
|
|
293
|
+
pass
|
|
291
294
|
if not isinstance(value, ast.Call):
|
|
292
295
|
return None
|
|
293
296
|
callee = unalias(value.func, scope.aliases)
|
|
@@ -174,11 +174,14 @@ def _recoverable_query_root(node: ast.expr, constructors: frozenset[str]) -> ast
|
|
|
174
174
|
|
|
175
175
|
|
|
176
176
|
def _qualified_name(node: ast.expr) -> str:
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
match node:
|
|
178
|
+
case ast.Name():
|
|
179
|
+
return node.id
|
|
180
|
+
case ast.Attribute():
|
|
181
|
+
owner = _qualified_name(node.value)
|
|
182
|
+
return f"{owner}.{node.attr}" if owner else node.attr
|
|
183
|
+
case _:
|
|
184
|
+
pass
|
|
182
185
|
return ""
|
|
183
186
|
|
|
184
187
|
|
|
@@ -160,10 +160,13 @@ class DocstringArgsRestateSignature(Rule):
|
|
|
160
160
|
pending: list[tuple[ast.AST, str | None]] = [(child, class_name) for child in reversed(children(node))]
|
|
161
161
|
while pending:
|
|
162
162
|
child, owner = pending.pop()
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
match child:
|
|
164
|
+
case ast.FunctionDef() | ast.AsyncFunctionDef():
|
|
165
|
+
self._check_function(child, owner, path, imports, diags)
|
|
166
|
+
case ast.ClassDef():
|
|
167
|
+
owner = child.name
|
|
168
|
+
case _:
|
|
169
|
+
pass
|
|
167
170
|
pending.extend((nested, owner) for nested in reversed(children(child)))
|
|
168
171
|
|
|
169
172
|
def _check_function(
|
|
@@ -230,10 +230,13 @@ class DocstringReturnsRestateSignature(Rule):
|
|
|
230
230
|
pending: list[tuple[ast.AST, str | None]] = [(child, class_name) for child in reversed(children(node))]
|
|
231
231
|
while pending:
|
|
232
232
|
child, owner = pending.pop()
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
233
|
+
match child:
|
|
234
|
+
case ast.FunctionDef() | ast.AsyncFunctionDef():
|
|
235
|
+
self._check_function(child, owner, path, imports, diags)
|
|
236
|
+
case ast.ClassDef():
|
|
237
|
+
owner = child.name
|
|
238
|
+
case _:
|
|
239
|
+
pass
|
|
237
240
|
pending.extend((nested, owner) for nested in reversed(children(child)))
|
|
238
241
|
|
|
239
242
|
def _check_function(
|
|
@@ -333,10 +336,13 @@ def _contains_yield(node: ast.FunctionDef | ast.AsyncFunctionDef) -> bool:
|
|
|
333
336
|
pending: list[ast.AST] = list(node.body)
|
|
334
337
|
while pending:
|
|
335
338
|
current = pending.pop()
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
339
|
+
match current:
|
|
340
|
+
case ast.Yield() | ast.YieldFrom():
|
|
341
|
+
return True
|
|
342
|
+
case ast.FunctionDef() | ast.AsyncFunctionDef() | ast.ClassDef() | ast.Lambda():
|
|
343
|
+
continue
|
|
344
|
+
case _:
|
|
345
|
+
pass
|
|
340
346
|
pending.extend(children(current))
|
|
341
347
|
return False
|
|
342
348
|
|