Development

Tracing Failures

Sometimes we want to trace where the Failure has occurred in our system, returns provide a way to trace those failures. By default tracing is disabled.

The trace is accessible by trace property that is available for Result, IOResult containers. It’s basically a list containing all inspect.FrameInfo objects from the call stack when the Failure was originally created.

To enable it you can use collect_traces. See examples bellow:

You can use it as a context manager:

>>> from inspect import FrameInfo

>>> from returns.result import Failure, Result
>>> from returns.primitives.tracing import collect_traces

>>> def get_failure(argument: str) -> Result[str, str]:
...     return Failure(argument)

>>> non_traced_failure = get_failure('Normal Failure')
>>> with collect_traces():
...     traced_failure = get_failure('Traced Failure')

>>> assert non_traced_failure.trace is None
>>> assert isinstance(traced_failure.trace, list)
>>> assert all(isinstance(trace_line, FrameInfo) for trace_line in traced_failure.trace)

>>> for trace_line in traced_failure.trace:
...     print(f"{trace_line.filename}:{trace_line.lineno} in `{trace_line.function}`") 
...
/returns/returns/result.py:529 in `Failure`
/example_folder/example.py:5 in `get_failure`
/example_folder/example.py:1 in `<module>`

Or as a decorator:

>>> from inspect import FrameInfo

>>> from returns.io import IOFailure, IOResult
>>> from returns.result import Failure, Result
>>> from returns.primitives.tracing import collect_traces

>>> @collect_traces
... def traced_function(value: str) -> IOResult[str, str]:
...     return IOFailure(value)

>>> non_traced_failure = Failure('Normal Failure')
>>> traced_failure = traced_function('Traced Failure')

>>> assert non_traced_failure.trace is None
>>> assert isinstance(traced_failure.trace, list)
>>> assert all(isinstance(trace_line, FrameInfo) for trace_line in traced_failure.trace)

>>> for trace_line in traced_failure.trace:
...     print(f"{trace_line.filename}:{trace_line.lineno} in `{trace_line.function}`") 
...
/returns/returns/result.py:525 in `Failure`
/returns/returns/io.py:852 in `IOFailure`
/example_folder/example.py:7: in `traced_function`
/usr/lib/python3.8/contextlib.py:75 in `inner`
/example_folder/example.py:1 in `<module>`

Warning

Activating trace can make your program noticeably slower if it has many points where Failure is often created.

Warning

collect_traces is not thread safe, beware to use it with threading!

Warning

Traces are meant to be used during development only.

API Reference

collect_traces() → ContextManager[None][source]
collect_traces(function: _FunctionType) → _FunctionType

Context Manager/Decorator to active traces collect to the Failures.

>>> from inspect import FrameInfo

>>> from returns.io import IOResult
>>> from returns.result import Result
>>> from returns.primitives.tracing import collect_traces

>>> with collect_traces():
...     traced_failure = Result.from_failure('Traced Failure')
>>> non_traced_failure = IOResult.from_failure('Non Traced Failure')

>>> assert non_traced_failure.trace is None
>>> assert isinstance(traced_failure.trace, list)
>>> assert all(isinstance(trace_line, FrameInfo) for trace_line in traced_failure.trace)

>>> for trace_line in traced_failure.trace:
...     print(f'{trace_line.filename}:{trace_line.lineno} in `{trace_line.function}`') 
...
/returns/returns/result.py:525 in `Failure`
/returns/returns/result.py:322 in `from_failure`
/example_folder/example.py:1 in `<module>`
Parameters

function (Optional[~_FunctionType]) –

Return type

Union[~_FunctionType, AbstractContextManager[None]]