25
25
import importlib .machinery
26
26
import sys
27
27
import warnings
28
+ from dataclasses import dataclass
28
29
from pathlib import Path
29
- from typing import Optional , Set , Generator , Tuple , Sequence , Iterable , Union
30
+ from typing import Optional , Set , Generator , Sequence , Iterable , Union
30
31
31
32
from .line import (
32
33
current_word ,
47
48
),
48
49
)
49
50
51
+ _LOADED_INODE_DATACLASS_ARGS = {"frozen" : True }
52
+ if sys .version_info [2 :] >= (3 , 10 ):
53
+ _LOADED_INODE_DATACLASS_ARGS ["slots" ] = True
54
+
55
+
56
+ @dataclass (** _LOADED_INODE_DATACLASS_ARGS )
57
+ class _LoadedInode :
58
+ dev : int
59
+ inode : int
60
+
50
61
51
62
class ModuleGatherer :
52
63
def __init__ (
@@ -60,7 +71,7 @@ def __init__(
60
71
# Cached list of all known modules
61
72
self .modules : Set [str ] = set ()
62
73
# Set of (st_dev, st_ino) to compare against so that paths are not repeated
63
- self .paths : Set [Tuple [ int , int ] ] = set ()
74
+ self .paths : Set [_LoadedInode ] = set ()
64
75
# Patterns to skip
65
76
self .skiplist : Sequence [str ] = (
66
77
skiplist if skiplist is not None else tuple ()
@@ -216,8 +227,9 @@ def find_modules(self, path: Path) -> Generator[Optional[str], None, None]:
216
227
stat = path_real .stat ()
217
228
except OSError :
218
229
continue
219
- if (stat .st_dev , stat .st_ino ) not in self .paths :
220
- self .paths .add ((stat .st_dev , stat .st_ino ))
230
+ loaded_inode = _LoadedInode (stat .st_dev , stat .st_ino )
231
+ if loaded_inode not in self .paths :
232
+ self .paths .add (loaded_inode )
221
233
for subname in self .find_modules (path_real ):
222
234
if subname is None :
223
235
yield None # take a break to avoid unresponsiveness
0 commit comments