from __future__ import annotations import os, json, sys from pathlib import Path def get_dropbox_root(prefer: str = "personal") -> Path: """ Return the Dropbox root folder as a Path. prefer: "personal" or "business" if both are configured. You can override via env var DROPBOX_ROOT. """ # 0) explicit override env_override = os.environ.get("DROPBOX_ROOT") if env_override: p = Path(env_override).expanduser() if p.exists(): return p # 1) official info.json locations candidates = [] if sys.platform.startswith("win"): appdata = os.environ.get("APPDATA") localappdata = os.environ.get("LOCALAPPDATA") if appdata: candidates.append(Path(appdata) / "Dropbox" / "info.json") if localappdata:candidates.append(Path(localappdata) / "Dropbox" / "info.json") else: candidates.append(Path.home() / ".dropbox" / "info.json") for jpath in candidates: try: if jpath.is_file(): data = json.loads(jpath.read_text(encoding="utf-8")) # data might have "personal" and/or "business" choices = [] if "personal" in data and "path" in data["personal"]: choices.append(("personal", Path(data["personal"]["path"]))) if "business" in data and "path" in data["business"]: choices.append(("business", Path(data["business"]["path"]))) if choices: # pick preferred, else first available for kind, p in choices: if kind == prefer and p.exists(): return p # fallback to any existing for _, p in choices: if p.exists(): return p except Exception: pass # ignore and try fallbacks # 2) common defaults as a last resort guesses = [ Path.home() / "Dropbox", Path.home() / "Dropbox (Personal)", Path.home() / "Dropbox (Business)", ] for p in guesses: if p.exists(): return p raise FileNotFoundError( "Could not locate Dropbox root. Set DROPBOX_ROOT env var to override." ) print (get_dropbox_root("personal"))