chipgraph 0.1.0__py3-none-any.whl
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.
- chipgraph/__init__.py +7 -0
- chipgraph/adapters/__init__.py +1 -0
- chipgraph/adapters/format/__init__.py +6 -0
- chipgraph/adapters/format/__main__.py +16 -0
- chipgraph/adapters/format/_yaml_lines.py +54 -0
- chipgraph/adapters/format/chip_yaml.py +323 -0
- chipgraph/adapters/format/qsoc_contract.py +246 -0
- chipgraph/adapters/llm/__init__.py +58 -0
- chipgraph/adapters/llm/_budget.py +173 -0
- chipgraph/adapters/llm/_errors.py +50 -0
- chipgraph/adapters/llm/_nda.py +30 -0
- chipgraph/adapters/llm/_retry.py +85 -0
- chipgraph/adapters/llm/anthropic.py +247 -0
- chipgraph/adapters/llm/decide_backend.py +179 -0
- chipgraph/adapters/llm/fake.py +87 -0
- chipgraph/adapters/llm/guard.py +68 -0
- chipgraph/adapters/parser/__init__.py +22 -0
- chipgraph/adapters/parser/cocotb.py +304 -0
- chipgraph/adapters/parser/generic_regex.py +75 -0
- chipgraph/adapters/parser/verible.py +55 -0
- chipgraph/adapters/parser/verilator.py +46 -0
- chipgraph/adapters/review/__init__.py +7 -0
- chipgraph/adapters/review/file.py +123 -0
- chipgraph/adapters/review/github.py +886 -0
- chipgraph/adapters/runner/__init__.py +7 -0
- chipgraph/adapters/runner/local.py +122 -0
- chipgraph/adapters/runtime/__init__.py +5 -0
- chipgraph/adapters/runtime/claude_code/__init__.py +24 -0
- chipgraph/adapters/runtime/claude_code/agents.py +158 -0
- chipgraph/adapters/runtime/claude_code/decisions.py +280 -0
- chipgraph/adapters/runtime/claude_code/guarded.py +310 -0
- chipgraph/adapters/runtime/claude_code/isolation.py +482 -0
- chipgraph/adapters/runtime/claude_code/loop.py +342 -0
- chipgraph/adapters/runtime/claude_code/previous.py +419 -0
- chipgraph/adapters/runtime/claude_code/review.py +492 -0
- chipgraph/adapters/runtime/claude_code/runtime.py +192 -0
- chipgraph/adapters/runtime/claude_code/service.py +2285 -0
- chipgraph/adapters/tool/__init__.py +7 -0
- chipgraph/adapters/tool/cmd.py +229 -0
- chipgraph/adapters/tool/edalize.py +773 -0
- chipgraph/adapters/tool/filelist.py +259 -0
- chipgraph/adapters/tool/pyslang.py +485 -0
- chipgraph/adapters/vcs/__init__.py +1 -0
- chipgraph/adapters/vcs/git.py +521 -0
- chipgraph/app/__init__.py +10 -0
- chipgraph/app/baseline.py +339 -0
- chipgraph/app/build.py +332 -0
- chipgraph/app/checks.py +202 -0
- chipgraph/app/context.py +191 -0
- chipgraph/app/errors.py +11 -0
- chipgraph/app/executors.py +79 -0
- chipgraph/app/findings.py +203 -0
- chipgraph/app/ingest.py +523 -0
- chipgraph/checks/__init__.py +52 -0
- chipgraph/checks/_cdc_analyze.py +272 -0
- chipgraph/checks/_cdc_elaborate.py +455 -0
- chipgraph/checks/_common.py +268 -0
- chipgraph/checks/_cross.py +96 -0
- chipgraph/checks/_model.py +64 -0
- chipgraph/checks/_naming_pyslang.py +235 -0
- chipgraph/checks/_naming_rules.py +127 -0
- chipgraph/checks/_xref_syntax.py +260 -0
- chipgraph/checks/cdc_struct.py +235 -0
- chipgraph/checks/connect.py +353 -0
- chipgraph/checks/cross_chip.py +454 -0
- chipgraph/checks/duplicate.py +153 -0
- chipgraph/checks/filelist.py +323 -0
- chipgraph/checks/format.py +268 -0
- chipgraph/checks/generated.py +151 -0
- chipgraph/checks/hardcode.py +233 -0
- chipgraph/checks/layout.py +155 -0
- chipgraph/checks/naming.py +311 -0
- chipgraph/checks/plan_check.py +901 -0
- chipgraph/checks/ports_diff.py +203 -0
- chipgraph/checks/spec_schema.py +277 -0
- chipgraph/checks/style.py +910 -0
- chipgraph/checks/tb_static.py +599 -0
- chipgraph/checks/trace.py +224 -0
- chipgraph/checks/vendor_guard.py +369 -0
- chipgraph/checks/wrap_check.py +486 -0
- chipgraph/cli/__init__.py +1688 -0
- chipgraph/cli/next_steps.py +137 -0
- chipgraph/core/__init__.py +1 -0
- chipgraph/core/config/__init__.py +93 -0
- chipgraph/core/config/defaults.py +14 -0
- chipgraph/core/config/errors.py +32 -0
- chipgraph/core/config/loader.py +766 -0
- chipgraph/core/config/models.py +845 -0
- chipgraph/core/config/templates.py +340 -0
- chipgraph/core/contracts/__init__.py +75 -0
- chipgraph/core/contracts/_paths.py +26 -0
- chipgraph/core/contracts/agent.py +49 -0
- chipgraph/core/contracts/artifact.py +68 -0
- chipgraph/core/contracts/check.py +76 -0
- chipgraph/core/contracts/event.py +70 -0
- chipgraph/core/contracts/export.py +128 -0
- chipgraph/core/contracts/finding.py +171 -0
- chipgraph/core/contracts/gate.py +50 -0
- chipgraph/core/contracts/rule.py +177 -0
- chipgraph/core/contracts/types.py +45 -0
- chipgraph/core/engine/__init__.py +70 -0
- chipgraph/core/engine/agent_rule.py +1362 -0
- chipgraph/core/engine/baseline.py +283 -0
- chipgraph/core/engine/decide.py +462 -0
- chipgraph/core/engine/fanout.py +1358 -0
- chipgraph/core/engine/gate.py +170 -0
- chipgraph/core/engine/graph.py +647 -0
- chipgraph/core/engine/records.py +60 -0
- chipgraph/core/engine/rules.py +92 -0
- chipgraph/core/engine/scheduler.py +637 -0
- chipgraph/core/engine/select.py +1239 -0
- chipgraph/core/engine/targets.py +342 -0
- chipgraph/core/model/__init__.py +98 -0
- chipgraph/core/model/entities.py +244 -0
- chipgraph/core/model/export.py +16 -0
- chipgraph/core/model/ingest.py +693 -0
- chipgraph/core/model/json_value.py +4 -0
- chipgraph/core/model/keys.py +95 -0
- chipgraph/core/model/model.py +153 -0
- chipgraph/core/model/provenance.py +27 -0
- chipgraph/core/model/query.py +583 -0
- chipgraph/core/model/registry.py +80 -0
- chipgraph/core/model/relations.py +61 -0
- chipgraph/core/model/store.py +279 -0
- chipgraph/core/plugin_api/__init__.py +81 -0
- chipgraph/core/plugin_api/local.py +167 -0
- chipgraph/core/plugin_api/pack.py +159 -0
- chipgraph/core/plugin_api/protocols.py +177 -0
- chipgraph/core/plugin_api/registry.py +111 -0
- chipgraph/core/plugin_api/types.py +94 -0
- chipgraph/core/runtime/__init__.py +41 -0
- chipgraph/core/runtime/executor.py +79 -0
- chipgraph/core/runtime/queue.py +565 -0
- chipgraph/core/runtime/roles/__init__.py +91 -0
- chipgraph/core/runtime/roles/data/author.md +41 -0
- chipgraph/core/runtime/roles/data/critic.md +56 -0
- chipgraph/core/runtime/roles/data/planner.md +38 -0
- chipgraph/core/runtime/roles/data/researcher.md +37 -0
- chipgraph/core/runtime/roles/data/rtl-author.md +64 -0
- chipgraph/core/runtime/roles/data/tb-author.md +48 -0
- chipgraph/core/runtime/roles/data/triage.md +34 -0
- chipgraph/core/runtime/roles/policy.py +299 -0
- chipgraph/core/runtime/roles/registry.py +52 -0
- chipgraph/core/runtime/roles/review.py +275 -0
- chipgraph/core/runtime/roles/schema.py +82 -0
- chipgraph/core/runtime/roles/skills.py +134 -0
- chipgraph/core/runtime/roles/spec.py +232 -0
- chipgraph/core/state/__init__.py +1 -0
- chipgraph/core/state/artifacts.py +156 -0
- chipgraph/core/state/backend.py +117 -0
- chipgraph/core/state/findings.py +151 -0
- chipgraph/core/state/handoff.py +411 -0
- chipgraph/core/state/idempotency.py +59 -0
- chipgraph/core/state/journal.py +238 -0
- chipgraph/core/state/layout.py +82 -0
- chipgraph/core/state/lock.py +195 -0
- chipgraph/core/state/trace.py +225 -0
- chipgraph/learn/__init__.py +96 -0
- chipgraph/learn/draft.py +187 -0
- chipgraph/learn/infer.py +580 -0
- chipgraph/learn/models.py +145 -0
- chipgraph/learn/try_run.py +228 -0
- chipgraph/mcp/__init__.py +12 -0
- chipgraph/mcp/model_tools.py +167 -0
- chipgraph/mcp/server.py +787 -0
- chipgraph/orgs/qnsc/naming-v1.yml +113 -0
- chipgraph/orgs/qnsc/profile.yml +5 -0
- chipgraph/packs/__init__.py +8 -0
- chipgraph/packs/assist/__init__.py +16 -0
- chipgraph/packs/assist/ask/__init__.py +58 -0
- chipgraph/packs/assist/ask/_db.py +57 -0
- chipgraph/packs/assist/ask/_project.py +230 -0
- chipgraph/packs/assist/ask/answer.py +266 -0
- chipgraph/packs/assist/ask/check.py +182 -0
- chipgraph/packs/assist/ask/contract.py +115 -0
- chipgraph/packs/assist/ask/documents.py +157 -0
- chipgraph/packs/assist/ask/fts.py +80 -0
- chipgraph/packs/assist/ask/retrieve.py +331 -0
- chipgraph/packs/assist/audit/__init__.py +383 -0
- chipgraph/packs/assist/pack.yml +13 -0
- chipgraph/packs/assist/triage/__init__.py +64 -0
- chipgraph/packs/assist/triage/contract.py +94 -0
- chipgraph/packs/assist/triage/parse.py +371 -0
- chipgraph/packs/assist/triage/question.py +384 -0
- chipgraph/packs/assist/triage/report.py +160 -0
- chipgraph/packs/assist/triage/rules.py +447 -0
- chipgraph/packs/assist/triage/run.py +224 -0
- chipgraph/packs/digital_rtl/__init__.py +19 -0
- chipgraph/packs/digital_rtl/layout.py +144 -0
- chipgraph/packs/digital_rtl/pack.yml +25 -0
- chipgraph/packs/digital_rtl/plan/__init__.py +34 -0
- chipgraph/packs/digital_rtl/plan/__main__.py +16 -0
- chipgraph/packs/digital_rtl/plan/context.py +82 -0
- chipgraph/packs/digital_rtl/plan/expand.py +94 -0
- chipgraph/packs/digital_rtl/plan/model.py +150 -0
- chipgraph/packs/digital_rtl/plan/resolver.py +400 -0
- chipgraph/packs/digital_rtl/plan/show.py +176 -0
- chipgraph/packs/digital_rtl/pr/__init__.py +11 -0
- chipgraph/packs/digital_rtl/pr/body.py +165 -0
- chipgraph/packs/digital_rtl/pr/gate.py +110 -0
- chipgraph/packs/digital_rtl/pr/open.py +397 -0
- chipgraph/packs/digital_rtl/rtl/__init__.py +9 -0
- chipgraph/packs/digital_rtl/rtl/context.py +272 -0
- chipgraph/packs/digital_rtl/rules/open_pr.yml +30 -0
- chipgraph/packs/digital_rtl/rules/plan.yml +28 -0
- chipgraph/packs/digital_rtl/rules/plan_expand.yml +29 -0
- chipgraph/packs/digital_rtl/rules/pr_gate.yml +27 -0
- chipgraph/packs/digital_rtl/rules/review.yml +31 -0
- chipgraph/packs/digital_rtl/rules/rtl_module.yml +53 -0
- chipgraph/packs/digital_rtl/skills/lang-sv-rtl.md +58 -0
- chipgraph/packs/digital_rtl/skills/org-naming.md +29 -0
- chipgraph/packs/digital_rtl/skills/plan-modules.md +63 -0
- chipgraph/packs/digital_rtl/skills/review-diff.md +41 -0
- chipgraph/packs/digital_rtl/targets/plan.yml +11 -0
- chipgraph/packs/digital_rtl/targets/rtl.yml +20 -0
- chipgraph/packs/digital_rtl/wrapper/__init__.py +24 -0
- chipgraph/packs/digital_rtl/wrapper/common.py +171 -0
- chipgraph/packs/digital_rtl/wrapper/context.py +222 -0
- chipgraph/packs/digital_rtl/wrapper/emacs.py +626 -0
- chipgraph/packs/digital_rtl/wrapper/expansion.py +304 -0
- chipgraph/packs/digital_rtl/wrapper/lisp.py +504 -0
- chipgraph/packs/digital_rtl/wrapper/resolver.py +60 -0
- chipgraph/packs/digital_rtl/wrapper/rules/wrapper.yml +41 -0
- chipgraph/packs/digital_rtl/wrapper/rules/wrapper_gen.yml +35 -0
- chipgraph/packs/digital_rtl/wrapper/skills/wrapper-auto.md +120 -0
- chipgraph/packs/dv/__init__.py +15 -0
- chipgraph/packs/dv/declaration.py +392 -0
- chipgraph/packs/dv/interface.py +596 -0
- chipgraph/packs/dv/pack.yml +14 -0
- chipgraph/packs/dv/rules/tb_module.yml +42 -0
- chipgraph/packs/dv/skills/dv/cocotb.md +72 -0
- chipgraph/packs/spec_core/__init__.py +9 -0
- chipgraph/packs/spec_core/extract/__init__.py +12 -0
- chipgraph/packs/spec_core/extract/_markdown.py +371 -0
- chipgraph/packs/spec_core/extract/_text.py +116 -0
- chipgraph/packs/spec_core/extract/mas.py +975 -0
- chipgraph/packs/spec_core/gen/__init__.py +11 -0
- chipgraph/packs/spec_core/gen/agents_md/__init__.py +148 -0
- chipgraph/packs/spec_core/gen/agents_md/_context.py +239 -0
- chipgraph/packs/spec_core/gen/agents_md/_markers.py +131 -0
- chipgraph/packs/spec_core/gen/agents_md/agents_md.md.j2 +178 -0
- chipgraph/packs/spec_core/gen/diagram/__init__.py +110 -0
- chipgraph/packs/spec_core/gen/diagram/__main__.py +44 -0
- chipgraph/packs/spec_core/gen/diagram/_diagrams.py +403 -0
- chipgraph/packs/spec_core/gen/diagram/_scene.py +163 -0
- chipgraph/packs/spec_core/pack.yml +6 -0
- chipgraph/py.typed +0 -0
- chipgraph-0.1.0.dist-info/METADATA +53 -0
- chipgraph-0.1.0.dist-info/RECORD +252 -0
- chipgraph-0.1.0.dist-info/WHEEL +4 -0
- chipgraph-0.1.0.dist-info/entry_points.txt +61 -0
- chipgraph-0.1.0.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"""`CmdTool`: a `ToolAdapter` that runs a project's own command line, e.g.
|
|
2
|
+
|
|
3
|
+
``make lint BLOCK={block}``, and reads its log through a `LogParser`. This lets a
|
|
4
|
+
project with its own EDA flow plug straight into chipgraph without a dedicated
|
|
5
|
+
adapter (DESIGN.md 7.1).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import hashlib
|
|
11
|
+
import shlex
|
|
12
|
+
import time
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from chipgraph.adapters.parser import PARSERS, GenericRegexParser
|
|
17
|
+
from chipgraph.core.contracts import CheckResult, CheckSpec, Issue
|
|
18
|
+
from chipgraph.core.contracts.types import CheckStatus
|
|
19
|
+
from chipgraph.core.plugin_api.protocols import LogParser
|
|
20
|
+
from chipgraph.core.plugin_api.types import ToolContext
|
|
21
|
+
|
|
22
|
+
_DEFAULT_OK_RETURNCODES = (0,)
|
|
23
|
+
_LOG_TAIL_MAX_CHARS = 4000
|
|
24
|
+
_MISSING_EXECUTABLE_RETURNCODE = 127
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CmdTool:
|
|
28
|
+
"""Runs `spec.args["cmd"]` through `ctx.runner` and parses its log into `Issue`s."""
|
|
29
|
+
|
|
30
|
+
name = "cmd"
|
|
31
|
+
capability = "any"
|
|
32
|
+
|
|
33
|
+
async def run(self, spec: CheckSpec, ctx: ToolContext) -> CheckResult:
|
|
34
|
+
start = time.monotonic()
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
argv = _build_argv(spec, ctx)
|
|
38
|
+
except _CmdArgError as exc:
|
|
39
|
+
return CheckResult(
|
|
40
|
+
check_id=spec.id,
|
|
41
|
+
status="error",
|
|
42
|
+
issues=(Issue(msg=str(exc), severity="error"),),
|
|
43
|
+
duration_s=time.monotonic() - start,
|
|
44
|
+
idempotency_key=_hash_key(spec, ctx, argv=None),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
cwd = _resolve_cwd(spec, ctx)
|
|
48
|
+
timeout_s = spec.args.get("timeout_s")
|
|
49
|
+
ok_returncodes = tuple(spec.args.get("ok_returncodes", _DEFAULT_OK_RETURNCODES))
|
|
50
|
+
|
|
51
|
+
result = await ctx.runner.run(argv, cwd=cwd, env=ctx.env, timeout_s=timeout_s)
|
|
52
|
+
|
|
53
|
+
log = result.stdout + result.stderr
|
|
54
|
+
log_tail = log[-_LOG_TAIL_MAX_CHARS:]
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
parser = _build_parser(spec)
|
|
58
|
+
except _CmdArgError as exc:
|
|
59
|
+
return CheckResult(
|
|
60
|
+
check_id=spec.id,
|
|
61
|
+
status="error",
|
|
62
|
+
issues=(Issue(msg=str(exc), severity="error"),),
|
|
63
|
+
log_tail=log_tail,
|
|
64
|
+
duration_s=time.monotonic() - start,
|
|
65
|
+
idempotency_key=_hash_key(spec, ctx, argv=argv),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
issues = parser.parse(log) if parser is not None else ()
|
|
69
|
+
|
|
70
|
+
duration_s = time.monotonic() - start
|
|
71
|
+
idempotency_key = _hash_key(spec, ctx, argv=argv)
|
|
72
|
+
|
|
73
|
+
if result.timed_out:
|
|
74
|
+
timeout_issue = Issue(
|
|
75
|
+
msg=f"command timed out after {timeout_s}s: {' '.join(argv)}",
|
|
76
|
+
severity="error",
|
|
77
|
+
)
|
|
78
|
+
return CheckResult(
|
|
79
|
+
check_id=spec.id,
|
|
80
|
+
status="error",
|
|
81
|
+
issues=(*issues, timeout_issue),
|
|
82
|
+
log_tail=log_tail,
|
|
83
|
+
duration_s=duration_s,
|
|
84
|
+
idempotency_key=idempotency_key,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if result.returncode == _MISSING_EXECUTABLE_RETURNCODE:
|
|
88
|
+
missing_issue = Issue(
|
|
89
|
+
msg=f"command not found: {' '.join(argv)}",
|
|
90
|
+
severity="error",
|
|
91
|
+
)
|
|
92
|
+
return CheckResult(
|
|
93
|
+
check_id=spec.id,
|
|
94
|
+
status="error",
|
|
95
|
+
issues=(*issues, missing_issue),
|
|
96
|
+
log_tail=log_tail,
|
|
97
|
+
duration_s=duration_s,
|
|
98
|
+
idempotency_key=idempotency_key,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
has_error_issue = any(issue.severity == "error" for issue in issues)
|
|
102
|
+
|
|
103
|
+
if result.returncode not in ok_returncodes:
|
|
104
|
+
if not issues:
|
|
105
|
+
issues = (
|
|
106
|
+
Issue(
|
|
107
|
+
msg=f"command exited with {result.returncode}",
|
|
108
|
+
severity="error",
|
|
109
|
+
),
|
|
110
|
+
)
|
|
111
|
+
return CheckResult(
|
|
112
|
+
check_id=spec.id,
|
|
113
|
+
status="fail",
|
|
114
|
+
issues=issues,
|
|
115
|
+
log_tail=log_tail,
|
|
116
|
+
duration_s=duration_s,
|
|
117
|
+
idempotency_key=idempotency_key,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
status: CheckStatus = "fail" if has_error_issue else "pass"
|
|
121
|
+
return CheckResult(
|
|
122
|
+
check_id=spec.id,
|
|
123
|
+
status=status,
|
|
124
|
+
issues=issues,
|
|
125
|
+
log_tail=log_tail,
|
|
126
|
+
duration_s=duration_s,
|
|
127
|
+
idempotency_key=idempotency_key,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def key_for(spec: CheckSpec, ctx: ToolContext) -> str:
|
|
132
|
+
"""A stable idempotency key for this check invocation.
|
|
133
|
+
|
|
134
|
+
Hashes the substituted argv, the (repo-relative) cwd, the sorted `ctx.env`
|
|
135
|
+
items and `ctx.params`. Never raises: an invalid or unsubstitutable `cmd`
|
|
136
|
+
(the same case that makes `run` return an `error` result) still yields a key,
|
|
137
|
+
it is just keyed on the raw, unsubstituted `args["cmd"]` instead.
|
|
138
|
+
"""
|
|
139
|
+
try:
|
|
140
|
+
argv: tuple[str, ...] | None = tuple(_build_argv(spec, ctx))
|
|
141
|
+
except _CmdArgError:
|
|
142
|
+
argv = None
|
|
143
|
+
return _hash_key(spec, ctx, argv=argv)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class _CmdArgError(Exception):
|
|
147
|
+
"""Raised for a malformed `CheckSpec.args`, turned into an `error` `CheckResult`."""
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _hash_key(spec: CheckSpec, ctx: ToolContext, *, argv: Sequence[str] | None) -> str:
|
|
151
|
+
cwd = spec.args.get("cwd", "")
|
|
152
|
+
digest_input = repr(
|
|
153
|
+
(
|
|
154
|
+
spec.id,
|
|
155
|
+
tuple(argv) if argv is not None else repr(spec.args.get("cmd")),
|
|
156
|
+
str(cwd),
|
|
157
|
+
tuple(sorted(ctx.env.items())),
|
|
158
|
+
tuple(sorted(ctx.params.items())),
|
|
159
|
+
)
|
|
160
|
+
)
|
|
161
|
+
return hashlib.sha256(digest_input.encode("utf-8")).hexdigest()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _build_argv(spec: CheckSpec, ctx: ToolContext) -> list[str]:
|
|
165
|
+
cmd = spec.args.get("cmd")
|
|
166
|
+
if cmd is None:
|
|
167
|
+
raise _CmdArgError(f"check {spec.id!r}: args['cmd'] is required")
|
|
168
|
+
|
|
169
|
+
if isinstance(cmd, str):
|
|
170
|
+
try:
|
|
171
|
+
template = cmd.format(**ctx.params)
|
|
172
|
+
except KeyError as exc:
|
|
173
|
+
raise _CmdArgError(
|
|
174
|
+
f"check {spec.id!r}: missing param {exc.args[0]!r} for cmd template {cmd!r}"
|
|
175
|
+
) from exc
|
|
176
|
+
return shlex.split(template)
|
|
177
|
+
|
|
178
|
+
if isinstance(cmd, list):
|
|
179
|
+
argv: list[str] = []
|
|
180
|
+
for token in cmd:
|
|
181
|
+
try:
|
|
182
|
+
argv.append(str(token).format(**ctx.params))
|
|
183
|
+
except KeyError as exc:
|
|
184
|
+
raise _CmdArgError(
|
|
185
|
+
f"check {spec.id!r}: missing param {exc.args[0]!r} for cmd token {token!r}"
|
|
186
|
+
) from exc
|
|
187
|
+
return argv
|
|
188
|
+
|
|
189
|
+
raise _CmdArgError(f"check {spec.id!r}: args['cmd'] must be a string or a list of strings")
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _resolve_cwd(spec: CheckSpec, ctx: ToolContext) -> Path:
|
|
193
|
+
cwd_arg = spec.args.get("cwd")
|
|
194
|
+
if cwd_arg is None:
|
|
195
|
+
return ctx.repo_root
|
|
196
|
+
return ctx.repo_root / str(cwd_arg)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _build_parser(spec: CheckSpec) -> LogParser | None:
|
|
200
|
+
parser_name = spec.args.get("parser")
|
|
201
|
+
regex = spec.args.get("regex")
|
|
202
|
+
|
|
203
|
+
if parser_name is not None and regex is not None:
|
|
204
|
+
raise _CmdArgError(
|
|
205
|
+
f"check {spec.id!r}: args['parser'] and args['regex'] are mutually exclusive"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
if regex is not None:
|
|
209
|
+
severity_group = spec.args.get("severity_group")
|
|
210
|
+
default_severity = spec.args.get("default_severity", "error")
|
|
211
|
+
try:
|
|
212
|
+
return GenericRegexParser(
|
|
213
|
+
pattern=regex,
|
|
214
|
+
severity_group=severity_group,
|
|
215
|
+
default_severity=default_severity,
|
|
216
|
+
)
|
|
217
|
+
except ValueError as exc:
|
|
218
|
+
raise _CmdArgError(f"check {spec.id!r}: {exc}") from exc
|
|
219
|
+
|
|
220
|
+
if parser_name is not None:
|
|
221
|
+
factory = PARSERS.get(parser_name)
|
|
222
|
+
if factory is None:
|
|
223
|
+
raise _CmdArgError(
|
|
224
|
+
f"check {spec.id!r}: unknown parser {parser_name!r}; "
|
|
225
|
+
f"known parsers: {sorted(PARSERS)}"
|
|
226
|
+
)
|
|
227
|
+
return factory()
|
|
228
|
+
|
|
229
|
+
return None
|