Advertisement
LinuxAIO

AppAgenda.py

Oct 21st, 2018
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.79 KB | None | 0 0
  1. import sys
  2. import pickle
  3. from functools import total_ordering
  4. from pdb import set_trace
  5.  
  6.  
  7. def nulo_o_vacio(texto):
  8.     return texto == None or not texto.strip()
  9.  
  10.  
  11. def valida_franja_entero(pregunta, inicio, fin, estandar=None):
  12.     while True:
  13.         try:
  14.             entrada = input(pregunta)
  15.             if nulo_o_vacio(entrada) and estandar != None:
  16.                 entrada = estandar
  17.             valor = int(entrada)
  18.             if inicio <= valor <= fin:
  19.                 return(valor)
  20.         except ValueError:
  21.             print("Valor inválido, favor digitar entre %d y %d" % (inicio, fin))
  22.  
  23.  
  24. def valida_franja_entero_o_blanco(pregunta, inicio, fin):
  25.     while True:
  26.         try:
  27.             entrada = input(pregunta)
  28.             if nulo_o_vacio(entrada):
  29.                 return None
  30.             valor = int(entrada)
  31.             if inicio <= valor <= fin:
  32.                 return(valor)
  33.         except ValueError:
  34.             print("Valor inválido, favor digitar entre %d y %d" % (inicio, fin))
  35.  
  36.  
  37. class ListaUnica:
  38.     def __init__(self, elem_class):
  39.         self.lista = []
  40.         self.elem_class = elem_class
  41.  
  42.     def __len__(self):
  43.         return len(self.lista)
  44.  
  45.     def __iter__(self):
  46.         return iter(self.lista)
  47.  
  48.     def __getitem__(self, p):
  49.         return self.lista[p]
  50.  
  51.     def indiceValido(self, i):
  52.         return i >= 0 and i < len(self.lista)
  53.  
  54.     def adiciona(self, elem):
  55.         if self.investigacion(elem) == -1:
  56.             self.lista.append(elem)
  57.  
  58.     def remove(self, elem):
  59.         self.lista.remove(elem)
  60.  
  61.     def investigacion(self, elem):
  62.         self.verifica_tipo(elem)
  63.         try:
  64.             return self.lista.index(elem)
  65.         except ValueError:
  66.             return -1
  67.  
  68.     def verifica_tipo(self, elem):
  69.         if type(elem) != self.elem_class:
  70.             raise TypeError("Tipo inválido")
  71.  
  72.     def ordena(self, clave=None):
  73.         self.lista.sort(key=clave)
  74.  
  75.  
  76. @total_ordering
  77. class Nombre:
  78.     def __init__(self, nombre):
  79.         self.nombre = nombre
  80.  
  81.     def __str__(self):
  82.         return self.nombre
  83.  
  84.     def __repr__(self):
  85.         return "<Clase {3} en 0x{0:x} Nombre: {1} Clave: {2}>".format(
  86.             id(self), self.__nombre, self.__clave, type(self).__name__)
  87.  
  88.     def __eq__(self, otro):
  89.         return self.nombre == otro.nombre
  90.  
  91.     def __lt__(self, otro):
  92.         return self.nombre < otro.nombre
  93.  
  94.     @property
  95.     def nombre(self):
  96.         return self.__nombre
  97.  
  98.     @nombre.setter
  99.     def nombre(self, valor):
  100.         if nulo_o_vacio(valor):
  101.             raise ValueError("Nombre no puede ser nulo ni en blanco")
  102.         self.__nombre = valor
  103.         self.__clave = Nombre.CreaClave(valor)
  104.  
  105.     @property
  106.     def clave(self):
  107.         return self.__clave
  108.  
  109.     @staticmethod
  110.     def CreaClave(nombre):
  111.         return nombre.strip().lower()
  112.  
  113.  
  114. @total_ordering
  115. class TipoTelefono:
  116.         def __init__(self, tipo):
  117.             self.tipo = tipo
  118.  
  119.         def __str__(self):
  120.             return "({0})".format(self.tipo)
  121.  
  122.         def __eq__(self, otro):
  123.             if otro is None:
  124.                 return False
  125.             return self.tipo == otro.tipo
  126.  
  127.         def __lt__(self, otro):
  128.             return self.tipo < otro.tipo
  129.  
  130.  
  131. class Telefono:
  132.     def __init__(self, numero, tipo=None):
  133.         self.numero = numero
  134.         self.tipo = tipo
  135.  
  136.     def __str__(self):
  137.         if self.tipo!=None:
  138.             tipo = self.tipo
  139.         else:
  140.             tipo = ""
  141.         return "{0} {1}".format(self.numero, tipo)
  142.  
  143.     def __eq__(self, otro):
  144.         return (self.numero == otro.numero and ((self.tipo == otro.tipo) or (self.tipo == None or otro.tipo == None))
  145.  
  146.     @property
  147.     def número(self):
  148.         return self.__número
  149.  
  150.     @número.setter
  151.     def número(self, valor):
  152.         if nulo_o_vacio(valor):
  153.             raise ValueError("Número no puede ser None o en blanco")
  154.         self.__número = valor
  155.  
  156.  
  157. class Telefonos(ListaUnica):
  158.     def __init__(self):
  159.         super().__init__(Telefono)
  160.  
  161.  
  162. class TiposTelefono(ListaUnica):
  163.     def __init__(self):
  164.         super().__init__(TipoTelefono)
  165.  
  166.  
  167. class DatoAgenda:
  168.     def __init__(self, nombre):
  169.         self.nombre = nombre
  170.         self.telefonos = Telefonos()
  171.  
  172.     @property
  173.     def nombre(self):
  174.         return self.__nombre
  175.  
  176.     @nombre.setter
  177.     def nombre(self, valor):
  178.         if type(valor) != Nombre:
  179.             raise TypeError("nombre debe ser una instancia de la clase Nombre")
  180.         self.__nombre = valor
  181.  
  182.     def investigacionTelefono(self, telefono):
  183.         posicion = self.telefonos.investigacion(Telefono(telefono))
  184.         if posicion == -1:
  185.             return None
  186.         else:
  187.             return self.telefonos[posicion]
  188.  
  189.  
  190. class Agenda(ListaUnica):
  191.     def __init__(self):
  192.         super().__init__(DatoAgenda)
  193.         self.tiposTelefono = TiposTelefono()
  194.  
  195.     def adicionaTipo(self, tipo):
  196.         self.tiposTelefono.adiciona(TipoTelefono(tipo))
  197.  
  198.     def investigacionNombre(self, nombre):
  199.         if type(nombre) == str:
  200.             nombre = Nombre(nombre)
  201.         for datos in self.lista:
  202.             if datos.nombre == nombre:
  203.                 return datos
  204.             else:
  205.                 return None
  206.  
  207.     def ordena(self):
  208.         super().ordena(lambda dato: str(dato.nombre))
  209.  
  210.  
  211. class Menu:
  212.     def __init__(self):
  213.         self.opciones = [["Salir", None]]
  214.  
  215.     def adicionaopcion(self, nombre, funcion):
  216.         self.opciones.append([nombre, funcion])
  217.  
  218.     def exhibe(self):
  219.         print("====")
  220.         print("Menú")
  221.         print("====\n")
  222.         for i, opcion in enumerate(self.opciones):
  223.             print("[{0}] - {1}".format(i, opcion[0]))
  224.         print()
  225.  
  226.     def ejecute(self):
  227.         while True:
  228.             self.exhibe()
  229.             elija = valida_franja_entero("Elija una opción: ",
  230.                                          0, len(self.opciones) - 1)
  231.             if elija == 0:
  232.                 break
  233.             self.opciones[elija][1]()
  234.  
  235.  
  236. class AppAgenda:
  237.     @staticmethod
  238.     def pide_nombre():
  239.         return(input("Nombre: "))
  240.  
  241.     @staticmethod
  242.     def pide_telefono():
  243.         return(input("Teléfono: "))
  244.  
  245.     @staticmethod
  246.     def muestra_datos(datos):
  247.         print("Nombre: %s" % datos.nombre)
  248.         for telefono in datos.telefonos:
  249.             print("Teléfono: %s" % telefono)
  250.         print()
  251.  
  252.     @staticmethod
  253.     def muestra_datos_telefono(datos):
  254.         print("Nombre: %s" % datos.nombre)
  255.         for i, telefono in enumerate(datos.telefonos):
  256.             print("{0} - Teléfono: {1}".format(i, telefono))
  257.         print()
  258.  
  259.     @staticmethod
  260.     def pide_nombre_archivo():
  261.         return(input("Nombre del archivo: "))
  262.  
  263.     def __init__(self):
  264.         self.agenda = Agenda()
  265.         self.agenda.adicionaTipo("Celular")
  266.         self.agenda.adicionaTipo("Residencia")
  267.         self.agenda.adicionaTipo("Trabajo")
  268.         self.agenda.adicionaTipo("Fax")
  269.         self.menu = Menu()
  270.         self.menu.adicionaopcion("Nuevo", self.nuevo)
  271.         self.menu.adicionaopcion("Altera", self.altera)
  272.         self.menu.adicionaopcion("Borra", self.borra)
  273.         self.menu.adicionaopcion("Lista", self.lista)
  274.         self.menu.adicionaopcion("Graba", self.graba)
  275.         self.menu.adicionaopcion("Lee", self.lee)
  276.         self.menu.adicionaopcion("Ordena", self.ordena)
  277.         self.ultimo_nombre = None
  278.  
  279.     def pide_tipo_telefono(self, estandar=None):
  280.         for i, tipo in enumerate(self.agenda.tiposTelefono):
  281.             print(" {0} - {1} ".format(i, tipo), end=None)
  282.         t = valida_franja_entero("Tipo: ", 0, len(self.agenda.tiposTelefono) - 1, estandar)
  283.         return self.agenda.tiposTelefono[t]
  284.  
  285.     def investigacion(self, nombre):
  286.         dato = self.agenda.investigacionNombre(nombre)
  287.         return dato
  288.  
  289.     def nuevo(self):
  290.         nuevo = AppAgenda.pide_nombre()
  291.         if nulo_o_vacio(nuevo):
  292.             return
  293.         nombre = Nombre(nuevo)
  294.         if self.investigacion(nombre) != None:
  295.             print("¡Nombre ya existe!")
  296.             return
  297.         registro = DatoAgenda(nombre)
  298.         self.menu_telefonos(registro)
  299.         self.agenda.adiciona(registro)
  300.  
  301.     def borra(self):
  302.         if len(self.agenda) == 0:
  303.             print("Agenda vacía, nada a borrar")
  304.         nombre = AppAgenda.pide_nombre()
  305.         if(nulo_o_vacio(nombre)):
  306.             return
  307.         p = self.investigacion(nombre)
  308.         if p != None:
  309.             self.agenda.remove(p)
  310.             print("Borrado. La agenda ahora tiene solo: %d registros" % len(self.agenda))
  311.         else:
  312.             print("Nombre no encontrado.")
  313.  
  314.     def altera(self):
  315.         if len(self.agenda) == 0:
  316.             print("Agenda vacía, nada a alterar")
  317.         nombre = AppAgenda.pide_nombre()
  318.         if(nulo_o_vacio(nombre)):
  319.             return
  320.         p = self.investigacion(nombre)
  321.         if p != None:
  322.             print("\nEncontrado:\n")
  323.         AppAgenda.muestra_datos(p)
  324.         print("Digite enter en caso de que no quiera alterar el nombre")
  325.         nuevo = AppAgenda.pide_nombre()
  326.         if not nulo_o_vacio(nuevo):
  327.             p.nombre = Nombre(nuevo)
  328.             self.menu_telefonos(p)
  329.         else:
  330.             print("¡Nombre no encontrado!")
  331.  
  332.     def menu_telefonos(self, datos):
  333.         while True:
  334.             print("\nEditando teléfonos\n")
  335.             AppAgenda.muestra_datos_telefono(datos)
  336.             if(len(datos.telefonos)>0):
  337.                 print("\n[A] - alterar\n[D] - borrar\n", end="")
  338.             print("[N] - nuevo\n[S] - salir\n")
  339.             operacion = input("Elija una operación: ")
  340.             operacion = operacion.lower()
  341.             if operacion not in ["a", "d", "n", "s"]:
  342.                 print("Operación inválida. Digite A, D, N o S")
  343.                 continue
  344.             if operacion == 'a' and len(datos.telefonos)>0:
  345.                 self.altera_telefonos(datos)
  346.             elif operacion == 'd' and len(datos.telefonos)>0:
  347.                 self.borra_telefono(datos)
  348.             elif operacion == 'n':
  349.                 self.nuevo_telefono(datos)
  350.             elif operacion == "s":
  351.                 break
  352.  
  353.     def nuevo_telefono(self, datos):
  354.         telefono = AppAgenda.pide_telefono()
  355.         if nulo_o_vacio(telefono):
  356.             return
  357.         if datos.investigacionTelefono(telefono) != None:
  358.             print("Teléfono ya existe")
  359.         tipo = self.pide_tipo_telefono()
  360.         datos.telefonos.adiciona(Telefono(telefono, tipo))
  361.  
  362.     def borra_telefono(self, datos):
  363.         t = valida_franja_entero_o_blanco(
  364.             "Digite la posición del número a borrar, enter para salir: ",
  365.             0, len(datos.telefonos) - 1)
  366.         if t == None:
  367.             return
  368.         datos.telefonos.remove(datos.telefonos[t])
  369.  
  370.     def altera_telefonos(self, datos):
  371.         t = valida_franja_entero_o_blanco(
  372.             "Digite la posición del número a alterar, enter para salir: ",
  373.             0, len(datos.telefonos) - 1)
  374.         if t == None:
  375.             return
  376.         telefono = datos.telefonos[t]
  377.         print("Teléfono: %s" % telefono)
  378.         print("Digite enter en caso de que no quiera alterar el número")
  379.         nuevotelefono = AppAgenda.pide_telefono()
  380.         if not nulo_o_vacio(nuevotelefono):
  381.             telefono.numero = nuevotelefono
  382.         print("Digite enter en caso de que no quiera alterar el tipo")
  383.         telefono.tipo = self.pide_tipo_telefono(
  384.             self.agenda.tiposTelefono.investigacion(telefono.tipo))
  385.  
  386.     def lista(self):
  387.         print("\nAgenda")
  388.         print("-" * 60)
  389.         for e in self.agenda:
  390.             AppAgenda.muestra_datos(e)
  391.         print("-" * 60)
  392.  
  393.     def lee(self, nombre_archivo=None):
  394.         if nombre_archivo == None:
  395.             nombre_archivo = AppAgenda.pide_nombre_archivo()
  396.         if nulo_o_vacio(nombre_archivo):
  397.             return
  398.         with open(nombre_archivo, "rb") as archivo:
  399.             self.agenda = pickle.load(archivo)
  400.         self.ultimo_nombre = nombre_archivo
  401.  
  402.     def ordena(self):
  403.         self.agenda.ordena()
  404.         print("\nAgenda ordenada\n")
  405.  
  406.     def graba(self):
  407.         if self.ultimo_nombre != None:
  408.             print("Último nombre utilizado fue '%s'" % self.ultimo_nombre)
  409.             print("Digite enter en caso de que quiera utilizar el mismo nombre")
  410.         nombre_archivo = AppAgenda.pide_nombre_archivo()
  411.         if nulo_o_vacio(nombre_archivo):
  412.             if self.ultimo_nombre != None:
  413.                 nombre_archivo = self.ultimo_nombre
  414.             else:
  415.                 return
  416.         with open(nombre_archivo, "wb") as archivo:
  417.             pickle.dump(self.agenda, archivo)
  418.  
  419.     def ejecute(self):
  420.         self.menu.ejecute()
  421.  
  422. if __name__ == "__main__":
  423.     app = AppAgenda()
  424.     if len(sys.argv) > 1:
  425.         app.lee(sys.argv[1])
  426.     app.ejecute()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement