@@ -1550,6 +1550,56 @@ def f(self):
1550
1550
self .assertIn (('f' , b .f ), inspect .getmembers (b ))
1551
1551
self .assertIn (('f' , b .f ), inspect .getmembers (b , inspect .ismethod ))
1552
1552
1553
+ def test_getmembers_custom_dir (self ):
1554
+ class CorrectDir :
1555
+ def __init__ (self , attr ):
1556
+ self .attr = attr
1557
+ def method (self ):
1558
+ return self .attr + 1
1559
+ def __dir__ (self ):
1560
+ return ['attr' , 'method' ]
1561
+
1562
+ cd = CorrectDir (5 )
1563
+ self .assertEqual (inspect .getmembers (cd ), [
1564
+ ('attr' , 5 ),
1565
+ ('method' , cd .method ),
1566
+ ])
1567
+ self .assertEqual (inspect .getmembers (cd , inspect .ismethod ), [
1568
+ ('method' , cd .method ),
1569
+ ])
1570
+
1571
+ def test_getmembers_custom_broken_dir (self ):
1572
+ # inspect.getmembers calls `dir()` on the passed object inside.
1573
+ # if `__dir__` mentions some non-existent attribute,
1574
+ # we still need to return others correctly.
1575
+ class BrokenDir :
1576
+ existing = 1
1577
+ def method (self ):
1578
+ return self .existing + 1
1579
+ def __dir__ (self ):
1580
+ return ['method' , 'missing' , 'existing' ]
1581
+
1582
+ bd = BrokenDir ()
1583
+ self .assertEqual (inspect .getmembers (bd ), [
1584
+ ('existing' , 1 ),
1585
+ ('method' , bd .method ),
1586
+ ])
1587
+ self .assertEqual (inspect .getmembers (bd , inspect .ismethod ), [
1588
+ ('method' , bd .method ),
1589
+ ])
1590
+
1591
+ def test_getmembers_custom_duplicated_dir (self ):
1592
+ # Duplicates in `__dir__` must not fail and return just one result.
1593
+ class DuplicatedDir :
1594
+ attr = 1
1595
+ def __dir__ (self ):
1596
+ return ['attr' , 'attr' ]
1597
+
1598
+ dd = DuplicatedDir ()
1599
+ self .assertEqual (inspect .getmembers (dd ), [
1600
+ ('attr' , 1 ),
1601
+ ])
1602
+
1553
1603
def test_getmembers_VirtualAttribute (self ):
1554
1604
class M (type ):
1555
1605
def __getattr__ (cls , name ):
0 commit comments