@@ -1364,6 +1364,56 @@ def f(self):
13641364 self .assertIn (('f' , b .f ), inspect .getmembers (b ))
13651365 self .assertIn (('f' , b .f ), inspect .getmembers (b , inspect .ismethod ))
13661366
1367+ def test_getmembers_custom_dir (self ):
1368+ class CorrectDir :
1369+ def __init__ (self , attr ):
1370+ self .attr = attr
1371+ def method (self ):
1372+ return self .attr + 1
1373+ def __dir__ (self ):
1374+ return ['attr' , 'method' ]
1375+
1376+ cd = CorrectDir (5 )
1377+ self .assertEqual (inspect .getmembers (cd ), [
1378+ ('attr' , 5 ),
1379+ ('method' , cd .method ),
1380+ ])
1381+ self .assertEqual (inspect .getmembers (cd , inspect .ismethod ), [
1382+ ('method' , cd .method ),
1383+ ])
1384+
1385+ def test_getmembers_custom_broken_dir (self ):
1386+ # inspect.getmembers calls `dir()` on the passed object inside.
1387+ # if `__dir__` mentions some non-existent attribute,
1388+ # we still need to return others correctly.
1389+ class BrokenDir :
1390+ existing = 1
1391+ def method (self ):
1392+ return self .existing + 1
1393+ def __dir__ (self ):
1394+ return ['method' , 'missing' , 'existing' ]
1395+
1396+ bd = BrokenDir ()
1397+ self .assertEqual (inspect .getmembers (bd ), [
1398+ ('existing' , 1 ),
1399+ ('method' , bd .method ),
1400+ ])
1401+ self .assertEqual (inspect .getmembers (bd , inspect .ismethod ), [
1402+ ('method' , bd .method ),
1403+ ])
1404+
1405+ def test_getmembers_custom_duplicated_dir (self ):
1406+ # Duplicates in `__dir__` must not fail and return just one result.
1407+ class DuplicatedDir :
1408+ attr = 1
1409+ def __dir__ (self ):
1410+ return ['attr' , 'attr' ]
1411+
1412+ dd = DuplicatedDir ()
1413+ self .assertEqual (inspect .getmembers (dd ), [
1414+ ('attr' , 1 ),
1415+ ])
1416+
13671417 def test_getmembers_VirtualAttribute (self ):
13681418 class M (type ):
13691419 def __getattr__ (cls , name ):
0 commit comments