assertpy2 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
assertpy2/contains.py ADDED
@@ -0,0 +1,386 @@
1
+ # Copyright (c) 2015-2019, Activision Publishing, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without modification,
5
+ # are permitted provided that the following conditions are met:
6
+ #
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # 3. Neither the name of the copyright holder nor the names of its contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+
30
+ from __future__ import annotations
31
+
32
+ from typing import TYPE_CHECKING
33
+
34
+ if TYPE_CHECKING:
35
+ from typing_extensions import Self
36
+
37
+ __tracebackhide__ = True
38
+
39
+
40
+ class ContainsMixin:
41
+ """Containment assertions mixin."""
42
+
43
+ def contains(self, *items) -> Self:
44
+ """Asserts that val contains the given item or items.
45
+
46
+ Checks if the collection contains the given item or items using ``in`` operator.
47
+
48
+ Args:
49
+ *items: the item or items expected to be contained
50
+
51
+ Examples:
52
+ Usage::
53
+
54
+ assert_that('foo').contains('f')
55
+ assert_that('foo').contains('f', 'oo')
56
+ assert_that(['a', 'b']).contains('b', 'a')
57
+ assert_that((1, 2, 3)).contains(3, 2, 1)
58
+ assert_that({'a': 1, 'b': 2}).contains('b', 'a') # checks keys
59
+ assert_that({'a', 'b'}).contains('b', 'a')
60
+ assert_that([1, 2, 3]).is_type_of(list).contains(1, 2).does_not_contain(4, 5)
61
+
62
+ Returns:
63
+ AssertionBuilder: returns this instance to chain to the next assertion
64
+
65
+ Raises:
66
+ AssertionError: if val does **not** contain the item or items
67
+
68
+ Tip:
69
+ Use the :meth:`~assertpy.dict.DictMixin.contains_key` alias when working with
70
+ *dict-like* objects to be self-documenting.
71
+
72
+ See Also:
73
+ :meth:`~assertpy.string.StringMixin.contains_ignoring_case` - for case-insensitive string contains
74
+ """
75
+ if len(items) == 0:
76
+ raise ValueError("one or more args must be given")
77
+ elif len(items) == 1:
78
+ if items[0] not in self.val:
79
+ if self._check_dict_like(self.val, return_as_bool=True):
80
+ return self.error("Expected <%s> to contain key <%s>, but did not." % (self.val, items[0]))
81
+ else:
82
+ return self.error("Expected <%s> to contain item <%s>, but did not." % (self.val, items[0]))
83
+ else:
84
+ missing = []
85
+ for i in items:
86
+ if i not in self.val:
87
+ missing.append(i)
88
+ if missing:
89
+ if self._check_dict_like(self.val, return_as_bool=True):
90
+ return self.error(
91
+ "Expected <%s> to contain keys %s, but did not contain key%s %s."
92
+ % (self.val, self._fmt_items(items), "" if len(missing) == 0 else "s", self._fmt_items(missing))
93
+ )
94
+ else:
95
+ return self.error(
96
+ "Expected <%s> to contain items %s, but did not contain %s."
97
+ % (self.val, self._fmt_items(items), self._fmt_items(missing))
98
+ )
99
+ return self
100
+
101
+ def does_not_contain(self, *items) -> Self:
102
+ """Asserts that val does not contain the given item or items.
103
+
104
+ Checks if the collection excludes the given item or items using ``in`` operator.
105
+
106
+ Args:
107
+ *items: the item or items expected to be excluded
108
+
109
+ Examples:
110
+ Usage::
111
+
112
+ assert_that('foo').does_not_contain('x')
113
+ assert_that(['a', 'b']).does_not_contain('x', 'y')
114
+ assert_that((1, 2, 3)).does_not_contain(4, 5)
115
+ assert_that({'a': 1, 'b': 2}).does_not_contain('x', 'y') # checks keys
116
+ assert_that({'a', 'b'}).does_not_contain('x', 'y')
117
+ assert_that([1, 2, 3]).is_type_of(list).contains(1, 2).does_not_contain(4, 5)
118
+
119
+ Returns:
120
+ AssertionBuilder: returns this instance to chain to the next assertion
121
+
122
+ Raises:
123
+ AssertionError: if val **does** contain the item or items
124
+
125
+ Tip:
126
+ Use the :meth:`~assertpy.dict.DictMixin.does_not_contain_key` alias when working with
127
+ *dict-like* objects to be self-documenting.
128
+ """
129
+ if len(items) == 0:
130
+ raise ValueError("one or more args must be given")
131
+ elif len(items) == 1:
132
+ if items[0] in self.val:
133
+ return self.error("Expected <%s> to not contain item <%s>, but did." % (self.val, items[0]))
134
+ else:
135
+ found = []
136
+ for i in items:
137
+ if i in self.val:
138
+ found.append(i)
139
+ if found:
140
+ return self.error(
141
+ "Expected <%s> to not contain items %s, but did contain %s."
142
+ % (self.val, self._fmt_items(items), self._fmt_items(found))
143
+ )
144
+ return self
145
+
146
+ def contains_only(self, *items) -> Self:
147
+ """Asserts that val contains *only* the given item or items.
148
+
149
+ Checks if the collection contains only the given item or items using ``in`` operator.
150
+
151
+ Args:
152
+ *items: the *only* item or items expected to be contained
153
+
154
+ Examples:
155
+ Usage::
156
+
157
+ assert_that('foo').contains_only('f', 'o')
158
+ assert_that(['a', 'a', 'b']).contains_only('a', 'b')
159
+ assert_that((1, 1, 2)).contains_only(1, 2)
160
+ assert_that({'a': 1, 'a': 2, 'b': 3}).contains_only('a', 'b')
161
+ assert_that({'a', 'a', 'b'}).contains_only('a', 'b')
162
+
163
+ Returns:
164
+ AssertionBuilder: returns this instance to chain to the next assertion
165
+
166
+ Raises:
167
+ AssertionError: if val contains anything **not** item or items
168
+ """
169
+ if len(items) == 0:
170
+ raise ValueError("one or more args must be given")
171
+ else:
172
+ extra = []
173
+ for i in self.val:
174
+ if i not in items:
175
+ extra.append(i)
176
+ if extra:
177
+ return self.error(
178
+ "Expected <%s> to contain only %s, but did contain %s."
179
+ % (self.val, self._fmt_items(items), self._fmt_items(extra))
180
+ )
181
+
182
+ missing = []
183
+ for i in items:
184
+ if i not in self.val:
185
+ missing.append(i)
186
+ if missing:
187
+ return self.error(
188
+ "Expected <%s> to contain only %s, but did not contain %s."
189
+ % (self.val, self._fmt_items(items), self._fmt_items(missing))
190
+ )
191
+ return self
192
+
193
+ def contains_sequence(self, *items) -> Self:
194
+ """Asserts that val contains the given ordered sequence of items.
195
+
196
+ Checks if the collection contains the given sequence of items using ``in`` operator.
197
+
198
+ Args:
199
+ *items: the sequence of items expected to be contained
200
+
201
+ Examples:
202
+ Usage::
203
+
204
+ assert_that('foo').contains_sequence('f', 'o')
205
+ assert_that('foo').contains_sequence('o', 'o')
206
+ assert_that(['a', 'b', 'c']).contains_sequence('b', 'c')
207
+ assert_that((1, 2, 3)).contains_sequence(1, 2)
208
+
209
+ Returns:
210
+ AssertionBuilder: returns this instance to chain to the next assertion
211
+
212
+ Raises:
213
+ AssertionError: if val does **not** contains the given sequence of items
214
+ """
215
+ if len(items) == 0:
216
+ raise ValueError("one or more args must be given")
217
+ if isinstance(self.val, str):
218
+ pos = 0
219
+ for item in items:
220
+ if not isinstance(item, str):
221
+ raise TypeError("given args must be strings when val is a string")
222
+ idx = self.val.find(item, pos)
223
+ if idx == -1:
224
+ return self.error(
225
+ "Expected <%s> to contain sequence %s, but did not." % (self.val, self._fmt_items(items))
226
+ )
227
+ pos = idx + len(item)
228
+ return self
229
+ try:
230
+ for i in range(len(self.val) - len(items) + 1):
231
+ for j in range(len(items)):
232
+ if self.val[i + j] != items[j]:
233
+ break
234
+ else:
235
+ return self
236
+ except TypeError:
237
+ raise TypeError("val is not iterable") from None
238
+ return self.error("Expected <%s> to contain sequence %s, but did not." % (self.val, self._fmt_items(items)))
239
+
240
+ def contains_duplicates(self) -> Self:
241
+ """Asserts that val is iterable and *does* contain duplicates.
242
+
243
+ Examples:
244
+ Usage::
245
+
246
+ assert_that('foo').contains_duplicates()
247
+ assert_that(['a', 'a', 'b']).contains_duplicates()
248
+ assert_that((1, 1, 2)).contains_duplicates()
249
+
250
+ Returns:
251
+ AssertionBuilder: returns this instance to chain to the next assertion
252
+
253
+ Raises:
254
+ AssertionError: if val does **not** contain any duplicates
255
+ """
256
+ try:
257
+ if len(self.val) != len(set(self.val)):
258
+ return self
259
+ except TypeError:
260
+ raise TypeError("val is not iterable") from None
261
+ return self.error("Expected <%s> to contain duplicates, but did not." % self.val)
262
+
263
+ def does_not_contain_duplicates(self) -> Self:
264
+ """Asserts that val is iterable and *does not* contain any duplicates.
265
+
266
+ Examples:
267
+ Usage::
268
+
269
+ assert_that('fox').does_not_contain_duplicates()
270
+ assert_that(['a', 'b', 'c']).does_not_contain_duplicates()
271
+ assert_that((1, 2, 3)).does_not_contain_duplicates()
272
+
273
+ Returns:
274
+ AssertionBuilder: returns this instance to chain to the next assertion
275
+
276
+ Raises:
277
+ AssertionError: if val **does** contain duplicates
278
+ """
279
+ try:
280
+ if len(self.val) == len(set(self.val)):
281
+ return self
282
+ except TypeError:
283
+ raise TypeError("val is not iterable") from None
284
+ return self.error("Expected <%s> to not contain duplicates, but did." % self.val)
285
+
286
+ def is_empty(self) -> Self:
287
+ """Asserts that val is empty.
288
+
289
+ Examples:
290
+ Usage::
291
+
292
+ assert_that('').is_empty()
293
+ assert_that([]).is_empty()
294
+ assert_that(()).is_empty()
295
+ assert_that({}).is_empty()
296
+ assert_that(set()).is_empty()
297
+
298
+ Returns:
299
+ AssertionBuilder: returns this instance to chain to the next assertion
300
+
301
+ Raises:
302
+ AssertionError: if val is **not** empty
303
+ """
304
+ if len(self.val) != 0:
305
+ if isinstance(self.val, str):
306
+ return self.error("Expected <%s> to be empty string, but was not." % self.val)
307
+ else:
308
+ return self.error("Expected <%s> to be empty, but was not." % self.val)
309
+ return self
310
+
311
+ def is_not_empty(self) -> Self:
312
+ """Asserts that val is *not* empty.
313
+
314
+ Examples:
315
+ Usage::
316
+
317
+ assert_that('foo').is_not_empty()
318
+ assert_that(['a', 'b']).is_not_empty()
319
+ assert_that((1, 2, 3)).is_not_empty()
320
+ assert_that({'a': 1, 'b': 2}).is_not_empty()
321
+ assert_that({'a', 'b'}).is_not_empty()
322
+
323
+ Returns:
324
+ AssertionBuilder: returns this instance to chain to the next assertion
325
+
326
+ Raises:
327
+ AssertionError: if val **is** empty
328
+ """
329
+ if len(self.val) == 0:
330
+ if isinstance(self.val, str):
331
+ return self.error("Expected not empty string, but was empty.")
332
+ else:
333
+ return self.error("Expected not empty, but was empty.")
334
+ return self
335
+
336
+ def is_in(self, *items) -> Self:
337
+ """Asserts that val is equal to one of the given items.
338
+
339
+ Args:
340
+ *items: the items expected to contain val
341
+
342
+ Examples:
343
+ Usage::
344
+
345
+ assert_that('foo').is_in('foo', 'bar', 'baz')
346
+ assert_that(1).is_in(0, 1, 2, 3)
347
+
348
+ Returns:
349
+ AssertionBuilder: returns this instance to chain to the next assertion
350
+
351
+ Raises:
352
+ AssertionError: if val is **not** in the given items
353
+ """
354
+ if len(items) == 0:
355
+ raise ValueError("one or more args must be given")
356
+ else:
357
+ for i in items:
358
+ if self.val == i:
359
+ return self
360
+ return self.error("Expected <%s> to be in %s, but was not." % (self.val, self._fmt_items(items)))
361
+
362
+ def is_not_in(self, *items) -> Self:
363
+ """Asserts that val is not equal to one of the given items.
364
+
365
+ Args:
366
+ *items: the items expected to exclude val
367
+
368
+ Examples:
369
+ Usage::
370
+
371
+ assert_that('foo').is_not_in('bar', 'baz', 'box')
372
+ assert_that(1).is_not_in(-1, -2, -3)
373
+
374
+ Returns:
375
+ AssertionBuilder: returns this instance to chain to the next assertion
376
+
377
+ Raises:
378
+ AssertionError: if val **is** in the given items
379
+ """
380
+ if len(items) == 0:
381
+ raise ValueError("one or more args must be given")
382
+ else:
383
+ for i in items:
384
+ if self.val == i:
385
+ return self.error("Expected <%s> to not be in %s, but was." % (self.val, self._fmt_items(items)))
386
+ return self
assertpy2/date.py ADDED
@@ -0,0 +1,219 @@
1
+ # Copyright (c) 2015-2019, Activision Publishing, Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without modification,
5
+ # are permitted provided that the following conditions are met:
6
+ #
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # 3. Neither the name of the copyright holder nor the names of its contributors
15
+ # may be used to endorse or promote products derived from this software without
16
+ # specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ from __future__ import annotations
30
+
31
+ import datetime
32
+ from typing import TYPE_CHECKING
33
+
34
+ if TYPE_CHECKING:
35
+ from typing_extensions import Self
36
+
37
+ __tracebackhide__ = True
38
+
39
+
40
+ class DateMixin:
41
+ """Date and time assertions mixin."""
42
+
43
+ def is_before(self, other) -> Self:
44
+ """Asserts that val is a date and is before other date.
45
+
46
+ Args:
47
+ other: the other date, expected to be after val
48
+
49
+ Examples:
50
+ Usage::
51
+
52
+ import datetime
53
+
54
+ today = datetime.datetime.now()
55
+ yesterday = today - datetime.timedelta(days=1)
56
+
57
+ assert_that(yesterday).is_before(today)
58
+
59
+ Returns:
60
+ AssertionBuilder: returns this instance to chain to the next assertion
61
+
62
+ Raises:
63
+ AssertionError: if val is **not** before the given date
64
+
65
+ See Also:
66
+ :meth:`~assertpy.string.NumericMixin.is_less_than` - numeric assertion, but also works with datetime BR
67
+ :meth:`~assertpy.string.NumericMixin.is_less_than_or_equal_to` - numeric assertion, but also works with datetime
68
+ """
69
+ if type(self.val) is not datetime.datetime:
70
+ raise TypeError("val must be datetime, but was type <%s>" % type(self.val).__name__)
71
+ if type(other) is not datetime.datetime:
72
+ raise TypeError("given arg must be datetime, but was type <%s>" % type(other).__name__)
73
+ if self.val >= other:
74
+ return self.error(
75
+ "Expected <%s> to be before <%s>, but was not."
76
+ % (self.val.strftime("%Y-%m-%d %H:%M:%S"), other.strftime("%Y-%m-%d %H:%M:%S"))
77
+ )
78
+ return self
79
+
80
+ def is_after(self, other) -> Self:
81
+ """Asserts that val is a date and is after other date.
82
+
83
+ Args:
84
+ other: the other date, expected to be before val
85
+
86
+ Examples:
87
+ Usage::
88
+
89
+ import datetime
90
+
91
+ today = datetime.datetime.now()
92
+ yesterday = today - datetime.timedelta(days=1)
93
+
94
+ assert_that(today).is_after(yesterday)
95
+
96
+ Returns:
97
+ AssertionBuilder: returns this instance to chain to the next assertion
98
+
99
+ Raises:
100
+ AssertionError: if val is **not** after the given date
101
+
102
+ See Also:
103
+ :meth:`~assertpy.string.NumericMixin.is_greater_than` - numeric assertion, but also works with datetime BR
104
+ :meth:`~assertpy.string.NumericMixin.is_greater_than_or_equal_to` - numeric assertion, but also works with datetime
105
+ """
106
+ if type(self.val) is not datetime.datetime:
107
+ raise TypeError("val must be datetime, but was type <%s>" % type(self.val).__name__)
108
+ if type(other) is not datetime.datetime:
109
+ raise TypeError("given arg must be datetime, but was type <%s>" % type(other).__name__)
110
+ if self.val <= other:
111
+ return self.error(
112
+ "Expected <%s> to be after <%s>, but was not."
113
+ % (self.val.strftime("%Y-%m-%d %H:%M:%S"), other.strftime("%Y-%m-%d %H:%M:%S"))
114
+ )
115
+ return self
116
+
117
+ def is_equal_to_ignoring_milliseconds(self, other) -> Self:
118
+ """Asserts that val is a date and is equal to other date to the second.
119
+
120
+ Args:
121
+ other: the other date, expected to be equal to the second
122
+
123
+ Examples:
124
+ Usage::
125
+
126
+ import datetime
127
+
128
+ d1 = datetime.datetime(2020, 1, 2, 3, 4, 5, 6) # 2020-01-02 03:04:05.000006
129
+ d2 = datetime.datetime(2020, 1, 2, 3, 4, 5, 777777) # 2020-01-02 03:04:05.777777
130
+
131
+ assert_that(d1).is_equal_to_ignoring_milliseconds(d2)
132
+
133
+ Returns:
134
+ AssertionBuilder: returns this instance to chain to the next assertion
135
+
136
+ Raises:
137
+ AssertionError: if val is **not** equal to the given date to the second
138
+ """
139
+ if type(self.val) is not datetime.datetime:
140
+ raise TypeError("val must be datetime, but was type <%s>" % type(self.val).__name__)
141
+ if type(other) is not datetime.datetime:
142
+ raise TypeError("given arg must be datetime, but was type <%s>" % type(other).__name__)
143
+ if (
144
+ self.val.date() != other.date()
145
+ or self.val.hour != other.hour
146
+ or self.val.minute != other.minute
147
+ or self.val.second != other.second
148
+ ):
149
+ return self.error(
150
+ "Expected <%s> to be equal to <%s>, but was not."
151
+ % (self.val.strftime("%Y-%m-%d %H:%M:%S"), other.strftime("%Y-%m-%d %H:%M:%S"))
152
+ )
153
+ return self
154
+
155
+ def is_equal_to_ignoring_seconds(self, other) -> Self:
156
+ """Asserts that val is a date and is equal to other date to the minute.
157
+
158
+ Args:
159
+ other: the other date, expected to be equal to the minute
160
+
161
+ Examples:
162
+ Usage::
163
+
164
+ import datetime
165
+
166
+ d1 = datetime.datetime(2020, 1, 2, 3, 4, 5) # 2020-01-02 03:04:05
167
+ d2 = datetime.datetime(2020, 1, 2, 3, 4, 55) # 2020-01-02 03:04:55
168
+
169
+ assert_that(d1).is_equal_to_ignoring_seconds(d2)
170
+
171
+ Returns:
172
+ AssertionBuilder: returns this instance to chain to the next assertion
173
+
174
+ Raises:
175
+ AssertionError: if val is **not** equal to the given date to the minute
176
+ """
177
+ if type(self.val) is not datetime.datetime:
178
+ raise TypeError("val must be datetime, but was type <%s>" % type(self.val).__name__)
179
+ if type(other) is not datetime.datetime:
180
+ raise TypeError("given arg must be datetime, but was type <%s>" % type(other).__name__)
181
+ if self.val.date() != other.date() or self.val.hour != other.hour or self.val.minute != other.minute:
182
+ return self.error(
183
+ "Expected <%s> to be equal to <%s>, but was not."
184
+ % (self.val.strftime("%Y-%m-%d %H:%M"), other.strftime("%Y-%m-%d %H:%M"))
185
+ )
186
+ return self
187
+
188
+ def is_equal_to_ignoring_time(self, other) -> Self:
189
+ """Asserts that val is a date and is equal to other date ignoring time.
190
+
191
+ Args:
192
+ other: the other date, expected to be equal ignoring time
193
+
194
+ Examples:
195
+ Usage::
196
+
197
+ import datetime
198
+
199
+ d1 = datetime.datetime(2020, 1, 2, 3, 4, 5) # 2020-01-02 03:04:05
200
+ d2 = datetime.datetime(2020, 1, 2, 13, 44, 55) # 2020-01-02 13:44:55
201
+
202
+ assert_that(d1).is_equal_to_ignoring_time(d2)
203
+
204
+ Returns:
205
+ AssertionBuilder: returns this instance to chain to the next assertion
206
+
207
+ Raises:
208
+ AssertionError: if val is **not** equal to the given date ignoring time
209
+ """
210
+ if type(self.val) is not datetime.datetime:
211
+ raise TypeError("val must be datetime, but was type <%s>" % type(self.val).__name__)
212
+ if type(other) is not datetime.datetime:
213
+ raise TypeError("given arg must be datetime, but was type <%s>" % type(other).__name__)
214
+ if self.val.date() != other.date():
215
+ return self.error(
216
+ "Expected <%s> to be equal to <%s>, but was not."
217
+ % (self.val.strftime("%Y-%m-%d"), other.strftime("%Y-%m-%d"))
218
+ )
219
+ return self