[docs]classQCoDeSDeprecationWarning(RuntimeWarning):""" A DeprecationWarning used internally in QCoDeS. This fixes `DeprecationWarning` being suppressed by default. """
defdeprecation_message(what:str,reason:str|None=None,alternative:str|None=None)->str:msg=f"The {what} is deprecated"ifreasonisnotNone:msg+=f", because {reason}"msg+="."ifalternativeisnotNone:msg+=f' Use "{alternative}" as an alternative.'returnmsg
[docs]defissue_deprecation_warning(what:str,reason:str|None=None,alternative:str|None=None,stacklevel:int=3,)->None:""" Issue a `QCoDeSDeprecationWarning` with a consistently formatted message """warnings.warn(deprecation_message(what,reason,alternative),QCoDeSDeprecationWarning,stacklevel=stacklevel,)
[docs]defdeprecate(reason:str|None=None,alternative:str|None=None)->Callable[...,Any]:""" A utility function to decorate deprecated functions and classes. Note that this is not recommended to be used for deprecation any new code. It is recommended to use typing_extensions.deprecated (which will be added to the std lib as warnings.deprecated in python 3.13) Args: reason: The reason of deprecation. alternative: The alternative function or class to put in use instead of the deprecated one. """@wrapt.decorator# type: ignore[misc]defdecorate_callable(func:Callable[...,Any],instance:object,args:Any,kwargs:Any)->Any:t,n=(("class",instance.__class__.__name__)iffunc.__name__=="__init__"else("function",func.__name__))issue_deprecation_warning(f"{t} <{n}>",reason,alternative,stacklevel=3)returnfunc(*args,**kwargs)defactual_decorator(obj:Any)->Any:ifisinstance(obj,(types.FunctionType,types.MethodType)):func=cast(Callable[...,Any],obj)returndecorate_callable(func)# pyright: ignore[reportCallIssue]else:# this would need to be recursiveform_nameindir(obj):m=getattr(obj,m_name)ifisinstance(m,(types.FunctionType,types.MethodType)):# skip static methods, since they are not wrapped correctly# by wrapt.# if anyone reading this knows how the following line# works please let me know.# wrapt cannot wrap class methods in 3.11.0# see https://github.com/python/cpython/issues/63272ifisinstance(obj.__dict__.get(m_name,None),(staticmethod,classmethod)):continuesetattr(obj,m_name,decorate_callable(m),# pyright: ignore[reportCallIssue])returnobjreturnactual_decorator