¿Cómo eliminar los efectos de un decorador mientras se prueba en python?

Estoy usando el decorador de retry en algún código en python. Pero quiero acelerar mis pruebas eliminando su efecto.

Mi código es:

 @retry(subprocess.CalledProcessError, tries=5, delay=1, backoff=2, logger=logger) def _sftp_command_with_retries(command, pem_path, user_at_host): # connect to sftp, blah blah blah pass 

¿Cómo puedo eliminar el efecto del decorador durante la prueba? No puedo crear una versión no decorada porque estoy probando funciones de nivel superior que usan esto.

Como retry usa time.sleep para retroceder, lo ideal sería poder parchear time.sleep pero como esto está en un decorador, no creo que sea posible.

¿Hay alguna manera de acelerar el código de prueba que utiliza esta función?

Actualizar

Básicamente estoy tratando de probar mis funciones de nivel superior que usan esto para asegurarme de que _sftp_command_with_retries cualquier excepción lanzada por _sftp_command_with_retries . Como el decorador de retry los propagará, necesito un simulacro más complicado.

Así que desde aquí puedo ver cómo burlarse de un decorador. Pero ahora necesito saber cómo escribir un simulacro que es en sí mismo un decorador. Debe llamar a _sftp_command_with_retries y si genera una excepción, _sftp_command_with_retries , de lo contrario, devuelva el valor de retorno.

Agregar esto después de importar mi función no funcionó:

 _sftp_command_with_retries = _sftp_command_with_retries.__wrapped__ 

El decorador de retry que está utilizando está creado sobre decorator.decorator utilitario decorator con un respaldo más simple si ese paquete no está instalado.

El resultado tiene un atributo __wrapped__ que le da acceso a la función original:

 orig = _sftp_command_with_retries.__wrapped__ 

Si el decorator no está instalado y está utilizando una versión de Python anterior a la 3.2, ese atributo no estará presente; Tendrías que alcanzar manualmente el cierre del decorador:

 orig = _sftp_command_with_retries.__closure__[1].cell_contents 

(el cierre en el índice 0 es el retry_decorator producido cuando se llama a retry_decorator retry() ).

Tenga en cuenta que el decorator aparece como una dependencia en los metadatos del paquete de retry y, si lo instaló con pip el paquete del decorator se habría instalado automáticamente.

Puedes apoyar ambas posibilidades con un try...except :

 try: orig = _sftp_command_with_retries.__wrapped__ except AttributeError: # decorator.decorator not available and not Python 3.2 or newer. orig = _sftp_command_with_retries.__closure__[1].cell_contents 

Tenga en cuenta que siempre puede parchear time.sleep() con un simulacro. El código de decoración utilizará el simulacro ya que hace referencia al módulo de time ‘global’ en el código fuente del módulo .

Alternativamente, puedes parchear retry.api.__retry_internal con:

 import retry.api def dontretry(f, *args, **kw): return f() with mock.patch.object(retry.api, '__retry_internal', dontretry): # use your decorated method 

Esto reemplaza temporalmente la función que realiza el rebash real con uno que simplemente llama directamente a su función original.