summaryrefslogtreecommitdiff
path: root/tests/alter_time.py
blob: aa2db3b9df969dc708221d1288f93ae47fd626ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This code is in the public domain
# Author: Raphaël Barrois


from __future__ import print_function

import datetime
from .compat import mock


real_datetime_class = datetime.datetime

def mock_datetime_now(target, datetime_module):
    """Override ``datetime.datetime.now()`` with a custom target value.

    This creates a new datetime.datetime class, and alters its now()/utcnow()
    methods.

    Returns:
        A mock.patch context, can be used as a decorator or in a with.
    """

    # See http://bugs.python.org/msg68532
    # And http://docs.python.org/reference/datamodel.html#customizing-instance-and-subclass-checks
    class DatetimeSubclassMeta(type):
        """We need to customize the __instancecheck__ method for isinstance().

        This must be performed at a metaclass level.
        """

        @classmethod
        def __instancecheck__(mcs, obj):
            return isinstance(obj, real_datetime_class)

    class BaseMockedDatetime(real_datetime_class):
        @classmethod
        def now(cls, tz=None):
            return target.replace(tzinfo=tz)

        @classmethod
        def utcnow(cls):
            return target

    # Python2 & Python3-compatible metaclass
    MockedDatetime = DatetimeSubclassMeta('datetime', (BaseMockedDatetime,), {})

    return mock.patch.object(datetime_module, 'datetime', MockedDatetime)

real_date_class = datetime.date

def mock_date_today(target, datetime_module):
    """Override ``datetime.date.today()`` with a custom target value.

    This creates a new datetime.date class, and alters its today() method.

    Returns:
        A mock.patch context, can be used as a decorator or in a with.
    """

    # See http://bugs.python.org/msg68532
    # And http://docs.python.org/reference/datamodel.html#customizing-instance-and-subclass-checks
    class DateSubclassMeta(type):
        """We need to customize the __instancecheck__ method for isinstance().

        This must be performed at a metaclass level.
        """

        @classmethod
        def __instancecheck__(mcs, obj):
            return isinstance(obj, real_date_class)

    class BaseMockedDate(real_date_class):
        @classmethod
        def today(cls):
            return target

    # Python2 & Python3-compatible metaclass
    MockedDate = DateSubclassMeta('date', (BaseMockedDate,), {})

    return mock.patch.object(datetime_module, 'date', MockedDate)


def main():  # pragma: no cover
    """Run a couple of tests"""
    target_dt = real_datetime_class(2009, 1, 1)
    target_date = real_date_class(2009, 1, 1)

    print("Entering mock")
    with mock_datetime_now(target_dt, datetime):
        print("- now                       ->", datetime.datetime.now())
        print("- isinstance(now, dt)       ->", isinstance(datetime.datetime.now(), datetime.datetime))
        print("- isinstance(target, dt)    ->", isinstance(target_dt, datetime.datetime))

    with mock_date_today(target_date, datetime):
        print("- today                     ->", datetime.date.today())
        print("- isinstance(now, date)     ->", isinstance(datetime.date.today(), datetime.date))
        print("- isinstance(target, date)  ->", isinstance(target_date, datetime.date))


    print("Outside mock")
    print("- now                       ->", datetime.datetime.now())
    print("- isinstance(now, dt)       ->", isinstance(datetime.datetime.now(), datetime.datetime))
    print("- isinstance(target, dt)    ->", isinstance(target_dt, datetime.datetime))

    print("- today                     ->", datetime.date.today())
    print("- isinstance(now, date)     ->", isinstance(datetime.date.today(), datetime.date))
    print("- isinstance(target, date)  ->", isinstance(target_date, datetime.date))


if __name__ == '__main__':  # pragma: no cover
    main()