importrandomimportstringfromcollections.abcimportGeneratorfromtimeimportsleepfromtypingimportAnyfromloguruimportloggeraslogfromwheneverimportInstant# current date for TZ=Europe/ZurichCURRENT_DATE=Instant.now().to_tz("Europe/Zurich")# timestamp (str) in format: YYYY-MM-DDTIMESTAMP_YMD=f"{str(CURRENT_DATE.year).zfill(4)}-{str(CURRENT_DATE.month).zfill(2)}-{str(CURRENT_DATE.day).zfill(2)}"# timestamp (str) in format: hh-mm-ssTIMESTAMP_HMS=f"{str(CURRENT_DATE.hour).zfill(2)}-{str(CURRENT_DATE.minute).zfill(2)}-{str(CURRENT_DATE.second).zfill(2)}"# timestamp (str) in format: YYYY-MM-DD_hh-mm-ssTIMESTAMP_FULL=f"{TIMESTAMP_YMD}T{TIMESTAMP_HMS}"
[docs]defprogress_bar(progress:float,total:float)->None:"""prints a progress bar. Args: progress: current progress to total. x/total. total: the total. """percent=int(progress/(int(total)/100))bar_length=50bar_progress=int(progress/(int(total)/bar_length))bar_texture="■"*bar_progresswhitespace_texture=" "*(bar_length-bar_progress)ifprogress==total:full_bar="■"*bar_lengthlog.info(f"\r[ PROGRESS ] ❙{full_bar}❙ 100%",end="\n")else:log.info(f"\r[ PROGRESS ] ❙{bar_texture}{whitespace_texture}❙ {percent}%",end="\r",)
[docs]defpop_dict(input_dict:dict[str,Any],keys:list[str])->dict[str,Any]:"""remove keys (and value for key) from `dict`. does not modify the input dict. does nothing if the keys don't exist in the dict. Args: input_dict: dict to remove keys from. keys: list of keys to remove. Returns: the new dict without the specified keys. """log.debug(f"cleaning dict keys={keys}")output_dict=input_dict.copy()forkeyinkeys:output_dict.pop(key,None)returnoutput_dict
[docs]defchunks(input_list:list[Any],output_length:int)->Generator[list[Any],None,None]:"""get chunks of list -> list of lists. Args: input_list: the list to split into chunks output_length: length of the chunks Yields: the chunked list of lists """foriinrange(0,len(input_list),output_length):yieldinput_list[i:i+output_length]
[docs]defget_random_letters(count:int)->str:"""get a string of random letters. Args: count: count of random characters in the returned string. Raises: ValueError: if count is smaller than 1. Returns: the string of random letters. """ifcount<=1:log.error(f"'{count}' is not a valid integer")raiseValueErrorrandom_letters=random.choices(string.ascii_letters,k=count)# noqareturn"".join(random_letters)
[docs]defwait_random(max_seconds:int)->None:"""wait random amount of seconds. Args: max_seconds: max seconds to wait """ifmax_seconds<=1:log.info("skipping wait")returnwait_time=random.randrange(1,max_seconds+1)# noqa: S311log.info(f"waiting {wait_time} seconds")sleep(wait_time)
[docs]deffix_punycode(zone_name:str)->str:"""fix punycode characters in domain name. Args: zone_name: domain/zone name Returns: fixed domain/zone name """returnzone_name.encode("idna").decode("utf8")