cuando termines y verifica que esté todo subido
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
"""Registra un vault en la app de escritorio Obsidian.
|
||||
|
||||
Opera sobre el archivo de configuracion de la app (~/.config/obsidian/obsidian.json),
|
||||
NO sobre el sistema de archivos del vault. Anade (o actualiza) la entrada del vault
|
||||
en la clave "vaults" de ese JSON para que Obsidian lo conozca en su lista de vaults.
|
||||
|
||||
Funcion impura: lee y escribe el archivo de configuracion de la app y crea un
|
||||
backup .bak antes de sobreescribir. Idempotente: si ya existe una entrada con ese
|
||||
path no la duplica, solo actualiza su flag "open" si difiere.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import secrets
|
||||
import shutil
|
||||
import time
|
||||
|
||||
|
||||
def _default_config_path() -> str:
|
||||
"""Ruta por defecto del obsidian.json de la app de escritorio Obsidian."""
|
||||
return os.path.expanduser("~/.config/obsidian/obsidian.json")
|
||||
|
||||
|
||||
def _load_config(config_path: str) -> dict:
|
||||
"""Carga obsidian.json. Si no existe devuelve la estructura vacia base."""
|
||||
if not os.path.exists(config_path):
|
||||
return {"vaults": {}}
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
if not isinstance(data, dict):
|
||||
raise ValueError(f"obsidian config is not a JSON object: {config_path}")
|
||||
if "vaults" not in data or not isinstance(data.get("vaults"), dict):
|
||||
data["vaults"] = {}
|
||||
return data
|
||||
|
||||
|
||||
def _save_config(config_path: str, data: dict) -> str:
|
||||
"""Escribe obsidian.json haciendo backup .bak previo si ya existia.
|
||||
|
||||
Crea los directorios padre que falten. Devuelve la ruta del backup creado
|
||||
(cadena vacia si no habia archivo previo que respaldar).
|
||||
"""
|
||||
parent = os.path.dirname(config_path)
|
||||
if parent:
|
||||
os.makedirs(parent, exist_ok=True)
|
||||
|
||||
backup_path = ""
|
||||
if os.path.exists(config_path):
|
||||
backup_path = config_path + ".bak"
|
||||
shutil.copy2(config_path, backup_path)
|
||||
|
||||
with open(config_path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
return backup_path
|
||||
|
||||
|
||||
def register_obsidian_vault(
|
||||
vault_path: str,
|
||||
open: bool = False,
|
||||
config_path: str = "",
|
||||
) -> dict:
|
||||
"""Registra un vault en la lista de vaults de la app Obsidian.
|
||||
|
||||
Args:
|
||||
vault_path: ruta al directorio del vault. Se normaliza a ruta absoluta.
|
||||
open: valor del flag "open" de la entrada del vault (si Obsidian deberia
|
||||
abrirlo al arrancar). Por defecto False.
|
||||
config_path: ruta al obsidian.json de la app. Vacio -> default
|
||||
~/.config/obsidian/obsidian.json.
|
||||
|
||||
Returns:
|
||||
dict con:
|
||||
- id: id hex de 16 chars de la entrada (existente o recien creada).
|
||||
- path: ruta absoluta normalizada del vault.
|
||||
- registered: True si se creo una entrada nueva.
|
||||
- already: True si ya existia una entrada con ese path.
|
||||
- open: flag "open" final de la entrada.
|
||||
- config_path: ruta del obsidian.json usado.
|
||||
- backup_path: ruta del backup .bak escrito (vacio si no habia archivo previo).
|
||||
|
||||
Raises:
|
||||
ValueError: si el obsidian.json existente no es un objeto JSON valido.
|
||||
OSError: si la lectura/escritura del archivo falla por I/O.
|
||||
"""
|
||||
cfg_path = config_path or _default_config_path()
|
||||
abs_path = os.path.abspath(os.path.expanduser(vault_path))
|
||||
|
||||
data = _load_config(cfg_path)
|
||||
vaults = data["vaults"]
|
||||
|
||||
# Idempotencia: buscar entrada existente por path.
|
||||
existing_id = None
|
||||
for vid, entry in vaults.items():
|
||||
if isinstance(entry, dict) and entry.get("path") == abs_path:
|
||||
existing_id = vid
|
||||
break
|
||||
|
||||
if existing_id is not None:
|
||||
entry = vaults[existing_id]
|
||||
changed = entry.get("open") != open
|
||||
if changed:
|
||||
entry["open"] = open
|
||||
backup_path = _save_config(cfg_path, data) if changed else ""
|
||||
return {
|
||||
"id": existing_id,
|
||||
"path": abs_path,
|
||||
"registered": False,
|
||||
"already": True,
|
||||
"open": entry.get("open", open),
|
||||
"config_path": cfg_path,
|
||||
"backup_path": backup_path,
|
||||
}
|
||||
|
||||
# Entrada nueva.
|
||||
new_id = secrets.token_hex(8)
|
||||
while new_id in vaults:
|
||||
new_id = secrets.token_hex(8)
|
||||
vaults[new_id] = {
|
||||
"path": abs_path,
|
||||
"ts": int(time.time() * 1000),
|
||||
"open": open,
|
||||
}
|
||||
backup_path = _save_config(cfg_path, data)
|
||||
return {
|
||||
"id": new_id,
|
||||
"path": abs_path,
|
||||
"registered": True,
|
||||
"already": False,
|
||||
"open": open,
|
||||
"config_path": cfg_path,
|
||||
"backup_path": backup_path,
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import tempfile
|
||||
|
||||
tmp = tempfile.mkdtemp()
|
||||
cfg = os.path.join(tmp, "obsidian.json")
|
||||
vault = os.path.join(tmp, "MiVault")
|
||||
os.makedirs(vault, exist_ok=True)
|
||||
|
||||
r1 = register_obsidian_vault(vault, open=True, config_path=cfg)
|
||||
assert r1["registered"] is True and r1["already"] is False, r1
|
||||
assert r1["open"] is True, r1
|
||||
assert len(r1["id"]) == 16, r1
|
||||
|
||||
r2 = register_obsidian_vault(vault, open=True, config_path=cfg)
|
||||
assert r2["already"] is True and r2["registered"] is False, r2
|
||||
assert r2["id"] == r1["id"], (r1, r2)
|
||||
assert os.path.isfile(cfg + ".bak") is False or True # backup solo si cambio
|
||||
|
||||
print("register_obsidian_vault smoke OK")
|
||||
Reference in New Issue
Block a user