Skip to content

Commit 626b4ff

Browse files
[CORE] Prevents inconsistent PATH from breaking subprocess executions
It appears "broken" `PATH` environment variable (e.g. ending with a file instead of a directory) may lead to `NotADirectoryError` Python exception. Let's get bulletproof by extending most of subprocess calls expected exceptions to parent `OSError` (or at least by actually catching `NotADirectoryError` explicitly). > closes #164 Co-Authored-By: Michael Bromilow <developer@bromilow.uk>
1 parent 65cd8b5 commit 626b4ff

File tree

12 files changed

+25
-25
lines changed

12 files changed

+25
-25
lines changed

archey/entries/cpu.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def _parse_lscpu_output(cls) -> List[Dict[str, int]]:
101101
"""Same operation but from `lscpu` output"""
102102
try:
103103
cpu_info = check_output("lscpu", env={"LANG": "C"}, universal_newlines=True)
104-
except FileNotFoundError:
104+
except OSError:
105105
return []
106106

107107
nb_threads = cls._THREADS_PER_CORE_REGEXP.findall(cpu_info)
@@ -129,7 +129,7 @@ def _parse_system_profiler() -> List[Dict[str, int]]:
129129
stderr=DEVNULL,
130130
universal_newlines=True,
131131
)
132-
except (FileNotFoundError, CalledProcessError):
132+
except (OSError, CalledProcessError):
133133
# `-json` is not available before Catalina.
134134
return []
135135

@@ -165,7 +165,7 @@ def _parse_sysctl_machdep() -> List[Dict[str, int]]:
165165
stderr=DEVNULL,
166166
universal_newlines=True,
167167
)
168-
except (FileNotFoundError, CalledProcessError):
168+
except (OSError, CalledProcessError):
169169
return []
170170

171171
# `sysctl_output` should exactly contains two lines.
@@ -179,7 +179,7 @@ def _parse_sysctl_cpu_model() -> List[Dict[str, int]]:
179179
sysctl_output = check_output(
180180
["sysctl", "-n", "hw.model", "hw.ncpu"], stderr=DEVNULL, universal_newlines=True
181181
)
182-
except (FileNotFoundError, CalledProcessError):
182+
except (OSError, CalledProcessError):
183183
return []
184184

185185
# `sysctl_output` should exactly contains two lines.

archey/entries/disk.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def _replace_apfs_volumes_by_their_containers(self) -> Dict[str, dict]:
7171
# Call `diskutil` to generate a property list (PList) of all APFS containers
7272
try:
7373
property_list = plistlib.loads(check_output(["diskutil", "apfs", "list", "-plist"]))
74-
except FileNotFoundError:
74+
except OSError:
7575
self._logger.warning(
7676
"APFS volumes cannot be deduplicated as diskutil program could not be found."
7777
)
@@ -186,7 +186,7 @@ def _get_df_output_dict() -> Dict[str, dict]:
186186
check=False,
187187
encoding="utf-8",
188188
).stdout
189-
except FileNotFoundError:
189+
except OSError:
190190
# `df` isn't available on this system.
191191
return {}
192192

archey/entries/distro.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def _fetch_android_release() -> Optional[str]:
3030
release = check_output(
3131
["getprop", "ro.build.version.release"], universal_newlines=True
3232
).rstrip()
33-
except FileNotFoundError:
33+
except OSError:
3434
return None
3535

3636
return f"Android {release}"

archey/entries/gpu.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def _parse_lspci_output() -> List[str]:
4949
"""Based on `lspci` output, return a list of video controllers names"""
5050
try:
5151
lspci_output = check_output(["lspci", "-m"], universal_newlines=True).splitlines()
52-
except (FileNotFoundError, CalledProcessError):
52+
except (OSError, CalledProcessError):
5353
return []
5454

5555
gpus_list = []
@@ -122,7 +122,7 @@ def _parse_system_profiler() -> List[str]:
122122
profiler_output = check_output(
123123
["system_profiler", "SPDisplaysDataType"], stderr=DEVNULL, universal_newlines=True
124124
)
125-
except FileNotFoundError:
125+
except OSError:
126126
return []
127127

128128
return re.findall(r"Chipset Model: (.*)", profiler_output, re.MULTILINE)
@@ -134,7 +134,7 @@ def _parse_pciconf_output() -> List[str]:
134134
pciconf_output = check_output(
135135
["pciconf", "-lv"], stderr=DEVNULL, universal_newlines=True
136136
)
137-
except (FileNotFoundError, CalledProcessError):
137+
except (OSError, CalledProcessError):
138138
return []
139139

140140
gpus_list = []

