code-standards 7.0.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.
- code_standards-7.0.0.dist-info/METADATA +53 -0
- code_standards-7.0.0.dist-info/RECORD +99 -0
- code_standards-7.0.0.dist-info/WHEEL +4 -0
- code_standards-7.0.0.dist-info/entry_points.txt +3 -0
- code_standards-7.0.0.dist-info/licenses/LICENSE +21 -0
- sarj_standards/__init__.py +30 -0
- sarj_standards/__main__.py +5 -0
- sarj_standards/_meta.py +22 -0
- sarj_standards/api.py +890 -0
- sarj_standards/cli/__init__.py +0 -0
- sarj_standards/cli/main.py +2466 -0
- sarj_standards/configs/cli-reference.v1.json +1 -0
- sarj_standards/configs/doctor.config.json +22 -0
- sarj_standards/configs/eslint.application.mjs +1366 -0
- sarj_standards/configs/eslint.peers.json +44 -0
- sarj_standards/configs/eslint.strict.mjs +1060 -0
- sarj_standards/configs/markdownlint.strict.yaml +12 -0
- sarj_standards/configs/pyright.strict.json +96 -0
- sarj_standards/configs/ruff.application.toml +363 -0
- sarj_standards/configs/ruff.strict.toml +338 -0
- sarj_standards/configs/rule-inventory.v1.json +1 -0
- sarj_standards/configs/rule-ledger.json +846 -0
- sarj_standards/configs/rule-warning-levels.v1.json +1 -0
- sarj_standards/configs/taplo.strict.toml +14 -0
- sarj_standards/configs/yamllint.strict.yaml +25 -0
- sarj_standards/libs/__init__.py +0 -0
- sarj_standards/libs/adoption/__init__.py +0 -0
- sarj_standards/libs/adoption/configs.py +36 -0
- sarj_standards/libs/adoption/doctor.py +1346 -0
- sarj_standards/libs/adoption/exclusions.py +66 -0
- sarj_standards/libs/adoption/hooks.py +423 -0
- sarj_standards/libs/adoption/launcher.py +240 -0
- sarj_standards/libs/adoption/lifecycle.py +493 -0
- sarj_standards/libs/adoption/manifest.py +550 -0
- sarj_standards/libs/adoption/packagemanager.py +285 -0
- sarj_standards/libs/adoption/retired_suppressions.py +371 -0
- sarj_standards/libs/adoption/scaffold.py +1660 -0
- sarj_standards/libs/adoption/service.py +441 -0
- sarj_standards/libs/adoption/transaction.py +274 -0
- sarj_standards/libs/adoption/upgrade.py +516 -0
- sarj_standards/libs/adoption/uvtool.py +62 -0
- sarj_standards/libs/catalogs/__init__.py +9 -0
- sarj_standards/libs/catalogs/slack_automations.py +627 -0
- sarj_standards/libs/corpus/__init__.py +25 -0
- sarj_standards/libs/corpus/manifest.py +211 -0
- sarj_standards/libs/corpus/snapshot.py +222 -0
- sarj_standards/libs/diagnostics/__init__.py +65 -0
- sarj_standards/libs/diagnostics/analysis.schema.json +161 -0
- sarj_standards/libs/diagnostics/baseline.py +131 -0
- sarj_standards/libs/diagnostics/models.py +574 -0
- sarj_standards/libs/diagnostics/serialize.py +290 -0
- sarj_standards/libs/diagnostics/source.py +172 -0
- sarj_standards/libs/filesystem.py +11 -0
- sarj_standards/libs/linting/__init__.py +0 -0
- sarj_standards/libs/linting/analysis.py +422 -0
- sarj_standards/libs/linting/external.py +1454 -0
- sarj_standards/libs/linting/library_policy.py +688 -0
- sarj_standards/libs/linting/policy.py +152 -0
- sarj_standards/libs/linting/runner.py +442 -0
- sarj_standards/libs/linting/textlint.py +1605 -0
- sarj_standards/libs/release/__init__.py +98 -0
- sarj_standards/libs/release/_values.py +24 -0
- sarj_standards/libs/release/artifacts.py +191 -0
- sarj_standards/libs/release/causality.py +80 -0
- sarj_standards/libs/release/changes.py +48 -0
- sarj_standards/libs/release/process.py +128 -0
- sarj_standards/libs/release/publish.py +85 -0
- sarj_standards/libs/release/registry.py +271 -0
- sarj_standards/libs/release/release_age.py +218 -0
- sarj_standards/libs/release/rollout.py +1163 -0
- sarj_standards/libs/release/tags.py +373 -0
- sarj_standards/libs/release/typescript.py +191 -0
- sarj_standards/libs/repository/__init__.py +0 -0
- sarj_standards/libs/repository/cli_reference_artifact.py +324 -0
- sarj_standards/libs/repository/comment_corpus.py +536 -0
- sarj_standards/libs/repository/config_generation.py +146 -0
- sarj_standards/libs/repository/docs.py +347 -0
- sarj_standards/libs/repository/hooks.py +118 -0
- sarj_standards/libs/repository/ledger.py +99 -0
- sarj_standards/libs/repository/repository.py +744 -0
- sarj_standards/libs/repository/rule_authoring.py +246 -0
- sarj_standards/libs/repository/rule_catalog_artifact.py +479 -0
- sarj_standards/libs/repository/rule_changes.py +318 -0
- sarj_standards/libs/repository/rule_inventory_artifact.py +142 -0
- sarj_standards/libs/repository/rule_lifecycle.py +167 -0
- sarj_standards/libs/repository/rule_maintenance.py +225 -0
- sarj_standards/libs/rules/__init__.py +74 -0
- sarj_standards/libs/rules/catalog.py +145 -0
- sarj_standards/libs/rules/contracts.py +382 -0
- sarj_standards/libs/rules/corpus_runner.py +365 -0
- sarj_standards/libs/rules/evaluation.py +177 -0
- sarj_standards/libs/setup/__init__.py +4 -0
- sarj_standards/libs/setup/repository.py +40 -0
- sarj_standards/py.typed +0 -0
- sarj_standards/schemas/__init__.py +4 -0
- sarj_standards/schemas/_paths.py +7 -0
- sarj_standards/schemas/rule-catalog.v1.json +1 -0
- sarj_standards/schemas/rule-catalog.v1.schema.json +112 -0
- sarj_standards/schemas/slack-automations.v1.schema.json +1751 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import re
|
|
5
|
+
import shlex
|
|
6
|
+
from typing import Final, NamedTuple
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
TOOL_PYTHON: Final = "3.14"
|
|
10
|
+
PACKAGE: Final = "code-standards"
|
|
11
|
+
COMMAND: Final = "code-standards"
|
|
12
|
+
BOOTSTRAP_SPEC: Final = "sarj-standards-bootstrap==2.0.0"
|
|
13
|
+
RETIRED_REPOSITORY_LAUNCHER: Final = Path(".sarj/standards")
|
|
14
|
+
RETIRED_LAUNCHER_PROTOCOL: Final = 1
|
|
15
|
+
_VERSION: Final = re.compile(r"(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\Z")
|
|
16
|
+
_SHELL_WHITESPACE: Final = r"(?:\s|\\\r?\n)+"
|
|
17
|
+
_LEGACY_REPOSITORY_INVOCATION: Final = re.compile(
|
|
18
|
+
rf"\buvx{_SHELL_WHITESPACE}(?:(?!--from\b)[^\s;&|\\]+{_SHELL_WHITESPACE})*"
|
|
19
|
+
rf"--from{_SHELL_WHITESPACE}['\"]?sarj-standards==[^\s;&|\\'\"]+['\"]?"
|
|
20
|
+
rf"{_SHELL_WHITESPACE}sarj-standards"
|
|
21
|
+
rf"(?:{_SHELL_WHITESPACE}--root(?:{_SHELL_WHITESPACE}|=)(?:\.|['\"]\.['\"]))?"
|
|
22
|
+
)
|
|
23
|
+
_REPOSITORY_LAUNCHER_INVOCATION: Final = re.compile(
|
|
24
|
+
rf"\buv{_SHELL_WHITESPACE}run{_SHELL_WHITESPACE}--no-config"
|
|
25
|
+
rf"{_SHELL_WHITESPACE}--no-project{_SHELL_WHITESPACE}--python"
|
|
26
|
+
rf"{_SHELL_WHITESPACE}3\.14{_SHELL_WHITESPACE}python"
|
|
27
|
+
rf"{_SHELL_WHITESPACE}(?:\./)?\.sarj/standards"
|
|
28
|
+
)
|
|
29
|
+
_BARE_REPOSITORY_LAUNCHER_INVOCATION: Final = re.compile(
|
|
30
|
+
rf"(?<![\w./-])python{_SHELL_WHITESPACE}(?:\./)?\.sarj/standards"
|
|
31
|
+
)
|
|
32
|
+
_LEGACY_MAKE_RUN: Final = re.compile(
|
|
33
|
+
r"(?m)^(?P<indent>\t?)(?:@)?\$\(STANDARDS_RUN\)[ \t]+sarj-standards"
|
|
34
|
+
r"(?:[ \t]+--root(?:[ \t]+|=)(?:\.|['\"]\.['\"]))?"
|
|
35
|
+
)
|
|
36
|
+
_LEGACY_MAKE_RUN_ASSIGNMENT: Final = re.compile(
|
|
37
|
+
r"(?m)^[ \t]*STANDARDS_RUN[ \t]*:?=[ \t]*uvx[^\r\n]*"
|
|
38
|
+
r"sarj-standards==(?:['\"])?\$\(STANDARDS_VERSION\)(?:['\"])?[^\r\n]*(?:\r?\n)?"
|
|
39
|
+
)
|
|
40
|
+
_LEGACY_MAKE_VERSION_ASSIGNMENT: Final = re.compile(r"(?m)^[ \t]*STANDARDS_VERSION[ \t]*:?=[ \t]*[^\r\n]+(?:\r?\n)?")
|
|
41
|
+
_LEGACY_MAKE_VERSION_PRINT: Final = re.compile(
|
|
42
|
+
r"(?m)^\t@?printf[ \t]+['\"]%s\\n['\"][ \t]+['\"]?\$\(STANDARDS_VERSION\)['\"]?[ \t]*$"
|
|
43
|
+
)
|
|
44
|
+
_LEGACY_PYTHON_ARGV_INVOCATION: Final = re.compile(
|
|
45
|
+
r"(?m)^(?P<indent>[ \t]*)['\"]uvx['\"],[ \t]*\r?\n"
|
|
46
|
+
r"(?:(?P=indent)['\"]--no-config['\"],[ \t]*\r?\n)?"
|
|
47
|
+
r"(?P=indent)['\"]--isolated['\"],[ \t]*\r?\n"
|
|
48
|
+
r"(?P=indent)['\"]--python['\"],[ \t]*\r?\n"
|
|
49
|
+
r"(?P=indent)['\"]3\.14['\"],[ \t]*\r?\n"
|
|
50
|
+
r"(?P=indent)['\"]--from['\"],[ \t]*\r?\n"
|
|
51
|
+
r"(?P=indent)['\"]sarj-standards==[^'\"\r\n]+['\"],[ \t]*\r?\n"
|
|
52
|
+
r"(?P=indent)['\"]sarj-standards['\"],[ \t]*\r?\n"
|
|
53
|
+
r"(?P=indent)['\"]--root['\"],[ \t]*\r?\n"
|
|
54
|
+
r"(?P=indent)['\"]\.['\"],[ \t]*\r?\n"
|
|
55
|
+
)
|
|
56
|
+
_REPOSITORY_PYTHON_ARGV_INVOCATION: Final = re.compile(
|
|
57
|
+
r"(?m)^(?P<indent>[ \t]*)['\"]uv['\"],[ \t]*\r?\n"
|
|
58
|
+
r"(?P=indent)['\"]run['\"],[ \t]*\r?\n"
|
|
59
|
+
r"(?P=indent)['\"]--no-config['\"],[ \t]*\r?\n"
|
|
60
|
+
r"(?P=indent)['\"]--no-project['\"],[ \t]*\r?\n"
|
|
61
|
+
r"(?P=indent)['\"]--python['\"],[ \t]*\r?\n"
|
|
62
|
+
r"(?P=indent)['\"]3\.14['\"],[ \t]*\r?\n"
|
|
63
|
+
r"(?P=indent)['\"]python['\"],[ \t]*\r?\n"
|
|
64
|
+
r"(?P=indent)['\"]\.sarj/standards['\"],[ \t]*\r?\n"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class LegacyInvocationRewrite(NamedTuple):
|
|
69
|
+
contents: str
|
|
70
|
+
replacements: int
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def argv(*, executable: str = "uvx", version: str | None = None, refresh: bool = False) -> tuple[str, ...]:
|
|
74
|
+
if version is not None and _VERSION.fullmatch(version) is None:
|
|
75
|
+
msg = f"invalid exact Standards version: {version!r}"
|
|
76
|
+
raise ValueError(msg)
|
|
77
|
+
package = PACKAGE if version is None else f"{PACKAGE}=={version}"
|
|
78
|
+
refresh_args = ("--refresh",) if refresh else ()
|
|
79
|
+
return (
|
|
80
|
+
executable,
|
|
81
|
+
"--no-config",
|
|
82
|
+
"--isolated",
|
|
83
|
+
"--python",
|
|
84
|
+
TOOL_PYTHON,
|
|
85
|
+
*refresh_args,
|
|
86
|
+
"--from",
|
|
87
|
+
package,
|
|
88
|
+
COMMAND,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def repository_argv(*arguments: str, executable: str = "uvx") -> tuple[str, ...]:
|
|
93
|
+
return (
|
|
94
|
+
executable,
|
|
95
|
+
"--no-config",
|
|
96
|
+
"--isolated",
|
|
97
|
+
"--python",
|
|
98
|
+
TOOL_PYTHON,
|
|
99
|
+
"--from",
|
|
100
|
+
BOOTSTRAP_SPEC,
|
|
101
|
+
COMMAND,
|
|
102
|
+
*arguments,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def repository_command(*arguments: str) -> str:
|
|
107
|
+
return shlex.join(repository_argv(*arguments))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def rewrite_legacy_repository_invocations(text: str) -> LegacyInvocationRewrite:
|
|
111
|
+
contents, count = _LEGACY_REPOSITORY_INVOCATION.subn(repository_command(), text)
|
|
112
|
+
contents, repository_count = _REPOSITORY_LAUNCHER_INVOCATION.subn(repository_command(), contents)
|
|
113
|
+
count += repository_count
|
|
114
|
+
contents, bare_repository_count = _BARE_REPOSITORY_LAUNCHER_INVOCATION.subn(repository_command(), contents)
|
|
115
|
+
count += bare_repository_count
|
|
116
|
+
update_target = re.compile(
|
|
117
|
+
rf"{re.escape(repository_command())}{_SHELL_WHITESPACE}update"
|
|
118
|
+
rf"{_SHELL_WHITESPACE}--to(?:{_SHELL_WHITESPACE}|=)[^\s;&|\\'\"]+"
|
|
119
|
+
)
|
|
120
|
+
contents, update_target_count = update_target.subn(f"{repository_command()} update", contents)
|
|
121
|
+
count += update_target_count
|
|
122
|
+
contents, python_argv_count = _LEGACY_PYTHON_ARGV_INVOCATION.subn(_python_repository_argv, contents)
|
|
123
|
+
count += python_argv_count
|
|
124
|
+
contents, repository_python_count = _REPOSITORY_PYTHON_ARGV_INVOCATION.subn(_python_repository_argv, contents)
|
|
125
|
+
count += repository_python_count
|
|
126
|
+
before_make = contents
|
|
127
|
+
make_invocations = tuple(_LEGACY_MAKE_RUN.finditer(contents))
|
|
128
|
+
if (
|
|
129
|
+
make_invocations
|
|
130
|
+
and _LEGACY_MAKE_RUN_ASSIGNMENT.search(contents) is not None
|
|
131
|
+
and _LEGACY_MAKE_VERSION_ASSIGNMENT.search(contents) is not None
|
|
132
|
+
):
|
|
133
|
+
contents = _LEGACY_MAKE_RUN.sub(
|
|
134
|
+
lambda match: f"{match.group('indent')}{repository_command()}",
|
|
135
|
+
contents,
|
|
136
|
+
)
|
|
137
|
+
contents = _LEGACY_MAKE_VERSION_PRINT.sub(f"\t@{repository_command('--version')}", contents)
|
|
138
|
+
contents = _LEGACY_MAKE_RUN_ASSIGNMENT.sub(
|
|
139
|
+
lambda match: (
|
|
140
|
+
"\r\n" if match.group(0).endswith("\r\n") else ("\n" if match.group(0).endswith("\n") else "")
|
|
141
|
+
),
|
|
142
|
+
contents,
|
|
143
|
+
)
|
|
144
|
+
contents = _LEGACY_MAKE_VERSION_ASSIGNMENT.sub(
|
|
145
|
+
f"STANDARDS_VERSION := $(shell {repository_command('--version')})\n",
|
|
146
|
+
contents,
|
|
147
|
+
)
|
|
148
|
+
if "$(STANDARDS_RUN)" not in contents:
|
|
149
|
+
count += len(make_invocations)
|
|
150
|
+
else:
|
|
151
|
+
return LegacyInvocationRewrite(before_make, count)
|
|
152
|
+
return LegacyInvocationRewrite(contents, count)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _python_repository_argv(match: re.Match[str]) -> str:
|
|
156
|
+
indent = match.group("indent")
|
|
157
|
+
return "".join(f'{indent}"{argument}",\n' for argument in repository_argv())
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def retired_repository_script() -> str:
|
|
161
|
+
return f"""# Managed by code-standards launcher protocol {RETIRED_LAUNCHER_PROTOCOL}; do not edit.
|
|
162
|
+
from __future__ import annotations
|
|
163
|
+
|
|
164
|
+
import os
|
|
165
|
+
from pathlib import Path
|
|
166
|
+
import re
|
|
167
|
+
import shutil
|
|
168
|
+
import subprocess
|
|
169
|
+
import sys
|
|
170
|
+
import tomllib
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
PROTOCOL = {RETIRED_LAUNCHER_PROTOCOL}
|
|
174
|
+
TOOL_PYTHON = {TOOL_PYTHON!r}
|
|
175
|
+
VERSION = re.compile(r"(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*)\\Z")
|
|
176
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
177
|
+
MANIFEST = ROOT / ".sarj-standards.toml"
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def fail(message: str) -> int:
|
|
181
|
+
print(f"code-standards launcher: {{message}}", file=sys.stderr)
|
|
182
|
+
return 2
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def main() -> int:
|
|
186
|
+
try:
|
|
187
|
+
with MANIFEST.open("rb") as stream:
|
|
188
|
+
document = tomllib.load(stream)
|
|
189
|
+
except (OSError, tomllib.TOMLDecodeError) as exc:
|
|
190
|
+
return fail(f"cannot read {{MANIFEST}}: {{exc}}")
|
|
191
|
+
schema = document.get("schema")
|
|
192
|
+
bundle = document.get("bundle")
|
|
193
|
+
if schema != 3:
|
|
194
|
+
return fail(f"unsupported manifest schema {{schema!r}}")
|
|
195
|
+
if not isinstance(bundle, str) or VERSION.fullmatch(bundle) is None:
|
|
196
|
+
return fail("manifest bundle must be one exact canonical release")
|
|
197
|
+
uvx = shutil.which("uvx")
|
|
198
|
+
if uvx is None:
|
|
199
|
+
return fail("uvx is required; install uv and retry")
|
|
200
|
+
environment = dict(os.environ)
|
|
201
|
+
for name in (
|
|
202
|
+
"PIP_EXTRA_INDEX_URL",
|
|
203
|
+
"PIP_INDEX_URL",
|
|
204
|
+
"UV_CONFIG_FILE",
|
|
205
|
+
"UV_EXTRA_INDEX_URL",
|
|
206
|
+
"UV_INDEX_URL",
|
|
207
|
+
"UV_PROJECT",
|
|
208
|
+
"VIRTUAL_ENV",
|
|
209
|
+
):
|
|
210
|
+
environment.pop(name, None)
|
|
211
|
+
command = (
|
|
212
|
+
uvx,
|
|
213
|
+
"--no-config",
|
|
214
|
+
"--isolated",
|
|
215
|
+
"--python",
|
|
216
|
+
TOOL_PYTHON,
|
|
217
|
+
"--from",
|
|
218
|
+
f"code-standards=={{bundle}}",
|
|
219
|
+
"code-standards",
|
|
220
|
+
"--root",
|
|
221
|
+
str(ROOT),
|
|
222
|
+
*sys.argv[1:],
|
|
223
|
+
)
|
|
224
|
+
try:
|
|
225
|
+
return subprocess.run(command, check=False, env=environment, shell=False).returncode # noqa: S603
|
|
226
|
+
except OSError as exc:
|
|
227
|
+
return fail(f"could not execute standards {{bundle}}: {{exc}}")
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
if __name__ == "__main__":
|
|
231
|
+
raise SystemExit(main())
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def latest() -> str:
|
|
236
|
+
return shlex.join(argv())
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def install() -> str:
|
|
240
|
+
return shlex.join(("uv", "tool", "install", "--python", TOOL_PYTHON, PACKAGE))
|