sarj-python-lint 0.80.11__tar.gz → 0.80.12__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-0.80.11 → sarj_python_lint-0.80.12}/PKG-INFO +1 -1
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/pyproject.toml +1 -1
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_registry.py +0 -2
- sarj_python_lint-0.80.11/src/sarj_python_lint/rules/trivially_true_assertion.py +0 -466
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/.gitignore +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/LICENSE +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/README.md +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/__main__.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/_analysis_session.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/_filesystem.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_comments.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_docstrings.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_fastapi.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_fixed_record.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_imports.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_project_index.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/complex_postgres_query_requires_architecture_review.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/excessive_commentary.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_positional_psycopg_row_escape.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_psycopg_execution_outside_injected_owner.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_raw_source_text_test_oracle.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_whole_request_response_payload_in_log.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_walrus_awaited_none_guard.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/pydantic_at_boundaries.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/stepdown.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/typed_error_reasons.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
- {sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sarj-python-lint
|
|
3
|
-
Version: 0.80.
|
|
3
|
+
Version: 0.80.12
|
|
4
4
|
Summary: Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults
|
|
5
5
|
Project-URL: Homepage, https://code-standards.sarj.ai/rules/python/
|
|
6
6
|
Project-URL: Documentation, https://code-standards.sarj.ai/rules/python/
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_registry.py
RENAMED
|
@@ -146,7 +146,6 @@ from sarj_python_lint.rules.store_insert_requires_on_conflict import (
|
|
|
146
146
|
)
|
|
147
147
|
from sarj_python_lint.rules.timestamp_order_requires_tiebreaker import TimestampOrderRequiresTiebreaker
|
|
148
148
|
from sarj_python_lint.rules.trailing_value_narration import TrailingValueNarration
|
|
149
|
-
from sarj_python_lint.rules.trivially_true_assertion import TriviallyTrueAssertion
|
|
150
149
|
from sarj_python_lint.rules.typed_error_reasons import TypedErrorReasons
|
|
151
150
|
from sarj_python_lint.rules.uncontrolled_randomness_in_test import UncontrolledRandomnessInTest
|
|
152
151
|
from sarj_python_lint.rules.unused_mock_setup import UnusedMockSetup
|
|
@@ -211,7 +210,6 @@ REGISTRY: Mapping[str, type[Rule]] = MappingProxyType(
|
|
|
211
210
|
OverMockedTest.id: OverMockedTest,
|
|
212
211
|
InvalidPydanticFieldDefault.id: InvalidPydanticFieldDefault,
|
|
213
212
|
NoFrozenAfterValidatorFieldWrite.id: NoFrozenAfterValidatorFieldWrite,
|
|
214
|
-
TriviallyTrueAssertion.id: TriviallyTrueAssertion,
|
|
215
213
|
NoRepeatedTestBody.id: NoRepeatedTestBody,
|
|
216
214
|
UnusedMockSetup.id: UnusedMockSetup,
|
|
217
215
|
PreferFstringOverConcat.id: PreferFstringOverConcat,
|
|
@@ -1,466 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import ast
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
from pathlib import PurePosixPath
|
|
6
|
-
from typing import TYPE_CHECKING, ClassVar, NamedTuple, override
|
|
7
|
-
|
|
8
|
-
from sarj_python_lint.rule_base import (
|
|
9
|
-
AutofixPolicy,
|
|
10
|
-
Diagnostic,
|
|
11
|
-
ExampleFile,
|
|
12
|
-
ExampleOutcome,
|
|
13
|
-
Rule,
|
|
14
|
-
RuleCategory,
|
|
15
|
-
RuleDocumentation,
|
|
16
|
-
RuleExample,
|
|
17
|
-
parse_or_none,
|
|
18
|
-
)
|
|
19
|
-
from sarj_python_lint.rules._paths import is_test_path
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if TYPE_CHECKING:
|
|
23
|
-
from pathlib import Path
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
_FUNC_NODES = (ast.FunctionDef, ast.AsyncFunctionDef)
|
|
27
|
-
|
|
28
|
-
_TEST_PREFIX = "test_"
|
|
29
|
-
|
|
30
|
-
# pytest's default `python_files`.
|
|
31
|
-
_COLLECTED_SUFFIX = "_test.py"
|
|
32
|
-
|
|
33
|
-
# Manual CLI probes carry `test_*.py` names but are never collected.
|
|
34
|
-
_UNCOLLECTED_DIR_NAMES = frozenset({"scripts"})
|
|
35
|
-
|
|
36
|
-
_ISINSTANCE = "isinstance"
|
|
37
|
-
|
|
38
|
-
_ISINSTANCE_ARITY = 2
|
|
39
|
-
|
|
40
|
-
_DUNDER_PREFIX = "__"
|
|
41
|
-
|
|
42
|
-
# Class-name endings that mark a collaborator rather than a record.
|
|
43
|
-
_COLLABORATOR_SUFFIXES = (
|
|
44
|
-
"backend",
|
|
45
|
-
"client",
|
|
46
|
-
"service",
|
|
47
|
-
"manager",
|
|
48
|
-
"handler",
|
|
49
|
-
"server",
|
|
50
|
-
"session",
|
|
51
|
-
"pool",
|
|
52
|
-
"engine",
|
|
53
|
-
"runner",
|
|
54
|
-
"worker",
|
|
55
|
-
"store",
|
|
56
|
-
"repository",
|
|
57
|
-
"factory",
|
|
58
|
-
"builder",
|
|
59
|
-
"adapter",
|
|
60
|
-
"connection",
|
|
61
|
-
"transport",
|
|
62
|
-
"receiver",
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
# Permit identity comparison only for boolean singleton assertions.
|
|
66
|
-
_ECHO_OPS = (ast.Eq, ast.Is)
|
|
67
|
-
|
|
68
|
-
_UNITTEST_ECHO_ASSERTS = frozenset({"assertEqual", "assertIs"})
|
|
69
|
-
|
|
70
|
-
_UNITTEST_ISINSTANCE_ASSERT = "assertIsInstance"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
@dataclass(frozen=True, slots=True)
|
|
74
|
-
class _EchoOperands:
|
|
75
|
-
left: ast.expr
|
|
76
|
-
right: ast.expr
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
type _Assertion = ast.Assert | ast.Call
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
class _AssertionFinding(NamedTuple):
|
|
83
|
-
node: _Assertion
|
|
84
|
-
diagnosis: str
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
_KWARG_DIAGNOSIS = (
|
|
88
|
-
"this reads back the literal the test just handed the constructor, so it can only fail if attribute "
|
|
89
|
-
"assignment stops working"
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
_ISINSTANCE_DIAGNOSIS = (
|
|
93
|
-
"the value was produced by calling this very class a line above, so the `isinstance` check pins the "
|
|
94
|
-
"language rather than the code"
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
# The advice when the test still has an assertion that can fail.
|
|
98
|
-
_ADVICE = ". Assert on something the code under test derived, or drop the assertion"
|
|
99
|
-
|
|
100
|
-
# The advice when it does not.
|
|
101
|
-
_ONLY_ASSERTION_ADVICE = (
|
|
102
|
-
". Every assertion this test makes is like it, so dropping them would leave a test that verifies "
|
|
103
|
-
"nothing. Assert the behaviour the test name claims to cover, or delete the test"
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
@dataclass(frozen=True, slots=True)
|
|
108
|
-
class _KwargEcho:
|
|
109
|
-
node: _Assertion
|
|
110
|
-
field: tuple[str, str]
|
|
111
|
-
echoes: bool
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
@dataclass(slots=True)
|
|
115
|
-
class _Scope:
|
|
116
|
-
asserts: list[_Assertion]
|
|
117
|
-
loads: dict[str, list[ast.Name]]
|
|
118
|
-
binds: dict[str, int]
|
|
119
|
-
calls: dict[str, ast.Call]
|
|
120
|
-
shadowed: set[str]
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
@dataclass(frozen=True, slots=True)
|
|
124
|
-
class _Index:
|
|
125
|
-
parents: dict[int, ast.AST]
|
|
126
|
-
scopes: list[_Scope]
|
|
127
|
-
owners: dict[int, _Scope]
|
|
128
|
-
imported_names: frozenset[str]
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
class TriviallyTrueAssertion(Rule):
|
|
132
|
-
id: str = "trivially-true-assertion"
|
|
133
|
-
code: str = "SARJ064"
|
|
134
|
-
documentation: ClassVar[RuleDocumentation | None] = RuleDocumentation(
|
|
135
|
-
summary="Assertions should depend on behavior rather than echoing values supplied by the test.",
|
|
136
|
-
rationale="Constructor keyword echoes and equivalent tautologies cannot reveal an application defect.",
|
|
137
|
-
remediation="Assert a transformation, validation result, or other value produced independently of the fixture literal.",
|
|
138
|
-
category=RuleCategory.TESTING,
|
|
139
|
-
autofix=AutofixPolicy.NONE,
|
|
140
|
-
limitations=(
|
|
141
|
-
"Literal-only assertions owned by Ruff or SARJ057 are excluded.",
|
|
142
|
-
"Constructor echoes with evidence of field coercion are excluded.",
|
|
143
|
-
"Imported constructors are excluded because their assignment, validation, and normalization behavior is not visible.",
|
|
144
|
-
),
|
|
145
|
-
examples=(
|
|
146
|
-
RuleExample(
|
|
147
|
-
example_id="constructor-keyword-echo",
|
|
148
|
-
title="Assertion repeats a constructor keyword",
|
|
149
|
-
outcome=ExampleOutcome.MATCH,
|
|
150
|
-
files=(
|
|
151
|
-
ExampleFile.python(
|
|
152
|
-
"tests/test_user.py",
|
|
153
|
-
'def test_user():\n user = User(name="Ada")\n assert user.name == "Ada"\n',
|
|
154
|
-
),
|
|
155
|
-
),
|
|
156
|
-
focus_path=PurePosixPath("tests/test_user.py"),
|
|
157
|
-
expected_count=1,
|
|
158
|
-
public=True,
|
|
159
|
-
),
|
|
160
|
-
RuleExample(
|
|
161
|
-
example_id="derived-value",
|
|
162
|
-
title="Assertion checks a derived value",
|
|
163
|
-
outcome=ExampleOutcome.NO_MATCH,
|
|
164
|
-
files=(
|
|
165
|
-
ExampleFile.python(
|
|
166
|
-
"tests/test_user.py",
|
|
167
|
-
'def test_user():\n user = User(name="Ada Lovelace")\n assert user.initials == "AL"\n',
|
|
168
|
-
),
|
|
169
|
-
),
|
|
170
|
-
focus_path=PurePosixPath("tests/test_user.py"),
|
|
171
|
-
expected_count=0,
|
|
172
|
-
public=True,
|
|
173
|
-
),
|
|
174
|
-
),
|
|
175
|
-
)
|
|
176
|
-
description: str = documentation.summary
|
|
177
|
-
|
|
178
|
-
@override
|
|
179
|
-
def check(self, path: Path, source: str) -> list[Diagnostic]:
|
|
180
|
-
if not is_test_path(path) or not _is_collected_module(path):
|
|
181
|
-
return []
|
|
182
|
-
tree = parse_or_none(path, source)
|
|
183
|
-
if tree is None:
|
|
184
|
-
return []
|
|
185
|
-
|
|
186
|
-
index = _index_module(tree)
|
|
187
|
-
findings: dict[int, _AssertionFinding] = {}
|
|
188
|
-
for node, diagnosis in _construction_findings(index):
|
|
189
|
-
_ = findings.setdefault(id(node), _AssertionFinding(node, diagnosis))
|
|
190
|
-
|
|
191
|
-
diags = [
|
|
192
|
-
Diagnostic(
|
|
193
|
-
path=path,
|
|
194
|
-
line=node.lineno,
|
|
195
|
-
col=node.col_offset + 1,
|
|
196
|
-
code=self.code,
|
|
197
|
-
message=diagnosis + _advice(index.owners.get(id(node)), findings),
|
|
198
|
-
)
|
|
199
|
-
for node, diagnosis in _one_per_test(index, findings)
|
|
200
|
-
]
|
|
201
|
-
diags.sort(key=lambda d: (d.line, d.col))
|
|
202
|
-
return diags
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
def _one_per_test(index: _Index, findings: dict[int, _AssertionFinding]) -> list[_AssertionFinding]:
|
|
206
|
-
anchors: dict[int, _AssertionFinding] = {}
|
|
207
|
-
for node, diagnosis in findings.values():
|
|
208
|
-
scope = index.owners.get(id(node))
|
|
209
|
-
key = id(node) if scope is None else id(scope)
|
|
210
|
-
earlier = anchors.get(key)
|
|
211
|
-
if earlier is None or (node.lineno, node.col_offset) < (earlier[0].lineno, earlier[0].col_offset):
|
|
212
|
-
anchors[key] = _AssertionFinding(node, diagnosis)
|
|
213
|
-
return list(anchors.values())
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
def _advice(scope: _Scope | None, findings: dict[int, _AssertionFinding]) -> str:
|
|
217
|
-
if scope is None or any(id(node) not in findings for node in scope.asserts):
|
|
218
|
-
return _ADVICE
|
|
219
|
-
return _ONLY_ASSERTION_ADVICE
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
def _is_collected_module(path: Path) -> bool:
|
|
223
|
-
name = path.name
|
|
224
|
-
matches_python_files = name.startswith(_TEST_PREFIX) or name.endswith(_COLLECTED_SUFFIX)
|
|
225
|
-
return matches_python_files and not any(part in _UNCOLLECTED_DIR_NAMES for part in path.parts)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def _index_module(tree: ast.Module) -> _Index:
|
|
229
|
-
parents: dict[int, ast.AST] = {}
|
|
230
|
-
scopes: list[_Scope] = []
|
|
231
|
-
owners: dict[int, _Scope] = {}
|
|
232
|
-
stack: list[tuple[ast.AST, _Scope | None]] = [(tree, None)]
|
|
233
|
-
while stack:
|
|
234
|
-
node, scope = stack.pop()
|
|
235
|
-
if scope is None and isinstance(node, _FUNC_NODES):
|
|
236
|
-
scope = _Scope(asserts=[], loads={}, binds={}, calls={}, shadowed=set())
|
|
237
|
-
scopes.append(scope)
|
|
238
|
-
if scope is not None:
|
|
239
|
-
if isinstance(node, ast.Assert) or (isinstance(node, ast.Call) and _is_unittest_assertion(node)):
|
|
240
|
-
scope.asserts.append(node)
|
|
241
|
-
owners[id(node)] = scope
|
|
242
|
-
else:
|
|
243
|
-
_record_local(node, scope)
|
|
244
|
-
for child in ast.iter_child_nodes(node):
|
|
245
|
-
parents[id(child)] = node
|
|
246
|
-
stack.append((child, scope))
|
|
247
|
-
return _Index(
|
|
248
|
-
parents=parents,
|
|
249
|
-
scopes=scopes,
|
|
250
|
-
owners=owners,
|
|
251
|
-
imported_names=_imported_names(tree),
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
def _imported_names(tree: ast.Module) -> frozenset[str]:
|
|
256
|
-
bindings: set[str] = set()
|
|
257
|
-
for node in ast.walk(tree):
|
|
258
|
-
if isinstance(node, ast.Import):
|
|
259
|
-
bindings.update(alias.asname or alias.name.split(".", maxsplit=1)[0] for alias in node.names)
|
|
260
|
-
elif isinstance(node, ast.ImportFrom):
|
|
261
|
-
bindings.update(alias.asname or alias.name for alias in node.names if alias.name != "*")
|
|
262
|
-
return frozenset(bindings)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
def _record_local(node: ast.AST, scope: _Scope) -> None:
|
|
266
|
-
if isinstance(node, ast.Name):
|
|
267
|
-
if isinstance(node.ctx, ast.Load):
|
|
268
|
-
scope.loads.setdefault(node.id, []).append(node)
|
|
269
|
-
else:
|
|
270
|
-
scope.binds[node.id] = scope.binds.get(node.id, 0) + 1
|
|
271
|
-
elif isinstance(node, ast.arg):
|
|
272
|
-
scope.shadowed.add(node.arg)
|
|
273
|
-
elif isinstance(node, (ast.Global, ast.Nonlocal)):
|
|
274
|
-
scope.shadowed.update(node.names)
|
|
275
|
-
elif isinstance(node, ast.Assign) and len(node.targets) == 1 and isinstance(node.value, ast.Call):
|
|
276
|
-
target = node.targets[0]
|
|
277
|
-
if isinstance(target, ast.Name):
|
|
278
|
-
scope.calls[target.id] = node.value
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
# Both shapes: what the test constructed a line earlier. #
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
def _construction_findings(index: _Index) -> list[_AssertionFinding]:
|
|
285
|
-
echoes: list[_KwargEcho] = []
|
|
286
|
-
hits: list[_AssertionFinding] = []
|
|
287
|
-
for scope in index.scopes:
|
|
288
|
-
if not scope.asserts or not scope.calls:
|
|
289
|
-
continue
|
|
290
|
-
constructed = _constructed_locals(scope, index.parents)
|
|
291
|
-
if not constructed:
|
|
292
|
-
continue
|
|
293
|
-
for node in scope.asserts:
|
|
294
|
-
echo = _kwarg_echo(node, constructed, index.imported_names)
|
|
295
|
-
if echo is not None:
|
|
296
|
-
echoes.append(echo)
|
|
297
|
-
elif _is_isinstance_echo(node, constructed, scope.asserts):
|
|
298
|
-
hits.append(_AssertionFinding(node, _ISINSTANCE_DIAGNOSIS))
|
|
299
|
-
|
|
300
|
-
coercing = {echo.field for echo in echoes if not echo.echoes}
|
|
301
|
-
hits.extend(
|
|
302
|
-
_AssertionFinding(echo.node, _KWARG_DIAGNOSIS) for echo in echoes if echo.echoes and echo.field not in coercing
|
|
303
|
-
)
|
|
304
|
-
return hits
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
def _constructed_locals(scope: _Scope, parents: dict[int, ast.AST]) -> dict[str, ast.Call]:
|
|
308
|
-
return {
|
|
309
|
-
name: call
|
|
310
|
-
for name, call in scope.calls.items()
|
|
311
|
-
if name not in scope.shadowed
|
|
312
|
-
and scope.binds.get(name) == 1
|
|
313
|
-
and all(_is_assertion_read(load, parents) for load in scope.loads.get(name, []))
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
def _is_assertion_read(node: ast.Name, parents: dict[int, ast.AST]) -> bool:
|
|
318
|
-
parent = parents.get(id(node))
|
|
319
|
-
if isinstance(parent, ast.Attribute):
|
|
320
|
-
grandparent = parents.get(id(parent))
|
|
321
|
-
if isinstance(grandparent, ast.Call) and grandparent.func is parent:
|
|
322
|
-
return False
|
|
323
|
-
return _under_assert(parent, parents)
|
|
324
|
-
if isinstance(parent, ast.Call) and parent.args and parent.args[0] is node:
|
|
325
|
-
if _is_isinstance_call(parent):
|
|
326
|
-
return _under_assert(parent, parents)
|
|
327
|
-
if (
|
|
328
|
-
isinstance(parent.func, ast.Attribute)
|
|
329
|
-
and parent.func.attr == _UNITTEST_ISINSTANCE_ASSERT
|
|
330
|
-
and _is_unittest_assertion(parent)
|
|
331
|
-
):
|
|
332
|
-
return True
|
|
333
|
-
return False
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
def _under_assert(node: ast.AST, parents: dict[int, ast.AST]) -> bool:
|
|
337
|
-
current: ast.AST | None = node
|
|
338
|
-
while current is not None:
|
|
339
|
-
if isinstance(current, ast.Assert) or _is_unittest_assertion(current):
|
|
340
|
-
return True
|
|
341
|
-
current = parents.get(id(current))
|
|
342
|
-
return False
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
def _is_isinstance_call(node: ast.Call) -> bool:
|
|
346
|
-
return isinstance(node.func, ast.Name) and node.func.id == _ISINSTANCE
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
def _is_unittest_assertion(node: ast.AST) -> bool:
|
|
350
|
-
return (
|
|
351
|
-
isinstance(node, ast.Call)
|
|
352
|
-
and isinstance(node.func, ast.Attribute)
|
|
353
|
-
and isinstance(node.func.value, ast.Name)
|
|
354
|
-
and node.func.value.id == "self"
|
|
355
|
-
and node.func.attr.startswith("assert")
|
|
356
|
-
)
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
def _kwarg_echo(
|
|
360
|
-
node: _Assertion,
|
|
361
|
-
constructed: dict[str, ast.Call],
|
|
362
|
-
imported_names: frozenset[str],
|
|
363
|
-
) -> _KwargEcho | None:
|
|
364
|
-
operands = _echo_operands(node)
|
|
365
|
-
if operands is None:
|
|
366
|
-
return None
|
|
367
|
-
for attribute, literal in ((operands.left, operands.right), (operands.right, operands.left)):
|
|
368
|
-
if not isinstance(attribute, ast.Attribute) or not isinstance(attribute.value, ast.Name):
|
|
369
|
-
continue
|
|
370
|
-
if attribute.attr.startswith(_DUNDER_PREFIX):
|
|
371
|
-
continue
|
|
372
|
-
call = constructed.get(attribute.value.id)
|
|
373
|
-
if call is None or node.lineno <= call.lineno:
|
|
374
|
-
continue
|
|
375
|
-
if _uses_imported_binding(call.func, imported_names):
|
|
376
|
-
continue
|
|
377
|
-
name = _constructor_name(call)
|
|
378
|
-
if name is None or not _is_pure_literal(literal):
|
|
379
|
-
continue
|
|
380
|
-
for keyword in call.keywords:
|
|
381
|
-
if keyword.arg == attribute.attr and _is_pure_literal(keyword.value):
|
|
382
|
-
echoes = ast.dump(keyword.value) == ast.dump(literal)
|
|
383
|
-
return _KwargEcho(node=node, field=(name, attribute.attr), echoes=echoes)
|
|
384
|
-
return None
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
def _uses_imported_binding(func: ast.expr, imported_names: frozenset[str]) -> bool:
|
|
388
|
-
current = func
|
|
389
|
-
while isinstance(current, ast.Attribute):
|
|
390
|
-
current = current.value
|
|
391
|
-
return isinstance(current, ast.Name) and current.id in imported_names
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
def _echo_operands(node: _Assertion) -> _EchoOperands | None:
|
|
395
|
-
if isinstance(node, ast.Assert):
|
|
396
|
-
test = node.test
|
|
397
|
-
if not isinstance(test, ast.Compare) or len(test.ops) != 1 or not isinstance(test.ops[0], _ECHO_OPS):
|
|
398
|
-
return None
|
|
399
|
-
return _EchoOperands(test.left, test.comparators[0])
|
|
400
|
-
if (
|
|
401
|
-
isinstance(node.func, ast.Attribute)
|
|
402
|
-
and node.func.attr in _UNITTEST_ECHO_ASSERTS
|
|
403
|
-
and len(node.args) >= _ISINSTANCE_ARITY
|
|
404
|
-
):
|
|
405
|
-
return _EchoOperands(node.args[0], node.args[1])
|
|
406
|
-
return None
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
def _constructor_name(call: ast.Call) -> str | None:
|
|
410
|
-
name = _called_name(call.func)
|
|
411
|
-
if name is None or not name[:1].isupper():
|
|
412
|
-
return None
|
|
413
|
-
lowered = name.lower()
|
|
414
|
-
return None if lowered.endswith(_COLLABORATOR_SUFFIXES) else name
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
def _called_name(func: ast.expr) -> str | None:
|
|
418
|
-
if isinstance(func, ast.Name):
|
|
419
|
-
return func.id
|
|
420
|
-
return func.attr if isinstance(func, ast.Attribute) else None
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
def _is_pure_literal(node: ast.expr) -> bool:
|
|
424
|
-
match node:
|
|
425
|
-
case ast.Constant():
|
|
426
|
-
return True
|
|
427
|
-
case ast.UnaryOp(op=ast.USub() | ast.UAdd(), operand=operand):
|
|
428
|
-
return _is_pure_literal(operand)
|
|
429
|
-
case ast.List() | ast.Set() | ast.Tuple():
|
|
430
|
-
return all(_is_pure_literal(elt) for elt in node.elts)
|
|
431
|
-
case ast.Dict(keys=keys, values=values):
|
|
432
|
-
keys_ok = all(key is not None and _is_pure_literal(key) for key in keys)
|
|
433
|
-
return keys_ok and all(_is_pure_literal(value) for value in values)
|
|
434
|
-
case _:
|
|
435
|
-
return False
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
def _is_isinstance_echo(node: _Assertion, constructed: dict[str, ast.Call], asserts: list[_Assertion]) -> bool:
|
|
439
|
-
if isinstance(node, ast.Assert):
|
|
440
|
-
test = node.test
|
|
441
|
-
if not isinstance(test, ast.Call) or not _is_isinstance_call(test) or len(test.args) != _ISINSTANCE_ARITY:
|
|
442
|
-
return False
|
|
443
|
-
target, cls = test.args
|
|
444
|
-
elif (
|
|
445
|
-
isinstance(node.func, ast.Attribute)
|
|
446
|
-
and node.func.attr == _UNITTEST_ISINSTANCE_ASSERT
|
|
447
|
-
and len(node.args) >= _ISINSTANCE_ARITY
|
|
448
|
-
):
|
|
449
|
-
target, cls = node.args[:_ISINSTANCE_ARITY]
|
|
450
|
-
else:
|
|
451
|
-
return False
|
|
452
|
-
if not isinstance(target, ast.Name):
|
|
453
|
-
return False
|
|
454
|
-
call = constructed.get(target.id)
|
|
455
|
-
if call is None or node.lineno <= call.lineno or ast.dump(call.func) != ast.dump(cls):
|
|
456
|
-
return False
|
|
457
|
-
return not _narrows_for_a_later_assertion(node, target.id, asserts)
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
def _narrows_for_a_later_assertion(node: _Assertion, name: str, asserts: list[_Assertion]) -> bool:
|
|
461
|
-
for other in asserts:
|
|
462
|
-
if other.lineno <= node.lineno:
|
|
463
|
-
continue
|
|
464
|
-
if any(isinstance(child, ast.Name) and child.id == name for child in ast.walk(other)):
|
|
465
|
-
return True
|
|
466
|
-
return False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/_analysis_session.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/__init__.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_ast_index.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_comments.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_docstrings.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_fastapi.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_first_party.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_fixed_record.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_imports.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_logging.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_project_index.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_prose_budget.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/_test_assertions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_comment_cruft.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_secret_in_log.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/no_select_star.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/over_mocked_test.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_class_row.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/prefer_str_enum.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.80.11 → sarj_python_lint-0.80.12}/src/sarj_python_lint/rules/stepdown.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|