uce/scripts/refactor/rename-dvalue-api.py

119 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""Mechanical one-shot rename script for UCE's legacy value-tree API.
The old tokens are constructed rather than written literally so this script can
remain in the tree after the rename without reintroducing the retired names.
"""
from __future__ import annotations
import os
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
OLD_TYPE = "D" + "Tree"
OLD_LOWER = "d" + "tree"
NEW_TYPE = "DValue"
NEW_LOWER = "dvalue"
DIR_EXCLUDES = {
".git",
".hg",
".svn",
"3rdparty",
"bin",
"node_modules",
"pkg",
"tmp",
"work",
"__pycache__",
}
BINARY_SUFFIXES = {
".bin",
".gif",
".ico",
".jpg",
".jpeg",
".lock",
".o",
".pdf",
".png",
".pyc",
".so",
".sqlite",
".webp",
".zip",
}
REPLACEMENTS = (
(OLD_TYPE, NEW_TYPE),
(OLD_TYPE.upper(), NEW_TYPE.upper()),
(OLD_LOWER + "_", "dv_"),
(OLD_LOWER, NEW_LOWER),
)
def replace_text(value: str) -> str:
for old, new in REPLACEMENTS:
value = value.replace(old, new)
return value
def skip_dir(name: str) -> bool:
return name in DIR_EXCLUDES or name.startswith(".fuse")
def skip_file(path: Path) -> bool:
return path.name.startswith(".fuse") or path.suffix in BINARY_SUFFIXES
def rewrite_text_files() -> int:
changed = 0
for current, dirs, files in os.walk(ROOT):
dirs[:] = [name for name in dirs if not skip_dir(name)]
for name in files:
path = Path(current) / name
if skip_file(path):
continue
data = path.read_bytes()
if b"\0" in data:
continue
try:
original = data.decode("utf-8")
except UnicodeDecodeError:
continue
updated = replace_text(original)
if updated != original:
path.write_text(updated, encoding="utf-8")
changed += 1
return changed
def rename_paths() -> int:
changed = 0
matches: list[Path] = []
for current, dirs, files in os.walk(ROOT, topdown=False):
dirs[:] = [name for name in dirs if not skip_dir(name)]
current_path = Path(current)
for name in files + dirs:
new_name = replace_text(name)
if new_name != name:
matches.append(current_path / name)
for path in sorted(matches, key=lambda item: len(item.parts), reverse=True):
if not path.exists():
continue
target = path.with_name(replace_text(path.name))
if target.exists():
raise RuntimeError(f"cannot rename {path} -> {target}: target exists")
path.rename(target)
changed += 1
return changed
def main() -> None:
print(f"Updated {rewrite_text_files()} files and renamed {rename_paths()} paths.")
if __name__ == "__main__":
main()