Skip to main content

1686. gopy exceptions

What we are porting

Objects/exceptions.c (~3000 lines). The full exception class hierarchy plus the special slots (__traceback__, __cause__, __context__, __suppress_context__, __notes__) and the constructor-specific args-slot handling.

The hierarchy is wide: BaseException -> Exception -> ArithmeticError -> {OverflowError, FloatingPointError, ZeroDivisionError}, LookupError -> {IndexError, KeyError}, OSError with the platform errno subclasses (FileNotFoundError, PermissionError, etc.), SyntaxError with the position fields, ImportError with name/path, StopIteration with value, and so on. ~70 leaf classes total.

v0.3 already shipped BaseException and the gating subset (1611); this spec is the full panel.

Go shape

// BaseException is the root. Mirrors PyBaseExceptionObject.
type BaseException struct {
Header
Args *Tuple
Traceback Object // *Traceback or None
Cause Object // BaseException or None
Context Object // BaseException or None
SuppressContext bool
Notes *List // PEP 678
Dict *Dict // instance __dict__
}

Each subclass either reuses BaseException's struct directly or embeds it and adds typed fields. The typed fields appear on:

  • SyntaxError: msg, filename, lineno, offset, text, end_lineno, end_offset, print_file_and_line.
  • ImportError: msg, name, path.
  • OSError: errno, strerror, filename, filename2, characters_written.
  • UnicodeError / Unicode{Encode,Decode,Translate}Error: encoding, object, start, end, reason.
  • StopIteration: value.
  • KeyError: overrides __str__ (the only subclass that does).

KeyError str

KeyError's __str__ returns repr(args[0]) when len(args) == 1, otherwise falls through to BaseException's __str__. The override exists so str({}[k]) shows the missing key with quotes if it is a string. Pinned by 1611 and re-exercised here.

OSError errno mapping

OSError dispatches on errno at construction time to the right subclass:

EINTR -> InterruptedError
EAGAIN -> BlockingIOError
EPIPE -> BrokenPipeError
EISDIR -> IsADirectoryError
...

Same mapping table as CPython. We hand-port the table from exceptions.c:_PyErr_OSErrorTraversalSetClassesEntry.

File mapping

C sourceGo target
Objects/exceptions.c BaseExceptionobjects/exc_base.go (already in 1611)
Exception / StopIteration / GeneratorExitobjects/exc_simple.go
ArithmeticError + subclassesobjects/exc_arithmetic.go
LookupError / IndexError / KeyErrorobjects/exc_lookup.go
OSError + errno-mapped subclassesobjects/exc_os.go
SyntaxErrorobjects/exc_syntax.go
ImportError + Module/Modulenot variantsobjects/exc_import.go
UnicodeError + 4 variantsobjects/exc_unicode.go
Warning + subclassesobjects/exc_warnings.go
ExceptionGroup / BaseExceptionGroupobjects/exc_group.go

Checklist

Status legend: [x] shipped, [ ] pending, [~] partial / scaffold, [n] deferred / not in scope this phase.

Files

  • [~] objects/exc_base.go: BaseException with args, traceback, cause, context, suppress_context, notes, dict. v0.3 shipped.
  • [~] objects/exc_lookup.go: LookupError, IndexError, KeyError with the __str__ override. v0.3 shipped.
  • objects/exc_simple.go: Exception, StopIteration (with value), StopAsyncIteration, GeneratorExit, AssertionError, AttributeError (with name/obj), NameError (with name), UnboundLocalError, RuntimeError, NotImplementedError, RecursionError, ReferenceError, BufferError, MemoryError, EOFError, KeyboardInterrupt, SystemExit (with code), TypeError, ValueError, TimeoutError.
  • objects/exc_arithmetic.go: ArithmeticError, OverflowError, FloatingPointError, ZeroDivisionError.
  • objects/exc_os.go: OSError with the errno -> subclass mapping; BlockingIOError, ChildProcessError, ConnectionError + 4 subclasses, FileExistsError, FileNotFoundError, InterruptedError, IsADirectoryError, NotADirectoryError, PermissionError, ProcessLookupError, TimeoutError.
  • objects/exc_syntax.go: SyntaxError with msg, filename, lineno, offset, text, end_lineno, end_offset, plus IndentationError and TabError.
  • objects/exc_import.go: ImportError with name/path, ModuleNotFoundError.
  • objects/exc_unicode.go: UnicodeError, UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError with encoding, object, start, end, reason.
  • objects/exc_warnings.go: Warning + DeprecationWarning, PendingDeprecationWarning, SyntaxWarning, RuntimeWarning, FutureWarning, ImportWarning, UnicodeWarning, BytesWarning, ResourceWarning, EncodingWarning.
  • objects/exc_group.go: BaseExceptionGroup, ExceptionGroup, with split, subgroup, derive. PEP 654.
  • objects/exc_test.go: args byte-equality panel, errno mapping, KeyError __str__.

Surface guarantees

  • KeyError({}).__str__() matches CPython byte-for-byte. Pinned by 1611.
  • Args slot is byte-equal to CPython for every constructor in the hierarchy. Pinned by compat/exc_args_test.go.
  • OSError(errno=2) returns FileNotFoundError per the errno table.
  • SyntaxError pretty-print includes the caret line for end_offset > offset.
  • ExceptionGroup split partitions per the type or callable predicate; cause / context propagate.
  • __notes__ survives pickling (lands with v0.8 marshal).
  • repr(exc) matches CPython (uses the class name plus repr(args)).
  • raise X from Y sets __cause__ and __suppress_context__ = True.

Cross-references

  • errors package raise/normalise: 1611.
  • Traceback object: 1687 (alongside frame).
  • Print exception (sys.excepthook default): 1611 / sysconfig.

Out of scope

  • User-defined exception subclassing through Python class syntax. Lands once user types are reachable (v0.7).