import re class Handle: __lexicon_string_format__ = "handle" PATTERN = re.compile( r"^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$" ) FORBIDDEN_TLDS = [ ".alt", ".arpa", ".example", ".internal", ".local", ".localhost", ".onion", ] __handle: str @property def valid(self) -> bool: return self.__handle != "handle.invalid" def __init__(self, handle: str): handle = handle.lower() if not self.PATTERN.match(handle): raise ValueError("Invalid Handle: does not match pattern") if any(handle.endswith(tld) for tld in self.FORBIDDEN_TLDS): raise ValueError("Invalid Handle: uses forbidden tld") if handle.endswith(".invalid") and not handle == "handle.invalid": raise ValueError( "Invalid Handle: '.invalid' tld may only be used with 'handle.invalid'" ) self.__handle = handle @property def labels(self) -> list[str]: return self.__handle.split(".") def __str__(self) -> str: return self.__handle def __repr__(self) -> str: return f"Handle({str(self)})"