#1078

Exception types in an ExternalModule cross as host functions, so sandbox code can't catch them

Openprpercivalopened 11d ago

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 allowed

Expected

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

0

No activity yet.