@@ -1364,6 +1364,56 @@ def f(self):
1364
1364
self .assertIn (('f' , b .f ), inspect .getmembers (b ))
1365
1365
self .assertIn (('f' , b .f ), inspect .getmembers (b , inspect .ismethod ))
1366
1366
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
+
1367
1417
def test_getmembers_VirtualAttribute (self ):
1368
1418
class M (type ):
1369
1419
def __getattr__ (cls , name ):
0 commit comments