api.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. import dateutil
  2. import datetime
  3. import functools
  4. import sys
  5. import time
  6. import uuid
  7. import calendar
  8. import unittest
  9. import platform
  10. import warnings
  11. import types
  12. import numbers
  13. import inspect
  14. from dateutil import parser
  15. from dateutil.tz import tzlocal
  16. try:
  17. from maya import MayaDT
  18. except ImportError:
  19. MayaDT = None
  20. _TIME_NS_PRESENT = hasattr(time, 'time_ns')
  21. _EPOCH = datetime.datetime(1970, 1, 1)
  22. _EPOCHTZ = datetime.datetime(1970, 1, 1, tzinfo=dateutil.tz.UTC)
  23. real_time = time.time
  24. real_localtime = time.localtime
  25. real_gmtime = time.gmtime
  26. real_strftime = time.strftime
  27. real_date = datetime.date
  28. real_datetime = datetime.datetime
  29. real_date_objects = [real_time, real_localtime, real_gmtime, real_strftime, real_date, real_datetime]
  30. if _TIME_NS_PRESENT:
  31. real_time_ns = time.time_ns
  32. real_date_objects.append(real_time_ns)
  33. _real_time_object_ids = {id(obj) for obj in real_date_objects}
  34. # time.clock is deprecated and was removed in Python 3.8
  35. real_clock = getattr(time, 'clock', None)
  36. freeze_factories = []
  37. tz_offsets = []
  38. ignore_lists = []
  39. tick_flags = []
  40. # Python3 doesn't have basestring, but it does have str.
  41. try:
  42. # noinspection PyUnresolvedReferences
  43. _string_type = basestring
  44. except NameError:
  45. _string_type = str
  46. try:
  47. # noinspection PyUnresolvedReferences
  48. real_uuid_generate_time = uuid._uuid_generate_time
  49. uuid_generate_time_attr = '_uuid_generate_time'
  50. except AttributeError:
  51. # noinspection PyUnresolvedReferences
  52. uuid._load_system_functions()
  53. # noinspection PyUnresolvedReferences
  54. real_uuid_generate_time = uuid._generate_time_safe
  55. uuid_generate_time_attr = '_generate_time_safe'
  56. except ImportError:
  57. real_uuid_generate_time = None
  58. uuid_generate_time_attr = None
  59. try:
  60. # noinspection PyUnresolvedReferences
  61. real_uuid_create = uuid._UuidCreate
  62. except (AttributeError, ImportError):
  63. real_uuid_create = None
  64. try:
  65. import copy_reg as copyreg
  66. except ImportError:
  67. import copyreg
  68. try:
  69. iscoroutinefunction = inspect.iscoroutinefunction
  70. if sys.version_info < (3, 5):
  71. from freezegun._async_coroutine import wrap_coroutine
  72. else:
  73. from freezegun._async import wrap_coroutine
  74. except AttributeError:
  75. iscoroutinefunction = lambda x: False
  76. def wrap_coroutine(*args):
  77. raise NotImplementedError()
  78. # keep a cache of module attributes otherwise freezegun will need to analyze too many modules all the time
  79. _GLOBAL_MODULES_CACHE = {}
  80. def _get_module_attributes(module):
  81. result = []
  82. try:
  83. module_attributes = dir(module)
  84. except (ImportError, TypeError):
  85. return result
  86. for attribute_name in module_attributes:
  87. try:
  88. attribute_value = getattr(module, attribute_name)
  89. except (ImportError, AttributeError, TypeError):
  90. # For certain libraries, this can result in ImportError(_winreg) or AttributeError (celery)
  91. continue
  92. else:
  93. result.append((attribute_name, attribute_value))
  94. return result
  95. def _setup_module_cache(module):
  96. date_attrs = []
  97. all_module_attributes = _get_module_attributes(module)
  98. for attribute_name, attribute_value in all_module_attributes:
  99. if id(attribute_value) in _real_time_object_ids:
  100. date_attrs.append((attribute_name, attribute_value))
  101. _GLOBAL_MODULES_CACHE[module.__name__] = (_get_module_attributes_hash(module), date_attrs)
  102. def _get_module_attributes_hash(module):
  103. try:
  104. module_dir = dir(module)
  105. except (ImportError, TypeError):
  106. module_dir = []
  107. return '{}-{}'.format(id(module), hash(frozenset(module_dir)))
  108. def _get_cached_module_attributes(module):
  109. module_hash, cached_attrs = _GLOBAL_MODULES_CACHE.get(module.__name__, ('0', []))
  110. if _get_module_attributes_hash(module) == module_hash:
  111. return cached_attrs
  112. # cache miss: update the cache and return the refreshed value
  113. _setup_module_cache(module)
  114. # return the newly cached value
  115. module_hash, cached_attrs = _GLOBAL_MODULES_CACHE[module.__name__]
  116. return cached_attrs
  117. # Stolen from six
  118. def with_metaclass(meta, *bases):
  119. """Create a base class with a metaclass."""
  120. return meta("NewBase", bases, {})
  121. _is_cpython = (
  122. hasattr(platform, 'python_implementation') and
  123. platform.python_implementation().lower() == "cpython"
  124. )
  125. call_stack_inspection_limit = 5
  126. def _should_use_real_time():
  127. if not call_stack_inspection_limit:
  128. return False
  129. if not ignore_lists[-1]:
  130. return False
  131. frame = inspect.currentframe().f_back.f_back
  132. for _ in range(call_stack_inspection_limit):
  133. module_name = frame.f_globals.get('__name__')
  134. if module_name and module_name.startswith(ignore_lists[-1]):
  135. return True
  136. frame = frame.f_back
  137. if frame is None:
  138. break
  139. return False
  140. def get_current_time():
  141. return freeze_factories[-1]()
  142. def fake_time():
  143. if _should_use_real_time():
  144. return real_time()
  145. current_time = get_current_time()
  146. return calendar.timegm(current_time.timetuple()) + current_time.microsecond / 1000000.0
  147. if _TIME_NS_PRESENT:
  148. def fake_time_ns():
  149. if _should_use_real_time():
  150. return real_time_ns()
  151. return int(int(fake_time()) * 1e9)
  152. def fake_localtime(t=None):
  153. if t is not None:
  154. return real_localtime(t)
  155. if _should_use_real_time():
  156. return real_localtime()
  157. shifted_time = get_current_time() - datetime.timedelta(seconds=time.timezone)
  158. return shifted_time.timetuple()
  159. def fake_gmtime(t=None):
  160. if t is not None:
  161. return real_gmtime(t)
  162. if _should_use_real_time():
  163. return real_gmtime()
  164. return get_current_time().timetuple()
  165. def fake_strftime(format, time_to_format=None):
  166. if time_to_format is None:
  167. if not _should_use_real_time():
  168. time_to_format = fake_localtime()
  169. if time_to_format is None:
  170. return real_strftime(format)
  171. else:
  172. return real_strftime(format, time_to_format)
  173. if real_clock is not None:
  174. def fake_clock():
  175. if _should_use_real_time():
  176. return real_clock()
  177. if len(freeze_factories) == 1:
  178. return 0.0 if not tick_flags[-1] else real_clock()
  179. first_frozen_time = freeze_factories[0]()
  180. last_frozen_time = get_current_time()
  181. timedelta = (last_frozen_time - first_frozen_time)
  182. total_seconds = timedelta.total_seconds()
  183. if tick_flags[-1]:
  184. total_seconds += real_clock()
  185. return total_seconds
  186. class FakeDateMeta(type):
  187. @classmethod
  188. def __instancecheck__(self, obj):
  189. return isinstance(obj, real_date)
  190. @classmethod
  191. def __subclasscheck__(cls, subclass):
  192. return issubclass(subclass, real_date)
  193. def datetime_to_fakedatetime(datetime):
  194. return FakeDatetime(datetime.year,
  195. datetime.month,
  196. datetime.day,
  197. datetime.hour,
  198. datetime.minute,
  199. datetime.second,
  200. datetime.microsecond,
  201. datetime.tzinfo)
  202. def date_to_fakedate(date):
  203. return FakeDate(date.year,
  204. date.month,
  205. date.day)
  206. class FakeDate(with_metaclass(FakeDateMeta, real_date)):
  207. def __new__(cls, *args, **kwargs):
  208. return real_date.__new__(cls, *args, **kwargs)
  209. def __add__(self, other):
  210. result = real_date.__add__(self, other)
  211. if result is NotImplemented:
  212. return result
  213. return date_to_fakedate(result)
  214. def __sub__(self, other):
  215. result = real_date.__sub__(self, other)
  216. if result is NotImplemented:
  217. return result
  218. if isinstance(result, real_date):
  219. return date_to_fakedate(result)
  220. else:
  221. return result
  222. @classmethod
  223. def today(cls):
  224. result = cls._date_to_freeze() + cls._tz_offset()
  225. return date_to_fakedate(result)
  226. @staticmethod
  227. def _date_to_freeze():
  228. return get_current_time()
  229. @classmethod
  230. def _tz_offset(cls):
  231. return tz_offsets[-1]
  232. FakeDate.min = date_to_fakedate(real_date.min)
  233. FakeDate.max = date_to_fakedate(real_date.max)
  234. class FakeDatetimeMeta(FakeDateMeta):
  235. @classmethod
  236. def __instancecheck__(self, obj):
  237. return isinstance(obj, real_datetime)
  238. @classmethod
  239. def __subclasscheck__(cls, subclass):
  240. return issubclass(subclass, real_datetime)
  241. class FakeDatetime(with_metaclass(FakeDatetimeMeta, real_datetime, FakeDate)):
  242. def __new__(cls, *args, **kwargs):
  243. return real_datetime.__new__(cls, *args, **kwargs)
  244. def __add__(self, other):
  245. result = real_datetime.__add__(self, other)
  246. if result is NotImplemented:
  247. return result
  248. return datetime_to_fakedatetime(result)
  249. def __sub__(self, other):
  250. result = real_datetime.__sub__(self, other)
  251. if result is NotImplemented:
  252. return result
  253. if isinstance(result, real_datetime):
  254. return datetime_to_fakedatetime(result)
  255. else:
  256. return result
  257. def astimezone(self, tz=None):
  258. if tz is None:
  259. tz = tzlocal()
  260. return datetime_to_fakedatetime(real_datetime.astimezone(self, tz))
  261. @classmethod
  262. def fromtimestamp(cls, t, tz=None):
  263. if tz is None:
  264. return real_datetime.fromtimestamp(
  265. t, tz=dateutil.tz.tzoffset("freezegun", cls._tz_offset())
  266. ).replace(tzinfo=None)
  267. return datetime_to_fakedatetime(real_datetime.fromtimestamp(t, tz))
  268. def timestamp(self):
  269. if self.tzinfo is None:
  270. return (self - _EPOCH - self._tz_offset()).total_seconds()
  271. return (self - _EPOCHTZ).total_seconds()
  272. @classmethod
  273. def now(cls, tz=None):
  274. now = cls._time_to_freeze() or real_datetime.now()
  275. if tz:
  276. result = tz.fromutc(now.replace(tzinfo=tz)) + cls._tz_offset()
  277. else:
  278. result = now + cls._tz_offset()
  279. return datetime_to_fakedatetime(result)
  280. def date(self):
  281. return date_to_fakedate(self)
  282. @property
  283. def nanosecond(self):
  284. try:
  285. # noinspection PyUnresolvedReferences
  286. return real_datetime.nanosecond
  287. except AttributeError:
  288. return 0
  289. @classmethod
  290. def today(cls):
  291. return cls.now(tz=None)
  292. @classmethod
  293. def utcnow(cls):
  294. result = cls._time_to_freeze() or real_datetime.utcnow()
  295. return datetime_to_fakedatetime(result)
  296. @staticmethod
  297. def _time_to_freeze():
  298. if freeze_factories:
  299. return get_current_time()
  300. @classmethod
  301. def _tz_offset(cls):
  302. return tz_offsets[-1]
  303. FakeDatetime.min = datetime_to_fakedatetime(real_datetime.min)
  304. FakeDatetime.max = datetime_to_fakedatetime(real_datetime.max)
  305. def convert_to_timezone_naive(time_to_freeze):
  306. """
  307. Converts a potentially timezone-aware datetime to be a naive UTC datetime
  308. """
  309. if time_to_freeze.tzinfo:
  310. time_to_freeze -= time_to_freeze.utcoffset()
  311. time_to_freeze = time_to_freeze.replace(tzinfo=None)
  312. return time_to_freeze
  313. def pickle_fake_date(datetime_):
  314. # A pickle function for FakeDate
  315. return FakeDate, (
  316. datetime_.year,
  317. datetime_.month,
  318. datetime_.day,
  319. )
  320. def pickle_fake_datetime(datetime_):
  321. # A pickle function for FakeDatetime
  322. return FakeDatetime, (
  323. datetime_.year,
  324. datetime_.month,
  325. datetime_.day,
  326. datetime_.hour,
  327. datetime_.minute,
  328. datetime_.second,
  329. datetime_.microsecond,
  330. datetime_.tzinfo,
  331. )
  332. def _parse_time_to_freeze(time_to_freeze_str):
  333. """Parses all the possible inputs for freeze_time
  334. :returns: a naive ``datetime.datetime`` object
  335. """
  336. if time_to_freeze_str is None:
  337. time_to_freeze_str = datetime.datetime.utcnow()
  338. if isinstance(time_to_freeze_str, datetime.datetime):
  339. time_to_freeze = time_to_freeze_str
  340. elif isinstance(time_to_freeze_str, datetime.date):
  341. time_to_freeze = datetime.datetime.combine(time_to_freeze_str, datetime.time())
  342. elif isinstance(time_to_freeze_str, datetime.timedelta):
  343. time_to_freeze = datetime.datetime.utcnow() + time_to_freeze_str
  344. else:
  345. time_to_freeze = parser.parse(time_to_freeze_str)
  346. return convert_to_timezone_naive(time_to_freeze)
  347. def _parse_tz_offset(tz_offset):
  348. if isinstance(tz_offset, datetime.timedelta):
  349. return tz_offset
  350. else:
  351. return datetime.timedelta(hours=tz_offset)
  352. class TickingDateTimeFactory(object):
  353. def __init__(self, time_to_freeze, start):
  354. self.time_to_freeze = time_to_freeze
  355. self.start = start
  356. def __call__(self):
  357. return self.time_to_freeze + (real_datetime.now() - self.start)
  358. class FrozenDateTimeFactory(object):
  359. def __init__(self, time_to_freeze):
  360. self.time_to_freeze = time_to_freeze
  361. def __call__(self):
  362. return self.time_to_freeze
  363. def tick(self, delta=datetime.timedelta(seconds=1)):
  364. if isinstance(delta, numbers.Real):
  365. # noinspection PyTypeChecker
  366. self.time_to_freeze += datetime.timedelta(seconds=delta)
  367. else:
  368. self.time_to_freeze += delta
  369. def move_to(self, target_datetime):
  370. """Moves frozen date to the given ``target_datetime``"""
  371. target_datetime = _parse_time_to_freeze(target_datetime)
  372. delta = target_datetime - self.time_to_freeze
  373. self.tick(delta=delta)
  374. class StepTickTimeFactory(object):
  375. def __init__(self, time_to_freeze, step_width):
  376. self.time_to_freeze = time_to_freeze
  377. self.step_width = step_width
  378. def __call__(self):
  379. return_time = self.time_to_freeze
  380. self.tick()
  381. return return_time
  382. def tick(self, delta=None):
  383. if not delta:
  384. delta = datetime.timedelta(seconds=self.step_width)
  385. self.time_to_freeze += delta
  386. def update_step_width(self, step_width):
  387. self.step_width = step_width
  388. def move_to(self, target_datetime):
  389. """Moves frozen date to the given ``target_datetime``"""
  390. target_datetime = _parse_time_to_freeze(target_datetime)
  391. delta = target_datetime - self.time_to_freeze
  392. self.tick(delta=delta)
  393. class _freeze_time(object):
  394. def __init__(self, time_to_freeze_str, tz_offset, ignore, tick, as_arg, auto_tick_seconds):
  395. self.time_to_freeze = _parse_time_to_freeze(time_to_freeze_str)
  396. self.tz_offset = _parse_tz_offset(tz_offset)
  397. self.ignore = tuple(ignore)
  398. self.tick = tick
  399. self.auto_tick_seconds = auto_tick_seconds
  400. self.undo_changes = []
  401. self.modules_at_start = set()
  402. self.as_arg = as_arg
  403. def __call__(self, func):
  404. if inspect.isclass(func):
  405. return self.decorate_class(func)
  406. elif iscoroutinefunction(func):
  407. return self.decorate_coroutine(func)
  408. return self.decorate_callable(func)
  409. def decorate_class(self, klass):
  410. if issubclass(klass, unittest.TestCase):
  411. # If it's a TestCase, we assume you want to freeze the time for the
  412. # tests, from setUpClass to tearDownClass
  413. # Use getattr as in Python 2.6 they are optional
  414. orig_setUpClass = getattr(klass, 'setUpClass', None)
  415. orig_tearDownClass = getattr(klass, 'tearDownClass', None)
  416. # noinspection PyDecorator
  417. @classmethod
  418. def setUpClass(cls):
  419. self.start()
  420. if orig_setUpClass is not None:
  421. orig_setUpClass()
  422. # noinspection PyDecorator
  423. @classmethod
  424. def tearDownClass(cls):
  425. if orig_tearDownClass is not None:
  426. orig_tearDownClass()
  427. self.stop()
  428. klass.setUpClass = setUpClass
  429. klass.tearDownClass = tearDownClass
  430. return klass
  431. else:
  432. seen = set()
  433. klasses = klass.mro() if hasattr(klass, 'mro') else [klass] + list(klass.__bases__)
  434. for base_klass in klasses:
  435. for (attr, attr_value) in base_klass.__dict__.items():
  436. if attr.startswith('_') or attr in seen:
  437. continue
  438. seen.add(attr)
  439. if not callable(attr_value) or inspect.isclass(attr_value):
  440. continue
  441. try:
  442. setattr(klass, attr, self(attr_value))
  443. except (AttributeError, TypeError):
  444. # Sometimes we can't set this for built-in types and custom callables
  445. continue
  446. return klass
  447. def __enter__(self):
  448. return self.start()
  449. def __exit__(self, *args):
  450. self.stop()
  451. def start(self):
  452. if self.auto_tick_seconds:
  453. freeze_factory = StepTickTimeFactory(self.time_to_freeze, self.auto_tick_seconds)
  454. elif self.tick:
  455. freeze_factory = TickingDateTimeFactory(self.time_to_freeze, real_datetime.now())
  456. else:
  457. freeze_factory = FrozenDateTimeFactory(self.time_to_freeze)
  458. is_already_started = len(freeze_factories) > 0
  459. freeze_factories.append(freeze_factory)
  460. tz_offsets.append(self.tz_offset)
  461. ignore_lists.append(self.ignore)
  462. tick_flags.append(self.tick)
  463. if is_already_started:
  464. return freeze_factory
  465. # Change the modules
  466. datetime.datetime = FakeDatetime
  467. datetime.date = FakeDate
  468. time.time = fake_time
  469. time.localtime = fake_localtime
  470. time.gmtime = fake_gmtime
  471. time.strftime = fake_strftime
  472. if uuid_generate_time_attr:
  473. setattr(uuid, uuid_generate_time_attr, None)
  474. uuid._UuidCreate = None
  475. uuid._last_timestamp = None
  476. copyreg.dispatch_table[real_datetime] = pickle_fake_datetime
  477. copyreg.dispatch_table[real_date] = pickle_fake_date
  478. # Change any place where the module had already been imported
  479. to_patch = [
  480. ('real_date', real_date, FakeDate),
  481. ('real_datetime', real_datetime, FakeDatetime),
  482. ('real_gmtime', real_gmtime, fake_gmtime),
  483. ('real_localtime', real_localtime, fake_localtime),
  484. ('real_strftime', real_strftime, fake_strftime),
  485. ('real_time', real_time, fake_time),
  486. ]
  487. if _TIME_NS_PRESENT:
  488. time.time_ns = fake_time_ns
  489. to_patch.append(('real_time_ns', real_time_ns, fake_time_ns))
  490. if real_clock is not None:
  491. # time.clock is deprecated and was removed in Python 3.8
  492. time.clock = fake_clock
  493. to_patch.append(('real_clock', real_clock, fake_clock))
  494. self.fake_names = tuple(fake.__name__ for real_name, real, fake in to_patch)
  495. self.reals = {id(fake): real for real_name, real, fake in to_patch}
  496. fakes = {id(real): fake for real_name, real, fake in to_patch}
  497. add_change = self.undo_changes.append
  498. # Save the current loaded modules
  499. self.modules_at_start = set(sys.modules.keys())
  500. with warnings.catch_warnings():
  501. warnings.filterwarnings('ignore')
  502. for mod_name, module in list(sys.modules.items()):
  503. if mod_name is None or module is None or mod_name == __name__:
  504. continue
  505. elif mod_name.startswith(self.ignore) or mod_name.endswith('.six.moves'):
  506. continue
  507. elif (not hasattr(module, "__name__") or module.__name__ in ('datetime', 'time')):
  508. continue
  509. module_attrs = _get_cached_module_attributes(module)
  510. for attribute_name, attribute_value in module_attrs:
  511. fake = fakes.get(id(attribute_value))
  512. if fake:
  513. setattr(module, attribute_name, fake)
  514. add_change((module, attribute_name, attribute_value))
  515. return freeze_factory
  516. def stop(self):
  517. freeze_factories.pop()
  518. ignore_lists.pop()
  519. tick_flags.pop()
  520. tz_offsets.pop()
  521. if not freeze_factories:
  522. datetime.datetime = real_datetime
  523. datetime.date = real_date
  524. copyreg.dispatch_table.pop(real_datetime)
  525. copyreg.dispatch_table.pop(real_date)
  526. for module, module_attribute, original_value in self.undo_changes:
  527. setattr(module, module_attribute, original_value)
  528. self.undo_changes = []
  529. # Restore modules loaded after start()
  530. modules_to_restore = set(sys.modules.keys()) - self.modules_at_start
  531. self.modules_at_start = set()
  532. with warnings.catch_warnings():
  533. warnings.simplefilter('ignore')
  534. for mod_name in modules_to_restore:
  535. module = sys.modules.get(mod_name, None)
  536. if mod_name is None or module is None:
  537. continue
  538. elif mod_name.startswith(self.ignore) or mod_name.endswith('.six.moves'):
  539. continue
  540. elif (not hasattr(module, "__name__") or module.__name__ in ('datetime', 'time')):
  541. continue
  542. for module_attribute in dir(module):
  543. if module_attribute in self.fake_names:
  544. continue
  545. try:
  546. attribute_value = getattr(module, module_attribute)
  547. except (ImportError, AttributeError, TypeError):
  548. # For certain libraries, this can result in ImportError(_winreg) or AttributeError (celery)
  549. continue
  550. real = self.reals.get(id(attribute_value))
  551. if real:
  552. setattr(module, module_attribute, real)
  553. time.time = real_time
  554. time.gmtime = real_gmtime
  555. time.localtime = real_localtime
  556. time.strftime = real_strftime
  557. time.clock = real_clock
  558. if _TIME_NS_PRESENT:
  559. time.time_ns = real_time_ns
  560. if uuid_generate_time_attr:
  561. setattr(uuid, uuid_generate_time_attr, real_uuid_generate_time)
  562. uuid._UuidCreate = real_uuid_create
  563. uuid._last_timestamp = None
  564. def decorate_coroutine(self, coroutine):
  565. return wrap_coroutine(self, coroutine)
  566. def decorate_callable(self, func):
  567. def wrapper(*args, **kwargs):
  568. with self as time_factory:
  569. if self.as_arg:
  570. result = func(time_factory, *args, **kwargs)
  571. else:
  572. result = func(*args, **kwargs)
  573. return result
  574. functools.update_wrapper(wrapper, func)
  575. # update_wrapper already sets __wrapped__ in Python 3.2+, this is only
  576. # needed for Python 2.x support
  577. wrapper.__wrapped__ = func
  578. return wrapper
  579. def freeze_time(time_to_freeze=None, tz_offset=0, ignore=None, tick=False, as_arg=False, auto_tick_seconds=0):
  580. acceptable_times = (type(None), _string_type, datetime.date, datetime.timedelta,
  581. types.FunctionType, types.GeneratorType)
  582. if MayaDT is not None:
  583. acceptable_times += MayaDT,
  584. if not isinstance(time_to_freeze, acceptable_times):
  585. raise TypeError(('freeze_time() expected None, a string, date instance, datetime '
  586. 'instance, MayaDT, timedelta instance, function or a generator, but got '
  587. 'type {}.').format(type(time_to_freeze)))
  588. if tick and not _is_cpython:
  589. raise SystemError('Calling freeze_time with tick=True is only compatible with CPython')
  590. if isinstance(time_to_freeze, types.FunctionType):
  591. return freeze_time(time_to_freeze(), tz_offset, ignore, tick, auto_tick_seconds)
  592. if isinstance(time_to_freeze, types.GeneratorType):
  593. return freeze_time(next(time_to_freeze), tz_offset, ignore, tick, auto_tick_seconds)
  594. if MayaDT is not None and isinstance(time_to_freeze, MayaDT):
  595. return freeze_time(time_to_freeze.datetime(), tz_offset, ignore,
  596. tick, as_arg)
  597. if ignore is None:
  598. ignore = []
  599. ignore = ignore[:]
  600. ignore.append('nose.plugins')
  601. ignore.append('six.moves')
  602. ignore.append('django.utils.six.moves')
  603. ignore.append('google.gax')
  604. ignore.append('threading')
  605. ignore.append('Queue')
  606. ignore.append('selenium')
  607. ignore.append('_pytest.terminal.')
  608. ignore.append('_pytest.runner.')
  609. return _freeze_time(time_to_freeze, tz_offset, ignore, tick, as_arg, auto_tick_seconds)
  610. # Setup adapters for sqlite
  611. try:
  612. # noinspection PyUnresolvedReferences
  613. import sqlite3
  614. except ImportError:
  615. # Some systems have trouble with this
  616. pass
  617. else:
  618. # These are copied from Python sqlite3.dbapi2
  619. def adapt_date(val):
  620. return val.isoformat()
  621. def adapt_datetime(val):
  622. return val.isoformat(" ")
  623. sqlite3.register_adapter(FakeDate, adapt_date)
  624. sqlite3.register_adapter(FakeDatetime, adapt_datetime)
  625. # Setup converters for pymysql
  626. try:
  627. import pymysql.converters
  628. except ImportError:
  629. pass
  630. else:
  631. pymysql.converters.encoders[FakeDate] = pymysql.converters.encoders[real_date]
  632. pymysql.converters.conversions[FakeDate] = pymysql.converters.encoders[real_date]
  633. pymysql.converters.encoders[FakeDatetime] = pymysql.converters.encoders[real_datetime]
  634. pymysql.converters.conversions[FakeDatetime] = pymysql.converters.encoders[real_datetime]