feat(infra): auto-commit con 88 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""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")
|
||||
Reference in New Issue
Block a user