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 below:
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.
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>`
function (Optional
[~_FunctionType]) –
Union
[~_FunctionType, AbstractContextManager
[None
]]