Metadata-Version: 2.4
Name: cs-trace
Version: 20260912
Summary: Utilities for tracing operations.
Keywords: python3
Author-email: Cameron Simpson <cs@cskk.id.au>
Description-Content-Type: text/markdown
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Requires-Dist: cs.fs>=20260610
Requires-Dist: cs.lex>=20260912
Requires-Dist: cs.py.stack>=20250724
Requires-Dist: cs.threads>=20260912
Project-URL: MonoRepo Commits, https://bitbucket.org/cameron_simpson/css/commits/branch/main
Project-URL: Monorepo Git Mirror, https://github.com/cameron-simpson/css
Project-URL: Monorepo Hg/Mercurial Mirror, https://hg.sr.ht/~cameron-simpson/css
Project-URL: Source, https://github.com/cameron-simpson/css/blob/main/lib/python/cs/trace.py

Utilities for tracing operations.

*Latest release 20260912*:
Initial PyPI release: Trace class for recording salient decisions and actions for later debugging.



Short summary:


* `Trace`: A class/decorator to trace control flow and decisions. This makes it possible to record function calls and their inner decision chains, and to show these in a nice printout after the fact.

# Classes

## class Trace(cs.threads.HasThreadState)

A class/decorator to trace control flow and decisions.
This makes it possible to record function calls and their
inner decision chains, and to show these in a nice printout
after the fact.

A new trace object adds itself to the records of the ambient trace object.

A trace object supports the context manager protocol, making
it the ambient object, so that it accrues any new trace objects
make inside the context.

    with Trace("name') as T:
        ... add records via T ...

Calling a trace object adds a new record to the trace

    if T("test x==2", x==2):
        T("acting on x==2")
    else:
        T("x != 2")

As a trace object:

    >>> from builtins import print
    >>> with Trace("decide!") as T:
    ...   print("start")
    ...   if T("test 1 for never", 1==2):
    ...     print("never")
    ...   elif T("test 2 for always", 1==1):
    ...     print("always")
    ...     with Trace("inside test 2", T) as T2:
    ...       assert T2 in T.tests
    ...       if T2("inside1",1==1):
    ...         print("true")
    ...       else:
    ...         print("false")
    ...
    start
    always
    true
    >>> T.printt()
    decide!
    ├─test 1 for never -> bool   False
    ├─test 2 for always -> bool  True
    ╰─inside test 2
      ╰─inside1 -> bool          True

As a decorator it calls the function with an additional named
argument `T` which is the `Trace` instance for that call of
the function:

    >>> @Trace
    ... def func(x, T):
    ...   x2 = T(f'{x=} + 2', x+2)
    ...   return x2
    ...
    >>> with Trace("func trace") as T:
    ...   x2 = T("call func with 3", func(3))
    ...   print("x2", x2)
    ...
    x2 5
    >>> T.printt() # doctest: +ELLIPSIS
    func trace
    ├─func(....)
    │ │ from <module>() <doctest cs.trace.Trace[4]>:2
    │ │ x2 = T("call func with 3", func(3))
    │ ├─x=3 + 2 -> int                                 5
    │ ╰─return -> int                                  5
    ╰─call func with 3 -> int                          5

### `Trace.__call__(self, label: str, result='', print=False)`

Calling the trace object records `(abel,result)` and
optionally `print`s.

### `Trace.__firstlineno__`

int([x]) -> integer
int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments
are given.  If x is a number, return x.__int__().  For floating-point
numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string,
bytes, or bytearray instance representing an integer literal in the
given base.  The literal can be preceded by '+' or '-' and be surrounded
by whitespace.  The base defaults to 10.  Valid bases are 0 and 2-36.
Base 0 means to interpret the base from the string as an integer literal.
>>> int('0b100', base=0)
4

### `Trace.__static_attributes__`

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple.
If iterable is specified the tuple is initialized from iterable's items.

If the argument is a tuple, the return value is the same object.

### `Trace.perthread_state`

A `Thread` local object with attributes
which can be used as a context manager to stack attribute values.

Example:

    from cs.threads import ThreadState

    S = ThreadState(verbose=False)

    with S(verbose=True) as prev_attrs:
        if S.verbose:
            print("verbose! (formerly verbose=%s)" % prev_attrs['verbose'])

### `Trace.printt(self, **printt_kw)`

Use `cs.lex.printt()` to print this trace object.
Keyword arguments are passed through.

### `Trace.tabulate(self)`

Tabulate this trace object for use with `cs.lex.printt()`.

# Release Log



*Release 20260912*:
Initial PyPI release: Trace class for recording salient decisions and actions for later debugging.
