File: development.rst

package info (click to toggle)
python-returns 0.26.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,652 kB
  • sloc: python: 11,000; makefile: 18
file content (95 lines) | stat: -rw-r--r-- 3,007 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
85
86
87
88
89
90
91
92
93
94
95
.. _development-tooling:

Development tooling
===================

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 :meth:`trace <returns.result.Result.trace>` property
that is available for ``Result``, ``IOResult`` containers. It's basically a list
containing all :class:`inspect.FrameInfo` objects from the call stack when the
``Failure`` was originally created.

To enable it you can use
:func:`collect_traces <returns.primitives.tracing.collect_traces>`.
See examples below:

You can use it as a context manager:

.. code:: python

  >>> 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}`") # doctest: +SKIP
  ...
  /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:

.. code:: python

  >>> 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}`") # doctest: +SKIP
  ...
  /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
-------------

.. automodule:: returns.primitives.tracing
  :members: