tamperward 2.24.1 → 2.24.2
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.
- package/dist/cli/index.js +51 -3
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3715,6 +3715,22 @@ var init_lint_suppression = __esm({
|
|
|
3715
3715
|
|
|
3716
3716
|
// src/detectors/test-skip.ts
|
|
3717
3717
|
import { posix as posix2 } from "node:path";
|
|
3718
|
+
function pyMarkAliases(source) {
|
|
3719
|
+
const out3 = /* @__PURE__ */ new Set();
|
|
3720
|
+
for (const m of source.matchAll(PY_MARK_ALIAS)) out3.add(m[1]);
|
|
3721
|
+
return out3;
|
|
3722
|
+
}
|
|
3723
|
+
function pyAliasDecoratorHits(c) {
|
|
3724
|
+
const added = addedLines(c);
|
|
3725
|
+
const aliases = pyMarkAliases(c.after ?? added.map((l) => l.content).join("\n"));
|
|
3726
|
+
if (aliases.size === 0) return [];
|
|
3727
|
+
const hits = [];
|
|
3728
|
+
for (const l of added) {
|
|
3729
|
+
const m = PY_DECORATOR.exec(l.content);
|
|
3730
|
+
if (m && aliases.has(m[1])) hits.push({ line: l.newLine ?? void 0, evidence: l.content.trim() });
|
|
3731
|
+
}
|
|
3732
|
+
return hits;
|
|
3733
|
+
}
|
|
3718
3734
|
function matchesOutsideString(p, content, lang) {
|
|
3719
3735
|
if (p.comment) return p.re.test(content);
|
|
3720
3736
|
const re = p.re.global ? p.re : new RegExp(p.re.source, p.re.flags + "g");
|
|
@@ -4046,7 +4062,7 @@ function astSkipHits(c, resolvers) {
|
|
|
4046
4062
|
}
|
|
4047
4063
|
return { hits, authoritative: true, unowned: analysis.unowned };
|
|
4048
4064
|
}
|
|
4049
|
-
var RULE4, acc, JS_RUNNER, JS_MOD, PATTERNS2, JS_RUNNERS, JS_CHAIN_MODIFIERS, JS_DEFAULT_RUNNER_MODULES, JS_TEST_MODULES, RUNNER2, NON_RUNNER, UNKNOWN, withCause, MODULE_EXTENSIONS, RunnerResolver, ModuleBinder, NO_AST, testSkip;
|
|
4065
|
+
var RULE4, acc, JS_RUNNER, JS_MOD, GO_SKIP_PATTERNS, PY_MARK, PY_CONFTEST_PATTERNS, PY_MARK_ALIAS, PY_DECORATOR, PATTERNS2, JS_RUNNERS, JS_CHAIN_MODIFIERS, JS_DEFAULT_RUNNER_MODULES, JS_TEST_MODULES, RUNNER2, NON_RUNNER, UNKNOWN, withCause, MODULE_EXTENSIONS, RunnerResolver, ModuleBinder, NO_AST, testSkip;
|
|
4050
4066
|
var init_test_skip = __esm({
|
|
4051
4067
|
"src/detectors/test-skip.ts"() {
|
|
4052
4068
|
"use strict";
|
|
@@ -4060,6 +4076,21 @@ var init_test_skip = __esm({
|
|
|
4060
4076
|
acc = (names) => `(?:\\s*\\.\\s*(?:${names})(?![\\w$])|\\s*\\[\\s*['"\`](?:${names})['"\`]\\s*\\])`;
|
|
4061
4077
|
JS_RUNNER = "\\b(?:it|test|describe|suite)";
|
|
4062
4078
|
JS_MOD = "concurrent|sequential|shuffle|serial|parallel";
|
|
4079
|
+
GO_SKIP_PATTERNS = [
|
|
4080
|
+
{ re: /\b\w+\.Skip(?:f|Now)?\(/, why: "a runtime t.Skip()/Skipf()/SkipNow() call" },
|
|
4081
|
+
{ re: /\bT\(\)\.Skip(?:f|Now)?\(/, why: "a runtime T().Skip()/Skipf()/SkipNow() call (testify suite)" }
|
|
4082
|
+
];
|
|
4083
|
+
PY_MARK = "(?:\\w+\\.)?mark\\.(?:skip|skipif|xfail)\\b";
|
|
4084
|
+
PY_CONFTEST_PATTERNS = [
|
|
4085
|
+
{ re: /\bdef\s+pytest_collection_modifyitems\s*\(/, why: "a pytest_collection_modifyitems hook (collected tests are filtered or marked before they run)" },
|
|
4086
|
+
{ re: /\bdef\s+pytest_pycollect_makeitem\s*\(/, why: "a pytest_pycollect_makeitem hook (what counts as a test is decided here)" },
|
|
4087
|
+
{ re: /\bdef\s+pytest_runtest_makereport\s*\(/, why: "a pytest_runtest_makereport hook (the test report can be rewritten)" },
|
|
4088
|
+
{ re: new RegExp("\\.add_marker\\(\\s*" + PY_MARK), why: "an add_marker(mark.skip/skipif/xfail) call (the test is skipped programmatically)" },
|
|
4089
|
+
{ re: new RegExp("^\\s*\\w+\\s*=\\s*" + PY_MARK), why: "a skip/skipif/xfail marker bound to a name (an aliased decorator)" },
|
|
4090
|
+
{ re: /\b\w+\.outcome\s*=\s*['"](?:passed|skipped)['"]/, why: "a report outcome rewritten to passed/skipped" }
|
|
4091
|
+
];
|
|
4092
|
+
PY_MARK_ALIAS = new RegExp("^\\s*(\\w+)\\s*=\\s*" + PY_MARK, "gm");
|
|
4093
|
+
PY_DECORATOR = /^\s*@(\w+)\s*(?:\(|$)/;
|
|
4063
4094
|
PATTERNS2 = {
|
|
4064
4095
|
js: [
|
|
4065
4096
|
// The skip/only/todo family on a runner, by dot-or-bracket access, with one optional
|
|
@@ -4103,10 +4134,13 @@ var init_test_skip = __esm({
|
|
|
4103
4134
|
{ re: /@(?:unittest\.)?(?:skip|skipIf|skipUnless|expectedFailure)\b/, why: "a unittest skip/expectedFailure decorator" },
|
|
4104
4135
|
{ re: /\bself\.skipTest\(/, why: "a runtime self.skipTest() call" },
|
|
4105
4136
|
{ re: /\braise\s+(?:unittest\.)?SkipTest\b/, why: "a raised SkipTest" },
|
|
4106
|
-
{ re: /\b__test__\s*=\s*False\b/, why: "__test__ = False hides the test from collection" }
|
|
4137
|
+
{ re: /\b__test__\s*=\s*False\b/, why: "__test__ = False hides the test from collection" },
|
|
4138
|
+
...PY_CONFTEST_PATTERNS
|
|
4139
|
+
// #441
|
|
4107
4140
|
],
|
|
4108
4141
|
go: [
|
|
4109
|
-
|
|
4142
|
+
...GO_SKIP_PATTERNS,
|
|
4143
|
+
// #441: any receiver, and testify's T()
|
|
4110
4144
|
{ re: /\bif\s+testing\.Short\(\)/, why: "a testing.Short() guard (the body is skipped under -short)" },
|
|
4111
4145
|
{ re: /^\s*\/\/\s*(?:go:build|\+build)\s+ignore\b/, why: "a build-ignore constraint (the file is excluded from the test run)", comment: true }
|
|
4112
4146
|
],
|
|
@@ -4440,6 +4474,20 @@ var init_test_skip = __esm({
|
|
|
4440
4474
|
);
|
|
4441
4475
|
}
|
|
4442
4476
|
}
|
|
4477
|
+
if (lang === "py") {
|
|
4478
|
+
for (const hit of pyAliasDecoratorHits(c)) {
|
|
4479
|
+
if (hit.line != null) astHitLines.add(hit.line);
|
|
4480
|
+
out3.push(
|
|
4481
|
+
makeFinding(RULE4, policy, {
|
|
4482
|
+
file: c.path,
|
|
4483
|
+
line: hit.line,
|
|
4484
|
+
message: "Test skipped or narrowed: a decorator aliasing a pytest skip/skipif/xfail marker.",
|
|
4485
|
+
evidence: hit.evidence,
|
|
4486
|
+
remediation: "Make the test pass rather than skipping it. If it is genuinely obsolete, a human must sign off."
|
|
4487
|
+
})
|
|
4488
|
+
);
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4443
4491
|
for (const l of addedLines(c)) {
|
|
4444
4492
|
if (l.newLine != null && astHitLines.has(l.newLine)) continue;
|
|
4445
4493
|
const comment = isCommentLine(l.content.trim(), lang);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamperward",
|
|
3
|
-
"version": "2.24.
|
|
3
|
+
"version": "2.24.2",
|
|
4
4
|
"description": "The deterministic agent-integrity gate. One ruleset, evaluated on the actual diff/commands as a verdict, enforced everywhere a change can be made.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "hexrift",
|