Untitled
unknown
plain_text
21 days ago
6.1 kB
4
Indexable
Never
from enum import Enum from enum import auto as autovalue from pathlib import Path from typing import Union from kcolors.refs import BOLD, GREEN, RED from doc.help import * import os import re import pwd ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) # This is your Project Root APP_NAME = f"sbackup" # TODO: Ver como se comportan accesable_path y get_path_perms en # windows. class Action(Enum): Create = autovalue() Restore = autovalue() ShowHelpLeave = autovalue() class NormalExit(Exception): """Excepción usada para detener el programa con un código de salida 0.""" pass class NotAbsolutePath(Exception): pass class NotParentAccess(Exception): pass class NotPathAccess(Exception): pass PathStr = Union[Path, str] Number = Union[int, float] def show_help(): """Muestra el mensaje de ayuda""" print(HELP) def get_executor(): """Retorna el nombre del usuario que ejecuta el programa""" # return os.getlogin() uid = os.getuid() username = pwd.getpwuid(uid).pw_name return username def is_integer(value) -> bool: """Valida que un valor sea instancia de un int pero excluye a bool. Esta función sirve para evitar confusiones a la hora de validar enteros.""" return isinstance(value, int) and not isinstance(value, bool) def validate_gname(gname: str): """Esta función retorna una cadena con un mensaje de error descriptivo acerca de por qué un nombre de grupo es inválido. Si el grupo no es inválido entonces se retornará una cadena vacia. Función usada por: _read_target_groups de Parameters _validate_gname de GroupSettings _validate_gname de UserSettings """ e = "" if re.match(r"^[-_]", gname): first = gname[0] e += "los nombres de los grupos no pueden empezar por guiones o barrabajas" e += f" '{BGRAY}_-{END}' pero '{BGRAY}{gname}{END}' empieza por" e += f" '{BGRAY}{first}{END}'" elif re.search(r"\d$", gname): e += "los nombres de los grupos no pueden terminar en digitos pero el" e += f" grupo '{BGRAY}{gname}{END}' termina en digitos." elif re.search(r"[^a-zA-Z0-9-_]", gname): invalid_chars = re.findall(r"[^a-zA-Z0-9-_]", gname) invalid_chars_str = f"".join(f"{char}" for char in invalid_chars) invalid_chars_str = f"{BGRAY}{invalid_chars_str}{END}" e += "los nombres de los grupos solo pueden contener letras, guiones," e += f" números o barras bajas pero el grupo '{BGRAY}{gname}{END}'" e += f" contiene los siguientes carácteres inválidos:" e += f" {invalid_chars_str}" return e def accesable_path(path: Path, do_raise: bool = False): """Esta función retornará None si tenemos los permisos necesarios para leer los detalles de un path y en caso contrario retornará un objeto descriptivo de una clase derivada de Excepción. NotParentAccess: no se puede acceder a alguno de sus parents -> el usuario no tiene los permisos r/x o ambos en alguno de sus parents NotPathAccess: no se puede acceder a los detalles del path -> el usuario no tiene el permiso de r en el file/dir """ uname = get_executor() if not os.access(path.parent, os.R_OK | os.X_OK): m = f"Se ha producido un error de acceso al tratar de acceder a los" m += f" detalles de '{BGRAY}{path}{END}' debido a que" m += f" '{BGRAY}{uname}{END}' no tiene los permisos necesarios de" m += f" ({GREEN}lectura{END}{BOLD}/{END}{RED}acceso{END})" m += f" en alguno/s de sus directorios padres." if do_raise: raise NotParentAccess(m) return NotParentAccess(m) if not os.access(path, os.R_OK): m = f"Se ha producido un error al tratar de acceder a los detalles de" m += f" '{BGRAY}{path}{END}' debido a '{BGRAY}{uname}{END}' no tiene el" m += " permiso necesario de lectura sobre el." if do_raise: raise NotPathAccess(m) return NotPathAccess(m) def get_path_perms(path: Path, do_raise: bool = False) -> Union[Exception, str]: """Función que retorna los detalles de un path absoluto. 'dr-x' dir | read | - | access '.rw-' file | read | writing | - [!] Esta función debe recibir un path absoluto, si no lo recibe lanzará una excepción con el fin de avisar al programador. Excepciones que puede retornar: NotParentAccess: no se puede acceder a alguno de sus parents. -> el usuario no tiene los permisos r/x o ambos en alguno de sus parents NotPathAccess: no se puede acceder a los detalles del path. -> el usuario no tiene el permiso de r en el file/dir FileNotFoundError: el fichero/directorio no existe. Si la función no ha retornado una excepción puedes averiguar los detalles: if 'd' in perms: # si es un directorio if '.' in perms: # si es un fichero if 'r' in perms: # si hay permiso de lectura """ if not path.is_absolute(): raise NotAbsolutePath( f"[DEV] Has pasado un path no absoluto a get_path_perms:" f" '{BGRAY}{path}{END}'" ) # 1. Si no podemos acceder al fichero retornamos una excepción con el motivo # nota: si do_raise es true accesable_path lanzará la excepción. exc = accesable_path(path, do_raise) if isinstance(exc, Exception): return exc # 2. Si el fichero no existe retornamos FileNotFound if not path.exists(): m = f"El path '{BGRAY}{path}{END}' no existe" if do_raise: raise FileNotFoundError(m) return FileNotFoundError(m) # 3. Apuntamos el tipo de fichero perms = "d" if path.is_dir() else "." # 4. Apuntamos los permisos r = os.access(path, os.R_OK) w = os.access(path, os.W_OK) x = os.access(path, os.X_OK) perms += "r" if r else "-" perms += "w" if w else "-" perms += "x" if x else "-" return perms
Leave a Comment