Metadata-Version: 2.4
Name: guardprint
Version: 1.0.0
Summary: Smart Debug Print & Variable Inspector - Drop-in replacement for print() with automatic context and change tracking
Home-page: https://github.com/soumyapriyagoswami/guardprint.git
Author: Soumyapriya Goswami
Author-email: Soumyapriya Goswami <soumyapriya.goswami.it2023@kgec.ac.in>
Maintainer: Soumyapriya Goswami
Maintainer-email: Soumyapriya Goswami <soumyapriya.goswami.it2023@kgec.ac.in>
License: MIT
Project-URL: Homepage, https://github.com/yourusername/guardprint
Project-URL: Documentation, https://guardprint.readthedocs.io
Project-URL: Repository, https://github.com/yourusername/guardprint.git
Project-URL: Issues, https://github.com/yourusername/guardprint/issues
Project-URL: Changelog, https://github.com/yourusername/guardprint/blob/main/CHANGELOG.md
Keywords: debug,print,debugging,output,inspect,variable,context,pretty-print,change-tracking,logging
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Debuggers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Monitoring
Classifier: Natural Language :: English
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: isort>=5.0; extra == "dev"
Requires-Dist: flake8>=6.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=5.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=1.0; extra == "docs"
Dynamic: author
Dynamic: home-page
Dynamic: maintainer
Dynamic: requires-python

# guardprint 🚨

**Smart Debug Print & Variable Inspector** — A drop-in replacement for `print()` with automatic context, pretty-printing, and change tracking.

