@@ -51,8 +51,8 @@ def set_package_root(self, package_root: list[str]) -> None:
51
51
52
52
def flush (self ) -> None :
53
53
"""Start another transaction and empty all caches."""
54
- self .stat_cache : dict [str , os .stat_result ] = {}
55
- self . stat_error_cache : dict [ str , OSError ] = {}
54
+ self .stat_or_none_cache : dict [str , os .stat_result | None ] = {}
55
+
56
56
self .listdir_cache : dict [str , list [str ]] = {}
57
57
self .listdir_error_cache : dict [str , OSError ] = {}
58
58
self .isfile_case_cache : dict [str , bool ] = {}
@@ -62,24 +62,21 @@ def flush(self) -> None:
62
62
self .hash_cache : dict [str , str ] = {}
63
63
self .fake_package_cache : set [str ] = set ()
64
64
65
- def stat (self , path : str ) -> os .stat_result :
66
- if path in self .stat_cache :
67
- return self .stat_cache [path ]
68
- if path in self . stat_error_cache :
69
- raise copy_os_error ( self . stat_error_cache [ path ])
65
+ def stat_or_none (self , path : str ) -> os .stat_result | None :
66
+ if path in self .stat_or_none_cache :
67
+ return self .stat_or_none_cache [path ]
68
+
69
+ st = None
70
70
try :
71
71
st = os .stat (path )
72
- except OSError as err :
72
+ except OSError :
73
73
if self .init_under_package_root (path ):
74
74
try :
75
- return self ._fake_init (path )
75
+ st = self ._fake_init (path )
76
76
except OSError :
77
77
pass
78
- # Take a copy to get rid of associated traceback and frame objects.
79
- # Just assigning to __traceback__ doesn't free them.
80
- self .stat_error_cache [path ] = copy_os_error (err )
81
- raise err
82
- self .stat_cache [path ] = st
78
+
79
+ self .stat_or_none_cache [path ] = st
83
80
return st
84
81
85
82
def init_under_package_root (self , path : str ) -> bool :
@@ -112,9 +109,9 @@ def init_under_package_root(self, path: str) -> bool:
112
109
if not os .path .basename (dirname ).isidentifier ():
113
110
# Can't put an __init__.py in a place that's not an identifier
114
111
return False
115
- try :
116
- st = self .stat (dirname )
117
- except OSError :
112
+
113
+ st = self .stat_or_none (dirname )
114
+ if st is None :
118
115
return False
119
116
else :
120
117
if not stat .S_ISDIR (st .st_mode ):
@@ -145,15 +142,14 @@ def _fake_init(self, path: str) -> os.stat_result:
145
142
assert basename == "__init__.py" , path
146
143
assert not os .path .exists (path ), path # Not cached!
147
144
dirname = os .path .normpath (dirname )
148
- st = self .stat (dirname ) # May raise OSError
145
+ st = os .stat (dirname ) # May raise OSError
149
146
# Get stat result as a list so we can modify it.
150
147
seq : list [float ] = list (st )
151
148
seq [stat .ST_MODE ] = stat .S_IFREG | 0o444
152
149
seq [stat .ST_INO ] = 1
153
150
seq [stat .ST_NLINK ] = 1
154
151
seq [stat .ST_SIZE ] = 0
155
152
st = os .stat_result (seq )
156
- self .stat_cache [path ] = st
157
153
# Make listdir() and read() also pretend this file exists.
158
154
self .fake_package_cache .add (dirname )
159
155
return st
@@ -181,9 +177,8 @@ def listdir(self, path: str) -> list[str]:
181
177
return results
182
178
183
179
def isfile (self , path : str ) -> bool :
184
- try :
185
- st = self .stat (path )
186
- except OSError :
180
+ st = self .stat_or_none (path )
181
+ if st is None :
187
182
return False
188
183
return stat .S_ISREG (st .st_mode )
189
184
@@ -248,18 +243,14 @@ def exists_case(self, path: str, prefix: str) -> bool:
248
243
return res
249
244
250
245
def isdir (self , path : str ) -> bool :
251
- try :
252
- st = self .stat (path )
253
- except OSError :
246
+ st = self .stat_or_none (path )
247
+ if st is None :
254
248
return False
255
249
return stat .S_ISDIR (st .st_mode )
256
250
257
251
def exists (self , path : str ) -> bool :
258
- try :
259
- self .stat (path )
260
- except FileNotFoundError :
261
- return False
262
- return True
252
+ st = self .stat_or_none (path )
253
+ return st is not None
263
254
264
255
def read (self , path : str ) -> bytes :
265
256
if path in self .read_cache :
@@ -269,7 +260,7 @@ def read(self, path: str) -> bytes:
269
260
270
261
# Need to stat first so that the contents of file are from no
271
262
# earlier instant than the mtime reported by self.stat().
272
- self .stat (path )
263
+ self .stat_or_none (path )
273
264
274
265
dirname , basename = os .path .split (path )
275
266
dirname = os .path .normpath (dirname )
@@ -294,8 +285,10 @@ def hash_digest(self, path: str) -> str:
294
285
return self .hash_cache [path ]
295
286
296
287
def samefile (self , f1 : str , f2 : str ) -> bool :
297
- s1 = self .stat (f1 )
298
- s2 = self .stat (f2 )
288
+ s1 = self .stat_or_none (f1 )
289
+ s2 = self .stat_or_none (f2 )
290
+ if s1 is None or s2 is None :
291
+ return False
299
292
return os .path .samestat (s1 , s2 )
300
293
301
294
0 commit comments