sarj-python-lint 0.67.7__tar.gz → 0.67.9__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.67.7 → sarj_python_lint-0.67.9}/PKG-INFO +1 -1
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/pyproject.toml +1 -1
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +2 -2
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +1 -1
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/duplicated_override_docstring.py +2 -3
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/fastapi_openapi_contract.py +9 -29
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/kwarg_heavy_construction_in_test.py +2 -1
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_file_level_escape_hatch_noqa.py +1 -1
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_file_level_suppression.py +1 -1
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +6 -7
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_generic_single_export_module.py +2 -2
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_secret_in_log.py +6 -1
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +1 -1
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_typed_doc_sections.py +3 -3
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +6 -4
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/restated_test_docstring.py +4 -4
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/.gitignore +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/LICENSE +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/README.md +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/__init__.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/__main__.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/_filesystem.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/_ratchet_cli.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/_secret_names.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/_version.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/py.typed +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/ratchet.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rule_base.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/__init__.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_ast_index.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_comments.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_docstrings.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_fastapi.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_first_party.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_imports.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_logging.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_paths.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_pytest.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_registry.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_sql.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/defect_xfail_requires_strict.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/duplicate_test_body.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/fixture_returns_bare_tuple.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_aggregation_in_store_query.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_gen_random_uuid_in_sql.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_isinstance_union_chain.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_long_comment.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_optional_tenant_predicate.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_query_with_many_joins.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_select_star.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_sentinel_return_on_except.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_stdlib_logging.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_timedelta_for_durations.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/pydantic_at_boundaries.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/stepdown.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/trivially_true_assertion.py +0 -0
- {sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sarj-python-lint
|
|
3
|
-
Version: 0.67.
|
|
3
|
+
Version: 0.67.9
|
|
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/
|
|
@@ -69,12 +69,12 @@ class DocstringArgsRestateSignature(Rule):
|
|
|
69
69
|
),
|
|
70
70
|
RuleExample(
|
|
71
71
|
example_id="argument-documents-unit",
|
|
72
|
-
title="
|
|
72
|
+
title="Redundant argument section removed",
|
|
73
73
|
outcome=ExampleOutcome.NO_MATCH,
|
|
74
74
|
files=(
|
|
75
75
|
ExampleFile.python(
|
|
76
76
|
"app/widgets.py",
|
|
77
|
-
'def
|
|
77
|
+
'def count_widgets(tenant_id: str) -> int:\n """Count active widgets."""\n return 0\n',
|
|
78
78
|
),
|
|
79
79
|
),
|
|
80
80
|
focus_path=PurePosixPath("app/widgets.py"),
|
|
@@ -135,7 +135,7 @@ class DocstringReturnsRestateSignature(Rule):
|
|
|
135
135
|
files=(
|
|
136
136
|
ExampleFile.python(
|
|
137
137
|
"app/lines.py",
|
|
138
|
-
'def get_line_length(line: list[str]) -> int:\n """Measure a rendered line.\n\n Returns:\n The
|
|
138
|
+
'def get_line_length(line: list[str]) -> int:\n """Measure a rendered line.\n\n Returns:\n The number of render fragments queued for output.\n """\n return len(line)\n',
|
|
139
139
|
),
|
|
140
140
|
),
|
|
141
141
|
focus_path=PurePosixPath("app/lines.py"),
|
|
@@ -84,7 +84,7 @@ class DuplicatedOverrideDocstring(Rule):
|
|
|
84
84
|
),
|
|
85
85
|
RuleExample(
|
|
86
86
|
example_id="override-specific-docstring",
|
|
87
|
-
title="Override
|
|
87
|
+
title="Override relies on the base contract",
|
|
88
88
|
outcome=ExampleOutcome.NO_MATCH,
|
|
89
89
|
files=(
|
|
90
90
|
ExampleFile.python(
|
|
@@ -93,9 +93,8 @@ class DuplicatedOverrideDocstring(Rule):
|
|
|
93
93
|
" def get(self, key: str) -> str:\n"
|
|
94
94
|
' """Get a value by key."""\n'
|
|
95
95
|
" return key\n\n"
|
|
96
|
-
"class
|
|
96
|
+
"class MemoryStore(Store):\n"
|
|
97
97
|
" def get(self, key: str) -> str:\n"
|
|
98
|
-
' """Get a value from the read replica."""\n'
|
|
99
98
|
" return key\n",
|
|
100
99
|
),
|
|
101
100
|
),
|
|
@@ -66,9 +66,9 @@ class FastapiOpenapiContract(Rule):
|
|
|
66
66
|
id: str = "fastapi-openapi-contract"
|
|
67
67
|
code: str = "SARJ094"
|
|
68
68
|
documentation: ClassVar[RuleDocumentation | None] = RuleDocumentation(
|
|
69
|
-
summary="FastAPI operations must publish
|
|
70
|
-
rationale="
|
|
71
|
-
remediation="Declare
|
|
69
|
+
summary="FastAPI operations must publish accurate request, response, and status contracts.",
|
|
70
|
+
rationale="Typed routes and explicit response behavior keep generated OpenAPI accurate without duplicating self-documenting names in prose.",
|
|
71
|
+
remediation="Declare status codes, typed parameters, response schemas, and alternate responses raised directly by the handler.",
|
|
72
72
|
category=RuleCategory.CORRECTNESS,
|
|
73
73
|
limitations=(
|
|
74
74
|
"Hidden routes, WebSocket handlers, tests, generated files, documentation-source examples, and unrelated decorators are excluded.",
|
|
@@ -78,7 +78,7 @@ class FastapiOpenapiContract(Rule):
|
|
|
78
78
|
examples=(
|
|
79
79
|
RuleExample(
|
|
80
80
|
example_id="missing-operation-metadata",
|
|
81
|
-
title="Visible operation without
|
|
81
|
+
title="Visible operation without an explicit success status",
|
|
82
82
|
outcome=ExampleOutcome.MATCH,
|
|
83
83
|
files=(
|
|
84
84
|
ExampleFile.python(
|
|
@@ -97,7 +97,7 @@ class FastapiOpenapiContract(Rule):
|
|
|
97
97
|
files=(
|
|
98
98
|
ExampleFile.python(
|
|
99
99
|
"api.py",
|
|
100
|
-
"from fastapi import APIRouter\n\nrouter = APIRouter()\n\n@router.get('/users',
|
|
100
|
+
"from fastapi import APIRouter\n\nrouter = APIRouter()\n\n@router.get('/users', status_code=200)\nasync def read_users() -> list[UserResponse]:\n return []\n",
|
|
101
101
|
),
|
|
102
102
|
),
|
|
103
103
|
focus_path=PurePosixPath("api.py"),
|
|
@@ -134,7 +134,7 @@ class FastapiOpenapiContract(Rule):
|
|
|
134
134
|
findings.extend(_check_raw_request(function, routes, index))
|
|
135
135
|
findings.extend(_check_direct_responses(function, routes, index))
|
|
136
136
|
for route in _operations(routes):
|
|
137
|
-
findings.extend(_check_metadata(
|
|
137
|
+
findings.extend(_check_metadata(route))
|
|
138
138
|
findings.extend(_check_projection(route))
|
|
139
139
|
findings.extend(_check_route_conflicts(declared))
|
|
140
140
|
return [
|
|
@@ -155,29 +155,13 @@ def _operations(routes: tuple[Route, ...]) -> tuple[Route, ...]:
|
|
|
155
155
|
return tuple({id(route.decorator): route for route in routes}.values())
|
|
156
156
|
|
|
157
157
|
|
|
158
|
-
def _check_metadata(
|
|
158
|
+
def _check_metadata(route: Route) -> list[_Finding]:
|
|
159
159
|
if route.has_unpack:
|
|
160
160
|
return []
|
|
161
161
|
keywords = route.keywords
|
|
162
|
-
|
|
163
|
-
if not _nonblank(keywords.get("summary")):
|
|
164
|
-
missing.append("summary")
|
|
165
|
-
docstring = ast.get_docstring(function, clean=False)
|
|
166
|
-
if not (_nonblank(keywords.get("description")) or bool(docstring and docstring.strip())):
|
|
167
|
-
missing.append("description or handler docstring")
|
|
168
|
-
if "status_code" not in keywords or _literal_none(keywords["status_code"]):
|
|
169
|
-
missing.append("status_code")
|
|
170
|
-
if not missing:
|
|
162
|
+
if "status_code" in keywords and not _literal_none(keywords["status_code"]):
|
|
171
163
|
return []
|
|
172
|
-
return [_Finding(route.decorator,
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def _nonblank(node: ast.expr | None) -> bool:
|
|
176
|
-
if node is None:
|
|
177
|
-
return False
|
|
178
|
-
if isinstance(node, ast.Constant):
|
|
179
|
-
return isinstance(node.value, str) and bool(node.value.strip())
|
|
180
|
-
return True
|
|
164
|
+
return [_Finding(route.decorator, "[metadata] operation requires explicit status_code.")]
|
|
181
165
|
|
|
182
166
|
|
|
183
167
|
def _literal_none(node: ast.expr) -> bool:
|
|
@@ -238,10 +222,6 @@ def _check_parameters(
|
|
|
238
222
|
findings.append(
|
|
239
223
|
_Finding(parameter, f"[parameter] `{parameter.arg}` must not duplicate FastAPI marker metadata.")
|
|
240
224
|
)
|
|
241
|
-
if marker_name in SCHEMA_MARKERS and not _nonblank(_keyword(marker_call, "description")):
|
|
242
|
-
findings.append(
|
|
243
|
-
_Finding(parameter, f"[parameter] `{parameter.arg}` marker requires a non-empty description.")
|
|
244
|
-
)
|
|
245
225
|
if marker_name in SCHEMA_MARKERS and _schema_erasing(value_type, index):
|
|
246
226
|
findings.append(
|
|
247
227
|
_Finding(
|
|
@@ -92,12 +92,13 @@ class KwargHeavyConstructionInTest(Rule):
|
|
|
92
92
|
"tests/test_call.py",
|
|
93
93
|
"def build_style(**overrides):\n"
|
|
94
94
|
" defaults = dict(\n"
|
|
95
|
+
' color="red", bgcolor="black", bold=True,\n'
|
|
95
96
|
" dim=True, italic=True, underline=True,\n"
|
|
96
97
|
" blink=True, blink2=True, reverse=True,\n"
|
|
97
98
|
" )\n"
|
|
98
99
|
" return Style(**(defaults | overrides))\n\n"
|
|
99
100
|
"def test_style():\n"
|
|
100
|
-
|
|
101
|
+
" style = build_style()\n"
|
|
101
102
|
" assert str(style)\n\n"
|
|
102
103
|
"def test_style_again():\n"
|
|
103
104
|
' other = build_style(color="blue", bgcolor="white", bold=False)\n'
|
|
@@ -68,7 +68,7 @@ class NoFileLevelEscapeHatchNoqa(Rule):
|
|
|
68
68
|
files=(
|
|
69
69
|
ExampleFile.python(
|
|
70
70
|
"app/service.py",
|
|
71
|
-
"
|
|
71
|
+
"import os # noqa: TID251 — vendor SDK boundary\n",
|
|
72
72
|
),
|
|
73
73
|
),
|
|
74
74
|
focus_path=PurePosixPath("app/service.py"),
|
|
@@ -76,7 +76,7 @@ class NoFileLevelSuppression(Rule):
|
|
|
76
76
|
example_id="scoped-type-checker-suppression",
|
|
77
77
|
title="Mypy suppression names its code",
|
|
78
78
|
outcome=ExampleOutcome.NO_MATCH,
|
|
79
|
-
files=(ExampleFile.python("service.py", "# type: ignore[
|
|
79
|
+
files=(ExampleFile.python("service.py", "# type: ignore[import-not-found]\nimport os\n"),),
|
|
80
80
|
focus_path=PurePosixPath("service.py"),
|
|
81
81
|
expected_count=0,
|
|
82
82
|
public=True,
|
|
@@ -86,20 +86,19 @@ class NoFrozenAfterValidatorFieldWrite(Rule):
|
|
|
86
86
|
),
|
|
87
87
|
RuleExample(
|
|
88
88
|
example_id="after-validator-only-validates-frozen-field",
|
|
89
|
-
title="
|
|
89
|
+
title="Before-validator normalizes the input value",
|
|
90
90
|
outcome=ExampleOutcome.NO_MATCH,
|
|
91
91
|
files=(
|
|
92
92
|
ExampleFile.python(
|
|
93
93
|
"app/models.py",
|
|
94
|
-
"from pydantic import BaseModel, ConfigDict,
|
|
94
|
+
"from pydantic import BaseModel, ConfigDict, field_validator\n\n"
|
|
95
95
|
"class Counter(BaseModel):\n"
|
|
96
96
|
" model_config = ConfigDict(frozen=True)\n"
|
|
97
97
|
" value: int\n\n"
|
|
98
|
-
' @
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
" return self\n",
|
|
98
|
+
' @field_validator("value", mode="before")\n'
|
|
99
|
+
" @classmethod\n"
|
|
100
|
+
" def normalize(cls, value: int) -> int:\n"
|
|
101
|
+
" return abs(value)\n",
|
|
103
102
|
),
|
|
104
103
|
),
|
|
105
104
|
focus_path=PurePosixPath("app/models.py"),
|
|
@@ -72,8 +72,8 @@ class NoGenericSingleExportModule(Rule):
|
|
|
72
72
|
example_id="specific-single-export-module",
|
|
73
73
|
title="Specific module contains one public definition",
|
|
74
74
|
outcome=ExampleOutcome.NO_MATCH,
|
|
75
|
-
files=(ExampleFile.python("
|
|
76
|
-
focus_path=PurePosixPath("
|
|
75
|
+
files=(ExampleFile.python("text_case.py", "def snake_case_text(value: str) -> str: ...\n"),),
|
|
76
|
+
focus_path=PurePosixPath("text_case.py"),
|
|
77
77
|
expected_count=0,
|
|
78
78
|
public=True,
|
|
79
79
|
),
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_secret_in_log.py
RENAMED
|
@@ -114,7 +114,12 @@ class NoSecretInLog(Rule):
|
|
|
114
114
|
example_id="redacted-logging-keyword",
|
|
115
115
|
title="Token prefix logged under a redacted name",
|
|
116
116
|
outcome=ExampleOutcome.NO_MATCH,
|
|
117
|
-
files=(
|
|
117
|
+
files=(
|
|
118
|
+
ExampleFile.python(
|
|
119
|
+
"service.py",
|
|
120
|
+
"token_prefix = token[:6]\nlogger.info('request', token_prefix=token_prefix)\n",
|
|
121
|
+
),
|
|
122
|
+
),
|
|
118
123
|
focus_path=PurePosixPath("service.py"),
|
|
119
124
|
expected_count=0,
|
|
120
125
|
public=True,
|
|
@@ -75,7 +75,7 @@ class NoStringConcatInLoop(Rule):
|
|
|
75
75
|
files=(
|
|
76
76
|
ExampleFile.python(
|
|
77
77
|
"app/render.py",
|
|
78
|
-
'def render(items):\n lines = []\n for item in items:\n lines.append(
|
|
78
|
+
'def render(items):\n lines = []\n for item in items:\n lines.append(f"{item}\\n")\n return "".join(lines)\n',
|
|
79
79
|
),
|
|
80
80
|
),
|
|
81
81
|
focus_path=PurePosixPath("app/render.py"),
|
|
@@ -60,11 +60,11 @@ class NoTypedDocSections(Rule):
|
|
|
60
60
|
outcome=ExampleOutcome.NO_MATCH,
|
|
61
61
|
files=(
|
|
62
62
|
ExampleFile.python(
|
|
63
|
-
"
|
|
64
|
-
'def
|
|
63
|
+
"app.py",
|
|
64
|
+
'def decode(value: str) -> dict[str, object]:\n """Decode the value.\n\n Args:\n value: Text to decode.\n """\n return {}\n',
|
|
65
65
|
),
|
|
66
66
|
),
|
|
67
|
-
focus_path=PurePosixPath("
|
|
67
|
+
focus_path=PurePosixPath("app.py"),
|
|
68
68
|
expected_count=0,
|
|
69
69
|
public=True,
|
|
70
70
|
),
|
|
@@ -855,12 +855,14 @@ class PreferMatchTypeDispatch(Rule):
|
|
|
855
855
|
"app/parser.py",
|
|
856
856
|
"def parse(value: object):\n"
|
|
857
857
|
" match value:\n"
|
|
858
|
-
" case
|
|
858
|
+
" case Text():\n"
|
|
859
|
+
" return value\n"
|
|
860
|
+
" case Binary():\n"
|
|
861
|
+
" return value\n"
|
|
862
|
+
" case PathValue():\n"
|
|
859
863
|
" return value\n"
|
|
860
|
-
" case int():\n"
|
|
861
|
-
" return str(value)\n"
|
|
862
864
|
" case _:\n"
|
|
863
|
-
" return
|
|
865
|
+
" return coerce(value)\n",
|
|
864
866
|
),
|
|
865
867
|
),
|
|
866
868
|
focus_path=PurePosixPath("app/parser.py"),
|
|
@@ -158,15 +158,15 @@ class RestatedTestDocstring(Rule):
|
|
|
158
158
|
),
|
|
159
159
|
RuleExample(
|
|
160
160
|
example_id="test-regression-context",
|
|
161
|
-
title="
|
|
161
|
+
title="Redundant docstring removed",
|
|
162
162
|
outcome=ExampleOutcome.NO_MATCH,
|
|
163
163
|
files=(
|
|
164
164
|
ExampleFile.python(
|
|
165
|
-
"tests/
|
|
166
|
-
|
|
165
|
+
"tests/test_widget.py",
|
|
166
|
+
"def test_widget_renders():\n assert render(widget)\n",
|
|
167
167
|
),
|
|
168
168
|
),
|
|
169
|
-
focus_path=PurePosixPath("tests/
|
|
169
|
+
focus_path=PurePosixPath("tests/test_widget.py"),
|
|
170
170
|
expected_count=0,
|
|
171
171
|
public=True,
|
|
172
172
|
),
|
|
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.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_ast_index.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_first_party.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_prose_budget.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/_test_assertions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/mock_without_spec.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/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
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/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
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_select_star.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/no_stdlib_logging.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/over_mocked_test.py
RENAMED
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/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.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/prefer_or_pattern.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/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
|
{sarj_python_lint-0.67.7 → sarj_python_lint-0.67.9}/src/sarj_python_lint/rules/unused_mock_setup.py
RENAMED
|
File without changes
|