"""Collections of various python utilities."""importimportlibimportsysimportwarningsfromcollectionsimportabcdef_one_pass(iters):i=0whilei<len(iters):try:yieldnext(iters[i])exceptStopIteration:deliters[i]else:i+=1
[docs]defzip_varlen(*iterables):"""Variable length zip() function."""iters=[iter(it)foritiniterables]whileTrue:# broken when an empty tuple is given by _one_passval=tuple(_one_pass(iters))ifval:yieldvalelse:break
[docs]defgrouped(iterable,n):"""Divide an iterable in subgroups of max n elements."""returnzip_varlen(*[iter(iterable)]*n)
[docs]defdeep_merge(a,b,path=None,update=True):"""Recursive updates of a dictionary."""ifpathisNone:path=[]forkey,valinb.items():ifkeyina:if(isinstance(a[key],abc.Mapping)andisinstance(val,abc.Mapping)):deep_merge(a[key],val,path+[str(key)],update)elifa[key]==val:pass# same leaf valueelifupdate:a[key]=valelse:raiseException(f"Conflict at {'.'.join(path+[str(key)])}")else:a[key]=valreturna
[docs]classSimpleWarning():""" Context manager overrides warning formatter to remove unneeded info. """old_formatter=Nonedef__enter__(self):# ignore everything except the messagedefcustom_formatwarning(msg,*args,**kwargs):returnstr(msg)+'\n'self.old_formatter=warnings.formatwarningwarnings.formatwarning=custom_formatwarningreturnTruedef__exit__(self,typ,value,traceback):warnings.formatwarning=self.old_formatterreturnTrue
def_load_lazy(fullname):""" This lazy load was used for non-critical modules to speed import time. Examples: matplotlib, scipy.optimize. However it tends to destroy the import system. Do not use. """try:returnsys.modules[fullname]exceptKeyErroraserr:spec=importlib.util.find_spec(fullname)ifnotspec:raiseModuleNotFoundError(f"Could not import {fullname}.")fromerrloader=importlib.util.LazyLoader(spec.loader)module=importlib.util.module_from_spec(spec)# Make module with proper locking and get it inserted into sys.modules.loader.exec_module(module)sys.modules[fullname]=modulereturnmodule