Follow-up promised when closing #23. Execution errors are mapped to the idiomatic builtin (RuntimeError, TypeError, KeyError, IndexError, ZeroDivisionError, OverflowError) and parse errors to ValueError, which is right for each case but means "did the rule run and fail" needs a five-clause except:
except (RuntimeError, TypeError, KeyError, IndexError, ArithmeticError):
Proposal
Add a cel.CelError hierarchy whose members also inherit from the builtin they replace, so nothing existing breaks:
class CelError(Exception): ...
class CelParseError(CelError, ValueError): ...
class CelRuntimeError(CelError, RuntimeError): ...
class CelTypeError(CelError, TypeError): ...
class CelKeyError(CelError, KeyError): ...
class CelIndexError(CelError, IndexError): ...
class CelZeroDivisionError(CelError, ZeroDivisionError): ...
class CelOverflowError(CelError, OverflowError): ...
except TypeError keeps working; except cel.CelError catches everything CEL raised; except cel.CelParseError separates a bad rule from a failed check.
Implementation notes
PyO3's create_exception! only takes a single base, so define the classes in a small python/cel/exceptions.py and have map_execution_error_to_python look them up from the module once (a GILOnceCell<Py<PyType>> per class) and raise with PyErr::from_type. Add them to cel.pyi and to the error-handling how-to, whose current table becomes the mapping between the two hierarchies.
Follow-up promised when closing #23. Execution errors are mapped to the idiomatic builtin (
RuntimeError,TypeError,KeyError,IndexError,ZeroDivisionError,OverflowError) and parse errors toValueError, which is right for each case but means "did the rule run and fail" needs a five-clauseexcept:Proposal
Add a
cel.CelErrorhierarchy whose members also inherit from the builtin they replace, so nothing existing breaks:except TypeErrorkeeps working;except cel.CelErrorcatches everything CEL raised;except cel.CelParseErrorseparates a bad rule from a failed check.Implementation notes
PyO3's
create_exception!only takes a single base, so define the classes in a smallpython/cel/exceptions.pyand havemap_execution_error_to_pythonlook them up from the module once (aGILOnceCell<Py<PyType>>per class) and raise withPyErr::from_type. Add them tocel.pyiand to the error-handling how-to, whose current table becomes the mapping between the two hierarchies.