mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 00:27:01 +01:00
`requires-python` and the CI pin already said 3.14, but ruff, mypy and pylint were still grading `meta/` against 3.10 -- three tools judging an interpreter nothing runs any more, and ruff withholding the pyupgrade fixes that only become safe at the newer target. `pin_ci_python.py` rewrites these three knobs. What the stale target was hiding: `datetime.timezone.utc` where `datetime.UTC` is now correct (UP017), and ruff's stable formatter applying PEP 758 -- `except (A, B):` becomes `except A, B:`. That makes the source 3.14-only at the syntax level, which is what `requires-python = ">=3.14"` already promised; kuhy chose it deliberately over holding ruff a release back (2026-08-29). Also drops a comment in `wsg_grabber/models.py` that the bump makes false: it explained why the file used ``str, Enum`` instead of ``StrEnum`` under mypy at 3.10, sitting directly above a ``class Verdict(StrEnum)`` that had already stopped obeying it. ruff, ruff-format, mypy --strict and pylint all clean at the new target. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SfnJmxxsZ534AKk16rC2Gr
105 lines
3.1 KiB
Python
105 lines
3.1 KiB
Python
"""Find VS Code installations and read and write their configuration.
|
|
|
|
Settings are JSON with Comments, which the stdlib cannot parse, so this
|
|
module carries a small JSONC reader. Every write is preceded by a backup.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
import json
|
|
from pathlib import Path
|
|
import re
|
|
import shutil
|
|
|
|
from python_pkg.vscode_optimizer._types import _Opt, _Variant
|
|
|
|
|
|
def _discover_variants() -> list[_Variant]:
|
|
"""Find all installed VS Code variants."""
|
|
cfg = Path.home() / ".config"
|
|
cands = [
|
|
("VS Code (stable)", "Code", "code-flags.conf", "code"),
|
|
(
|
|
"VS Code Insiders",
|
|
"Code - Insiders",
|
|
"code-insiders-flags.conf",
|
|
"code-insiders",
|
|
),
|
|
("VSCodium", "VSCodium", "vscodium-flags.conf", "codium"),
|
|
]
|
|
found: list[_Variant] = []
|
|
for name, dir_name, flags_name, binary in cands:
|
|
sp = cfg / dir_name / "User" / "settings.json"
|
|
fp = cfg / flags_name
|
|
if sp.exists() or shutil.which(binary):
|
|
found.append(_Variant(name, sp, fp, binary))
|
|
return found
|
|
|
|
|
|
def _parse_jsonc(text: str) -> dict[str, object]:
|
|
"""Parse JSON with Comments (JSONC) used by VS Code."""
|
|
out: list[str] = []
|
|
i, n = 0, len(text)
|
|
while i < n:
|
|
ch = text[i]
|
|
if ch == '"':
|
|
j = i + 1
|
|
while j < n:
|
|
if text[j] == "\\":
|
|
j += 2
|
|
continue
|
|
if text[j] == '"':
|
|
j += 1
|
|
break
|
|
j += 1
|
|
out.append(text[i:j])
|
|
i = j
|
|
elif ch == "/" and i + 1 < n and text[i + 1] == "/":
|
|
while i < n and text[i] != "\n":
|
|
i += 1
|
|
elif ch == "/" and i + 1 < n and text[i + 1] == "*":
|
|
end = text.find("*/", i + 2)
|
|
i = end + 2 if end != -1 else n
|
|
else:
|
|
out.append(ch)
|
|
i += 1
|
|
cleaned = re.sub(r",(\s*[}\]])", r"\1", "".join(out))
|
|
if not cleaned.strip():
|
|
return {}
|
|
parsed: dict[str, object] = json.loads(cleaned)
|
|
return parsed
|
|
|
|
|
|
def _backup(path: Path) -> Path | None:
|
|
if not path.exists():
|
|
return None
|
|
ts = datetime.now(tz=UTC).strftime("%Y%m%dT%H%M%SZ")
|
|
dst = path.with_suffix(f".{ts}.bak")
|
|
shutil.copy2(path, dst)
|
|
return dst
|
|
|
|
|
|
def _read_settings(path: Path) -> dict[str, object]:
|
|
return _parse_jsonc(path.read_text()) if path.exists() else {}
|
|
|
|
|
|
def _write_settings(path: Path, current: dict[str, object], opts: list[_Opt]) -> None:
|
|
merged = {**current, **{o.key: o.value for o in opts}}
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(json.dumps(merged, indent=4, ensure_ascii=False) + "\n")
|
|
|
|
|
|
def _read_flags(path: Path) -> list[str]:
|
|
if not path.exists():
|
|
return []
|
|
return [
|
|
ln.strip()
|
|
for ln in path.read_text().splitlines()
|
|
if ln.strip() and not ln.strip().startswith("#")
|
|
]
|
|
|
|
|
|
def _write_flags(path: Path, flags: list[str]) -> None:
|
|
path.write_text("\n".join(flags) + "\n")
|