Summary
An exception class passed as an ExternalModule attribute crosses as a host function, because it is callable. Sandbox code then can't use it as an exception type: except hostmod.MyError: raises TypeError: catching classes that do not inherit from BaseException is not allowed.
That makes it impossible for a host module to mirror a stdlib module that defines its own exception, e.g. statistics.StatisticsError (a ValueError subclass), so that except statistics.StatisticsError: works inside the sandbox.
Reproduction (pydantic-monty 1.2.0, CPython 3.12)
from pydantic_monty import ExternalModule, Monty
with Monty() as pool:
module = ExternalModule({"MyError": ValueError})
with pool.checkout(external_modules={"hostmod": module}) as session:
print(session.feed_run("import hostmod\n[repr(hostmod.MyError), hostmod.MyError is ValueError]"))
print(session.feed_run(
"try:\n"
" raise ValueError('x')\n"
"except hostmod.MyError:\n"
" 'caught'\n"
))Output:
["<function 'hostmod.MyError' external>", False]
Traceback (most recent call last):
...
pydantic_monty.MontyRuntimeError: TypeError: catching classes that do not inherit from BaseException is not allowedExpected
hostmod.MyError binds as the builtin type ValueError (so hostmod.MyError is ValueError and the except catches), or the docs say exception types can't be module attributes.
A subclass of a builtin exception defined on the host (class StatisticsError(ValueError)) would ideally bind as its nearest builtin base, or as a sandbox type that inherits from it, so except works with either name.
Notes
The ExternalModule docstring says "callables cross as host functions", so this may be working as designed for functions. Exception types are the case where that rule surprises, since they're callables that code needs as types. The protocol already has a Type node, which looks like the natural form for them.
Activity
0No activity yet.