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
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | |
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
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
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
15 16 17 18 19 20 21 22 23 | |
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
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
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
144 145 146 147 148 149 150 | |
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
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
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
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
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
17 18 | |
UnwatchedRaiseError
Bases: SafeRaiseError
A @raises-decorated function declared exceptions not in the current watched set.
Attrs
func_name: The name of the function that declared the missing exception. declared: The tuple of exceptions declared by the function. missing: The exception not in the current watched set.
Source code in src/saferaise/_errors.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
__str__() -> str
Return a human-readable error message.
Source code in src/saferaise/_errors.py
36 37 38 39 40 41 42 43 44 | |
NotEnteredError
Bases: SafeRaiseError
A context manager was exited without being entered.
Attrs
context_name: The name of the context manager that was not entered.
Source code in src/saferaise/_errors.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
__str__() -> str
Return a human-readable error message.
Source code in src/saferaise/_errors.py
59 60 61 62 | |
NameCollisionError
Bases: SafeRaiseError
The injected watcher key already exists in a module's namespace.
Attrs
module_name: The name of the module where the collision occurred. key: The name of the key that caused the collision.
Source code in src/saferaise/_errors.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
__str__() -> str
Return a human-readable error message.
Source code in src/saferaise/_errors.py
78 79 80 81 | |