Files
fn_registry/python/functions/obsidian/read_obsidian_note.py
T
egutierrez eb8dbf66a1 feat(infra): auto-commit con 88 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-11 00:16:46 +02:00

85 lines
2.9 KiB
Python

"""Lee una nota de Obsidian (.md) desde disco y la descompone en sus partes.
Compone funciones puras del grupo obsidian: parse_obsidian_frontmatter y
extract_obsidian_wikilinks. Funcion impura: hace I/O de lectura de archivo.
"""
import os
from obsidian import extract_obsidian_wikilinks, parse_obsidian_frontmatter
def _normalize_tags(raw) -> list:
"""Normaliza el campo tags del frontmatter a una lista de strings.
Acepta None, un string CSV ("a, b, c") o una lista. Devuelve siempre
una lista de strings sin espacios sobrantes y sin entradas vacias.
"""
if raw is None:
return []
if isinstance(raw, str):
return [t.strip() for t in raw.split(",") if t.strip()]
if isinstance(raw, (list, tuple)):
return [str(t).strip() for t in raw if str(t).strip()]
# Cualquier otro tipo (int, etc.) -> representacion como unico tag.
return [str(raw).strip()] if str(raw).strip() else []
def read_obsidian_note(path: str) -> dict:
"""Lee una nota Markdown de Obsidian y devuelve sus partes estructuradas.
Args:
path: ruta al archivo .md a leer.
Returns:
dict con las claves:
- path: la ruta leida (tal cual fue pasada).
- frontmatter: dict con el frontmatter YAML parseado.
- body: str con el cuerpo Markdown sin el frontmatter.
- wikilinks: list con los destinos de los wikilinks [[...]] del body.
- tags: list normalizada a partir de frontmatter["tags"].
Raises:
FileNotFoundError: si el archivo no existe.
IsADirectoryError: si la ruta apunta a un directorio.
OSError: si la lectura falla por otro motivo de I/O.
"""
if not os.path.exists(path):
raise FileNotFoundError(f"obsidian note not found: {path}")
if os.path.isdir(path):
raise IsADirectoryError(f"expected a file, got a directory: {path}")
with open(path, "r", encoding="utf-8") as f:
content = f.read()
parsed = parse_obsidian_frontmatter(content)
frontmatter = parsed.get("frontmatter", {}) or {}
body = parsed.get("body", "") or ""
wikilinks = extract_obsidian_wikilinks(body)
tags = _normalize_tags(frontmatter.get("tags"))
return {
"path": path,
"frontmatter": frontmatter,
"body": body,
"wikilinks": wikilinks,
"tags": tags,
}
if __name__ == "__main__":
import tempfile
sample = "---\ntitle: Demo\ntags: [a, b]\n---\n\nHola [[Otra Nota]] y [[Tercera]].\n"
fd, tmp = tempfile.mkstemp(suffix=".md")
os.close(fd)
with open(tmp, "w", encoding="utf-8") as f:
f.write(sample)
note = read_obsidian_note(tmp)
assert note["frontmatter"].get("title") == "Demo", note["frontmatter"]
assert note["tags"] == ["a", "b"], note["tags"]
assert "Otra Nota" in note["wikilinks"], note["wikilinks"]
os.remove(tmp)
print("read_obsidian_note smoke OK")