import contextlib import dataclasses import plistlib import sqlite3 import subprocess from pathlib import Path from typing import Optional DB_PATH = Path("~/Library/Application Support/Dock/desktoppicture.db").expanduser() @dataclasses.dataclass class SpaceInfo: uuid: str image_path: Optional[Path] data_id: Optional[Path] @contextlib.contextmanager def get_connection() -> sqlite3.Connection: con = sqlite3.connect(str(DB_PATH)) con.row_factory = sqlite3.Row yield con con.close() def get_current_wallpapers() -> list[SpaceInfo]: sql = """ select distinct s.space_uuid, pr.key, d.rowid, d.value from preferences pr left join payload d on d.rowid = pr.data_id left join pictures p on p.rowid = pr.picture_id inner join spaces s on s.rowid = p.space_id where key = 1 order by space_uuid, key """ spaces = list_spaces() with get_connection() as con: cur = con.execute(sql) space_props = {} for i, row in enumerate(cur): space_uuid = row["space_uuid"] data_id = row["rowid"] image_path = row["value"] if image_path: image_path = Path(image_path).expanduser() space_props[space_uuid] = SpaceInfo(uuid=space_uuid, image_path=image_path, data_id=data_id) return [space_props.get(id, SpaceInfo(uuid="", image_path=None, data_id=None)) for id in spaces] def read_plist(plist_path): with plist_path.open("rb") as f: return plistlib.load(f) def list_spaces(): spaces_plist_path = Path("~/Library/Preferences/com.apple.spaces.plist").expanduser() data = read_plist(spaces_plist_path) spaces = data["SpacesDisplayConfiguration"]["Management Data"]["Monitors"][0]["Spaces"] return [s["uuid"] for s in spaces] def set_wallpaper(image_path: Path): script = f'tell application "Finder" to set desktop picture to "{image_path.expanduser().resolve()}" as POSIX file' subprocess.run(["osascript", "-e", script], check=True) if __name__ == "__main__": pass