Metadata-Version: 2.5
Name: varview
Version: 0.5.4
Summary: A tiny debug-printing helper that prints name: value pairs from the caller's scope, with a one-line kill switch to prevent leaked debug output.
Author-email: Henry <osas2henry@gmail.com>
Keywords: data-validation,debug,debugging,logging,print,variables
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
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: Topic :: Software Development :: Debuggers
Classifier: Topic :: Utilities
Requires-Python: >=3.7
Description-Content-Type: text/markdown

# varview

A tiny, zero-dependency debug-printing helper for people who check their work, for clean automation.

```python
from varview import debug

count = 42
total = 137
status = "active"

debug(["count", "total", "status"])
```

```
count: 42

total: 137

status: active
```

## Why this exists

Most debugging habits start the same way: `print(f"count: {count}")`,
scattered through a script, forgotten about, and left in, or worse,
silently shaping a result nobody meant to ship.

`varview` was built out of a data analyst's day-to-day discipline: **if
you can't see your intermediate values clearly, you can't trust your
final ones.** Threshold sweeps, fold splits, feature combos, backtest
tables, every step that touches a metric is a step where leakage,
silent type coercion, or an off-by-one slice can quietly corrupt a
result. The habit that catches this isn't a debugger or a notebook
full of stray `print()` calls, it's making every checkpoint visible,
on purpose, every time, with a single flip to turn it all off before
anything ships.

That's the whole philosophy behind this package:

- **See it before you trust it.** Print the name and the value, side
  by side, with no risk of the label drifting out of sync with what
  it's labeling.
- **Validate loudly, not quietly.** Every parameter is checked up
  front. Bad input fails fast with a clear error instead of
  producing a confusing result three functions later.
- **Make leakage a choice, not an accident.** One global switch
  silences every debug call in a file at once, so nothing you used to
  sanity-check a fold split or a train/test boundary can slip into
  a shared notebook or a production run by accident.

## Install

```bash
pip install varview
```

## Usage

### Basic

```python
from varview import debug

count = 42
debug(["count"])       # list of names
debug("count")          # a single string also works, no need to wrap it
```

### Unquoted variables also work

You don't have to quote the name at all. `varview` reads the call's
own source code to recover the label, so the variable itself can be
passed directly:

```python
debug([count])          # prints "count: 42", same as debug(["count"])
debug([count, total])   # prints both, labels taken straight from source
```

This is resolved from the source text of the call, not from the
runtime type of the value, so it stays correct even if a variable
happens to hold a string. `bench_marks = "hello"` passed unquoted as
`debug([bench_marks])` still prints `bench_marks: hello`, it is never
mistaken for a name lookup the way a quoted `"bench_marks"` would be.

If the source can't be recovered (for example, calls made from a REPL
or from `exec()`'d code), `varview` falls back to a best-effort
heuristic instead of failing.

### Color-code by what the value means to you

```python
debug(["count"], color="green")   # default, all good
debug(["count"], color="yellow")  # worth a second look
debug(["count"], color="red")     # flag it
```

### Lay it out the way you're scanning

```python
debug(["count", "total", "status"])                              # vertical (default)
debug(["count", "total", "status"], orientation="horizontal")     # count: 42, total: 137, status: active
```

In vertical layout, labels are padded so every colon lines up in a
neat column. Use `align` to control how that padding is applied:

```python
debug(["count", "total", "status"], align="right")   # default, labels right-aligned
debug(["count", "total", "status"], align="left")    # labels left-aligned
debug(["count", "total", "status"], align="center")  # labels centered
```

`align` only affects `orientation="vertical"`. It has no effect on
horizontal output, since there's only one line to begin with.

### Trim the surrounding whitespace

```python
debug(["count", "total"], margin=False)
```

By default, `debug()` prints a blank line before and after its
output so it stands out in a busy terminal or log. Set `margin=False`
for tightly packed output with nothing extra around it.

### Turn one call off without deleting it

```python
debug(["count"], display=False)
```

### Turn every call off at once, before you share or ship

```python
from varview import debug_off, debug_on

debug_off()   # every debug() call in the process goes silent, even display=True ones
# ... run the rest of your pipeline, notebook export, whatever needs to be clean ...
debug_on()    # back to normal for your next debugging session
```

`debug_off()` is the one-line answer to "did I leave a debug print
in this notebook before I sent it to someone." Flip it at the top of
a cell, or right before a scheduled job runs, and every `debug()`
call downstream goes quiet, no hunting through the file for calls
you forgot about.

### Typos don't kill the whole block

```python
debug(["count", "totall", "status"])
# count: 42
# totall: <not found>
# status: active
```

One bad name prints `<not found>` in place instead of raising and
losing every other value you wanted to see. This applies to quoted
names only. Unquoted variables are resolved directly from the
argument itself, so there is no lookup that can fail.

## API

### `debug(names, color="green", display=True, orientation="vertical", align="right", margin=True)`

| Param | Type | Default | Notes |
|---|---|---|---|
| `names` | `str`, `list`/`tuple` of `str`, or unquoted variables | (required) | Names to look up in the caller's local scope, or bare variable expressions whose label is recovered from source |
| `color` | `"green"`, `"red"`, `"yellow"` | `"green"` | Label color only, values always print in black |
| `display` | `bool` | `True` | Silences this one call when `False` |
| `orientation` | `"vertical"`, `"horizontal"` | `"vertical"` | Layout of the printed pairs |
| `align` | `"left"`, `"center"`, `"right"` | `"right"` | Label padding within the column, vertical layout only |
| `margin` | `bool` | `True` | Blank line before and after the printed output |

All parameters are validated on every call: an invalid `color`,
`orientation`, or `align` raises `ValueError`, an invalid `display` or
`margin` type raises `TypeError`, and `names` must be a string, a
list/tuple, or an unquoted expression the source parser can recover,
or it raises `TypeError`. Nothing gets a chance to fail silently or
print something misleading.

### `debug_off()` / `debug_on()`

Module-level switch. `debug_off()` silences every `debug()` call in
the running process, regardless of that call's own `display` value.
`debug_on()` restores normal behavior.

## License

MIT