pytracecall


Namepytracecall JSON
Version 3.0.2 PyPI version JSON
download
home_pageNone
Summarypytracecall: A debugging module with sync and async decorators (CallTracer and aCallTracer) for tracing function calls, and a function (stack) for logging the current call stack
upload_time2025-08-03 00:44:29
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords debug debugging trace tracer decorator logging stacktrace callstack inspect recursion
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # pytracecall
[![PyPI version](https://img.shields.io/pypi/v/pytracecall.svg)](https://pypi.org/project/pytracecall/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pytracecall.svg)](https://pypi.org/project/pytracecall/)
[![PyPI - License](https://img.shields.io/pypi/l/pytracecall.svg)](https://pypi.org/project/pytracecall/)
[![Coverage Status](https://coveralls.io/repos/github/alexsemenyaka/calltracer/badge.svg?branch=main)](https://coveralls.io/github/alexsemenyaka/calltracer?branch=main)
[![CI/CD Status](https://github.com/alexsemenyaka/calltracer/actions/workflows/ci.yml/badge.svg)](https://github.com/alexsemenyaka/calltracer/actions/workflows/ci.yml)

# Python Call Tracer Module

A debugging module with decorators (`CallTracer`, `aCallTracer`) and a function (`stack`) for tracing function calls and logging the call stack.

This module provides simple yet powerful tools to help you understand your code's execution flow without the need for a full step-by-step debugger. It is designed to integrate seamlessly with Python's standard `logging` module.

***

## Features

-   **Synchronous and Asynchronous Tracing**: Decorators for both standard (`def`) and asynchronous (`async def`) functions.
-   **Concurrency Safe**: The async tracer (`aCallTracer`) uses `contextvars` to safely trace concurrent tasks without mixing up logs.
-   **Data Flow Visibility**: Logs function arguments and return values.
-   **Recursion Visualization**: Automatically indents log messages to clearly show recursion depth, even in concurrent contexts.
-   **Stack Inspection**: Use the `stack()` function to log the current call stack at any point in your code.
-   **Logging Integration**: Works with the standard `logging` module.

***

## Installation

You can install the package from the Python Package Index (PyPI) using **`pip`**.

```bash
pip install pytracecall
```

To ensure you have the latest version, you can use the `--upgrade` flag:

```bash
pip install --upgrade pytracecall
```

***

## Synchronous Usage

First, ensure you configure Python's `logging` module to see the output.

### Basic Configuration

```python
import logging

# Configure logging to display DEBUG level messages
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%H:%M:%S'
)
```

### Basic Tracing

Use the `CallTracer` instance as a decorator to trace a synchronous function.

```python
from calltracer import CallTracer

trace = CallTracer()

@trace
def add(x, y):
    return x + y

add(10, 5)
```

**Output:**

```
21:15:10 - DEBUG - --> Calling add(10, 5)
21:15:10 - DEBUG - <-- Exiting add, returned: 15
```

***

## Asynchronous Usage

The `aCallTracer` decorator is designed specifically for `async def` functions and is safe for concurrent execution.

### Async Example

```python
import asyncio
import logging
from calltracer import aCallTracer, stack

# Basic logging configuration (can be done once)
logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    datefmt="%H:%M:%S",
)

# Create an instance of the ASYNCHRONOUS tracer
async_trace = aCallTracer(level=logging.DEBUG)

class AsyncDataFetcher:
    @async_trace
    async def process_item(self, item_id: str, delay: float):
        await asyncio.sleep(delay)
        return f"Processed {item_id}"

async def main():
    fetcher = AsyncDataFetcher()
    print("\n--- Running two tasks concurrently to show task-safety ---")
    results = await asyncio.gather(
        fetcher.process_item(item_id="A", delay=0.2),
        fetcher.process_item(item_id="B", delay=0.1),
    )
    logging.info("Concurrent results: %s", results)

if __name__ == "__main__":
    asyncio.run(main())
```

### Example Output (Async)

Note how the logs from Task A and B are interleaved, but the indentation remains correct for each independent task.

```
--- Running two tasks concurrently to show task-safety ---
22:01:05 - calltracer.async_tracer - DEBUG - --> Calling AsyncDataFetcher.process_item(<...>, item_id='A', delay=0.2)
22:01:05 - calltracer.async_tracer - DEBUG - --> Calling AsyncDataFetcher.process_item(<...>, item_id='B', delay=0.1)
22:01:05 - calltracer.async_tracer - DEBUG - <-- Exiting AsyncDataFetcher.process_item, returned: 'Processed B'
22:01:05 - calltracer.async_tracer - DEBUG - <-- Exiting AsyncDataFetcher.process_item, returned: 'Processed A'
22:01:05 - root - INFO - Concurrent results: ['Processed A', 'Processed B']
```

***

## API Reference

### `CallTracer` Class (Synchronous)

A factory for creating decorators that trace synchronous (`def`) function/method calls.

#### Initialization

```python
from calltracer import CallTracer
trace = CallTracer(level=logging.INFO)
```

### `aCallTracer` Class (Asynchronous)

A factory for creating decorators that trace asynchronous (`async def`) function/method calls. This tracer is task-safe for concurrent code using `contextvars`.

#### Initialization

```python
from calltracer import aCallTracer
async_trace = aCallTracer(level=logging.INFO)
```

**Parameters for both classes:**

-   **`level`** (`int`, optional): The logging level for trace messages. Defaults to `logging.DEBUG`.
-   **`trace_chain`** (`bool`, optional): If True, accumulates and logs the call chain. Default to False.
-   **`logger`** (`logging.Logger`, optional): The logger instance to use. Defaults to the internal module logger.

### `stack()` Function

Logs the current call stack to the specified logger. This function works in both synchronous and asynchronous code.

#### Signature

```python
stack(level=logging.DEBUG, logger=None, limit=None, start=0)
```

-   **`level`** (`int`, optional): The logging level for the message. Defaults to `logging.DEBUG`.
-   **`logger`** (`logging.Logger`, optional): The logger instance to use. Defaults to the internal module logger.
-   **`limit`** (`int`, optional): The maximum number of frames to display. Defaults to `None` (all frames).
-   **`start`** (`int`, optional): The offset of the first frame to display. Defaults to `0`.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pytracecall",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "debug, debugging, trace, tracer, decorator, logging, stacktrace, callstack, inspect, recursion",
    "author": null,
    "author_email": "Alex Semenyaka <alex.semenyaka@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/61/4b/670df9fa923741ec6e690bc2027572aa7f0f9c4a25b5c8ecdf3df4ba52d2/pytracecall-3.0.2.tar.gz",
    "platform": null,
    "description": "# pytracecall\n[![PyPI version](https://img.shields.io/pypi/v/pytracecall.svg)](https://pypi.org/project/pytracecall/)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pytracecall.svg)](https://pypi.org/project/pytracecall/)\n[![PyPI - License](https://img.shields.io/pypi/l/pytracecall.svg)](https://pypi.org/project/pytracecall/)\n[![Coverage Status](https://coveralls.io/repos/github/alexsemenyaka/calltracer/badge.svg?branch=main)](https://coveralls.io/github/alexsemenyaka/calltracer?branch=main)\n[![CI/CD Status](https://github.com/alexsemenyaka/calltracer/actions/workflows/ci.yml/badge.svg)](https://github.com/alexsemenyaka/calltracer/actions/workflows/ci.yml)\n\n# Python Call Tracer Module\n\nA debugging module with decorators (`CallTracer`, `aCallTracer`) and a function (`stack`) for tracing function calls and logging the call stack.\n\nThis module provides simple yet powerful tools to help you understand your code's execution flow without the need for a full step-by-step debugger. It is designed to integrate seamlessly with Python's standard `logging` module.\n\n***\n\n## Features\n\n-   **Synchronous and Asynchronous Tracing**: Decorators for both standard (`def`) and asynchronous (`async def`) functions.\n-   **Concurrency Safe**: The async tracer (`aCallTracer`) uses `contextvars` to safely trace concurrent tasks without mixing up logs.\n-   **Data Flow Visibility**: Logs function arguments and return values.\n-   **Recursion Visualization**: Automatically indents log messages to clearly show recursion depth, even in concurrent contexts.\n-   **Stack Inspection**: Use the `stack()` function to log the current call stack at any point in your code.\n-   **Logging Integration**: Works with the standard `logging` module.\n\n***\n\n## Installation\n\nYou can install the package from the Python Package Index (PyPI) using **`pip`**.\n\n```bash\npip install pytracecall\n```\n\nTo ensure you have the latest version, you can use the `--upgrade` flag:\n\n```bash\npip install --upgrade pytracecall\n```\n\n***\n\n## Synchronous Usage\n\nFirst, ensure you configure Python's `logging` module to see the output.\n\n### Basic Configuration\n\n```python\nimport logging\n\n# Configure logging to display DEBUG level messages\nlogging.basicConfig(\n    level=logging.DEBUG,\n    format='%(asctime)s - %(levelname)s - %(message)s',\n    datefmt='%H:%M:%S'\n)\n```\n\n### Basic Tracing\n\nUse the `CallTracer` instance as a decorator to trace a synchronous function.\n\n```python\nfrom calltracer import CallTracer\n\ntrace = CallTracer()\n\n@trace\ndef add(x, y):\n    return x + y\n\nadd(10, 5)\n```\n\n**Output:**\n\n```\n21:15:10 - DEBUG - --> Calling add(10, 5)\n21:15:10 - DEBUG - <-- Exiting add, returned: 15\n```\n\n***\n\n## Asynchronous Usage\n\nThe `aCallTracer` decorator is designed specifically for `async def` functions and is safe for concurrent execution.\n\n### Async Example\n\n```python\nimport asyncio\nimport logging\nfrom calltracer import aCallTracer, stack\n\n# Basic logging configuration (can be done once)\nlogging.basicConfig(\n    level=logging.DEBUG,\n    format=\"%(asctime)s - %(name)s - %(levelname)s - %(message)s\",\n    datefmt=\"%H:%M:%S\",\n)\n\n# Create an instance of the ASYNCHRONOUS tracer\nasync_trace = aCallTracer(level=logging.DEBUG)\n\nclass AsyncDataFetcher:\n    @async_trace\n    async def process_item(self, item_id: str, delay: float):\n        await asyncio.sleep(delay)\n        return f\"Processed {item_id}\"\n\nasync def main():\n    fetcher = AsyncDataFetcher()\n    print(\"\\n--- Running two tasks concurrently to show task-safety ---\")\n    results = await asyncio.gather(\n        fetcher.process_item(item_id=\"A\", delay=0.2),\n        fetcher.process_item(item_id=\"B\", delay=0.1),\n    )\n    logging.info(\"Concurrent results: %s\", results)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n### Example Output (Async)\n\nNote how the logs from Task A and B are interleaved, but the indentation remains correct for each independent task.\n\n```\n--- Running two tasks concurrently to show task-safety ---\n22:01:05 - calltracer.async_tracer - DEBUG - --> Calling AsyncDataFetcher.process_item(<...>, item_id='A', delay=0.2)\n22:01:05 - calltracer.async_tracer - DEBUG - --> Calling AsyncDataFetcher.process_item(<...>, item_id='B', delay=0.1)\n22:01:05 - calltracer.async_tracer - DEBUG - <-- Exiting AsyncDataFetcher.process_item, returned: 'Processed B'\n22:01:05 - calltracer.async_tracer - DEBUG - <-- Exiting AsyncDataFetcher.process_item, returned: 'Processed A'\n22:01:05 - root - INFO - Concurrent results: ['Processed A', 'Processed B']\n```\n\n***\n\n## API Reference\n\n### `CallTracer` Class (Synchronous)\n\nA factory for creating decorators that trace synchronous (`def`) function/method calls.\n\n#### Initialization\n\n```python\nfrom calltracer import CallTracer\ntrace = CallTracer(level=logging.INFO)\n```\n\n### `aCallTracer` Class (Asynchronous)\n\nA factory for creating decorators that trace asynchronous (`async def`) function/method calls. This tracer is task-safe for concurrent code using `contextvars`.\n\n#### Initialization\n\n```python\nfrom calltracer import aCallTracer\nasync_trace = aCallTracer(level=logging.INFO)\n```\n\n**Parameters for both classes:**\n\n-   **`level`** (`int`, optional): The logging level for trace messages. Defaults to `logging.DEBUG`.\n-   **`trace_chain`** (`bool`, optional): If True, accumulates and logs the call chain. Default to False.\n-   **`logger`** (`logging.Logger`, optional): The logger instance to use. Defaults to the internal module logger.\n\n### `stack()` Function\n\nLogs the current call stack to the specified logger. This function works in both synchronous and asynchronous code.\n\n#### Signature\n\n```python\nstack(level=logging.DEBUG, logger=None, limit=None, start=0)\n```\n\n-   **`level`** (`int`, optional): The logging level for the message. Defaults to `logging.DEBUG`.\n-   **`logger`** (`logging.Logger`, optional): The logger instance to use. Defaults to the internal module logger.\n-   **`limit`** (`int`, optional): The maximum number of frames to display. Defaults to `None` (all frames).\n-   **`start`** (`int`, optional): The offset of the first frame to display. Defaults to `0`.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "pytracecall: A debugging module with sync and async decorators (CallTracer and aCallTracer) for tracing function calls, and a function (stack) for logging the current call stack",
    "version": "3.0.2",
    "project_urls": null,
    "split_keywords": [
        "debug",
        " debugging",
        " trace",
        " tracer",
        " decorator",
        " logging",
        " stacktrace",
        " callstack",
        " inspect",
        " recursion"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "62bc5803c37cde6d71ed561e034df985c339787ac2820cfc97bfebf9a8887332",
                "md5": "73056db9c30be9dddc257a42c16b7677",
                "sha256": "07ea8a84719849acb7efbad590f2b096b2a82cda55194b100465b980a0695685"
            },
            "downloads": -1,
            "filename": "pytracecall-3.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "73056db9c30be9dddc257a42c16b7677",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 11927,
            "upload_time": "2025-08-03T00:44:28",
            "upload_time_iso_8601": "2025-08-03T00:44:28.789215Z",
            "url": "https://files.pythonhosted.org/packages/62/bc/5803c37cde6d71ed561e034df985c339787ac2820cfc97bfebf9a8887332/pytracecall-3.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "614b670df9fa923741ec6e690bc2027572aa7f0f9c4a25b5c8ecdf3df4ba52d2",
                "md5": "db5c8aa09cb79aa02b8341f5fa6a3bcf",
                "sha256": "50fed4401185f2ea5c397b83dac02afc7779e95556afbedaade3cd1755483a87"
            },
            "downloads": -1,
            "filename": "pytracecall-3.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "db5c8aa09cb79aa02b8341f5fa6a3bcf",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 11373,
            "upload_time": "2025-08-03T00:44:29",
            "upload_time_iso_8601": "2025-08-03T00:44:29.929969Z",
            "url": "https://files.pythonhosted.org/packages/61/4b/670df9fa923741ec6e690bc2027572aa7f0f9c4a25b5c8ecdf3df4ba52d2/pytracecall-3.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-03 00:44:29",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "pytracecall"
}
        
Elapsed time: 1.35452s