Skip to content

Commit df3750d

Browse files
committed
Really handle OSError
1 parent 1fb4041 commit df3750d

File tree

1 file changed

+55
-53
lines changed

1 file changed

+55
-53
lines changed

bpython/importcompletion.py

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -175,65 +175,67 @@ def find_modules(self, path: Path) -> Generator[Optional[str], None, None]:
175175
# Path is on skiplist
176176
return
177177

178-
try:
179-
children = path.iterdir()
180-
except OSError:
181-
# Path is not readable
182-
return
183-
184178
finder = importlib.machinery.FileFinder(str(path), *LOADERS) # type: ignore
185-
for p in children:
186-
if p.name.startswith(".") or p.name == "__pycache__":
187-
# Impossible to import from names starting with . and we can skip __pycache__
188-
continue
189-
elif any(fnmatch.fnmatch(p.name, entry) for entry in self.skiplist):
190-
# Path is on skiplist
191-
continue
192-
elif not any(p.name.endswith(suffix) for suffix in SUFFIXES):
193-
# Possibly a package
194-
if "." in p.name:
179+
try:
180+
for p in path.iterdir():
181+
if p.name.startswith(".") or p.name == "__pycache__":
182+
# Impossible to import from names starting with . and we can skip __pycache__
195183
continue
196-
elif p.is_dir():
197-
# Unfortunately, CPython just crashes if there is a directory
198-
# which ends with a python extension, so work around.
199-
continue
200-
name = p.name
201-
for suffix in SUFFIXES:
202-
if name.endswith(suffix):
203-
name = name[: -len(suffix)]
204-
break
205-
if name == "badsyntax_pep3120":
206-
# Workaround for issue #166
207-
continue
208-
209-
package_pathname = None
210-
try:
211-
with warnings.catch_warnings():
212-
warnings.simplefilter("ignore", ImportWarning)
213-
spec = finder.find_spec(name)
214-
if spec is None:
184+
elif any(
185+
fnmatch.fnmatch(p.name, entry) for entry in self.skiplist
186+
):
187+
# Path is on skiplist
188+
continue
189+
elif not any(p.name.endswith(suffix) for suffix in SUFFIXES):
190+
# Possibly a package
191+
if "." in p.name:
215192
continue
216-
if spec.submodule_search_locations is not None:
217-
package_pathname = spec.submodule_search_locations[0]
218-
except (ImportError, OSError, SyntaxError, UnicodeEncodeError):
219-
# UnicodeEncodeError happens with Python 3 when there is a filename in some invalid encoding
220-
continue
193+
elif p.is_dir():
194+
# Unfortunately, CPython just crashes if there is a directory
195+
# which ends with a python extension, so work around.
196+
continue
197+
name = p.name
198+
for suffix in SUFFIXES:
199+
if name.endswith(suffix):
200+
name = name[: -len(suffix)]
201+
break
202+
if name == "badsyntax_pep3120":
203+
# Workaround for issue #166
204+
continue
221205

222-
if package_pathname is not None:
223-
path_real = Path(package_pathname).resolve()
206+
package_pathname = None
224207
try:
225-
stat = path_real.stat()
226-
except OSError:
208+
with warnings.catch_warnings():
209+
warnings.simplefilter("ignore", ImportWarning)
210+
spec = finder.find_spec(name)
211+
if spec is None:
212+
continue
213+
if spec.submodule_search_locations is not None:
214+
package_pathname = spec.submodule_search_locations[
215+
0
216+
]
217+
except (ImportError, OSError, SyntaxError, UnicodeEncodeError):
218+
# UnicodeEncodeError happens with Python 3 when there is a filename in some invalid encoding
227219
continue
228-
loaded_inode = _LoadedInode(stat.st_dev, stat.st_ino)
229-
if loaded_inode not in self.paths:
230-
self.paths.add(loaded_inode)
231-
for subname in self.find_modules(path_real):
232-
if subname is None:
233-
yield None # take a break to avoid unresponsiveness
234-
elif subname != "__init__":
235-
yield f"{name}.{subname}"
236-
yield name
220+
221+
if package_pathname is not None:
222+
path_real = Path(package_pathname).resolve()
223+
try:
224+
stat = path_real.stat()
225+
except OSError:
226+
continue
227+
loaded_inode = _LoadedInode(stat.st_dev, stat.st_ino)
228+
if loaded_inode not in self.paths:
229+
self.paths.add(loaded_inode)
230+
for subname in self.find_modules(path_real):
231+
if subname is None:
232+
yield None # take a break to avoid unresponsiveness
233+
elif subname != "__init__":
234+
yield f"{name}.{subname}"
235+
yield name
236+
except OSError:
237+
# Path is not readable
238+
return
237239
yield None # take a break to avoid unresponsiveness
238240

239241
def find_all_modules(

0 commit comments

Comments
 (0)