Files
tzzr-cli/tzzr/models.py
ARCHITECT 0327df5277 TZZR CLI v0.1.0 - Herramienta de gestión sistema TZZR
- Comandos: search, list, tree, copy, info, add, grupos, stats
- Conexión SSH a HST (72.62.2.84)
- Estructura autoreferenciada (sin cat/subcat)
- Grupos válidos: hst, spe, vsn, vue, flg

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 15:07:26 +00:00

155 lines
4.5 KiB
Python

"""
Modelos de datos para TZZR
Representa la tabla hst con su estructura:
- id: integer (PK)
- ref: referencia corta
- h_maestro: referencia única completa
- grupo: hst, spe, hsu, msu, cat, subcat
- nombre_es, nombre_en: nombres
- padre_h_maestro: referencia al padre
- rootref, descripcion, imagen_url, mrf
"""
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional, List
@dataclass
class Hashtag:
"""Representa un hashtag en la tabla hst"""
id: int
ref: str
h_maestro: str
grupo: str
nombre_es: Optional[str] = None
nombre_en: Optional[str] = None
padre_h_maestro: Optional[str] = None
rootref: Optional[str] = None
descripcion: Optional[str] = None
imagen_url: Optional[str] = None
mrf: Optional[str] = None
created_at: Optional[datetime] = None
children: List["Hashtag"] = field(default_factory=list)
@classmethod
def from_dict(cls, data: dict) -> "Hashtag":
"""Crea un Hashtag desde un diccionario"""
return cls(
id=data.get("id"),
ref=data.get("ref", ""),
h_maestro=data.get("h_maestro", ""),
grupo=data.get("grupo", ""),
nombre_es=data.get("nombre_es"),
nombre_en=data.get("nombre_en"),
padre_h_maestro=data.get("padre_h_maestro"),
rootref=data.get("rootref"),
descripcion=data.get("descripcion"),
imagen_url=data.get("imagen_url"),
mrf=data.get("mrf"),
created_at=data.get("created_at"),
)
def to_dict(self) -> dict:
"""Convierte a diccionario"""
return {
"id": self.id,
"ref": self.ref,
"h_maestro": self.h_maestro,
"grupo": self.grupo,
"nombre_es": self.nombre_es,
"nombre_en": self.nombre_en,
"padre_h_maestro": self.padre_h_maestro,
"rootref": self.rootref,
"descripcion": self.descripcion,
"imagen_url": self.imagen_url,
"mrf": self.mrf,
"created_at": self.created_at,
}
@property
def display_name(self) -> str:
"""Nombre para mostrar"""
name = self.nombre_es or self.ref
return f"{self.ref}: {name}"
def __str__(self) -> str:
return self.display_name
@dataclass
class TreeNode:
"""Nodo de árbol para visualización jerárquica"""
hashtag: Hashtag
depth: int = 0
is_last: bool = False
parent_is_last: List[bool] = field(default_factory=list)
@property
def prefix(self) -> str:
"""Genera el prefijo visual para el árbol"""
if self.depth == 0:
return ""
parts = []
for is_last in self.parent_is_last[:-1]:
parts.append(" " if is_last else "| ")
if self.parent_is_last:
parts.append("+-- " if self.is_last else "|-- ")
return "".join(parts)
def __str__(self) -> str:
return f"{self.prefix}{self.hashtag.display_name}"
def build_tree(hashtags: List[dict], root_h_maestro: str) -> List[TreeNode]:
"""
Construye una lista de TreeNodes para visualización
Args:
hashtags: Lista de diccionarios con datos de hashtags
root_h_maestro: h_maestro del nodo raíz
"""
# Convertir a Hashtags
items = [Hashtag.from_dict(h) for h in hashtags]
# Crear índice por h_maestro
by_maestro = {h.h_maestro: h for h in items}
# Encontrar hijos de cada nodo
children_map = {}
for h in items:
if h.padre_h_maestro:
if h.padre_h_maestro not in children_map:
children_map[h.padre_h_maestro] = []
children_map[h.padre_h_maestro].append(h)
# Construir lista de nodos
nodes = []
def add_node(hashtag: Hashtag, depth: int, parent_is_last: List[bool]):
children = children_map.get(hashtag.h_maestro, [])
children.sort(key=lambda x: x.nombre_es or x.ref)
for i, child in enumerate(children):
is_last = i == len(children) - 1
node = TreeNode(
hashtag=child,
depth=depth,
is_last=is_last,
parent_is_last=parent_is_last + [is_last]
)
nodes.append(node)
add_node(child, depth + 1, parent_is_last + [is_last])
# Agregar raíz
if root_h_maestro in by_maestro:
root = by_maestro[root_h_maestro]
nodes.append(TreeNode(hashtag=root, depth=0, is_last=True, parent_is_last=[]))
add_node(root, 1, [True])
return nodes