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