sarj-python-lint 0.37.0__tar.gz → 0.38.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.37.0 → sarj_python_lint-0.38.0}/PKG-INFO +1 -1
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/pyproject.toml +1 -1
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/_secret_names.py +9 -2
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_logging.py +23 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_fstring_in_log.py +2 -18
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_secret_in_log.py +2 -5
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_sentinel_return_on_except.py +2 -15
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +5 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +2 -17
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/.gitignore +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/README.md +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/__main__.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_comments.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_docstrings.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_registry.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/conditional_assertion_in_test.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/duplicate_test_body.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/duplicated_override_docstring.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/fixture_returns_bare_tuple.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/inefficient_string_concat_in_loop.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/interaction_only_test.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/kwarg_heavy_construction_in_test.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/kwonly_same_type_params.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_aggregation_in_store_query.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_fat_try_blocks.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_file_level_escape_hatch_noqa.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_file_level_suppression.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_gen_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_isinstance_union_chain.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_optional_tenant_predicate.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_query_with_many_joins.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_raw_sql_in_tests.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_sequential_await.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_sleep_in_test_body.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_stdlib_logging.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_unreachable_after_terminal.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_match_pattern_destructuring.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_real_store_in_tests.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_timedelta_for_durations.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/pydantic_at_boundaries.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/single_public_export.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/sleep_with_computed_arg_in_test.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/stepdown.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/tautological_mock_assertion.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/test_loops_over_literal_cases.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/trivially_true_assertion.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/xfail_requires_strict.py +0 -0
- {sarj_python_lint-0.37.0 → sarj_python_lint-0.38.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.38.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
|
|
@@ -42,7 +42,7 @@ from itertools import pairwise
|
|
|
42
42
|
import re
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
SECRET_WORDS = frozenset(
|
|
46
46
|
{
|
|
47
47
|
"token",
|
|
48
48
|
"secret",
|
|
@@ -59,9 +59,16 @@ _SECRET_WORDS = frozenset(
|
|
|
59
59
|
"digest",
|
|
60
60
|
"hash",
|
|
61
61
|
"apikey",
|
|
62
|
+
# `bearer` is in the TypeScript twin's SECRET_WORDS and was in neither
|
|
63
|
+
# Python set, so `bearer == provided` was a flagged timing attack in one
|
|
64
|
+
# engine and silent in the other. The lists are otherwise identical,
|
|
65
|
+
# which is exactly what made the gap invisible.
|
|
66
|
+
"bearer",
|
|
62
67
|
}
|
|
63
68
|
)
|
|
64
69
|
|
|
70
|
+
_SECRET_WORDS = SECRET_WORDS
|
|
71
|
+
|
|
65
72
|
# Tokens that mark a counter, row-id, feature flag, or boolean presence/state
|
|
66
73
|
# marker. As the TRAILING token they mean the identifier is metadata *about* a
|
|
67
74
|
# secret, not the secret itself, so it is not a leak / timing surface even when a
|
|
@@ -165,7 +172,7 @@ def is_secret_name(identifier: str) -> bool:
|
|
|
165
172
|
return False
|
|
166
173
|
if leading_word(identifier) in _FLAG_PREFIXES:
|
|
167
174
|
return False
|
|
168
|
-
if any(tok in
|
|
175
|
+
if any(tok in SECRET_WORDS for tok in tokens):
|
|
169
176
|
return True
|
|
170
177
|
return _has_api_key(tokens)
|
|
171
178
|
|
|
@@ -17,6 +17,29 @@ _LOGGER_NAMES = frozenset({"logger", "log", "logging", "loguru", "_logger", "_lo
|
|
|
17
17
|
LOGGER_FACTORIES = frozenset({"getlogger", "get_logger"})
|
|
18
18
|
_LOGGER_FACTORIES = LOGGER_FACTORIES
|
|
19
19
|
|
|
20
|
+
# Public: the `.attr` of a logging call. SARJ012 (secret-in-log) once carried a
|
|
21
|
+
# SHORTER list than SARJ017 (f-string-in-log) -- 7 names against 11 -- so
|
|
22
|
+
# `logger.success("auth", token=token)` was a log call to one rule and not to
|
|
23
|
+
# the other, and the SECURITY rule was the one that could not see it. `success`,
|
|
24
|
+
# `trace` and `log` are documented loguru levels and `loguru` is already in
|
|
25
|
+
# `_LOGGER_NAMES`, so the omission was a silent false negative on a real idiom.
|
|
26
|
+
# One set, imported everywhere, is what stops that recurring.
|
|
27
|
+
LOG_METHODS = frozenset(
|
|
28
|
+
{
|
|
29
|
+
"critical",
|
|
30
|
+
"debug",
|
|
31
|
+
"error",
|
|
32
|
+
"exception",
|
|
33
|
+
"fatal",
|
|
34
|
+
"info",
|
|
35
|
+
"log",
|
|
36
|
+
"success",
|
|
37
|
+
"trace",
|
|
38
|
+
"warn",
|
|
39
|
+
"warning",
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
20
43
|
|
|
21
44
|
def is_logger_expr(expr: ast.expr) -> bool:
|
|
22
45
|
"""Report whether `expr` evaluates to a logger.
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_fstring_in_log.py
RENAMED
|
@@ -11,29 +11,13 @@ from typing import TYPE_CHECKING, override
|
|
|
11
11
|
|
|
12
12
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
13
13
|
from sarj_python_lint.rules._ast_index import nodes
|
|
14
|
-
from sarj_python_lint.rules._logging import LOGGER_FACTORIES, is_logger_expr
|
|
14
|
+
from sarj_python_lint.rules._logging import LOG_METHODS, LOGGER_FACTORIES, is_logger_expr
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
if TYPE_CHECKING:
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
_LOG_METHODS = frozenset(
|
|
22
|
-
{
|
|
23
|
-
"debug",
|
|
24
|
-
"info",
|
|
25
|
-
"warning",
|
|
26
|
-
"warn",
|
|
27
|
-
"error",
|
|
28
|
-
"exception",
|
|
29
|
-
"critical",
|
|
30
|
-
"fatal",
|
|
31
|
-
"trace",
|
|
32
|
-
"success",
|
|
33
|
-
"log",
|
|
34
|
-
}
|
|
35
|
-
)
|
|
36
|
-
|
|
37
21
|
# Keyword arguments defined by stdlib `logging` (and never structured fields).
|
|
38
22
|
# Their presence marks the call as a stdlib logger, for which the loguru-style
|
|
39
23
|
# structured-keyword rewrite is wrong.
|
|
@@ -97,7 +81,7 @@ def _candidates(tree: ast.Module) -> list[tuple[ast.Call, ast.JoinedStr]]:
|
|
|
97
81
|
|
|
98
82
|
def _is_logging_call(node: ast.Call) -> bool:
|
|
99
83
|
func = node.func
|
|
100
|
-
if not isinstance(func, ast.Attribute) or func.attr not in
|
|
84
|
+
if not isinstance(func, ast.Attribute) or func.attr not in LOG_METHODS:
|
|
101
85
|
return False
|
|
102
86
|
return is_logger_expr(func.value)
|
|
103
87
|
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_secret_in_log.py
RENAMED
|
@@ -13,16 +13,13 @@ from typing import TYPE_CHECKING, override
|
|
|
13
13
|
from sarj_python_lint._secret_names import identifier_tokens, is_secret_name
|
|
14
14
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
15
15
|
from sarj_python_lint.rules._ast_index import nodes
|
|
16
|
-
from sarj_python_lint.rules._logging import is_logger_expr
|
|
16
|
+
from sarj_python_lint.rules._logging import LOG_METHODS, is_logger_expr
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
# Logging method names (the `.attr` of the call's func).
|
|
24
|
-
_LOG_METHODS = frozenset({"debug", "info", "warning", "warn", "error", "exception", "critical"})
|
|
25
|
-
|
|
26
23
|
# A redaction marker (`token_prefix`, `password_hash`, `secret_masked`,
|
|
27
24
|
# `api_key_tag`) means the keyword carries a masked/derived value, not the raw
|
|
28
25
|
# secret — the intended safe form.
|
|
@@ -88,6 +85,6 @@ def _is_logging_call(node: ast.Call) -> bool:
|
|
|
88
85
|
func = node.func
|
|
89
86
|
if not isinstance(func, ast.Attribute):
|
|
90
87
|
return False
|
|
91
|
-
if func.attr not in
|
|
88
|
+
if func.attr not in LOG_METHODS:
|
|
92
89
|
return False
|
|
93
90
|
return is_logger_expr(func.value)
|
|
@@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, override
|
|
|
12
12
|
|
|
13
13
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
14
14
|
from sarj_python_lint.rules._ast_index import children, nodes, walk
|
|
15
|
+
from sarj_python_lint.rules._logging import LOG_METHODS
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
if TYPE_CHECKING:
|
|
@@ -375,20 +376,6 @@ def _is_sentinel(value: ast.expr) -> bool:
|
|
|
375
376
|
return False
|
|
376
377
|
|
|
377
378
|
|
|
378
|
-
_LOG_METHODS: frozenset[str] = frozenset(
|
|
379
|
-
{
|
|
380
|
-
"debug",
|
|
381
|
-
"info",
|
|
382
|
-
"warning",
|
|
383
|
-
"warn",
|
|
384
|
-
"error",
|
|
385
|
-
"exception",
|
|
386
|
-
"critical",
|
|
387
|
-
"fatal",
|
|
388
|
-
}
|
|
389
|
-
)
|
|
390
|
-
|
|
391
|
-
|
|
392
379
|
def _handler_logs_before_return(handler: ast.ExceptHandler) -> bool:
|
|
393
380
|
"""Report whether some logging call can reach the handler's final sentinel return."""
|
|
394
381
|
_, logged_fallthrough = _list_props(handler.body[:-1])
|
|
@@ -502,7 +489,7 @@ def _is_logging_call(node: ast.AST) -> bool:
|
|
|
502
489
|
if not isinstance(node, ast.Call):
|
|
503
490
|
return False
|
|
504
491
|
func = node.func
|
|
505
|
-
if not isinstance(func, ast.Attribute) or func.attr not in
|
|
492
|
+
if not isinstance(func, ast.Attribute) or func.attr not in LOG_METHODS:
|
|
506
493
|
return False
|
|
507
494
|
return _is_logger_receiver(func.value)
|
|
508
495
|
|
|
@@ -57,6 +57,11 @@ _AUTH_WORDS = frozenset(
|
|
|
57
57
|
"signature",
|
|
58
58
|
"hmac",
|
|
59
59
|
"apikey",
|
|
60
|
+
# `bearer` was in the TypeScript twin's AUTH_WORDS and in neither Python
|
|
61
|
+
# list, so `bearer == provided` was a flagged timing attack in TS and a
|
|
62
|
+
# silent one here. The two lists are otherwise identical, which is what
|
|
63
|
+
# made the gap invisible.
|
|
64
|
+
"bearer",
|
|
60
65
|
}
|
|
61
66
|
)
|
|
62
67
|
|
|
@@ -14,7 +14,7 @@ from typing import TYPE_CHECKING, override
|
|
|
14
14
|
|
|
15
15
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
16
16
|
from sarj_python_lint.rules._ast_index import nodes, walk
|
|
17
|
-
from sarj_python_lint.rules._logging import is_logger_expr
|
|
17
|
+
from sarj_python_lint.rules._logging import LOG_METHODS, is_logger_expr
|
|
18
18
|
from sarj_python_lint.rules._paths import is_generated
|
|
19
19
|
|
|
20
20
|
|
|
@@ -24,21 +24,6 @@ if TYPE_CHECKING:
|
|
|
24
24
|
|
|
25
25
|
# Method names that make a logger-receiver call a logging call. Kept in sync by
|
|
26
26
|
# construction with SARJ017's list; the receiver test is the shared helper.
|
|
27
|
-
_LOG_METHODS = frozenset(
|
|
28
|
-
{
|
|
29
|
-
"debug",
|
|
30
|
-
"info",
|
|
31
|
-
"warning",
|
|
32
|
-
"warn",
|
|
33
|
-
"error",
|
|
34
|
-
"exception",
|
|
35
|
-
"critical",
|
|
36
|
-
"fatal",
|
|
37
|
-
"trace",
|
|
38
|
-
"success",
|
|
39
|
-
"log",
|
|
40
|
-
}
|
|
41
|
-
)
|
|
42
27
|
|
|
43
28
|
# A literal ENDING in an UPPERCASE SQL keyword is a query fragment awaiting
|
|
44
29
|
# interpolation — ruff's S608 and SARJ021 own that shape. Anchored at the end,
|
|
@@ -174,7 +159,7 @@ def _comment_lines(source: str) -> frozenset[int]:
|
|
|
174
159
|
def _is_logging_call(node: ast.Call) -> bool:
|
|
175
160
|
"""Report whether `node` is a logging call, using SARJ017's receiver resolver."""
|
|
176
161
|
func = node.func
|
|
177
|
-
if not isinstance(func, ast.Attribute) or func.attr not in
|
|
162
|
+
if not isinstance(func, ast.Attribute) or func.attr not in LOG_METHODS:
|
|
178
163
|
return False
|
|
179
164
|
return is_logger_expr(func.value)
|
|
180
165
|
|
|
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.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_ast_index.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/_docstrings.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.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
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/mock_without_spec.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_comment_cruft.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_fat_try_blocks.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
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_select_star.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/no_stdlib_logging.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/over_mocked_test.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.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
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/prefer_or_pattern.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.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
|
{sarj_python_lint-0.37.0 → sarj_python_lint-0.38.0}/src/sarj_python_lint/rules/unused_mock_setup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|