Есть ли способ заставить python pickle игнорировать ошибки "это не один и тот же объект"


Есть ли способ заставить python pickle игнорировать ошибки "это не один и тот же объект"?

Я пишу тест с использованием макета, чтобы иметь точный контроль над результатами, которые датируются временем.utcnow() производит. Код, который я использую, чувствителен ко времени, поэтому патч МОКа облегчает его тестирование.

Те же тесты должны мариновать объекты и отправлять результаты на удаленный сервер. Для целей теста, если бы стандартный datetime был замаринован и получен удаленным сервером, все было бы хорошо.

К сожалению, модуль pickle блюет со следующей ошибкой:

Не могу засолить : это не тот же самый объект, что и значение datetime.datetime

Вот минимальный пример для воспроизведения ошибки.

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()

Есть ли какая-то комбинация __reduce__ и __getstate__ методов, которые могли бы обмануть механизм маринования, думая, что MockDatetime-это дата-время, когда я маринуюсь?

2 6

2 ответа:

Глядя на раздел где исправить в документации, я вижу этот совет:

Основной принцип заключается в том, что вы исправляете место, где объект используется, что не обязательно совпадает с местом, где он определен.

Следуя этой рекомендации, я попытался заменить:

@patch('datetime.datetime', MockDatetime)

С:

@patch('__main__.datetime', MockDatetime)

И я не получил никакой ошибки от pickle. Кроме того, я добавил заявление print, чтобы убедиться, что datetime действительно исправляется, и я получил ожидаемое значение.

В случае, если кто-то хочет общее решение мариновать издевается:

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

Обратите внимание, что это, похоже, не сохраняет внутреннее содержание используемого макета (например, вызовы).