Skip to main content

brokk_bifrost_python/
exception_identity.rs

1/// Whether one exact builtin exception class is a subtype of another builtin
2/// exception class. `None` means either name is outside the known hierarchy.
3pub fn python_builtin_exception_is_subclass(name: &str, expected: &str) -> Option<bool> {
4    let name = canonical_exception_name(name)?;
5    let expected = canonical_exception_name(expected)?;
6    if name == expected {
7        return Some(true);
8    }
9
10    let mut current = name;
11    while let Some(parent) = exception_parent(current) {
12        if parent == expected {
13            return Some(true);
14        }
15        // ExceptionGroup inherits from both BaseExceptionGroup and Exception.
16        if current == "ExceptionGroup" && expected == "Exception" {
17            return Some(true);
18        }
19        current = parent;
20    }
21    Some(false)
22}
23
24/// Return the canonical exception class name when `name` is a builtin exception.
25/// Builtin identity itself must be established by the shared lexical identity path.
26pub fn python_builtin_exception_name(name: &str) -> Option<&'static str> {
27    EXCEPTION_PARENTS
28        .iter()
29        .find_map(|(exception, _)| (*exception == name).then_some(*exception))
30}
31
32fn canonical_exception_name(name: &str) -> Option<&'static str> {
33    if matches!(name, "EnvironmentError" | "IOError") {
34        return Some("OSError");
35    }
36    python_builtin_exception_name(name)
37}
38
39fn exception_parent(name: &str) -> Option<&'static str> {
40    EXCEPTION_PARENTS
41        .iter()
42        .find_map(|(exception, parent)| (*exception == name).then_some(*parent))
43        .flatten()
44}
45
46const EXCEPTION_PARENTS: &[(&str, Option<&str>)] = &[
47    ("BaseException", None),
48    ("BaseExceptionGroup", Some("BaseException")),
49    ("Exception", Some("BaseException")),
50    ("ExceptionGroup", Some("BaseExceptionGroup")),
51    ("GeneratorExit", Some("BaseException")),
52    ("KeyboardInterrupt", Some("BaseException")),
53    ("SystemExit", Some("BaseException")),
54    ("ArithmeticError", Some("Exception")),
55    ("FloatingPointError", Some("ArithmeticError")),
56    ("OverflowError", Some("ArithmeticError")),
57    ("ZeroDivisionError", Some("ArithmeticError")),
58    ("AssertionError", Some("Exception")),
59    ("AttributeError", Some("Exception")),
60    ("BufferError", Some("Exception")),
61    ("EOFError", Some("Exception")),
62    ("ImportError", Some("Exception")),
63    ("ModuleNotFoundError", Some("ImportError")),
64    ("LookupError", Some("Exception")),
65    ("IndexError", Some("LookupError")),
66    ("KeyError", Some("LookupError")),
67    ("MemoryError", Some("Exception")),
68    ("NameError", Some("Exception")),
69    ("UnboundLocalError", Some("NameError")),
70    ("OSError", Some("Exception")),
71    ("EnvironmentError", Some("OSError")),
72    ("IOError", Some("OSError")),
73    ("BlockingIOError", Some("OSError")),
74    ("ChildProcessError", Some("OSError")),
75    ("ConnectionError", Some("OSError")),
76    ("BrokenPipeError", Some("ConnectionError")),
77    ("ConnectionAbortedError", Some("ConnectionError")),
78    ("ConnectionRefusedError", Some("ConnectionError")),
79    ("ConnectionResetError", Some("ConnectionError")),
80    ("FileExistsError", Some("OSError")),
81    ("FileNotFoundError", Some("OSError")),
82    ("InterruptedError", Some("OSError")),
83    ("IsADirectoryError", Some("OSError")),
84    ("NotADirectoryError", Some("OSError")),
85    ("PermissionError", Some("OSError")),
86    ("ProcessLookupError", Some("OSError")),
87    ("TimeoutError", Some("OSError")),
88    ("ReferenceError", Some("Exception")),
89    ("RuntimeError", Some("Exception")),
90    ("NotImplementedError", Some("RuntimeError")),
91    ("RecursionError", Some("RuntimeError")),
92    ("StopIteration", Some("Exception")),
93    ("StopAsyncIteration", Some("Exception")),
94    ("SyntaxError", Some("Exception")),
95    ("IndentationError", Some("SyntaxError")),
96    ("TabError", Some("IndentationError")),
97    ("SystemError", Some("Exception")),
98    ("TypeError", Some("Exception")),
99    ("ValueError", Some("Exception")),
100    ("UnicodeError", Some("ValueError")),
101    ("UnicodeDecodeError", Some("UnicodeError")),
102    ("UnicodeEncodeError", Some("UnicodeError")),
103    ("UnicodeTranslateError", Some("UnicodeError")),
104    ("Warning", Some("Exception")),
105    ("BytesWarning", Some("Warning")),
106    ("DeprecationWarning", Some("Warning")),
107    ("EncodingWarning", Some("Warning")),
108    ("FutureWarning", Some("Warning")),
109    ("ImportWarning", Some("Warning")),
110    ("PendingDeprecationWarning", Some("Warning")),
111    ("ResourceWarning", Some("Warning")),
112    ("RuntimeWarning", Some("Warning")),
113    ("SyntaxWarning", Some("Warning")),
114    ("UnicodeWarning", Some("Warning")),
115    ("UserWarning", Some("Warning")),
116];