sarj-python-lint 0.45.0__tar.gz → 0.46.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-0.45.0 → sarj_python_lint-0.46.0}/PKG-INFO +2 -2
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/README.md +1 -1
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/pyproject.toml +1 -1
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/__main__.py +1 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_comments.py +2 -1
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_prose_budget.py +17 -2
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +32 -20
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/.gitignore +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_docstrings.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_fastapi.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_registry.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/conditional_assertion_in_test.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/duplicate_test_body.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/duplicated_override_docstring.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/fastapi_openapi_contract.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/fixture_returns_bare_tuple.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/inefficient_string_concat_in_loop.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/interaction_only_test.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/kwarg_heavy_construction_in_test.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/kwonly_same_type_params.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_aggregation_in_store_query.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_fat_try_blocks.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_file_level_escape_hatch_noqa.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_file_level_suppression.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_fstring_in_log.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_gen_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_isinstance_union_chain.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_long_comment.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_optional_tenant_predicate.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_query_with_many_joins.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_raw_sql_in_tests.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_sentinel_return_on_except.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_sequential_await.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_sleep_in_test_body.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_stdlib_logging.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_unreachable_after_terminal.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_real_store_in_tests.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_single_sentence_comment.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_timedelta_for_durations.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/pydantic_at_boundaries.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/single_public_export.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/sleep_with_computed_arg_in_test.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/stepdown.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/tautological_mock_assertion.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/test_loops_over_literal_cases.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/trivially_true_assertion.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/xfail_requires_strict.py +0 -0
- {sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/zero_assertion_test.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sarj-python-lint
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.46.0
|
|
4
4
|
Summary: Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults
|
|
5
5
|
Project-URL: Homepage, https://github.com/sarj-ai/standards/tree/main/packages/python
|
|
6
6
|
Project-URL: Repository, https://github.com/sarj-ai/standards
|
|
@@ -28,7 +28,7 @@ uv tool install sarj-python-lint
|
|
|
28
28
|
|
|
29
29
|
```yaml
|
|
30
30
|
- repo: https://github.com/sarj-ai/standards
|
|
31
|
-
rev: python-v0.
|
|
31
|
+
rev: python-v0.46.0
|
|
32
32
|
hooks:
|
|
33
33
|
- id: sarj-no-sequential-await
|
|
34
34
|
- id: sarj-inefficient-string-concat-in-loop
|
|
@@ -9,6 +9,7 @@ import tokenize
|
|
|
9
9
|
from typing import TYPE_CHECKING, NamedTuple
|
|
10
10
|
|
|
11
11
|
from sarj_python_lint.rule_base import parse_or_none
|
|
12
|
+
from sarj_python_lint.rules._ast_index import nodes
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
if TYPE_CHECKING:
|
|
@@ -498,7 +499,7 @@ def statement_comment_walls(
|
|
|
498
499
|
return {}
|
|
499
500
|
comments = {line: (col, body) for line, col, body in standalone}
|
|
500
501
|
walls: dict[int, frozenset[int]] = {}
|
|
501
|
-
for owner in ast.
|
|
502
|
+
for owner in nodes(tree, ast.AST):
|
|
502
503
|
for value in _owned_statement_lists(owner):
|
|
503
504
|
statements = [item for item in value if _is_wall_statement(item)]
|
|
504
505
|
if len(statements) < _WALL_MIN_STATEMENTS:
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_prose_budget.py
RENAMED
|
@@ -10,6 +10,7 @@ import tokenize
|
|
|
10
10
|
from typing import TYPE_CHECKING, Final
|
|
11
11
|
|
|
12
12
|
from sarj_python_lint.rule_base import parse_or_none
|
|
13
|
+
from sarj_python_lint.rules._ast_index import nodes
|
|
13
14
|
from sarj_python_lint.rules._docstrings import PROMPT_DECORATOR_MARKERS, decorator_markers, sections
|
|
14
15
|
from sarj_python_lint.rules._paths import is_generated
|
|
15
16
|
|
|
@@ -53,6 +54,9 @@ class ProseGroup:
|
|
|
53
54
|
typed_sections: frozenset[str] = frozenset()
|
|
54
55
|
|
|
55
56
|
|
|
57
|
+
_last_groups: tuple[str, str, tuple[ProseGroup, ...]] | None = None
|
|
58
|
+
|
|
59
|
+
|
|
56
60
|
def sentence_units(text: str) -> int:
|
|
57
61
|
"""Count prose sentences and unpunctuated list items deterministically."""
|
|
58
62
|
text = _without_examples_metadata(text)
|
|
@@ -98,6 +102,17 @@ def _without_examples_metadata(text: str) -> str:
|
|
|
98
102
|
|
|
99
103
|
def groups(path: Path, source: str) -> list[ProseGroup]:
|
|
100
104
|
"""Extract docstrings and contiguous own-line comment runs from one file."""
|
|
105
|
+
global _last_groups # ruff: ignore[global-statement] -- rules run sequentially per file.
|
|
106
|
+
path_key = str(path)
|
|
107
|
+
if _last_groups is not None and _last_groups[0] == path_key and _last_groups[1] is source:
|
|
108
|
+
return list(_last_groups[2])
|
|
109
|
+
extracted = _extract_groups(path, source)
|
|
110
|
+
_last_groups = (path_key, source, tuple(extracted))
|
|
111
|
+
return extracted
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _extract_groups(path: Path, source: str) -> list[ProseGroup]:
|
|
115
|
+
"""Perform the shared parse and tokenization once for adjacent prose rules."""
|
|
101
116
|
if is_generated(path, source):
|
|
102
117
|
return []
|
|
103
118
|
tree = parse_or_none(path, source)
|
|
@@ -140,8 +155,8 @@ def _comment_run(run: list[tokenize.TokenInfo]) -> ProseGroup:
|
|
|
140
155
|
|
|
141
156
|
def _docstring_groups(tree: ast.Module) -> list[ProseGroup]:
|
|
142
157
|
out: list[ProseGroup] = []
|
|
143
|
-
for node in ast.
|
|
144
|
-
if not
|
|
158
|
+
for node in nodes(tree, ast.Module, ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef):
|
|
159
|
+
if not node.body:
|
|
145
160
|
continue
|
|
146
161
|
first = node.body[0]
|
|
147
162
|
if not (
|
|
@@ -52,6 +52,12 @@ class _Binding:
|
|
|
52
52
|
symbol: str | None
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
@dataclass(frozen=True, slots=True)
|
|
56
|
+
class _HiddenParameter:
|
|
57
|
+
parameter: ast.arg
|
|
58
|
+
uses_boolean_or: bool
|
|
59
|
+
|
|
60
|
+
|
|
55
61
|
@final
|
|
56
62
|
class NoHiddenConstructorFallback(Rule):
|
|
57
63
|
id = "no-hidden-constructor-fallback"
|
|
@@ -88,19 +94,24 @@ class NoHiddenConstructorFallback(Rule):
|
|
|
88
94
|
hidden = _hidden_parameters(init, resolver)
|
|
89
95
|
if not hidden or not _has_composition_call(path, class_node.name):
|
|
90
96
|
continue
|
|
91
|
-
names = ", ".join(f"`{parameter.arg}`" for
|
|
97
|
+
names = ", ".join(f"`{match.parameter.arg}`" for match in hidden)
|
|
92
98
|
noun = "parameter" if len(hidden) == 1 else "parameters"
|
|
93
99
|
verb = "falls" if len(hidden) == 1 else "fall"
|
|
100
|
+
falsey_warning = (
|
|
101
|
+
" A boolean `or` also treats explicit falsey values as omitted."
|
|
102
|
+
if any(match.uses_boolean_or for match in hidden)
|
|
103
|
+
else ""
|
|
104
|
+
)
|
|
94
105
|
diagnostics.append(
|
|
95
106
|
Diagnostic(
|
|
96
107
|
path=path,
|
|
97
|
-
line=hidden[0].lineno,
|
|
98
|
-
col=hidden[0].col_offset + 1,
|
|
108
|
+
line=hidden[0].parameter.lineno,
|
|
109
|
+
col=hidden[0].parameter.col_offset + 1,
|
|
99
110
|
code=self.code,
|
|
100
111
|
message=(
|
|
101
112
|
f"Constructor {noun} {names} {verb} back to application settings when omitted; "
|
|
102
|
-
"make the argument required and resolve the fallback at the call site or composition root.
|
|
103
|
-
"
|
|
113
|
+
"make the argument required and resolve the fallback at the call site or composition root."
|
|
114
|
+
f"{falsey_warning}"
|
|
104
115
|
),
|
|
105
116
|
severity=Severity.WARNING,
|
|
106
117
|
)
|
|
@@ -115,7 +126,7 @@ def _is_descriptor(node: ast.FunctionDef | ast.AsyncFunctionDef) -> bool:
|
|
|
115
126
|
def _hidden_parameters(
|
|
116
127
|
init: ast.FunctionDef | ast.AsyncFunctionDef,
|
|
117
128
|
resolver: _RuntimeConfigResolver,
|
|
118
|
-
) -> list[
|
|
129
|
+
) -> list[_HiddenParameter]:
|
|
119
130
|
candidates = {
|
|
120
131
|
parameter.arg: parameter
|
|
121
132
|
for parameter, default in zip(init.args.kwonlyargs, init.args.kw_defaults, strict=True)
|
|
@@ -124,15 +135,16 @@ def _hidden_parameters(
|
|
|
124
135
|
if not candidates:
|
|
125
136
|
return []
|
|
126
137
|
|
|
127
|
-
hidden:
|
|
138
|
+
hidden: dict[str, bool] = {}
|
|
128
139
|
rebound: set[str] = set()
|
|
129
140
|
shadowed = _argument_names(init.args)
|
|
130
141
|
for statement in init.body:
|
|
131
142
|
available = candidates.keys() - rebound
|
|
132
|
-
|
|
143
|
+
for name, uses_boolean_or in _statement_fallbacks(statement, available, resolver, shadowed).items():
|
|
144
|
+
hidden[name] = hidden.get(name, False) or uses_boolean_or
|
|
133
145
|
rebound.update(_directly_bound_names(statement) & candidates.keys())
|
|
134
146
|
shadowed.update(_directly_bound_names(statement))
|
|
135
|
-
return [parameter for name, parameter in candidates.items() if name in hidden]
|
|
147
|
+
return [_HiddenParameter(parameter, hidden[name]) for name, parameter in candidates.items() if name in hidden]
|
|
136
148
|
|
|
137
149
|
|
|
138
150
|
def _statement_fallbacks(
|
|
@@ -140,16 +152,16 @@ def _statement_fallbacks(
|
|
|
140
152
|
candidates: set[str],
|
|
141
153
|
resolver: _RuntimeConfigResolver,
|
|
142
154
|
shadowed: set[str],
|
|
143
|
-
) ->
|
|
155
|
+
) -> dict[str, bool]:
|
|
144
156
|
if isinstance(statement, ast.Assign):
|
|
145
157
|
return _expression_fallbacks(statement.value, candidates, resolver, shadowed)
|
|
146
158
|
if isinstance(statement, ast.AnnAssign) and statement.value is not None:
|
|
147
159
|
return _expression_fallbacks(statement.value, candidates, resolver, shadowed)
|
|
148
160
|
if not isinstance(statement, ast.If) or statement.orelse or len(statement.body) != 1:
|
|
149
|
-
return
|
|
161
|
+
return {}
|
|
150
162
|
parameter = _none_comparison_parameter(statement.test, candidates, expect_not=False)
|
|
151
163
|
if parameter is None:
|
|
152
|
-
return
|
|
164
|
+
return {}
|
|
153
165
|
body = statement.body[0]
|
|
154
166
|
if isinstance(body, ast.Assign):
|
|
155
167
|
value = body.value if len(body.targets) == 1 and _is_name(body.targets[0], parameter) else None
|
|
@@ -157,7 +169,7 @@ def _statement_fallbacks(
|
|
|
157
169
|
value = body.value if _is_name(body.target, parameter) else None
|
|
158
170
|
else:
|
|
159
171
|
value = None
|
|
160
|
-
return {parameter} if value is not None and resolver.is_runtime_config(value, shadowed) else
|
|
172
|
+
return {parameter: False} if value is not None and resolver.is_runtime_config(value, shadowed) else {}
|
|
161
173
|
|
|
162
174
|
|
|
163
175
|
def _expression_fallbacks(
|
|
@@ -165,15 +177,15 @@ def _expression_fallbacks(
|
|
|
165
177
|
candidates: set[str],
|
|
166
178
|
resolver: _RuntimeConfigResolver,
|
|
167
179
|
shadowed: set[str],
|
|
168
|
-
) ->
|
|
180
|
+
) -> dict[str, bool]:
|
|
169
181
|
if isinstance(expression, ast.BoolOp) and isinstance(expression.op, ast.Or):
|
|
170
182
|
match expression.values:
|
|
171
183
|
case [ast.Name(id=parameter), fallback] if parameter in candidates:
|
|
172
|
-
return {parameter} if resolver.is_runtime_config(fallback, shadowed) else
|
|
184
|
+
return {parameter: True} if resolver.is_runtime_config(fallback, shadowed) else {}
|
|
173
185
|
case _:
|
|
174
|
-
return
|
|
186
|
+
return {}
|
|
175
187
|
if not isinstance(expression, ast.IfExp):
|
|
176
|
-
return
|
|
188
|
+
return {}
|
|
177
189
|
not_none = _none_comparison_parameter(expression.test, candidates, expect_not=True)
|
|
178
190
|
if (
|
|
179
191
|
not_none is not None
|
|
@@ -181,7 +193,7 @@ def _expression_fallbacks(
|
|
|
181
193
|
and expression.body.id == not_none
|
|
182
194
|
and resolver.is_runtime_config(expression.orelse, shadowed)
|
|
183
195
|
):
|
|
184
|
-
return {not_none}
|
|
196
|
+
return {not_none: False}
|
|
185
197
|
is_none = _none_comparison_parameter(expression.test, candidates, expect_not=False)
|
|
186
198
|
if (
|
|
187
199
|
is_none is not None
|
|
@@ -189,8 +201,8 @@ def _expression_fallbacks(
|
|
|
189
201
|
and expression.orelse.id == is_none
|
|
190
202
|
and resolver.is_runtime_config(expression.body, shadowed)
|
|
191
203
|
):
|
|
192
|
-
return {is_none}
|
|
193
|
-
return
|
|
204
|
+
return {is_none: False}
|
|
205
|
+
return {}
|
|
194
206
|
|
|
195
207
|
|
|
196
208
|
def _none_comparison_parameter(test: ast.expr, candidates: set[str], *, expect_not: bool) -> str | None:
|
|
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.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_ast_index.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/_first_party.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
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/mock_without_spec.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_comment_cruft.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_fat_try_blocks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_fstring_in_log.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_long_comment.py
RENAMED
|
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.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_secret_in_log.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_select_star.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/no_stdlib_logging.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/over_mocked_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/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
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/prefer_or_pattern.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/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
|
{sarj_python_lint-0.45.0 → sarj_python_lint-0.46.0}/src/sarj_python_lint/rules/unused_mock_setup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|