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:
2026-06-15 01:33:35 +02:00
parent e1e9bb7499
commit a90b7443e4
20 changed files with 1855 additions and 2 deletions
@@ -0,0 +1,151 @@
"""Desregistra un vault de la app de escritorio Obsidian.
Quita la entrada del vault de la clave "vaults" del archivo de configuracion de la
app (~/.config/obsidian/obsidian.json). NO borra la carpeta del vault en disco: solo
hace que la app Obsidian deje de conocerlo. Preserva el resto del JSON intacto.
Funcion impura: lee y escribe la config de la app y hace backup .bak antes de
sobreescribir.
"""
import json
import os
import shutil
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.
Devuelve la ruta del backup creado (cadena vacia si no habia archivo previo).
"""
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 unregister_obsidian_vault(vault_ref: str, config_path: str = "") -> dict:
"""Quita un vault de la lista de vaults conocidos por la app Obsidian.
Args:
vault_ref: id exacto de la entrada (hex de 16 chars) O una ruta al vault.
Si parece una ruta se normaliza a absoluta y se compara con "path".
Primero se intenta match por id; si no hay, por path.
config_path: ruta al obsidian.json de la app. Vacio -> default
~/.config/obsidian/obsidian.json.
Returns:
dict con:
- removed: True si se quito una entrada, False si no se encontro.
- id: id de la entrada quitada ("" si no se encontro).
- path: path de la entrada quitada ("" si no se encontro).
- config_path: ruta del obsidian.json usado.
- backup_path: ruta del backup .bak escrito ("" si no se escribio nada).
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()
not_found = {
"removed": False,
"id": "",
"path": "",
"config_path": cfg_path,
"backup_path": "",
}
if not os.path.exists(cfg_path):
return not_found
data = _load_config(cfg_path)
vaults = data["vaults"]
target_id = None
# 1) Match directo por id.
if vault_ref in vaults:
target_id = vault_ref
else:
# 2) Match por path normalizado.
abs_ref = os.path.abspath(os.path.expanduser(vault_ref))
for vid, entry in vaults.items():
if isinstance(entry, dict) and entry.get("path") == abs_ref:
target_id = vid
break
if target_id is None:
return not_found
removed_path = ""
entry = vaults.get(target_id)
if isinstance(entry, dict):
removed_path = entry.get("path", "")
del vaults[target_id]
backup_path = _save_config(cfg_path, data)
return {
"removed": True,
"id": target_id,
"path": removed_path,
"config_path": cfg_path,
"backup_path": backup_path,
}
if __name__ == "__main__":
import tempfile
import time
tmp = tempfile.mkdtemp()
cfg = os.path.join(tmp, "obsidian.json")
payload = {
"extra": "preservar",
"vaults": {
"aaaaaaaaaaaaaaaa": {"path": "/a/Alpha", "ts": int(time.time() * 1000), "open": True},
"bbbbbbbbbbbbbbbb": {"path": "/b/Beta", "ts": int(time.time() * 1000), "open": False},
},
}
with open(cfg, "w", encoding="utf-8") as f:
json.dump(payload, f)
r = unregister_obsidian_vault("/a/Alpha", config_path=cfg)
assert r["removed"] is True and r["id"] == "aaaaaaaaaaaaaaaa", r
r2 = unregister_obsidian_vault("bbbbbbbbbbbbbbbb", config_path=cfg)
assert r2["removed"] is True and r2["path"] == "/b/Beta", r2
with open(cfg, "r", encoding="utf-8") as f:
final = json.load(f)
assert final["extra"] == "preservar", final
assert final["vaults"] == {}, final
assert unregister_obsidian_vault("nope", config_path=cfg)["removed"] is False
print("unregister_obsidian_vault smoke OK")