mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Improve exception handling (#3290)
* fix: except only non-system-exiting exceptions see https://youtu.be/zrVfY9SuO64 * chore: add myself to CONTRIBUTORS file * refactor: explicitly specify possible exceptions If an exception is not an Exception, there are only three options left. see https://docs.python.org/3/library/exceptions.html#exception-hierarchy * refactor: use BaseException for fallback Co-authored-by: Damien Elmes <dae@users.noreply.github.com> * chore: add myself to contributors
This commit is contained in:
parent
a5a39c9302
commit
c0349ea9da
20 changed files with 39 additions and 38 deletions
|
@ -35,7 +35,7 @@ def runHook(hook: str, *args: Any) -> None:
|
|||
for func in hookFuncs:
|
||||
try:
|
||||
func(*args)
|
||||
except:
|
||||
except Exception:
|
||||
hookFuncs.remove(func)
|
||||
raise
|
||||
|
||||
|
@ -46,7 +46,7 @@ def runFilter(hook: str, arg: Any, *args: Any) -> Any:
|
|||
for func in hookFuncs:
|
||||
try:
|
||||
arg = func(arg, *args)
|
||||
except:
|
||||
except Exception:
|
||||
hookFuncs.remove(func)
|
||||
raise
|
||||
return arg
|
||||
|
|
|
@ -99,15 +99,15 @@ class TextImporter(NoteImporter):
|
|||
if not self.delimiter:
|
||||
try:
|
||||
self.dialect = sniffer.sniff("\n".join(self.data[:10]), self.patterns)
|
||||
except:
|
||||
except Exception:
|
||||
try:
|
||||
self.dialect = sniffer.sniff(self.data[0], self.patterns)
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
if self.dialect:
|
||||
try:
|
||||
reader = csv.reader(self.data, self.dialect, doublequote=True)
|
||||
except:
|
||||
except Exception:
|
||||
err()
|
||||
else:
|
||||
if not self.delimiter:
|
||||
|
@ -126,7 +126,7 @@ class TextImporter(NoteImporter):
|
|||
if row:
|
||||
self.numFields = len(row)
|
||||
break
|
||||
except:
|
||||
except Exception:
|
||||
err()
|
||||
self.initMapping()
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ def get_def_lang(user_lang: str | None = None) -> tuple[int, str]:
|
|||
# this will return a different format on Windows (e.g. Italian_Italy), resulting in us falling back to en_US
|
||||
# further below
|
||||
(sys_lang, enc) = locale.getlocale()
|
||||
except:
|
||||
except Exception:
|
||||
# fails on osx
|
||||
sys_lang = "en_US"
|
||||
if user_lang in compatMap:
|
||||
|
|
|
@ -170,7 +170,7 @@ def _err_msg(col: anki.collection.Collection, type: str, texpath: str) -> str:
|
|||
if not log:
|
||||
raise Exception()
|
||||
msg += f"<small><pre>{html.escape(log)}</pre></small>"
|
||||
except:
|
||||
except Exception:
|
||||
msg += col.tr.media_have_you_installed_latex_and_dvipngdvisvgm()
|
||||
return msg
|
||||
|
||||
|
|
|
@ -722,7 +722,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = {QUEUE
|
|||
tot = bad + good
|
||||
try:
|
||||
pct = good / float(tot) * 100
|
||||
except:
|
||||
except Exception:
|
||||
pct = 0
|
||||
i.append(
|
||||
"Correct: <b>%(pct)0.2f%%</b><br>(%(good)d of %(tot)d)"
|
||||
|
|
|
@ -29,7 +29,7 @@ try:
|
|||
|
||||
to_json_bytes: Callable[[Any], bytes] = orjson.dumps
|
||||
from_json_bytes = orjson.loads
|
||||
except:
|
||||
except Exception:
|
||||
print("orjson is missing; DB operations will be slower")
|
||||
|
||||
def to_json_bytes(obj: Any) -> bytes:
|
||||
|
@ -215,7 +215,7 @@ def call(argv: list[str], wait: bool = True, **kwargs: Any) -> int:
|
|||
info = subprocess.STARTUPINFO() # type: ignore
|
||||
try:
|
||||
info.dwFlags |= subprocess.STARTF_USESHOWWINDOW # type: ignore
|
||||
except:
|
||||
except Exception:
|
||||
# pylint: disable=no-member
|
||||
info.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW # type: ignore
|
||||
else:
|
||||
|
@ -286,7 +286,7 @@ def plat_desc() -> str:
|
|||
else:
|
||||
theos = system
|
||||
break
|
||||
except:
|
||||
except Exception:
|
||||
continue
|
||||
return theos
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ def clear_tempfile(tf):
|
|||
try:
|
||||
tf.close()
|
||||
os.unlink(tf.name)
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ class {self.classname()}:
|
|||
for hook in self._hooks:
|
||||
try:
|
||||
hook({", ".join(arg_names)})
|
||||
except:
|
||||
except Exception:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(hook)
|
||||
raise
|
||||
|
@ -163,7 +163,7 @@ class {self.classname()}:
|
|||
for filter in self._hooks:
|
||||
try:
|
||||
{arg_names[0]} = filter({", ".join(arg_names)})
|
||||
except:
|
||||
except Exception:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(filter)
|
||||
raise
|
||||
|
|
|
@ -232,7 +232,7 @@ def setupLangAndBackend(
|
|||
global _qtrans
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, "")
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# add _ and ngettext globals used by legacy code
|
||||
|
@ -630,7 +630,7 @@ def _run(argv: list[str] | None = None, exec: bool = True) -> AnkiApp | None:
|
|||
pmLoadResult = pm.setupMeta()
|
||||
|
||||
Collection.initialize_backend_logging()
|
||||
except:
|
||||
except Exception:
|
||||
# will handle below
|
||||
traceback.print_exc()
|
||||
pm = None
|
||||
|
@ -720,7 +720,7 @@ def _run(argv: list[str] | None = None, exec: bool = True) -> AnkiApp | None:
|
|||
# we must have a usable temp dir
|
||||
try:
|
||||
tempfile.gettempdir()
|
||||
except:
|
||||
except Exception:
|
||||
QMessageBox.critical(
|
||||
None,
|
||||
tr.qt_misc_error(),
|
||||
|
|
|
@ -87,6 +87,7 @@ def show(mw: aqt.AnkiQt) -> QDialog:
|
|||
"Christian Krause",
|
||||
"Christian Rusche",
|
||||
"Dave Druelinger",
|
||||
"David Culley",
|
||||
"David Smith",
|
||||
"Dmitry Mikheev",
|
||||
"Dotan Cohen",
|
||||
|
|
|
@ -248,7 +248,7 @@ class AddonManager:
|
|||
__import__(addon.dir_name)
|
||||
except AbortAddonImport:
|
||||
pass
|
||||
except:
|
||||
except Exception:
|
||||
name = html.escape(addon.human_name())
|
||||
page = addon.page()
|
||||
if page:
|
||||
|
@ -341,7 +341,7 @@ class AddonManager:
|
|||
except json.JSONDecodeError as e:
|
||||
print(f"json error in add-on {module}:\n{e}")
|
||||
return dict()
|
||||
except:
|
||||
except Exception:
|
||||
# missing meta file, etc
|
||||
return dict()
|
||||
|
||||
|
@ -644,7 +644,7 @@ class AddonManager:
|
|||
try:
|
||||
with open(path, encoding="utf8") as f:
|
||||
return json.load(f)
|
||||
except:
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def set_config_help_action(self, module: str, action: Callable[[], str]) -> None:
|
||||
|
|
|
@ -243,7 +243,7 @@ class DataModel(QAbstractTableModel):
|
|||
self._state = self._state.toggle_state()
|
||||
try:
|
||||
self._search_inner(context)
|
||||
except:
|
||||
except Exception:
|
||||
# rollback to prevent inconsistent state
|
||||
self._state = self._state.toggle_state()
|
||||
raise
|
||||
|
|
|
@ -293,7 +293,7 @@ class DebugConsole(QDialog):
|
|||
try:
|
||||
# pylint: disable=exec-used
|
||||
exec(text, vars)
|
||||
except:
|
||||
except Exception:
|
||||
self._output += traceback.format_exc()
|
||||
self._captureOutput(False)
|
||||
buf = ""
|
||||
|
|
|
@ -267,7 +267,7 @@ class DeckConf(QDialog):
|
|||
if i == int(i):
|
||||
i = int(i)
|
||||
ret.append(i)
|
||||
except:
|
||||
except Exception:
|
||||
# invalid, don't update
|
||||
showWarning(tr.scheduling_steps_must_be_numbers())
|
||||
return
|
||||
|
|
|
@ -200,7 +200,7 @@ class AnkiQt(QMainWindow):
|
|||
self.setupUI()
|
||||
self.setupAddons(args)
|
||||
self.finish_ui_setup()
|
||||
except:
|
||||
except Exception:
|
||||
showInfo(tr.qt_misc_error_during_startup(val=traceback.format_exc()))
|
||||
sys.exit(1)
|
||||
# must call this after ui set up
|
||||
|
@ -351,7 +351,7 @@ class AnkiQt(QMainWindow):
|
|||
f.profiles.addItems(profs)
|
||||
try:
|
||||
idx = profs.index(self.pm.name)
|
||||
except:
|
||||
except Exception:
|
||||
idx = 0
|
||||
f.profiles.setCurrentRow(idx)
|
||||
|
||||
|
@ -681,7 +681,7 @@ class AnkiQt(QMainWindow):
|
|||
self.maybeOptimize()
|
||||
if not dev_mode:
|
||||
corrupt = self.col.db.scalar("pragma quick_check") != "ok"
|
||||
except:
|
||||
except Exception:
|
||||
corrupt = True
|
||||
|
||||
try:
|
||||
|
@ -693,7 +693,7 @@ class AnkiQt(QMainWindow):
|
|||
force=False,
|
||||
wait_for_completion=False,
|
||||
)
|
||||
except:
|
||||
except Exception:
|
||||
print("backup on close failed")
|
||||
self.col.close(downgrade=False)
|
||||
except Exception as e:
|
||||
|
|
|
@ -44,7 +44,7 @@ def _patch_pkgutil() -> None:
|
|||
reader = module.__loader__.get_resource_reader(package) # type: ignore[attr-defined]
|
||||
with reader.open_resource(resource) as f:
|
||||
return f.read()
|
||||
except:
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
pkgutil.get_data = get_data_custom
|
||||
|
|
|
@ -384,7 +384,7 @@ class Preferences(QDialog):
|
|||
lang = lang.replace("-", "_")
|
||||
try:
|
||||
return codes.index(lang)
|
||||
except:
|
||||
except Exception:
|
||||
return codes.index("en_US")
|
||||
|
||||
def on_language_index_changed(self, idx: int) -> None:
|
||||
|
|
|
@ -216,7 +216,7 @@ class ProfileManager:
|
|||
self.name = name
|
||||
try:
|
||||
self.profile = self._unpickle(data)
|
||||
except:
|
||||
except Exception:
|
||||
print(traceback.format_exc())
|
||||
QMessageBox.warning(
|
||||
None,
|
||||
|
@ -285,7 +285,7 @@ class ProfileManager:
|
|||
showWarning(tr.profiles_anki_could_not_rename_your_profile())
|
||||
else:
|
||||
raise
|
||||
except:
|
||||
except BaseException:
|
||||
self.db.rollback()
|
||||
raise
|
||||
else:
|
||||
|
@ -386,7 +386,7 @@ class ProfileManager:
|
|||
if self.db:
|
||||
try:
|
||||
self.db.close()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
for suffix in ("", "-journal"):
|
||||
fpath = path + suffix
|
||||
|
@ -406,7 +406,7 @@ create table if not exists profiles
|
|||
data = self.db.scalar(
|
||||
"select cast(data as blob) from profiles where name = '_global'"
|
||||
)
|
||||
except:
|
||||
except Exception:
|
||||
traceback.print_stack()
|
||||
if result.loadError:
|
||||
# already failed, prevent infinite loop
|
||||
|
@ -420,7 +420,7 @@ create table if not exists profiles
|
|||
try:
|
||||
self.meta = self._unpickle(data)
|
||||
return result
|
||||
except:
|
||||
except Exception:
|
||||
traceback.print_stack()
|
||||
print("resetting corrupt _global")
|
||||
result.loadError = True
|
||||
|
|
|
@ -13,7 +13,7 @@ from typing import TypeVar, Union
|
|||
|
||||
try:
|
||||
import PyQt6
|
||||
except:
|
||||
except Exception:
|
||||
from .qt5 import * # type: ignore
|
||||
else:
|
||||
if os.getenv("ENABLE_QT5_COMPAT"):
|
||||
|
|
|
@ -504,13 +504,13 @@ if is_win:
|
|||
def _voice_to_objects(self, voice: Any) -> list[WindowsVoice]:
|
||||
try:
|
||||
langs = voice.GetAttribute("language")
|
||||
except:
|
||||
except Exception:
|
||||
# no associated language; ignore
|
||||
return []
|
||||
langs = lcid_hex_str_to_lang_codes(langs)
|
||||
try:
|
||||
name = voice.GetAttribute("name")
|
||||
except:
|
||||
except Exception:
|
||||
# some voices may not have a name
|
||||
name = "unknown"
|
||||
name = self._tidy_name(name)
|
||||
|
|
Loading…
Reference in a new issue