@@ -1553,6 +1553,56 @@ def f(self):
15531553 self .assertIn (('f' , b .f ), inspect .getmembers (b ))
15541554 self .assertIn (('f' , b .f ), inspect .getmembers (b , inspect .ismethod ))
15551555
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+
15561606 def test_getmembers_VirtualAttribute (self ):
15571607 class M (type ):
15581608 def __getattr__ (cls , name ):
0 commit comments