Source code for qsarkit.base.exceptions

"""Shared exception hierarchy for qsarkit.

Keeping a single hierarchy lets callers catch ``QsarkitError`` at a package
boundary (e.g. a curation pipeline that must not crash on one bad record)
while still being able to distinguish failure modes when needed.
"""

from __future__ import annotations


[docs] class QsarkitError(Exception): """Base class for all qsarkit exceptions."""
[docs] class InvalidMoleculeError(QsarkitError): """Raised when an input cannot be parsed or sanitized into an RDKit Mol."""
[docs] class ModelNotFittedError(QsarkitError): """Raised when ``.transform``/``.predict`` is called before ``.fit``."""
[docs] class OptionalDependencyError(QsarkitError): """Raised when an optional dependency required by a feature is missing.""" def __init__(self, package: str, extra: str | None = None): msg = f"This feature requires the optional dependency '{package}'." if extra: msg += f" Install it with: pip install qsarkit-learn[{extra}]" else: msg += f" Install it with: pip install {package}" super().__init__(msg) self.package = package self.extra = extra
#: Exceptions RDKit raises when it cannot process one particular molecule. #: #: Catch this rather than bare ``Exception`` in a per-molecule loop. The #: three members cover every way RDKit signals "this structure is not #: usable": #: #: * ``ValueError`` -- the base of RDKit's whole sanitization hierarchy #: (``MolSanitizeException``, ``AtomValenceException``, #: ``KekulizeException``), and of InChI generation failures. #: * ``RuntimeError`` -- lower-level C++ errors surfaced by the wrapper, #: such as a conformer or substructure-match failure. #: * ``TypeError`` -- a non-``Mol`` argument reaching a wrapped function. #: ``Boost.Python.ArgumentError`` subclasses this. #: #: What it deliberately does *not* catch is ``MemoryError`` (which is an #: ``Exception`` subclass, so a bare ``except Exception`` swallows it) or #: ``KeyboardInterrupt``. Those are real failures of the run, not of one #: molecule, and must propagate. #: #: Examples #: -------- #: >>> from rdkit import Chem #: >>> from qsarkit.base import RDKIT_MOLECULE_ERRORS #: >>> def safe_inchikey(mol): #: ... try: #: ... return Chem.MolToInchiKey(mol) #: ... except RDKIT_MOLECULE_ERRORS: #: ... return None #: >>> safe_inchikey("not a molecule") is None #: True RDKIT_MOLECULE_ERRORS = (ValueError, RuntimeError, TypeError)