Summary
update_self()'s own error handler crashes with an unrelated AttributeError instead of showing the intended "Failed to update" message, when the pip install step fails after uninstall has already succeeded.
Where
user_scanner/utils/update.py, line 22
Details
def update_self():
print("Updating user-scanner using pip...\n")
try:
subprocess.check_call([
sys.executable, "-m", "pip", "uninstall", "user-scanner", "-y"
])
subprocess.check_call([
sys.executable, "-m", "pip", "install", "user-scanner"
])
except subprocess.CalledProcessError as e:
print(f"{Fore.RED}Failed to update user-scanner: {e}{Fore.reset}")
return
Fore.reset is lowercase. Colorama's Fore class only exposes Fore.RESET (uppercase), Fore.reset doesn't exist.
Reproduction
Mocked subprocess.check_call so uninstall succeeds and install raises a real subprocess.CalledProcessError (matching what pip actually raises on failure), then called update_self():
Updating user-scanner using pip...
Traceback (most recent call last):
...
File ".../user_scanner/utils/update.py", line 22, in update_self
print(f"{Fore.RED}Failed to update user-scanner: {e}{Fore.reset}")
^^^^^^^^^^
AttributeError: 'AnsiFore' object has no attribute 'reset'
Impact
update_self() uninstalls first, then reinstalls, with no rollback if install fails, for example if the user is offline, which is also the most likely reason a version check would have failed in the first place, see #480. The except block exists specifically to warn the user when this happens, but it crashes before the message is printed, so the user gets a raw traceback with no indication that the tool is now uninstalled.
Suggested fix
Change Fore.reset to Fore.RESET on line 22.
I would like to work on this myself.
Summary
update_self()'s own error handler crashes with an unrelatedAttributeErrorinstead of showing the intended "Failed to update" message, when the pip install step fails after uninstall has already succeeded.Where
user_scanner/utils/update.py, line 22Details
Fore.resetis lowercase. Colorama'sForeclass only exposesFore.RESET(uppercase),Fore.resetdoesn't exist.Reproduction
Mocked
subprocess.check_callso uninstall succeeds and install raises a realsubprocess.CalledProcessError(matching what pip actually raises on failure), then calledupdate_self():Updating user-scanner using pip...
Traceback (most recent call last):
...
File ".../user_scanner/utils/update.py", line 22, in update_self
print(f"{Fore.RED}Failed to update user-scanner: {e}{Fore.reset}")
^^^^^^^^^^
AttributeError: 'AnsiFore' object has no attribute 'reset'
Impact
update_self()uninstalls first, then reinstalls, with no rollback if install fails, for example if the user is offline, which is also the most likely reason a version check would have failed in the first place, see #480. Theexceptblock exists specifically to warn the user when this happens, but it crashes before the message is printed, so the user gets a raw traceback with no indication that the tool is now uninstalled.Suggested fix
Change
Fore.resettoFore.RESETon line 22.I would like to work on this myself.