Есть ли способ заставить Python Pickle игнорировать ошибки "это не тот же объект" - PullRequest
6 голосов
/ 05 декабря 2011

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

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

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

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

Можетсолёный: это не тот же объект, что и 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 ]

5 голосов
/ 15 декабря 2011

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

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

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

@patch('datetime.datetime', MockDatetime)

с:

@patch('__main__.datetime', MockDatetime)

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

2 голосов
/ 10 августа 2016

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

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

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

...