Coverage for qpdk / install_tech.py: 22%
27 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-14 10:27 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-14 10:27 +0000
1"""Symlink tech to klayout."""
3import shutil
4import sys
5from pathlib import Path
7from qpdk.logger import logger
10def remove_path_or_dir(dest: Path) -> None:
11 """Remove a path or directory."""
12 if not dest.exists():
13 raise FileNotFoundError(f"Path does not exist: {dest}")
15 if dest.is_dir():
16 shutil.rmtree(dest)
17 else:
18 dest.unlink()
21def make_link(src: str | Path, dest: str | Path, overwrite: bool = True) -> None:
22 """Make a symbolic link from src to dest."""
23 src, dest = Path(src), Path(dest)
24 if not src.exists():
25 raise FileNotFoundError(f"{src} does not exist")
27 if dest.exists() and not overwrite:
28 logger.warning("{} already exists", dest)
29 return
30 if dest.exists() or dest.is_symlink():
31 logger.info("removing {} already installed", dest)
32 remove_path_or_dir(dest)
33 try:
34 Path.symlink_to(src, dest, target_is_directory=True)
35 except OSError:
36 shutil.copytree(src, dest)
37 logger.info("link made:")
38 logger.info("From: {}", src)
39 logger.info("To: {}", dest)
42if __name__ == "__main__":
43 klayout_folder = "KLayout" if sys.platform == "win32" else ".klayout"
44 home = Path.home()
45 dest_folder = home / klayout_folder / "tech"
46 dest_folder.mkdir(exist_ok=True, parents=True)
47 cwd = Path(__file__).resolve().parent
48 repo_root = cwd.parent
49 src = repo_root / "qpdk" / "klayout"
50 dest = dest_folder / "qpdk"
51 make_link(src=src, dest=dest)