|
16 | 16 | from copy import deepcopy |
17 | 17 | from contextlib import redirect_stdout |
18 | 18 | from test import support |
| 19 | +from test.support import import_helper |
19 | 20 | from test.support.script_helper import assert_python_ok |
20 | 21 |
|
21 | 22 | try: |
@@ -6319,5 +6320,139 @@ class IntSubclass(int): |
6319 | 6320 | weakref_descriptor.__get__(IntSubclass(), IntSubclass) |
6320 | 6321 |
|
6321 | 6322 |
|
| 6323 | +class TestSubtableDispatchInvariants(unittest.TestCase): |
| 6324 | + |
| 6325 | + def test_int_times_list(self): |
| 6326 | + self.assertEqual(2 * [1], [1, 1]) |
| 6327 | + |
| 6328 | + def test_list_times_int(self): |
| 6329 | + self.assertEqual([1] * 2, [1, 1]) |
| 6330 | + |
| 6331 | + def test_int_times_tuple(self): |
| 6332 | + self.assertEqual(2 * (1,), (1, 1)) |
| 6333 | + |
| 6334 | + def test_tuple_times_int(self): |
| 6335 | + self.assertEqual((1,) * 2, (1, 1)) |
| 6336 | + |
| 6337 | + def test_int_times_str(self): |
| 6338 | + self.assertEqual(2 * "ab", "abab") |
| 6339 | + |
| 6340 | + def test_str_times_int(self): |
| 6341 | + self.assertEqual("ab" * 2, "abab") |
| 6342 | + |
| 6343 | + def test_int_times_bytes(self): |
| 6344 | + self.assertEqual(2 * b"ab", b"abab") |
| 6345 | + |
| 6346 | + def test_int_imul_list(self): |
| 6347 | + a = 2 |
| 6348 | + a *= [1] |
| 6349 | + self.assertEqual(a, [1, 1]) |
| 6350 | + |
| 6351 | + def test_list_imul_int(self): |
| 6352 | + a = [1] |
| 6353 | + a *= 2 |
| 6354 | + self.assertEqual(a, [1, 1]) |
| 6355 | + |
| 6356 | + def test_str_imul_int(self): |
| 6357 | + a = "ab" |
| 6358 | + a *= 2 |
| 6359 | + self.assertEqual(a, "abab") |
| 6360 | + |
| 6361 | + def test_class_without_mul_imul_seq_raises(self): |
| 6362 | + class NoSeq: |
| 6363 | + pass |
| 6364 | + a = NoSeq() |
| 6365 | + with self.assertRaises(TypeError): |
| 6366 | + a *= [1] |
| 6367 | + |
| 6368 | + def test_class_with_empty_seq_methods_imul_seq_raises(self): |
| 6369 | + class HasMulOnly: |
| 6370 | + def __mul__(self, other): |
| 6371 | + return NotImplemented |
| 6372 | + def __index__(self): |
| 6373 | + return 2 |
| 6374 | + a = HasMulOnly() |
| 6375 | + with self.assertRaises(TypeError): |
| 6376 | + a *= [1] |
| 6377 | + |
| 6378 | + def test_int_getitem_raises_type_error(self): |
| 6379 | + x = 5 |
| 6380 | + with self.assertRaises(TypeError): |
| 6381 | + x[0] |
| 6382 | + |
| 6383 | + def test_int_setitem_raises_type_error(self): |
| 6384 | + x = 5 |
| 6385 | + with self.assertRaises(TypeError): |
| 6386 | + x[0] = 1 |
| 6387 | + |
| 6388 | + def test_object_setitem_does_not_coerce_index(self): |
| 6389 | + class BadIndex: |
| 6390 | + called = False |
| 6391 | + |
| 6392 | + def __index__(self): |
| 6393 | + self.called = True |
| 6394 | + raise AssertionError("__index__ called") |
| 6395 | + |
| 6396 | + obj = object() |
| 6397 | + key = BadIndex() |
| 6398 | + with self.assertRaisesRegex(TypeError, |
| 6399 | + "does not support item assignment"): |
| 6400 | + obj[key] = 1 |
| 6401 | + self.assertFalse(key.called) |
| 6402 | + |
| 6403 | + def test_object_delitem_does_not_coerce_index(self): |
| 6404 | + class BadIndex: |
| 6405 | + called = False |
| 6406 | + |
| 6407 | + def __index__(self): |
| 6408 | + self.called = True |
| 6409 | + raise AssertionError("__index__ called") |
| 6410 | + |
| 6411 | + obj = object() |
| 6412 | + key = BadIndex() |
| 6413 | + with self.assertRaisesRegex(TypeError, |
| 6414 | + "does not support item deletion"): |
| 6415 | + del obj[key] |
| 6416 | + self.assertFalse(key.called) |
| 6417 | + |
| 6418 | + def test_object_bool_default(self): |
| 6419 | + class C: |
| 6420 | + pass |
| 6421 | + self.assertTrue(bool(C())) |
| 6422 | + |
| 6423 | + def test_object_bool_with_len(self): |
| 6424 | + class C: |
| 6425 | + def __len__(self): |
| 6426 | + return 0 |
| 6427 | + self.assertFalse(bool(C())) |
| 6428 | + |
| 6429 | + def test_object_bool_with_dunder_bool(self): |
| 6430 | + class C: |
| 6431 | + def __bool__(self): |
| 6432 | + return False |
| 6433 | + self.assertFalse(bool(C())) |
| 6434 | + |
| 6435 | + def test_sequence_check_int_is_false(self): |
| 6436 | + _testlimitedcapi = import_helper.import_module("_testlimitedcapi") |
| 6437 | + self.assertFalse(_testlimitedcapi.sequence_check(5)) |
| 6438 | + |
| 6439 | + def test_mapping_check_int_is_false(self): |
| 6440 | + _testlimitedcapi = import_helper.import_module("_testlimitedcapi") |
| 6441 | + self.assertFalse(_testlimitedcapi.mapping_check(5)) |
| 6442 | + |
| 6443 | + def test_int_index_protocol(self): |
| 6444 | + class MyInt(int): |
| 6445 | + pass |
| 6446 | + a = [10, 20, 30] |
| 6447 | + self.assertEqual(a[MyInt(1)], 20) |
| 6448 | + |
| 6449 | + def test_class_without_index_protocol_subscript_raises(self): |
| 6450 | + class NoIndex: |
| 6451 | + pass |
| 6452 | + a = [10, 20, 30] |
| 6453 | + with self.assertRaises(TypeError): |
| 6454 | + a[NoIndex()] |
| 6455 | + |
| 6456 | + |
6322 | 6457 | if __name__ == "__main__": |
6323 | 6458 | unittest.main() |
0 commit comments