@@ -270,29 +270,100 @@ def x(self):
270
270
class C (metaclass = meta ):
271
271
pass
272
272
273
+ def test_isinstance_direct_inheritance (self ):
274
+ class A (metaclass = abc_ABCMeta ):
275
+ pass
276
+ class B (A ):
277
+ pass
278
+ class C (A ):
279
+ pass
280
+ a = A ()
281
+ b = B ()
282
+ c = C ()
283
+ # trigger caching
284
+ for _ in range (2 ):
285
+ self .assertIsInstance (a , A )
286
+ self .assertIsInstance (a , (A ,))
287
+ self .assertNotIsInstance (a , B )
288
+ self .assertNotIsInstance (a , (B ,))
289
+ self .assertNotIsInstance (a , C )
290
+ self .assertNotIsInstance (a , (C ,))
291
+
292
+ self .assertIsInstance (b , B )
293
+ self .assertIsInstance (b , (B ,))
294
+ self .assertIsInstance (b , A )
295
+ self .assertIsInstance (b , (A ,))
296
+ self .assertNotIsInstance (b , C )
297
+ self .assertNotIsInstance (b , (C ,))
298
+
299
+ self .assertIsInstance (c , C )
300
+ self .assertIsInstance (c , (C ,))
301
+ self .assertIsInstance (c , A )
302
+ self .assertIsInstance (c , (A ,))
303
+ self .assertNotIsInstance (c , B )
304
+ self .assertNotIsInstance (c , (B ,))
305
+
306
+ self .assertIsSubclass (B , A )
307
+ self .assertIsSubclass (B , (A ,))
308
+ self .assertIsSubclass (C , A )
309
+ self .assertIsSubclass (C , (A ,))
310
+ self .assertNotIsSubclass (B , C )
311
+ self .assertNotIsSubclass (B , (C ,))
312
+ self .assertNotIsSubclass (C , B )
313
+ self .assertNotIsSubclass (C , (B ,))
314
+ self .assertNotIsSubclass (A , B )
315
+ self .assertNotIsSubclass (A , (B ,))
316
+ self .assertNotIsSubclass (A , C )
317
+ self .assertNotIsSubclass (A , (C ,))
318
+
273
319
def test_registration_basics (self ):
274
320
class A (metaclass = abc_ABCMeta ):
275
321
pass
276
322
class B (object ):
277
323
pass
324
+ a = A ()
278
325
b = B ()
279
- self .assertNotIsSubclass (B , A )
280
- self .assertNotIsSubclass (B , (A ,))
281
- self .assertNotIsInstance (b , A )
282
- self .assertNotIsInstance (b , (A ,))
326
+
327
+ # trigger caching
328
+ for _ in range (2 ):
329
+ self .assertNotIsSubclass (B , A )
330
+ self .assertNotIsSubclass (B , (A ,))
331
+ self .assertNotIsInstance (b , A )
332
+ self .assertNotIsInstance (b , (A ,))
333
+
334
+ self .assertNotIsSubclass (A , B )
335
+ self .assertNotIsSubclass (A , (B ,))
336
+ self .assertNotIsInstance (a , B )
337
+ self .assertNotIsInstance (a , (B ,))
338
+
283
339
B1 = A .register (B )
284
- self .assertIsSubclass (B , A )
285
- self .assertIsSubclass (B , (A ,))
286
- self .assertIsInstance (b , A )
287
- self .assertIsInstance (b , (A ,))
288
- self .assertIs (B1 , B )
340
+ # trigger caching
341
+ for _ in range (2 ):
342
+ self .assertIsSubclass (B , A )
343
+ self .assertIsSubclass (B , (A ,))
344
+ self .assertIsInstance (b , A )
345
+ self .assertIsInstance (b , (A ,))
346
+ self .assertIs (B1 , B )
347
+
348
+ self .assertNotIsSubclass (A , B )
349
+ self .assertNotIsSubclass (A , (B ,))
350
+ self .assertNotIsInstance (a , B )
351
+ self .assertNotIsInstance (a , (B ,))
352
+
289
353
class C (B ):
290
354
pass
291
355
c = C ()
292
- self .assertIsSubclass (C , A )
293
- self .assertIsSubclass (C , (A ,))
294
- self .assertIsInstance (c , A )
295
- self .assertIsInstance (c , (A ,))
356
+ # trigger caching
357
+ for _ in range (2 ):
358
+ self .assertIsSubclass (C , A )
359
+ self .assertIsSubclass (C , (A ,))
360
+ self .assertIsInstance (c , A )
361
+ self .assertIsInstance (c , (A ,))
362
+
363
+ self .assertNotIsSubclass (A , C )
364
+ self .assertNotIsSubclass (A , (C ,))
365
+ self .assertNotIsInstance (a , C )
366
+ self .assertNotIsInstance (a , (C ,))
296
367
297
368
def test_register_as_class_deco (self ):
298
369
class A (metaclass = abc_ABCMeta ):
@@ -377,41 +448,75 @@ class A(metaclass=abc_ABCMeta):
377
448
pass
378
449
self .assertIsSubclass (A , A )
379
450
self .assertIsSubclass (A , (A ,))
451
+
380
452
class B (metaclass = abc_ABCMeta ):
381
453
pass
382
454
self .assertNotIsSubclass (A , B )
383
455
self .assertNotIsSubclass (A , (B ,))
384
456
self .assertNotIsSubclass (B , A )
385
457
self .assertNotIsSubclass (B , (A ,))
458
+
386
459
class C (metaclass = abc_ABCMeta ):
387
460
pass
388
461
A .register (B )
389
462
class B1 (B ):
390
463
pass
391
- self .assertIsSubclass (B1 , A )
392
- self .assertIsSubclass (B1 , (A ,))
464
+ # trigger caching
465
+ for _ in range (2 ):
466
+ self .assertIsSubclass (B1 , A )
467
+ self .assertIsSubclass (B1 , (A ,))
468
+
393
469
class C1 (C ):
394
470
pass
395
471
B1 .register (C1 )
396
- self .assertNotIsSubclass (C , B )
397
- self .assertNotIsSubclass (C , (B ,))
398
- self .assertNotIsSubclass (C , B1 )
399
- self .assertNotIsSubclass (C , (B1 ,))
400
- self .assertIsSubclass (C1 , A )
401
- self .assertIsSubclass (C1 , (A ,))
402
- self .assertIsSubclass (C1 , B )
403
- self .assertIsSubclass (C1 , (B ,))
404
- self .assertIsSubclass (C1 , B1 )
405
- self .assertIsSubclass (C1 , (B1 ,))
472
+ # trigger caching
473
+ for _ in range (2 ):
474
+ self .assertNotIsSubclass (C , B )
475
+ self .assertNotIsSubclass (C , (B ,))
476
+ self .assertNotIsSubclass (C , B1 )
477
+ self .assertNotIsSubclass (C , (B1 ,))
478
+ self .assertIsSubclass (C1 , A )
479
+ self .assertIsSubclass (C1 , (A ,))
480
+ self .assertIsSubclass (C1 , B )
481
+ self .assertIsSubclass (C1 , (B ,))
482
+ self .assertIsSubclass (C1 , B1 )
483
+ self .assertIsSubclass (C1 , (B1 ,))
484
+
406
485
C1 .register (int )
407
486
class MyInt (int ):
408
487
pass
409
- self .assertIsSubclass (MyInt , A )
410
- self .assertIsSubclass (MyInt , (A ,))
411
- self .assertIsInstance (42 , A )
412
- self .assertIsInstance (42 , (A ,))
488
+ # trigger caching
489
+ for _ in range (2 ):
490
+ self .assertIsSubclass (MyInt , A )
491
+ self .assertIsSubclass (MyInt , (A ,))
492
+ self .assertIsInstance (42 , A )
493
+ self .assertIsInstance (42 , (A ,))
413
494
414
- def test_subclasses_bad_arguments (self ):
495
+ def test_custom_subclasses (self ):
496
+ class A : pass
497
+ class B : pass
498
+
499
+ class Parent1 (metaclass = abc_ABCMeta ):
500
+ @classmethod
501
+ def __subclasses__ (cls ):
502
+ return [A ]
503
+
504
+ class Parent2 (metaclass = abc_ABCMeta ):
505
+ __subclasses__ = lambda : [A ]
506
+
507
+ # trigger caching
508
+ for _ in range (2 ):
509
+ self .assertIsInstance (A (), Parent1 )
510
+ self .assertIsSubclass (A , Parent1 )
511
+ self .assertNotIsInstance (B (), Parent1 )
512
+ self .assertNotIsSubclass (B , Parent1 )
513
+
514
+ self .assertIsInstance (A (), Parent2 )
515
+ self .assertIsSubclass (A , Parent2 )
516
+ self .assertNotIsInstance (B (), Parent2 )
517
+ self .assertNotIsSubclass (B , Parent2 )
518
+
519
+ def test_issubclass_bad_arguments (self ):
415
520
class A (metaclass = abc_ABCMeta ):
416
521
pass
417
522
@@ -429,6 +534,37 @@ class C:
429
534
with self .assertRaises (TypeError ):
430
535
issubclass (C (), A )
431
536
537
+ # bpo-34441: Check that issubclass() doesn't crash on bogus
538
+ # classes.
539
+ bogus_subclasses = [
540
+ None ,
541
+ lambda x : [],
542
+ lambda : 42 ,
543
+ lambda : [42 ],
544
+ ]
545
+
546
+ for i , func in enumerate (bogus_subclasses ):
547
+ class S (metaclass = abc_ABCMeta ):
548
+ __subclasses__ = func
549
+
550
+ with self .subTest (i = i ):
551
+ with self .assertRaises (TypeError ):
552
+ issubclass (int , S )
553
+
554
+ # Also check that issubclass() propagates exceptions raised by
555
+ # __subclasses__.
556
+ class CustomError (Exception ): ...
557
+ exc_msg = "exception from __subclasses__"
558
+
559
+ def raise_exc ():
560
+ raise CustomError (exc_msg )
561
+
562
+ class S (metaclass = abc_ABCMeta ):
563
+ __subclasses__ = raise_exc
564
+
565
+ with self .assertRaisesRegex (CustomError , exc_msg ):
566
+ issubclass (int , S )
567
+
432
568
def test_subclasshook (self ):
433
569
class A (metaclass = abc .ABCMeta ):
434
570
@classmethod
@@ -491,7 +627,6 @@ def foo(self):
491
627
self .assertEqual (A .__abstractmethods__ , set ())
492
628
A ()
493
629
494
-
495
630
def test_update_new_abstractmethods (self ):
496
631
class A (metaclass = abc_ABCMeta ):
497
632
@abc .abstractmethod
0 commit comments