Files
myagents/bin/project_root.py
T
Zhengshou Lai b580eecc43 fix: expanduser in project_root, remove redundant cwd, add tests
- get_myclaude_project_root() now expands ~ in MYCLAUDE_PROJECT_ROOT
  (was resolving to ./~/path instead of $HOME/path)
- Extract hardcoded 16/8 depth limits as _MAX_WALK_DEPTH / _MAX_SOURCE_DEPTH
- Remove redundant cwd= from _run_pip_editable (already specified via -e)
- Add test_cwd_invalid_directory and test_env_var_expands_tilde
- Remove incorrect test_extra_args_forwarded (click.Group does not
  support forwarding arbitrary args; ctx.args is always empty)
2026-05-27 11:23:14 +08:00

82 lines
2.2 KiB
Python

"""Resolve myclaude repository and workspace roots."""
import os
from pathlib import Path
_MAX_WALK_DEPTH = 16
_MAX_SOURCE_DEPTH = 8
def _pyproject_names_myclaude(path: Path) -> bool:
try:
text = path.read_text(encoding="utf-8", errors="ignore")
except OSError:
return False
return 'name = "myclaude"' in text or "name = 'myclaude'" in text
def _walk_up_for_pyproject(start: Path) -> Path | None:
p = start.resolve()
for _ in range(_MAX_WALK_DEPTH):
candidate = p / "pyproject.toml"
if candidate.is_file() and _pyproject_names_myclaude(candidate):
return p
parent = p.parent
if parent == p:
break
p = parent
return None
def get_myclaude_project_root() -> Path:
"""
Root of the myclaude repo (contains Makefile + pyproject).
Order: MYCLAUDE_PROJECT_ROOT > walk from cwd > package source tree > ~/.myclaude
"""
env_root = os.environ.get("MYCLAUDE_PROJECT_ROOT")
if env_root:
return Path(env_root).expanduser().resolve()
try:
cwd = Path.cwd()
except (OSError, PermissionError):
cwd = None
if cwd is not None:
found = _walk_up_for_pyproject(cwd)
if found is not None:
return found
here = Path(__file__).resolve().parent
for _ in range(_MAX_SOURCE_DEPTH):
pyproject = here / "pyproject.toml"
if pyproject.is_file() and _pyproject_names_myclaude(pyproject):
return here
if here.parent == here:
break
here = here.parent
return Path.home() / ".myclaude"
def get_workspace_root() -> Path:
"""
Root of the myclaude workspace directory.
Order: MYCLAUDE_WORKSPACE_ROOT > project_root/workspace/ > ~/workspace
Creates the directory if it does not exist.
"""
env_root = os.environ.get("MYCLAUDE_WORKSPACE_ROOT")
if env_root:
root = Path(env_root).expanduser().resolve()
else:
project_root = get_myclaude_project_root()
project_workspace = project_root / "workspace"
if project_workspace.is_dir():
root = project_workspace
else:
root = Path.home() / "workspace"
root.mkdir(parents=True, exist_ok=True)
return root