API Reference
Top-level API
Safe exception handling through compile-time and runtime validation of raised exceptions.
raises(*exceptions: type[BaseException]) -> Callable[[T], T]
Declare the exceptions a function may raise.
At runtime, validates that each declared exception is in the current
watched set (see enable). Adds the declared exceptions to the
watched set for the duration of the call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*exceptions
|
type[BaseException]
|
Exception types the decorated function is allowed to raise. |
()
|
Returns:
| Type | Description |
|---|---|
Callable[[T], T]
|
A decorator that wraps the function with exception validation. |
Raises:
| Type | Description |
|---|---|
UnwatchedRaiseError
|
If a declared exception is not in the watched set. |
Source code in src/saferaise/_decorator.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
register(*roots: str) -> None
Install the import hook for the given package roots.
Must be called before importing the packages you want to instrument,
and in a separate file from those packages. The hook rewrites every
try/except block at import time so that caught exception types are
automatically added to the watched set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*roots
|
str
|
Top-level package names to instrument (e.g. |
()
|
Example
import saferaise
saferaise.register("myapp") # must come before `import myapp`
import myapp
with saferaise.enable():
myapp.run()
Raises:
| Type | Description |
|---|---|
NameCollisionError
|
If an instrumented module already has an attribute
named |
Source code in src/saferaise/_patcher/_hook.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
is_registered() -> bool
Check if saferaise is registered for the current file.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if saferaise is registered, False otherwise. |
Source code in src/saferaise/_patcher/_common.py
6 7 8 9 10 11 12 13 14 | |
enable() -> Iterator[None]
Enable exception watching with an empty watched set.
Inside this context, any @raises-decorated function will validate that
its declared exceptions are being watched. Use this at the top level of
your application or in tests to activate enforcement.
Example
import saferaise
saferaise.register("myapp")
import myapp
with saferaise.enable():
myapp.run()
Source code in src/saferaise/_watched_exceptions.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
is_enabled() -> bool
Check if exception watching is currently enabled.
Returns:
| Type | Description |
|---|---|
bool
|
True if watching is enabled, False otherwise. |
Source code in src/saferaise/_watched_exceptions.py
128 129 130 131 132 133 134 | |
disable() -> Iterator[None]
Temporarily disable exception watching.
Inside this context, @raises validation is skipped entirely,
regardless of any outer enable or watch_exceptions context.
Use this in production hot paths or during migration when you want
instrumentation in place but enforcement off.
Example
import os
from saferaise import enable, disable
ctx = enable if os.getenv("ENV") != "production" else disable
with ctx():
myapp.run()
Source code in src/saferaise/_watched_exceptions.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | |
unsafe(*exceptions: type[BaseException]) -> Iterator[None]
Add exceptions to the watched set without validating callers.
Useful at bootstrapping boundaries where a try/except would be
artificial - for example, entry points or test harnesses that need
to manually declare which exceptions are acceptable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*exceptions
|
type[BaseException]
|
Exception types to add to the watched set. |
()
|
Example
from saferaise import enable, unsafe, raises
@raises(ValueError)
def parse(raw: str) -> int:
return int(raw)
with enable():
with unsafe(ValueError):
parse("abc") # OK - ValueError manually added to watched set
Source code in src/saferaise/_watched_exceptions.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
Errors
All errors inherit from SafeRaiseError, which itself inherits from BaseException rather than Exception. This is intentional: a bare except Exception block should never silently swallow a saferaise violation.
Note
Import error classes directly from saferaise._errors or catch them by type - they are raised as BaseException subclasses, not Exception.
SafeRaiseError
Bases: BaseException
Base error for all saferaise library errors.
Source code in src/saferaise/_errors.py
1 2 | |
UnwatchedRaiseError
Bases: SafeRaiseError
A @raises-decorated function declared exceptions not in the current watched set.
Source code in src/saferaise/_errors.py
5 6 7 8 9 10 11 12 13 14 15 16 17 | |
NotEnteredError
Bases: SafeRaiseError
A context manager was exited without being entered.
Source code in src/saferaise/_errors.py
20 21 22 23 24 25 | |
NameCollisionError
Bases: SafeRaiseError
The injected watcher key already exists in a module's namespace.
Source code in src/saferaise/_errors.py
28 29 30 31 32 33 34 | |