2011-12-05 13 views
6

¿Hay alguna manera de hacer que python pickle ignore los errores de "no es el mismo objeto"?¿Hay alguna manera de hacer que python pickle ignore los errores de "no es el mismo objeto"

Estoy escribiendo una prueba utilizando Mock para tener un control fino sobre los resultados que produce datetime.utcnow(). El código que estoy usando es sensible al tiempo, por lo que el parche de prueba facilita la prueba.

Las mismas pruebas deben encurtir objetos y enviar los resultados a un servidor remoto. A los efectos de la prueba, si el servidor remoto decapaba y recibía una fecha y hora estándar, todo estaría bien.

Desafortunadamente el módulo pickle se Barfing con el siguiente error:

Can't pickle <type 'datetime.datetime'>: it's not the same object as datetime.datetime

Aquí está un ejemplo mínimo para reproducir el error.

from mock import patch 
from datetime import datetime 
import pickle 

class MockDatetime(datetime): 
    frozendt = datetime(2011,05,31) 

    @classmethod 
    def advance(cls, **kw): 
    cls.frozendt = cls.frozendt + timedelta(**kw) 

    @classmethod 
    def utcnow(cls): 
    return cls.frozendt 

@patch('datetime.datetime', MockDatetime) 
def test(): 
    pickle.dumps(datetime.utcnow()) 

if __name__ == '__main__': 
    test() 

¿Hay alguna combinación de __reduce__ y __getstate__ métodos que podrían engañar a la maquinaria de la salmuera en el pensamiento de MockDatetime es una fecha y hora cuando pepinillo?

Respuesta

5

En cuanto a la sección where to patch en la documentación que ver este consejo:

The basic principle is that you patch where an object is used, which is not necessarily the same place as where it is defined.

Siguiendo esta recomendación, he tratado de sustituir:

@patch('datetime.datetime', MockDatetime) 

con:

@patch('__main__.datetime', MockDatetime) 

y no recibí ningún error de pickle. Además, agregué una declaración print para asegurarme de que realmente estaba siendo parchado el datetime y obtuve el valor esperado.

2

En caso de que alguien quiere una solución genérica para la salmuera se burla:

m = mock.MagicMock() 
m.__reduce__ = lambda self: (mock.MagicMock,()) 

Tenga en cuenta que este no parece guardar el contenido interno de la maqueta utilizada (por ejemplo las llamadas).

Cuestiones relacionadas