sarj-python-lint 0.17.0__tar.gz → 0.18.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.17.0 → sarj_python_lint-0.18.0}/PKG-INFO +1 -1
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/pyproject.toml +1 -1
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/_paths.py +6 -1
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/inefficient_string_concat_in_loop.py +9 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_fat_try_blocks.py +57 -42
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_repeated_string_literal.py +8 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +9 -1
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_timedelta_for_durations.py +9 -1
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/single_public_export.py +8 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/stepdown.py +8 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/xfail_requires_strict.py +3 -1
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/.gitignore +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/README.md +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/__main__.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/_registry.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/fixture_returns_bare_tuple.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/kwarg_heavy_construction_in_test.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/kwonly_same_type_params.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_aggregation_in_store_query.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_file_level_suppression.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_fstring_in_log.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_isinstance_union_chain.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_query_with_many_joins.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_raw_sql_in_tests.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_sentinel_return_on_except.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_sequential_await.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_sleep_in_test_body.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_unreachable_after_terminal.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/pydantic_at_boundaries.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/sleep_with_computed_arg_in_test.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/test_loops_over_literal_cases.py +0 -0
- {sarj_python_lint-0.17.0 → sarj_python_lint-0.18.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.18.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
|
|
@@ -23,7 +23,12 @@ if TYPE_CHECKING:
|
|
|
23
23
|
|
|
24
24
|
_TEST_DIR_NAMES = frozenset({"tests", "test"})
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
# `auto-?generated` misses "automatically generated", which is the phrase
|
|
27
|
+
# @generated tooling, protoc and OpenAPI generators emit most often.
|
|
28
|
+
_GENERATED_RE = re.compile(
|
|
29
|
+
r"auto(?:-|matically )?generated|generated by|do not edit|@generated",
|
|
30
|
+
re.IGNORECASE,
|
|
31
|
+
)
|
|
27
32
|
|
|
28
33
|
_GENERATED_HEADER_LINES = 5
|
|
29
34
|
|
|
@@ -34,6 +34,12 @@ References:
|
|
|
34
34
|
- https://docs.python.org/3/library/stdtypes.html#str.join
|
|
35
35
|
- https://wiki.python.org/moin/PythonSpeed/PerformanceTips
|
|
36
36
|
|
|
37
|
+
* **generated files** (`_paths.is_generated_source`). Their layout is the
|
|
38
|
+
generator's, and re-running the generator discards any edit, so a finding
|
|
39
|
+
there can never be acted on in place. Measured on the 69 `DO NOT EDIT`
|
|
40
|
+
files git-tracked across bulbul and noura-be — Speakeasy's
|
|
41
|
+
`python/sdk/src/sarj_platform_sdk/` accounts for all of them.
|
|
42
|
+
|
|
37
43
|
"""
|
|
38
44
|
|
|
39
45
|
from __future__ import annotations
|
|
@@ -42,6 +48,7 @@ import ast
|
|
|
42
48
|
from typing import TYPE_CHECKING, TypeGuard, override
|
|
43
49
|
|
|
44
50
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
51
|
+
from sarj_python_lint.rules._paths import is_generated_source
|
|
45
52
|
|
|
46
53
|
|
|
47
54
|
if TYPE_CHECKING:
|
|
@@ -58,6 +65,8 @@ class InefficientStringConcatInLoop(Rule):
|
|
|
58
65
|
|
|
59
66
|
@override
|
|
60
67
|
def check(self, path: Path, source: str) -> list[Diagnostic]:
|
|
68
|
+
if is_generated_source(source):
|
|
69
|
+
return []
|
|
61
70
|
tree = parse_or_none(path, source)
|
|
62
71
|
if tree is None:
|
|
63
72
|
return []
|
{sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_fat_try_blocks.py
RENAMED
|
@@ -69,6 +69,12 @@ References:
|
|
|
69
69
|
- https://docs.python.org/3/tutorial/errors.html#handling-exceptions
|
|
70
70
|
- https://docs.python.org/3/library/ast.html#ast.Try
|
|
71
71
|
|
|
72
|
+
* **generated files** (`_paths.is_generated_source`). Their layout is the
|
|
73
|
+
generator's, and re-running the generator discards any edit, so a finding
|
|
74
|
+
there can never be acted on in place. Measured on the 69 `DO NOT EDIT`
|
|
75
|
+
files git-tracked across bulbul and noura-be — Speakeasy's
|
|
76
|
+
`python/sdk/src/sarj_platform_sdk/` accounts for all of them.
|
|
77
|
+
|
|
72
78
|
"""
|
|
73
79
|
|
|
74
80
|
from __future__ import annotations
|
|
@@ -79,6 +85,7 @@ from typing import TYPE_CHECKING, override
|
|
|
79
85
|
|
|
80
86
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
81
87
|
from sarj_python_lint.rules._logging import is_logger_expr
|
|
88
|
+
from sarj_python_lint.rules._paths import is_generated_source
|
|
82
89
|
|
|
83
90
|
|
|
84
91
|
if TYPE_CHECKING:
|
|
@@ -124,38 +131,42 @@ def _nested_scope_body_ids(node: ast.AST) -> frozenset[int]:
|
|
|
124
131
|
#: `set` and `record` are deliberately ABSENT — `cache.set(k, v)` /
|
|
125
132
|
#: `store.record(row)` collide with them and are real work whose failure a handler
|
|
126
133
|
#: is plausibly written for.
|
|
127
|
-
_OBSERVABILITY_METHODS = frozenset(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
134
|
+
_OBSERVABILITY_METHODS = frozenset(
|
|
135
|
+
{
|
|
136
|
+
"inc",
|
|
137
|
+
"dec",
|
|
138
|
+
"observe",
|
|
139
|
+
"set_to_current_time",
|
|
140
|
+
"labels",
|
|
141
|
+
"increment",
|
|
142
|
+
"decrement",
|
|
143
|
+
"gauge",
|
|
144
|
+
"timing",
|
|
145
|
+
"histogram",
|
|
146
|
+
"record_exception",
|
|
147
|
+
"add_event",
|
|
148
|
+
"set_attribute",
|
|
149
|
+
"set_attributes",
|
|
150
|
+
"set_status",
|
|
151
|
+
}
|
|
152
|
+
)
|
|
144
153
|
|
|
145
154
|
#: Clock reads. `time.monotonic()` / `perf_counter()` / `time()` and
|
|
146
155
|
#: `datetime.now()` / `utcnow()` cannot raise at all, but they are the calls that
|
|
147
156
|
#: turn an elapsed-time bookkeeping line into a "throwing" statement.
|
|
148
157
|
_CLOCK_ROOTS = frozenset({"time", "datetime", "date"})
|
|
149
|
-
_CLOCK_METHODS = frozenset(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
_CLOCK_METHODS = frozenset(
|
|
159
|
+
{
|
|
160
|
+
"monotonic",
|
|
161
|
+
"monotonic_ns",
|
|
162
|
+
"perf_counter",
|
|
163
|
+
"perf_counter_ns",
|
|
164
|
+
"time",
|
|
165
|
+
"time_ns",
|
|
166
|
+
"now",
|
|
167
|
+
"utcnow",
|
|
168
|
+
}
|
|
169
|
+
)
|
|
159
170
|
|
|
160
171
|
#: Value-shaping builtins. These are what an instrumentation line calls on its
|
|
161
172
|
#: arguments — `logger.info(..., n=len(items), elapsed_s=round(t, 2))`,
|
|
@@ -163,21 +174,23 @@ _CLOCK_METHODS = frozenset({
|
|
|
163
174
|
#: line passes them, so they don't make the statement a candidate for the
|
|
164
175
|
#: handler. Builtins that genuinely do work and raise (`open`, `eval`, `next`,
|
|
165
176
|
#: `getattr`) are deliberately absent.
|
|
166
|
-
_INERT_BUILTINS = frozenset(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
_INERT_BUILTINS = frozenset(
|
|
178
|
+
{
|
|
179
|
+
"abs",
|
|
180
|
+
"bool",
|
|
181
|
+
"float",
|
|
182
|
+
"format",
|
|
183
|
+
"id",
|
|
184
|
+
"int",
|
|
185
|
+
"len",
|
|
186
|
+
"list",
|
|
187
|
+
"repr",
|
|
188
|
+
"round",
|
|
189
|
+
"str",
|
|
190
|
+
"tuple",
|
|
191
|
+
"type",
|
|
192
|
+
}
|
|
193
|
+
)
|
|
181
194
|
|
|
182
195
|
|
|
183
196
|
def _attr_root(expr: ast.expr) -> str | None:
|
|
@@ -316,6 +329,8 @@ class NoFatTryBlocks(Rule):
|
|
|
316
329
|
|
|
317
330
|
@override
|
|
318
331
|
def check(self, path: Path, source: str) -> list[Diagnostic]:
|
|
332
|
+
if is_generated_source(source):
|
|
333
|
+
return []
|
|
319
334
|
tree = parse_or_none(path, source)
|
|
320
335
|
if tree is None:
|
|
321
336
|
return []
|
|
@@ -70,6 +70,11 @@ duplicate can be suppressed per-line with `# sarj-noqa: SARJ024 — <reason>`.
|
|
|
70
70
|
|
|
71
71
|
Skipped entirely: `conftest.py`, test files (`test_*.py` or under a `tests/`
|
|
72
72
|
directory) — fixtures legitimately repeat literal payloads.
|
|
73
|
+
* **generated files** (`_paths.is_generated_source`). Their layout is the
|
|
74
|
+
generator's, and re-running the generator discards any edit, so a finding
|
|
75
|
+
there can never be acted on in place. Measured on the 69 `DO NOT EDIT`
|
|
76
|
+
files git-tracked across bulbul and noura-be — Speakeasy's
|
|
77
|
+
`python/sdk/src/sarj_platform_sdk/` accounts for all of them.
|
|
73
78
|
"""
|
|
74
79
|
|
|
75
80
|
from __future__ import annotations
|
|
@@ -80,6 +85,7 @@ import re
|
|
|
80
85
|
from typing import TYPE_CHECKING, override
|
|
81
86
|
|
|
82
87
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
88
|
+
from sarj_python_lint.rules._paths import is_generated_source
|
|
83
89
|
|
|
84
90
|
|
|
85
91
|
if TYPE_CHECKING:
|
|
@@ -109,6 +115,8 @@ class NoRepeatedStringLiteral(Rule):
|
|
|
109
115
|
|
|
110
116
|
@override
|
|
111
117
|
def check(self, path: Path, source: str) -> list[Diagnostic]:
|
|
118
|
+
if is_generated_source(source):
|
|
119
|
+
return []
|
|
112
120
|
if _is_skipped_path(path):
|
|
113
121
|
return []
|
|
114
122
|
tree = parse_or_none(path, source)
|
|
@@ -70,6 +70,12 @@ Suppress a deliberate positional return with `# sarj-noqa: SARJ026 — <reason>`
|
|
|
70
70
|
References:
|
|
71
71
|
- https://docs.python.org/3/library/typing.html#typing.NamedTuple
|
|
72
72
|
|
|
73
|
+
* **generated files** (`_paths.is_generated_source`). Their layout is the
|
|
74
|
+
generator's, and re-running the generator discards any edit, so a finding
|
|
75
|
+
there can never be acted on in place. Measured on the 69 `DO NOT EDIT`
|
|
76
|
+
files git-tracked across bulbul and noura-be — Speakeasy's
|
|
77
|
+
`python/sdk/src/sarj_platform_sdk/` accounts for all of them.
|
|
78
|
+
|
|
73
79
|
"""
|
|
74
80
|
|
|
75
81
|
from __future__ import annotations
|
|
@@ -80,7 +86,7 @@ from types import EllipsisType
|
|
|
80
86
|
from typing import TYPE_CHECKING, override
|
|
81
87
|
|
|
82
88
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
83
|
-
from sarj_python_lint.rules._paths import is_test_path
|
|
89
|
+
from sarj_python_lint.rules._paths import is_generated_source, is_test_path
|
|
84
90
|
|
|
85
91
|
|
|
86
92
|
if TYPE_CHECKING:
|
|
@@ -140,6 +146,8 @@ class PreferNamedtupleOverTupleReturn(Rule):
|
|
|
140
146
|
|
|
141
147
|
@override
|
|
142
148
|
def check(self, path: Path, source: str) -> list[Diagnostic]:
|
|
149
|
+
if is_generated_source(source):
|
|
150
|
+
return []
|
|
143
151
|
if is_test_path(path):
|
|
144
152
|
return []
|
|
145
153
|
tree = parse_or_none(path, source)
|
|
@@ -71,6 +71,12 @@ Suppress an intentional raw-numeric duration with `# sarj-noqa: SARJ014 — <rea
|
|
|
71
71
|
References:
|
|
72
72
|
- https://docs.python.org/3/library/datetime.html#timedelta-objects
|
|
73
73
|
|
|
74
|
+
* **generated files** (`_paths.is_generated_source`). Their layout is the
|
|
75
|
+
generator's, and re-running the generator discards any edit, so a finding
|
|
76
|
+
there can never be acted on in place. Measured on the 69 `DO NOT EDIT`
|
|
77
|
+
files git-tracked across bulbul and noura-be — Speakeasy's
|
|
78
|
+
`python/sdk/src/sarj_platform_sdk/` accounts for all of them.
|
|
79
|
+
|
|
74
80
|
"""
|
|
75
81
|
|
|
76
82
|
from __future__ import annotations
|
|
@@ -80,7 +86,7 @@ import re
|
|
|
80
86
|
from typing import TYPE_CHECKING, override
|
|
81
87
|
|
|
82
88
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
83
|
-
from sarj_python_lint.rules._paths import is_test_path
|
|
89
|
+
from sarj_python_lint.rules._paths import is_generated_source, is_test_path
|
|
84
90
|
|
|
85
91
|
|
|
86
92
|
if TYPE_CHECKING:
|
|
@@ -138,6 +144,8 @@ class PreferTimedeltaForDurations(Rule):
|
|
|
138
144
|
|
|
139
145
|
@override
|
|
140
146
|
def check(self, path: Path, source: str) -> list[Diagnostic]:
|
|
147
|
+
if is_generated_source(source):
|
|
148
|
+
return []
|
|
141
149
|
if is_test_path(path):
|
|
142
150
|
return []
|
|
143
151
|
tree = parse_or_none(path, source)
|
|
@@ -39,6 +39,11 @@ a `tests/` directory), and framework-convention filenames whose stem is fixed by
|
|
|
39
39
|
a framework/tool and cannot be renamed (`models.py`, `views.py`, `base.py`, ...).
|
|
40
40
|
Modules whose single export already snake-cases to the stem are not flagged
|
|
41
41
|
(there is nothing to improve).
|
|
42
|
+
* **generated files** (`_paths.is_generated_source`). Their layout is the
|
|
43
|
+
generator's, and re-running the generator discards any edit, so a finding
|
|
44
|
+
there can never be acted on in place. Measured on the 69 `DO NOT EDIT`
|
|
45
|
+
files git-tracked across bulbul and noura-be — Speakeasy's
|
|
46
|
+
`python/sdk/src/sarj_platform_sdk/` accounts for all of them.
|
|
42
47
|
"""
|
|
43
48
|
|
|
44
49
|
from __future__ import annotations
|
|
@@ -48,6 +53,7 @@ import re
|
|
|
48
53
|
from typing import TYPE_CHECKING, override
|
|
49
54
|
|
|
50
55
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
56
|
+
from sarj_python_lint.rules._paths import is_generated_source
|
|
51
57
|
|
|
52
58
|
|
|
53
59
|
if TYPE_CHECKING:
|
|
@@ -128,6 +134,8 @@ class SinglePublicExport(Rule):
|
|
|
128
134
|
|
|
129
135
|
@override
|
|
130
136
|
def check(self, path: Path, source: str) -> list[Diagnostic]:
|
|
137
|
+
if is_generated_source(source):
|
|
138
|
+
return []
|
|
131
139
|
if _is_skipped_path(path):
|
|
132
140
|
return []
|
|
133
141
|
if path.stem.lower() not in _JUNK_DRAWER_STEMS:
|
|
@@ -58,6 +58,11 @@ Never fires on:
|
|
|
58
58
|
`_code_str`). Siblings are excluded — an identically-named sibling method is a
|
|
59
59
|
different method. Callers in classes outside the module remain invisible to
|
|
60
60
|
syntactic analysis.
|
|
61
|
+
* **generated files** (`_paths.is_generated_source`). Their layout is the
|
|
62
|
+
generator's, and re-running the generator discards any edit, so a finding
|
|
63
|
+
there can never be acted on in place. Measured on the 69 `DO NOT EDIT`
|
|
64
|
+
files git-tracked across bulbul and noura-be — Speakeasy's
|
|
65
|
+
`python/sdk/src/sarj_platform_sdk/` accounts for all of them.
|
|
61
66
|
"""
|
|
62
67
|
|
|
63
68
|
from __future__ import annotations
|
|
@@ -67,6 +72,7 @@ from collections import Counter
|
|
|
67
72
|
from typing import TYPE_CHECKING, override
|
|
68
73
|
|
|
69
74
|
from sarj_python_lint.rule_base import Diagnostic, Rule, parse_or_none
|
|
75
|
+
from sarj_python_lint.rules._paths import is_generated_source
|
|
70
76
|
|
|
71
77
|
|
|
72
78
|
if TYPE_CHECKING:
|
|
@@ -105,6 +111,8 @@ class Stepdown(Rule):
|
|
|
105
111
|
|
|
106
112
|
@override
|
|
107
113
|
def check(self, path: Path, source: str) -> list[Diagnostic]:
|
|
114
|
+
if is_generated_source(source):
|
|
115
|
+
return []
|
|
108
116
|
if _is_test_path(path):
|
|
109
117
|
return []
|
|
110
118
|
tree = parse_or_none(path, source)
|
|
@@ -189,7 +189,9 @@ def _is_rotting_xfail(dec: ast.expr) -> bool:
|
|
|
189
189
|
_ENV_PROBE_MODULES = frozenset({"sys", "os", "platform", "sysconfig"})
|
|
190
190
|
|
|
191
191
|
# Attribute / name words that identify an interpreter- or OS-version probe.
|
|
192
|
-
_ENV_PROBE_RE = re.compile(
|
|
192
|
+
_ENV_PROBE_RE = re.compile(
|
|
193
|
+
r"version|implementation|platform|machine|pypy|jython|win32|windows|linux|darwin|macos", re.IGNORECASE
|
|
194
|
+
)
|
|
193
195
|
|
|
194
196
|
|
|
195
197
|
def _is_environment_gated(dec: ast.Call) -> bool:
|
|
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.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/mock_without_spec.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_comment_cruft.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_fstring_in_log.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/no_secret_in_log.py
RENAMED
|
File without changes
|
{sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/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
|
{sarj_python_lint-0.17.0 → sarj_python_lint-0.18.0}/src/sarj_python_lint/rules/prefer_class_row.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.17.0 → sarj_python_lint-0.18.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
|