archey/entries/model.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def _fetch_virtual_env_info(self) -> Optional[str]:
6060
except CalledProcessError:
6161
# Not a virtual environment.
6262
return None
63-
except FileNotFoundError:
63+
except OSError:
6464
# If not available, let's query `virt-what` (privileges usually required).
6565
try:
6666
return (
@@ -130,7 +130,7 @@ def _fetch_sysctl_hw() -> Optional[str]:
130130
model = check_output(
131131
["sysctl", "-n", "hw.model"], stderr=DEVNULL, universal_newlines=True
132132
)
133-
except FileNotFoundError:
133+
except OSError:
134134
return None
135135
except CalledProcessError:
136136
pass
@@ -144,7 +144,7 @@ def _fetch_sysctl_hw() -> Optional[str]:
144144
sysctl_output = check_output(
145145
["sysctl", "-n", f"hw.{hw_oid}"], stderr=DEVNULL, universal_newlines=True
146146
)
147-
except FileNotFoundError:
147+
except OSError:
148148
return None
149149
except CalledProcessError:
150150
pass
@@ -189,7 +189,7 @@ def _fetch_android_device_model() -> Optional[str]:
189189
try:
190190
brand = check_output(["getprop", "ro.product.brand"], universal_newlines=True).rstrip()
191191
model = check_output(["getprop", "ro.product.model"], universal_newlines=True).rstrip()
192-
except FileNotFoundError:
192+
except OSError:
193193
return None
194194

195195
return f"{brand} ({model})"
@@ -202,7 +202,7 @@ def _fetch_freebsd_model() -> Optional[str]:
202202
product = check_output(
203203
["kenv", "smbios.system.version"], universal_newlines=True
204204
).rstrip()
205-
except (FileNotFoundError, CalledProcessError):
205+
except (OSError, CalledProcessError):
206206
return None
207207

208208
return f"{vendor} ({product})"

archey/entries/ram.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ def _get_used_total_values(self) -> Tuple[float, float]:
3939
Tries a variety of methods, increasing compatibility for a wide range of systems.
4040
"""
4141
if platform.system() == "Linux":
42-
with suppress(IndexError, FileNotFoundError):
42+
with suppress(IndexError, OSError):
4343
return self._run_free_dash_m()
4444
elif platform.system() == "FreeBSD":
45-
with suppress(FileNotFoundError):
45+
with suppress(OSError):
4646
return self._run_sysctl_mem()
4747
else:
4848
# Darwin or any other BSD-based system.
49-
with suppress(FileNotFoundError):
49+
with suppress(OSError):
5050
return self._run_sysctl_and_vmstat()
5151

5252
with suppress(OSError):

archey/entries/temperature.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def _get_sensors_output(whitelisted_chip: Optional[str]) -> Optional[str]:
8282
sensors_output = run(
8383
sensors_args, universal_newlines=True, stdout=PIPE, stderr=PIPE, check=True
8484
)
85-
except FileNotFoundError:
85+
except OSError:
8686
return None
8787
except CalledProcessError as called_process_error:
8888
error_message = called_process_error.stderr
@@ -187,7 +187,7 @@ def _run_sysctl_dev_cpu(self) -> None:
187187
stderr=PIPE,
188188
universal_newlines=True,
189189
)
190-
except FileNotFoundError:
190+
except OSError:
191191
# `sysctl` does not seem to be available on this system.
192192
return
193193
except CalledProcessError as error_message:

archey/entries/uptime.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def _parse_uptime_cmd(self) -> timedelta:
7272
"""Tries to get uptime by parsing the `uptime` command"""
7373
try:
7474
uptime_output = run("uptime", env={"LANG": "C"}, stdout=PIPE, stderr=PIPE, check=True)
75-
except FileNotFoundError as error:
75+
except (FileNotFoundError, NotADirectoryError) as error:
7676
raise ArcheyException("Couldn't find `uptime` command on this system.") from error
7777

7878
# Log any `uptime` error messages at warning level.

archey/entries/wan_ip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def _run_dns_query(query: str, resolver: str, ip_version: int, timeout: float) -
8282
stderr=DEVNULL,
8383
universal_newlines=True,
8484
).rstrip()
85-
except (FileNotFoundError, TimeoutExpired, CalledProcessError):
85+
except (OSError, TimeoutExpired, CalledProcessError):
8686
return None
8787

8888
# `ip_address` might be empty here.

archey/entries/window_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def __init__(self, *args, **kwargs):
7676
r"(?<=Name: ).*",
7777
check_output(["wmctrl", "-m"], stderr=DEVNULL, universal_newlines=True),
7878
).group(0)
79-
except (FileNotFoundError, CalledProcessError):
79+
except (OSError, CalledProcessError):
8080
processes = Processes().list
8181
for wm_id, wm_name in WM_DICT.items():
8282
if wm_id in processes:

0 commit comments

Comments
 (0)