@@ -1550,6 +1550,56 @@ def f(self):
15501550 self .assertIn (('f' , b .f ), inspect .getmembers (b ))
15511551 self .assertIn (('f' , b .f ), inspect .getmembers (b , inspect .ismethod ))
15521552
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+
15531603 def test_getmembers_VirtualAttribute (self ):
15541604 class M (type ):
15551605 def __getattr__ (cls , name ):
0 commit comments