[docs]classoverride_mysql_variables:""" Based on Django's override_settings, but for connection settings. Give a connection alias in using and variable=value pairs to save on that connection. Keeps the old values MySQL-side using session variables of the form @overridden_X. Acts as either a decorator, or a context manager. If it's a decorator it takes a function and returns a wrapped function. If it's a contextmanager it's used with the ``with`` statement. In either event entering/exiting are called before and after, respectively, the function/block is executed. """def__init__(self,using:str=DEFAULT_DB_ALIAS,**options:str|int)->None:self.db=usingself.options=optionsself.prefix:str=uuid.uuid1().hex.replace("-","")[:16]def__enter__(self)->None:self.enable()def__exit__(self,exc_type:type[BaseException]|None,exc_value:BaseException|None,exc_traceback:TracebackType|None,)->None:self.disable()def__call__(self,test_func:Any)->Any:fromunittestimportTestCaseifisinstance(test_func,type):ifnotissubclass(test_func,TestCase):raiseTypeError("{} only works with TestCase classes.".format(self.__class__.__name__))self.wrap_class(test_func)returntest_funcelse:@wraps(test_func)definner(*args:Any,**kwargs:Any)->Any:withself:returntest_func(*args,**kwargs)returninnerdefwrap_class(self,klass:type[Any])->None:kwargs:dict[str,Any]={"using":self.db,**self.options}fornameindir(klass):ifnotname.startswith("test_"):continuemethod=getattr(klass,name)# Reconstruct self over and over on each methodwrapped=self.__class__(**kwargs)(method)setattr(klass,name,wrapped)defenable(self)->None:withconnections[self.db].cursor()ascursor:forkey,valueinself.options.items():cursor.execute("""SET @overridden_{prefix}_{name} = @@{name}, @@{name} = %s """.format(prefix=self.prefix,name=key),(value,),)defdisable(self)->None:withconnections[self.db].cursor()ascursor:forkeyinself.options:cursor.execute("""SET @@{name} = @overridden_{prefix}_{name}, @overridden_{prefix}_{name} = NULL """.format(name=key,prefix=self.prefix))