fix(xurl): treat PermissionError from PATH lookup as unavailable (#322)
is_available() only caught FileNotFoundError and TimeoutExpired. On WSL, a /mnt/c/.../WindowsApps entry on $PATH returns EACCES during exec, and Python raises PermissionError. That escaped is_available() and crashed pipeline.diagnose() before any source ran. Catch OSError instead. It covers FileNotFoundError, PermissionError, and any other spawn-time OS error, so a non-executable xurl on PATH falls through to the next backend instead of aborting the run.
This commit is contained in:
@@ -46,9 +46,10 @@ def is_available() -> bool:
|
|||||||
timeout=10,
|
timeout=10,
|
||||||
)
|
)
|
||||||
return result.returncode == 0 and '"username"' in result.stdout
|
return result.returncode == 0 and '"username"' in result.stdout
|
||||||
except FileNotFoundError:
|
except (OSError, subprocess.TimeoutExpired):
|
||||||
return False
|
# OSError covers FileNotFoundError (no xurl on PATH) and
|
||||||
except subprocess.TimeoutExpired:
|
# PermissionError (a non-executable match on PATH, e.g. WSL's
|
||||||
|
# /mnt/c/.../WindowsApps shim returning EACCES on exec).
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ class TestIsAvailable(unittest.TestCase):
|
|||||||
with mock.patch("subprocess.run", side_effect=FileNotFoundError):
|
with mock.patch("subprocess.run", side_effect=FileNotFoundError):
|
||||||
self.assertFalse(xurl_x.is_available())
|
self.assertFalse(xurl_x.is_available())
|
||||||
|
|
||||||
|
def test_returns_false_on_permission_error(self):
|
||||||
|
# WSL hits this when a Windows-mounted PATH entry points at an
|
||||||
|
# exec-blocked shim (e.g. WindowsApps), which raises PermissionError
|
||||||
|
# before any other PATH candidate is tried.
|
||||||
|
with mock.patch("subprocess.run", side_effect=PermissionError(13, "Permission denied", "xurl")):
|
||||||
|
self.assertFalse(xurl_x.is_available())
|
||||||
|
|
||||||
def test_returns_false_on_timeout(self):
|
def test_returns_false_on_timeout(self):
|
||||||
import subprocess
|
import subprocess
|
||||||
with mock.patch("subprocess.run", side_effect=subprocess.TimeoutExpired("xurl", 10)):
|
with mock.patch("subprocess.run", side_effect=subprocess.TimeoutExpired("xurl", 10)):
|
||||||
|
|||||||
Reference in New Issue
Block a user