![Python 3.6+](https://img.shields.io/badge/Python-3.6%2B-blue)
![License: MIT](https://img.shields.io/badge/License-MIT-green)

## 🎯 The Problem

Debugging in Python is messy:

- 🔧 People spam `print(x)` everywhere
- 😕 No context (file, line, function, time)
- 🌀 Hard to track nested structures or changes over time
- 📝 Logging is overkill for quick debugging

## ✨ The Solution

`guardprint` is an **intelligent print function** that automatically adds:
- ✅ Variable names + values
- ✅ File name, line number, function name
- ✅ Timestamps
- ✅ Pretty-printed complex objects
- ✅ Change detection between calls
- ✅ Colorized terminal output

## 🚀 Quick Start

### Installation

```bash
pip install guardprint
```

### Basic Usage

```python
from guardprint import gprint

x = 10
y = {"a": 1, "b": [1, 2, 3]}

gprint(x)
gprint(y)
```

**Output:**
```
[example.py:5 | <module>] 12:34:56.789
x = 10

[example.py:6 | <module>] 12:34:57.012
y = {
    'a': 1,
    'b': [1, 2, 3]
}
```

## 🔥 Killer Feature: Change Detection

Track when variables change:

```python
from guardprint import gprint

x = 10
gprint(x)

x = 20
gprint(x)
```

**Output:**
```
✎ CHANGED: 10 → 20
```

Perfect for debugging loops and state mutations!

## 📚 API Reference

### Core Functions

#### `gprint(*args, **kwargs)`

Smart print with automatic context and formatting.

```python
from guardprint import gprint

# Single variable (auto-detects name)
x = 42
gprint(x)

# Multiple variables
a, b, c = 1, 2, 3
gprint(a, b, c)

# Complex objects (pretty-printed)
data = {"name": "Alice", "scores": [95, 87, 92]}
gprint(data)

# Custom label (when name detection fails)
gprint(expensive_calculation(), label="result")

# Standard print options
gprint(x, sep=" | ", end="\n\n")
```

#### `trace(label="TRACE")`

Display the current call stack.

```python
from guardprint import trace

def process_data():
    trace("checkpoint_1")
    # ... more code ...
    trace("checkpoint_2")
```

**Output:**
```
[TRACE] Call Stack:
  1. main.py:42 in process_data
     process_data()
  2. main.py:55 in <module>
     process_data()
```

#### `diff(obj1, obj2, label="DIFF")`

Show detailed differences between two objects.

```python
from guardprint import diff

old_config = {"debug": False, "port": 8080, "timeout": 30}
new_config = {"debug": True, "port": 8080, "timeout": 60, "workers": 4}

diff(old_config, new_config, label="Config Changes")
```

**Output:**
```
[Config Changes]
  ~ debug:
      was: False
      now: True
  ~ timeout:
      was: 30
      now: 60
  + workers: 4
```

#### `timer(name="timer", action="start|end|lap")`

Measure execution time with microsecond precision.

```python
from guardprint import timer
import time

# Start timer
timer("download", "start")

# ... do some work ...
time.sleep(1.5)

# End timer and get elapsed time
elapsed = timer("download", "end")

# Or use lap for split times
timer("process", "start")
timer("process", "lap")  # Shows elapsed since start
time.sleep(0.5)
timer("process", "lap")  # Shows elapsed since last lap
timer("process", "end")
```

**Output:**
```
⏱ Timer [download] started
⏱ Timer [download]: 1.50s
⏱ Timer [process] lap: 0.00ms
⏱ Timer [process] lap: 500.25ms
⏱ Timer [process]: 500.25ms
```

#### `config(**kwargs)`

Dynamically configure guardprint.

```python
from guardprint import config

# Disable colors
config(use_color=False)

# Disable timestamps
config(use_timestamps=False)

# Disable change tracking
config(track_changes=False)

# Multiple options
config(use_color=False, use_timestamps=False, use_context=False)
```

#### `clear_history()`

Clear the change tracking history.

```python
from guardprint import gprint, clear_history

x = 1
gprint(x)

clear_history()  # Forget previous values

x = 2
gprint(x)  # Will NOT show as changed
```

### Advanced Usage: Custom Instance

Create custom instances with different configurations:

```python
from guardprint import GuardPrint
import sys

# Create instance with specific settings
logger = GuardPrint(
    use_color=True,          # Enable colors
    use_timestamps=True,     # Show timestamps
    use_context=True,        # Show file:line:function
    pretty_print=True,       # Pretty-print objects
    track_changes=True,      # Track value changes
    max_depth=5,             # Max nesting depth
    width=80,                # Line width
    output=sys.stderr        # Output stream
)

# Use like normal
x = 42
logger.gprint(x)

# Each instance has its own change history
logger.clear_history()
```

## 🎨 Configuration Options

All options can be set during initialization or via `config()`:

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `use_color` | bool | `True` | Enable ANSI color output (auto-detects terminal support) |
| `use_timestamps` | bool | `True` | Show timestamps in HH:MM:SS.mmm format |
| `use_context` | bool | `True` | Show file:line:function context |
| `pretty_print` | bool | `True` | Pretty-print dicts, lists, and complex objects |
| `track_changes` | bool | `True` | Enable change detection between calls |
| `max_depth` | int | `5` | Maximum nesting depth for object traversal |
| `width` | int | `80` | Line width for pretty-printing |
| `output` | file | `sys.stdout` | Output stream (stdout, stderr, file, etc.) |

## 🎯 Use Cases

### 1. **Data Pipeline Debugging**

```python
from guardprint import gprint, timer

def process_batch(data):
    timer("batch", "start")
    
    cleaned = clean_data(data)
    gprint(cleaned)
    
    validated = validate_data(cleaned)
    gprint(validated)
    
    timer("batch", "end")
```

### 2. **Configuration Management**

```python
from guardprint import gprint, diff

old_config = load_config("config.old.json")
new_config = load_config("config.json")

diff(old_config, new_config, label="Config Migration")
gprint(new_config)
```

### 3. **State Tracking in Loops**

```python
from guardprint import gprint

for i, item in enumerate(items):
    processed = process(item)
    gprint(processed)  # Easily see when values change
```

### 4. **API Response Inspection**

```python
from guardprint import gprint
import requests

response = requests.get("https://api.example.com/data")
data = response.json()

gprint(data)  # Beautifully formatted JSON
```

### 5. **Performance Profiling**

```python
from guardprint import timer

for algorithm in ["quick", "merge", "bubble"]:
    timer(algorithm, "start")
    run_sort(algorithm)
    elapsed = timer(algorithm, "end")
    # Compare across algorithms
```

## 🌈 Color Support

guardprint automatically detects terminal support and uses colors when available:

- **File/Line Info**: Blue
- **Variable Names**: Yellow
- **Values**: Cyan (numbers), Green (strings), Yellow (None), Red (False)
- **Changes**: Magenta with arrows
- **Traces**: Red
- **Diffs**: Green (+), Red (-), Yellow (~)

Colors can be disabled:

```python
from guardprint import config

config(use_color=False)  # Disable colors
```

## ⚡ Performance Considerations

- **Minimal Overhead**: Only extracts caller info when needed
- **Efficient Change Tracking**: Uses shallow copies for comparison
- **Stream-Based**: Writes directly to output, no buffering
- **No External Dependencies**: Pure Python (uses only stdlib)

## 🔧 Troubleshooting

### Variable Name Not Detected

If `gprint(x)` shows `= value` without the variable name:
- This can happen with complex expressions: `gprint(obj.get("key"))`
- Solution: Use the `label` parameter: `gprint(obj.get("key"), label="key")`

### Colors Not Showing

Colors are auto-detected based on terminal support:
- On non-TTY outputs (redirected to file), colors are disabled automatically
- To force disable: `config(use_color=False)`
- To force enable: `GuardPrint(use_color=True)`

### Change Detection Not Working

Change tracking only works for variables with detected names:
- Ensure gprint is called directly: `gprint(x)` ✅
- Avoid expressions: `gprint(x + 1)` ❌
- Use label for complex cases: `gprint(x + 1, label="result")`

## 📦 Installation & Distribution

### From PyPI (Recommended)

```bash
pip install guardprint
```

### From Source

```bash
git clone https://github.com/yourusername/guardprint.git
cd guardprint
pip install -e .
```

### Requirements

- Python 3.6+
- No external dependencies (uses only Python stdlib)

## 🧪 Testing

Run the test suite:

```bash
pytest test_guardprint.py -v
```

Test coverage:

```bash
pytest test_guardprint.py --cov=guardprint --cov-report=html
```

## 📖 Examples

### Example 1: Web Scraping Debugging

```python
from guardprint import gprint, timer
import requests
from bs4 import BeautifulSoup

timer("scrape", "start")

url = "https://example.com"
response = requests.get(url)
gprint(response.status_code)

soup = BeautifulSoup(response.content, "html.parser")
articles = soup.find_all("article")
gprint(len(articles))

data = [
    {
        "title": a.h2.text,
        "link": a.a["href"],
        "published": a.find("time")["datetime"]
    }
    for a in articles
]

gprint(data)

timer("scrape", "end")
```

### Example 2: Data Processing Pipeline

```python
from guardprint import gprint, diff, trace

def transform_user_data(raw_users):
    trace("start_transform")
    
    # Step 1: Parse
    users = [parse_user(u) for u in raw_users]
    gprint(users)
    
    # Step 2: Validate
    valid_users = [u for u in users if validate_user(u)]
    gprint(len(valid_users))
    
    # Step 3: Enrich
    enriched = [enrich_user(u) for u in valid_users]
    gprint(enriched)
    
    trace("end_transform")
    return enriched
```

### Example 3: Configuration Migration

```python
from guardprint import gprint, diff, config

# Load configs
old_config = load_yaml("config.v1.yaml")
new_config = load_yaml("config.v2.yaml")

# Show what changed
diff(old_config, new_config, label="Breaking Changes")

# Disable timestamps for cleaner output
config(use_timestamps=False)

# Validate each section
for section in ["database", "cache", "logging"]:
    gprint(new_config[section])
```

## 🤝 Contributing

Contributions welcome! Areas for enhancement:

- [ ] JSON/YAML output mode
- [ ] Export to file functionality
- [ ] Remote logging integration
- [ ] Custom formatters
- [ ] Jupyter notebook support
- [ ] Rich library integration
- [ ] Performance metrics collection

## 📄 License

MIT License - see LICENSE.txt for details

## 🙌 Acknowledgments

Inspired by debugging tools in Ruby, JavaScript, and other languages that make development more enjoyable.

## 💭 Why guardprint?

The name comes from the concept of "guarding" your code with smart print statements. It's a pun on:
- **guard**: protecting/watching your code
- **print**: the core Python debugging tool
- **guardprint**: the combination - intelligent debugging

## 📞 Support

- 📖 [Full Documentation](https://guardprint.readthedocs.io)
- 🐛 [Bug Reports](https://github.com/yourusername/guardprint/issues)
- 💬 [Discussions](https://github.com/yourusername/guardprint/discussions)
- 🚀 [Feature Requests](https://github.com/yourusername/guardprint/issues/new?template=feature.md)

---

**Happy debugging! 🚀**
