varview 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,144 @@
1
+ # varview
2
+
3
+ A tiny, zero-dependency debug-printing helper for people who check their work, for clean automation.
4
+
5
+ ```python
6
+ from varview import debug
7
+
8
+ count = 42
9
+ total = 137
10
+ status = "active"
11
+
12
+ debug(["count", "total", "status"])
13
+ ```
14
+
15
+ ```
16
+ count: 42
17
+
18
+ total: 137
19
+
20
+ status: active
21
+ ```
22
+
23
+ ## Why this exists
24
+
25
+ Most debugging habits start the same way: `print(f"count: {count}")`,
26
+ scattered through a script, forgotten about, and left in, or worse,
27
+ silently shaping a result nobody meant to ship.
28
+
29
+ `varview` was built out of a data analyst's day-to-day discipline: **if
30
+ you can't see your intermediate values clearly, you can't trust your
31
+ final ones.** Threshold sweeps, fold splits, feature combos, backtest
32
+ tables: every step that touches a metric is a step where leakage,
33
+ silent type coercion, or an off-by-one slice can quietly corrupt a
34
+ result. The habit that catches this isn't a debugger or a notebook
35
+ full of stray `print()` calls, it's making every checkpoint visible,
36
+ on purpose, every time, with a single flip to turn it all off before
37
+ anything ships.
38
+
39
+ That's the whole philosophy behind this package:
40
+
41
+ - **See it before you trust it.** Print the name *and* the value,
42
+ side by side, with no risk of the label drifting out of sync with
43
+ what it's labeling.
44
+ - **Validate loudly, not quietly.** Every parameter is checked up
45
+ front; bad input fails fast with a clear error instead of
46
+ producing a confusing result three functions later.
47
+ - **Make leakage a choice, not an accident.** One global switch
48
+ silences every debug call in a file at once, so nothing you used to
49
+ sanity-check a fold split or a train/test boundary can slip into
50
+ a shared notebook or a production run by accident.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pip install varview
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ### Basic
61
+
62
+ ```python
63
+ from varview import debug
64
+
65
+ count = 42
66
+ debug(["count"]) # list of names
67
+ debug("count") # a single string also works, no need to wrap it
68
+ ```
69
+
70
+ ### Color-code by what the value means to you
71
+
72
+ ```python
73
+ debug(["count"], color="green") # default, all good
74
+ debug(["count"], color="yellow") # worth a second look
75
+ debug(["count"], color="red") # flag it
76
+ ```
77
+
78
+ ### Lay it out the way you're scanning
79
+
80
+ ```python
81
+ debug(["count", "total", "status"]) # vertical (default)
82
+ debug(["count", "total", "status"], orientation="horizontal") # count: 42, total: 137, status: active
83
+ ```
84
+
85
+ ### Turn one call off without deleting it
86
+
87
+ ```python
88
+ debug(["count"], display=False)
89
+ ```
90
+
91
+ ### Turn every call off at once, before you share or ship
92
+
93
+ ```python
94
+ from varview import debug_off, debug_on
95
+
96
+ debug_off() # every debug() call in the process goes silent, even display=True ones
97
+ # ... run the rest of your pipeline, notebook export, whatever needs to be clean ...
98
+ debug_on() # back to normal for your next debugging session
99
+ ```
100
+
101
+ `debug_off()` is the one-line answer to "did I leave a debug print
102
+ in this notebook before I sent it to someone." Flip it at the top of
103
+ a cell, or right before a scheduled job runs, and every `debug()`
104
+ call downstream goes quiet, no hunting through the file for calls
105
+ you forgot about.
106
+
107
+ ### Typos don't kill the whole block
108
+
109
+ ```python
110
+ debug(["count", "totall", "status"])
111
+ # count: 42
112
+ # totall: <not found>
113
+ # status: active
114
+ ```
115
+
116
+ One bad name prints `<not found>` in place instead of raising and
117
+ losing every other value you wanted to see.
118
+
119
+ ## API
120
+
121
+ ### `debug(names, color="green", display=True, orientation="vertical")`
122
+
123
+ | Param | Type | Default | Notes |
124
+ |---|---|---|---|
125
+ | `names` | `str` or `list`/`tuple` of `str` | (required) | Variable names to look up in the *caller's* local scope |
126
+ | `color` | `"green"`, `"red"`, `"yellow"` | `"green"` | Label color only; values always print in black |
127
+ | `display` | `bool` | `True` | Silences this one call when `False` |
128
+ | `orientation` | `"vertical"`, `"horizontal"` | `"vertical"` | Layout of the printed pairs |
129
+
130
+ All four parameters are validated on every call: an invalid `color`
131
+ or `orientation` raises `ValueError`, an invalid `display` type raises
132
+ `TypeError`, and `names` must be a string or a list/tuple of strings
133
+ or it raises `TypeError`. Nothing gets a chance to fail silently or
134
+ print something misleading.
135
+
136
+ ### `debug_off()` / `debug_on()`
137
+
138
+ Module-level switch. `debug_off()` silences every `debug()` call in
139
+ the running process, regardless of that call's own `display` value.
140
+ `debug_on()` restores normal behavior.
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "varview"
7
+ version = "0.1.0"
8
+ description = "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."
9
+ readme = "README.md"
10
+ requires-python = ">=3.7"
11
+ authors = [
12
+ { name = "Henry", email = "osas2henry@gmail.com" }
13
+ ]
14
+ keywords = ["debug", "debugging", "print", "variables", "logging", "data-validation"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.7",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Software Development :: Debuggers",
26
+ "Topic :: Utilities",
27
+ ]
@@ -0,0 +1,30 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ with open("README.md", "r", encoding="utf-8") as f:
4
+ long_description = f.read()
5
+
6
+ setup(
7
+ name="varview",
8
+ version="0.1.0",
9
+ description="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.",
10
+ long_description=long_description,
11
+ long_description_content_type="text/markdown",
12
+ author="Henry",
13
+ author_email="osas2henry@gmail.com",
14
+ packages=find_packages(),
15
+ keywords=["debug", "debugging", "print", "variables", "logging", "data-validation"],
16
+ classifiers=[
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.7",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Software Development :: Debuggers",
27
+ "Topic :: Utilities",
28
+ ],
29
+ python_requires=">=3.7",
30
+ )
varview-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.5
2
+ Name: varview
3
+ Version: 0.1.0
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.
5
+ Author-email: Henry <osas2henry@gmail.com>
6
+ Keywords: data-validation,debug,debugging,logging,print,variables
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.7
11
+ Classifier: Programming Language :: Python :: 3.8
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Debuggers
17
+ Classifier: Topic :: Utilities
18
+ Requires-Python: >=3.7
19
+ Description-Content-Type: text/markdown
20
+
21
+ # varview
22
+
23
+ A tiny, zero-dependency debug-printing helper for people who check their work, for clean automation.
24
+
25
+ ```python
26
+ from varview import debug
27
+
28
+ count = 42
29
+ total = 137
30
+ status = "active"
31
+
32
+ debug(["count", "total", "status"])
33
+ ```
34
+
35
+ ```
36
+ count: 42
37
+
38
+ total: 137
39
+
40
+ status: active
41
+ ```
42
+
43
+ ## Why this exists
44
+
45
+ Most debugging habits start the same way: `print(f"count: {count}")`,
46
+ scattered through a script, forgotten about, and left in, or worse,
47
+ silently shaping a result nobody meant to ship.
48
+
49
+ `varview` was built out of a data analyst's day-to-day discipline: **if
50
+ you can't see your intermediate values clearly, you can't trust your
51
+ final ones.** Threshold sweeps, fold splits, feature combos, backtest
52
+ tables: every step that touches a metric is a step where leakage,
53
+ silent type coercion, or an off-by-one slice can quietly corrupt a
54
+ result. The habit that catches this isn't a debugger or a notebook
55
+ full of stray `print()` calls, it's making every checkpoint visible,
56
+ on purpose, every time, with a single flip to turn it all off before
57
+ anything ships.
58
+
59
+ That's the whole philosophy behind this package:
60
+
61
+ - **See it before you trust it.** Print the name *and* the value,
62
+ side by side, with no risk of the label drifting out of sync with
63
+ what it's labeling.
64
+ - **Validate loudly, not quietly.** Every parameter is checked up
65
+ front; bad input fails fast with a clear error instead of
66
+ producing a confusing result three functions later.
67
+ - **Make leakage a choice, not an accident.** One global switch
68
+ silences every debug call in a file at once, so nothing you used to
69
+ sanity-check a fold split or a train/test boundary can slip into
70
+ a shared notebook or a production run by accident.
71
+
72
+ ## Install
73
+
74
+ ```bash
75
+ pip install varview
76
+ ```
77
+
78
+ ## Usage
79
+
80
+ ### Basic
81
+
82
+ ```python
83
+ from varview import debug
84
+
85
+ count = 42
86
+ debug(["count"]) # list of names
87
+ debug("count") # a single string also works, no need to wrap it
88
+ ```
89
+
90
+ ### Color-code by what the value means to you
91
+
92
+ ```python
93
+ debug(["count"], color="green") # default, all good
94
+ debug(["count"], color="yellow") # worth a second look
95
+ debug(["count"], color="red") # flag it
96
+ ```
97
+
98
+ ### Lay it out the way you're scanning
99
+
100
+ ```python
101
+ debug(["count", "total", "status"]) # vertical (default)
102
+ debug(["count", "total", "status"], orientation="horizontal") # count: 42, total: 137, status: active
103
+ ```
104
+
105
+ ### Turn one call off without deleting it
106
+
107
+ ```python
108
+ debug(["count"], display=False)
109
+ ```
110
+
111
+ ### Turn every call off at once, before you share or ship
112
+
113
+ ```python
114
+ from varview import debug_off, debug_on
115
+
116
+ debug_off() # every debug() call in the process goes silent, even display=True ones
117
+ # ... run the rest of your pipeline, notebook export, whatever needs to be clean ...
118
+ debug_on() # back to normal for your next debugging session
119
+ ```
120
+
121
+ `debug_off()` is the one-line answer to "did I leave a debug print
122
+ in this notebook before I sent it to someone." Flip it at the top of
123
+ a cell, or right before a scheduled job runs, and every `debug()`
124
+ call downstream goes quiet, no hunting through the file for calls
125
+ you forgot about.
126
+
127
+ ### Typos don't kill the whole block
128
+
129
+ ```python
130
+ debug(["count", "totall", "status"])
131
+ # count: 42
132
+ # totall: <not found>
133
+ # status: active
134
+ ```
135
+
136
+ One bad name prints `<not found>` in place instead of raising and
137
+ losing every other value you wanted to see.
138
+
139
+ ## API
140
+
141
+ ### `debug(names, color="green", display=True, orientation="vertical")`
142
+
143
+ | Param | Type | Default | Notes |
144
+ |---|---|---|---|
145
+ | `names` | `str` or `list`/`tuple` of `str` | (required) | Variable names to look up in the *caller's* local scope |
146
+ | `color` | `"green"`, `"red"`, `"yellow"` | `"green"` | Label color only; values always print in black |
147
+ | `display` | `bool` | `True` | Silences this one call when `False` |
148
+ | `orientation` | `"vertical"`, `"horizontal"` | `"vertical"` | Layout of the printed pairs |
149
+
150
+ All four parameters are validated on every call: an invalid `color`
151
+ or `orientation` raises `ValueError`, an invalid `display` type raises
152
+ `TypeError`, and `names` must be a string or a list/tuple of strings
153
+ or it raises `TypeError`. Nothing gets a chance to fail silently or
154
+ print something misleading.
155
+
156
+ ### `debug_off()` / `debug_on()`
157
+
158
+ Module-level switch. `debug_off()` silences every `debug()` call in
159
+ the running process, regardless of that call's own `display` value.
160
+ `debug_on()` restores normal behavior.
161
+
162
+ ## License
163
+
164
+ MIT
@@ -0,0 +1,144 @@
1
+ # varview
2
+
3
+ A tiny, zero-dependency debug-printing helper for people who check their work, for clean automation.
4
+
5
+ ```python
6
+ from varview import debug
7
+
8
+ count = 42
9
+ total = 137
10
+ status = "active"
11
+
12
+ debug(["count", "total", "status"])
13
+ ```
14
+
15
+ ```
16
+ count: 42
17
+
18
+ total: 137
19
+
20
+ status: active
21
+ ```
22
+
23
+ ## Why this exists
24
+
25
+ Most debugging habits start the same way: `print(f"count: {count}")`,
26
+ scattered through a script, forgotten about, and left in, or worse,
27
+ silently shaping a result nobody meant to ship.
28
+
29
+ `varview` was built out of a data analyst's day-to-day discipline: **if
30
+ you can't see your intermediate values clearly, you can't trust your
31
+ final ones.** Threshold sweeps, fold splits, feature combos, backtest
32
+ tables: every step that touches a metric is a step where leakage,
33
+ silent type coercion, or an off-by-one slice can quietly corrupt a
34
+ result. The habit that catches this isn't a debugger or a notebook
35
+ full of stray `print()` calls, it's making every checkpoint visible,
36
+ on purpose, every time, with a single flip to turn it all off before
37
+ anything ships.
38
+
39
+ That's the whole philosophy behind this package:
40
+
41
+ - **See it before you trust it.** Print the name *and* the value,
42
+ side by side, with no risk of the label drifting out of sync with
43
+ what it's labeling.
44
+ - **Validate loudly, not quietly.** Every parameter is checked up
45
+ front; bad input fails fast with a clear error instead of
46
+ producing a confusing result three functions later.
47
+ - **Make leakage a choice, not an accident.** One global switch
48
+ silences every debug call in a file at once, so nothing you used to
49
+ sanity-check a fold split or a train/test boundary can slip into
50
+ a shared notebook or a production run by accident.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pip install varview
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ### Basic
61
+
62
+ ```python
63
+ from varview import debug
64
+
65
+ count = 42
66
+ debug(["count"]) # list of names
67
+ debug("count") # a single string also works, no need to wrap it
68
+ ```
69
+
70
+ ### Color-code by what the value means to you
71
+
72
+ ```python
73
+ debug(["count"], color="green") # default, all good
74
+ debug(["count"], color="yellow") # worth a second look
75
+ debug(["count"], color="red") # flag it
76
+ ```
77
+
78
+ ### Lay it out the way you're scanning
79
+
80
+ ```python
81
+ debug(["count", "total", "status"]) # vertical (default)
82
+ debug(["count", "total", "status"], orientation="horizontal") # count: 42, total: 137, status: active
83
+ ```
84
+
85
+ ### Turn one call off without deleting it
86
+
87
+ ```python
88
+ debug(["count"], display=False)
89
+ ```
90
+
91
+ ### Turn every call off at once, before you share or ship
92
+
93
+ ```python
94
+ from varview import debug_off, debug_on
95
+
96
+ debug_off() # every debug() call in the process goes silent, even display=True ones
97
+ # ... run the rest of your pipeline, notebook export, whatever needs to be clean ...
98
+ debug_on() # back to normal for your next debugging session
99
+ ```
100
+
101
+ `debug_off()` is the one-line answer to "did I leave a debug print
102
+ in this notebook before I sent it to someone." Flip it at the top of
103
+ a cell, or right before a scheduled job runs, and every `debug()`
104
+ call downstream goes quiet, no hunting through the file for calls
105
+ you forgot about.
106
+
107
+ ### Typos don't kill the whole block
108
+
109
+ ```python
110
+ debug(["count", "totall", "status"])
111
+ # count: 42
112
+ # totall: <not found>
113
+ # status: active
114
+ ```
115
+
116
+ One bad name prints `<not found>` in place instead of raising and
117
+ losing every other value you wanted to see.
118
+
119
+ ## API
120
+
121
+ ### `debug(names, color="green", display=True, orientation="vertical")`
122
+
123
+ | Param | Type | Default | Notes |
124
+ |---|---|---|---|
125
+ | `names` | `str` or `list`/`tuple` of `str` | (required) | Variable names to look up in the *caller's* local scope |
126
+ | `color` | `"green"`, `"red"`, `"yellow"` | `"green"` | Label color only; values always print in black |
127
+ | `display` | `bool` | `True` | Silences this one call when `False` |
128
+ | `orientation` | `"vertical"`, `"horizontal"` | `"vertical"` | Layout of the printed pairs |
129
+
130
+ All four parameters are validated on every call: an invalid `color`
131
+ or `orientation` raises `ValueError`, an invalid `display` type raises
132
+ `TypeError`, and `names` must be a string or a list/tuple of strings
133
+ or it raises `TypeError`. Nothing gets a chance to fail silently or
134
+ print something misleading.
135
+
136
+ ### `debug_off()` / `debug_on()`
137
+
138
+ Module-level switch. `debug_off()` silences every `debug()` call in
139
+ the running process, regardless of that call's own `display` value.
140
+ `debug_on()` restores normal behavior.
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,144 @@
1
+ # varview
2
+
3
+ A tiny, zero-dependency debug-printing helper for people who check their work, for clean automation.
4
+
5
+ ```python
6
+ from varview import debug
7
+
8
+ count = 42
9
+ total = 137
10
+ status = "active"
11
+
12
+ debug(["count", "total", "status"])
13
+ ```
14
+
15
+ ```
16
+ count: 42
17
+
18
+ total: 137
19
+
20
+ status: active
21
+ ```
22
+
23
+ ## Why this exists
24
+
25
+ Most debugging habits start the same way: `print(f"count: {count}")`,
26
+ scattered through a script, forgotten about, and left in, or worse,
27
+ silently shaping a result nobody meant to ship.
28
+
29
+ `varview` was built out of a data analyst's day-to-day discipline: **if
30
+ you can't see your intermediate values clearly, you can't trust your
31
+ final ones.** Threshold sweeps, fold splits, feature combos, backtest
32
+ tables: every step that touches a metric is a step where leakage,
33
+ silent type coercion, or an off-by-one slice can quietly corrupt a
34
+ result. The habit that catches this isn't a debugger or a notebook
35
+ full of stray `print()` calls, it's making every checkpoint visible,
36
+ on purpose, every time, with a single flip to turn it all off before
37
+ anything ships.
38
+
39
+ That's the whole philosophy behind this package:
40
+
41
+ - **See it before you trust it.** Print the name *and* the value,
42
+ side by side, with no risk of the label drifting out of sync with
43
+ what it's labeling.
44
+ - **Validate loudly, not quietly.** Every parameter is checked up
45
+ front; bad input fails fast with a clear error instead of
46
+ producing a confusing result three functions later.
47
+ - **Make leakage a choice, not an accident.** One global switch
48
+ silences every debug call in a file at once, so nothing you used to
49
+ sanity-check a fold split or a train/test boundary can slip into
50
+ a shared notebook or a production run by accident.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pip install varview
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ### Basic
61
+
62
+ ```python
63
+ from varview import debug
64
+
65
+ count = 42
66
+ debug(["count"]) # list of names
67
+ debug("count") # a single string also works, no need to wrap it
68
+ ```
69
+
70
+ ### Color-code by what the value means to you
71
+
72
+ ```python
73
+ debug(["count"], color="green") # default, all good
74
+ debug(["count"], color="yellow") # worth a second look
75
+ debug(["count"], color="red") # flag it
76
+ ```
77
+
78
+ ### Lay it out the way you're scanning
79
+
80
+ ```python
81
+ debug(["count", "total", "status"]) # vertical (default)
82
+ debug(["count", "total", "status"], orientation="horizontal") # count: 42, total: 137, status: active
83
+ ```
84
+
85
+ ### Turn one call off without deleting it
86
+
87
+ ```python
88
+ debug(["count"], display=False)
89
+ ```
90
+
91
+ ### Turn every call off at once, before you share or ship
92
+
93
+ ```python
94
+ from varview import debug_off, debug_on
95
+
96
+ debug_off() # every debug() call in the process goes silent, even display=True ones
97
+ # ... run the rest of your pipeline, notebook export, whatever needs to be clean ...
98
+ debug_on() # back to normal for your next debugging session
99
+ ```
100
+
101
+ `debug_off()` is the one-line answer to "did I leave a debug print
102
+ in this notebook before I sent it to someone." Flip it at the top of
103
+ a cell, or right before a scheduled job runs, and every `debug()`
104
+ call downstream goes quiet, no hunting through the file for calls
105
+ you forgot about.
106
+
107
+ ### Typos don't kill the whole block
108
+
109
+ ```python
110
+ debug(["count", "totall", "status"])
111
+ # count: 42
112
+ # totall: <not found>
113
+ # status: active
114
+ ```
115
+
116
+ One bad name prints `<not found>` in place instead of raising and
117
+ losing every other value you wanted to see.
118
+
119
+ ## API
120
+
121
+ ### `debug(names, color="green", display=True, orientation="vertical")`
122
+
123
+ | Param | Type | Default | Notes |
124
+ |---|---|---|---|
125
+ | `names` | `str` or `list`/`tuple` of `str` | (required) | Variable names to look up in the *caller's* local scope |
126
+ | `color` | `"green"`, `"red"`, `"yellow"` | `"green"` | Label color only; values always print in black |
127
+ | `display` | `bool` | `True` | Silences this one call when `False` |
128
+ | `orientation` | `"vertical"`, `"horizontal"` | `"vertical"` | Layout of the printed pairs |
129
+
130
+ All four parameters are validated on every call: an invalid `color`
131
+ or `orientation` raises `ValueError`, an invalid `display` type raises
132
+ `TypeError`, and `names` must be a string or a list/tuple of strings
133
+ or it raises `TypeError`. Nothing gets a chance to fail silently or
134
+ print something misleading.
135
+
136
+ ### `debug_off()` / `debug_on()`
137
+
138
+ Module-level switch. `debug_off()` silences every `debug()` call in
139
+ the running process, regardless of that call's own `display` value.
140
+ `debug_on()` restores normal behavior.
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "varview"
7
+ version = "0.1.0"
8
+ description = "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."
9
+ readme = "README.md"
10
+ requires-python = ">=3.7"
11
+ authors = [
12
+ { name = "Henry", email = "osas2henry@gmail.com" }
13
+ ]
14
+ keywords = ["debug", "debugging", "print", "variables", "logging", "data-validation"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.7",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Software Development :: Debuggers",
26
+ "Topic :: Utilities",
27
+ ]
varview-0.1.0/setup.py ADDED
@@ -0,0 +1,30 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ with open("README.md", "r", encoding="utf-8") as f:
4
+ long_description = f.read()
5
+
6
+ setup(
7
+ name="varview",
8
+ version="0.1.0",
9
+ description="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.",
10
+ long_description=long_description,
11
+ long_description_content_type="text/markdown",
12
+ author="Henry",
13
+ author_email="osas2henry@gmail.com",
14
+ packages=find_packages(),
15
+ keywords=["debug", "debugging", "print", "variables", "logging", "data-validation"],
16
+ classifiers=[
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.7",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Software Development :: Debuggers",
27
+ "Topic :: Utilities",
28
+ ],
29
+ python_requires=">=3.7",
30
+ )
@@ -0,0 +1,192 @@
1
+ """
2
+ varview
3
+ ~~~~~~~
4
+
5
+ A tiny debug-printing helper: pass variable names as strings and it
6
+ prints "name: value" pairs pulled straight from the caller's local
7
+ scope — no need to write out f"{name}: {value}" by hand.
8
+
9
+ Basic usage:
10
+ from varview import debug
11
+
12
+ count = 42
13
+ debug(["count"]) # green label, black value
14
+ debug("count") # single string also works
15
+ debug(["count"], color="red")
16
+ debug(["count"], orientation="horizontal")
17
+
18
+ Global kill switch (silence every debug() call in one line, e.g.
19
+ before sharing a notebook or shipping to prod):
20
+ from varview import debug_off, debug_on
21
+ debug_off()
22
+ debug_on()
23
+ """
24
+
25
+ import inspect
26
+
27
+ __all__ = ["debug", "debug_off", "debug_on"]
28
+ __version__ = "0.1.0"
29
+
30
+ _DEBUG_GLOBAL_ENABLED = True # flip via debug_off()/debug_on() to silence ALL debug() calls at once
31
+
32
+
33
+ def debug(names, color="green", display=True, orientation="vertical"):
34
+ """
35
+ Pass a list of variable name strings, or a single name as a plain
36
+ string, and this prints each one as "name: value" (name bolded in
37
+ the chosen color, value always black).
38
+
39
+ e.g. debug(["count", "total", "status"])
40
+ debug("count") <- single string also works, auto-wrapped
41
+ into a one-item list so it isn't split
42
+ into characters.
43
+
44
+ `color` picks the name/label color: "green", "red", or "yellow".
45
+ Defaults to "green". Raises ValueError if anything else is passed.
46
+
47
+ `display` toggles THIS SPECIFIC call. Defaults to True. Must be a
48
+ bool, or TypeError is raised.
49
+
50
+ Printing only happens if BOTH `display=True` for this call AND the
51
+ module-level global switch is enabled. Call `debug_off()` to
52
+ silence every debug() call in the file at once (e.g. before
53
+ sharing a notebook, to eliminate leakage), and `debug_on()` to
54
+ restore them — no need to touch individual call sites.
55
+
56
+ `orientation` picks the layout: "vertical" (default) prints one
57
+ "name: value" pair per line with a blank line between each pair.
58
+ "horizontal" prints all pairs on a single line, separated by ", ".
59
+ Raises ValueError if anything else is passed.
60
+
61
+ Looks up each name in the CALLER's local variables (via inspect) —
62
+ you don't need to pass the values yourself, just the names as
63
+ strings, in the order you want them printed.
64
+ `names` must be a string or a list/tuple of strings, or TypeError
65
+ is raised.
66
+ A name not found in the caller's locals prints as
67
+ "name: <not found>" (label still in the chosen color) instead of
68
+ raising, so one typo doesn't kill the whole debug block.
69
+ """
70
+ VALID_COLORS = {"green", "red", "yellow"}
71
+ VALID_ORIENTATIONS = {"vertical", "horizontal"}
72
+
73
+ if not isinstance(display, bool):
74
+ raise TypeError(f"display must be a bool, got {type(display).__name__}")
75
+
76
+ if color not in VALID_COLORS:
77
+ raise ValueError(f"color must be one of {sorted(VALID_COLORS)}, got {color!r}")
78
+
79
+ if orientation not in VALID_ORIENTATIONS:
80
+ raise ValueError(f"orientation must be one of {sorted(VALID_ORIENTATIONS)}, got {orientation!r}")
81
+
82
+ if isinstance(names, str):
83
+ names = [names]
84
+ elif isinstance(names, (list, tuple)):
85
+ if not all(isinstance(n, str) for n in names):
86
+ raise TypeError("all items in names must be strings")
87
+ else:
88
+ raise TypeError(f"names must be a str or list/tuple of str, got {type(names).__name__}")
89
+
90
+ if not display or not _DEBUG_GLOBAL_ENABLED:
91
+ return
92
+
93
+ COLORS = {
94
+ "green": "\033[1;32m",
95
+ "red": "\033[1;91m", # bright red
96
+ "yellow": "\033[1;93m", # bright yellow
97
+ }
98
+ NAME_COLOR = COLORS[color]
99
+ BLACK = "\033[30m"
100
+ RESET = "\033[0m"
101
+
102
+ caller_locals = inspect.currentframe().f_back.f_locals
103
+ lines = []
104
+ for name in names:
105
+ if name in caller_locals:
106
+ value = caller_locals[name]
107
+ lines.append(f"{NAME_COLOR}{name}{RESET}: {BLACK}{value}{RESET}")
108
+ else:
109
+ lines.append(f"{NAME_COLOR}{name}{RESET}: {BLACK}<not found>{RESET}")
110
+
111
+ if orientation == "horizontal":
112
+ print(", ".join(lines))
113
+ else:
114
+ print("\n\n".join(lines))
115
+
116
+
117
+ def debug_off():
118
+ """Silence ALL debug() calls in this module (global kill switch)."""
119
+ global _DEBUG_GLOBAL_ENABLED
120
+ _DEBUG_GLOBAL_ENABLED = False
121
+
122
+
123
+ def debug_on():
124
+ """Re-enable debug() calls after debug_off()."""
125
+ global _DEBUG_GLOBAL_ENABLED
126
+ _DEBUG_GLOBAL_ENABLED = True
127
+
128
+
129
+ """
130
+ if __name__ == "__main__":
131
+ count = 42
132
+ total = 137
133
+ status = "active"
134
+
135
+ print("--- default (vertical, green, display=True) ---")
136
+ debug(["count", "total", "status"])
137
+
138
+ print("\n--- single string, not a list ---")
139
+ debug("count")
140
+
141
+ print("\n--- color='red' ---")
142
+ debug(["count", "total"], color="red")
143
+
144
+ print("\n--- color='yellow' ---")
145
+ debug(["count", "total"], color="yellow")
146
+
147
+ print("\n--- orientation='horizontal' (comma-separated) ---")
148
+ debug(["count", "total", "status"], orientation="horizontal")
149
+
150
+ print("\n--- horizontal + color='red' ---")
151
+ debug(["count", "total", "status"], color="red", orientation="horizontal")
152
+
153
+ print("\n--- missing variable (typo) ---")
154
+ debug(["count", "totall", "status"])
155
+
156
+ print("\n--- display=False (should print nothing below this line) ---")
157
+ debug(["count", "total"], display=False)
158
+ print("(nothing printed above if display=False worked)")
159
+
160
+ print("\n--- global debug_off() silences everything, even display=True ---")
161
+ debug_off()
162
+ debug(["count", "total", "status"])
163
+ print("(nothing printed above if debug_off() worked)")
164
+
165
+ print("\n--- debug_on() restores normal behavior ---")
166
+ debug_on()
167
+ debug(["count", "total", "status"])
168
+
169
+ print("\n--- invalid color raises ValueError ---")
170
+ try:
171
+ debug(["count"], color="purple")
172
+ except ValueError as e:
173
+ print(f"Caught: {e}")
174
+
175
+ print("\n--- invalid orientation raises ValueError ---")
176
+ try:
177
+ debug(["count"], orientation="diagonal")
178
+ except ValueError as e:
179
+ print(f"Caught: {e}")
180
+
181
+ print("\n--- invalid display type raises TypeError ---")
182
+ try:
183
+ debug(["count"], display="yes")
184
+ except TypeError as e:
185
+ print(f"Caught: {e}")
186
+
187
+ print("\n--- invalid names type raises TypeError ---")
188
+ try:
189
+ debug(123)
190
+ """
191
+ except TypeError as e:
192
+ print(f"Caught: {e}")
@@ -0,0 +1,192 @@
1
+ """
2
+ varview
3
+ ~~~~~~~
4
+
5
+ A tiny debug-printing helper: pass variable names as strings and it
6
+ prints "name: value" pairs pulled straight from the caller's local
7
+ scope — no need to write out f"{name}: {value}" by hand.
8
+
9
+ Basic usage:
10
+ from varview import debug
11
+
12
+ count = 42
13
+ debug(["count"]) # green label, black value
14
+ debug("count") # single string also works
15
+ debug(["count"], color="red")
16
+ debug(["count"], orientation="horizontal")
17
+
18
+ Global kill switch (silence every debug() call in one line, e.g.
19
+ before sharing a notebook or shipping to prod):
20
+ from varview import debug_off, debug_on
21
+ debug_off()
22
+ debug_on()
23
+ """
24
+
25
+ import inspect
26
+
27
+ __all__ = ["debug", "debug_off", "debug_on"]
28
+ __version__ = "0.1.0"
29
+
30
+ _DEBUG_GLOBAL_ENABLED = True # flip via debug_off()/debug_on() to silence ALL debug() calls at once
31
+
32
+
33
+ def debug(names, color="green", display=True, orientation="vertical"):
34
+ """
35
+ Pass a list of variable name strings, or a single name as a plain
36
+ string, and this prints each one as "name: value" (name bolded in
37
+ the chosen color, value always black).
38
+
39
+ e.g. debug(["count", "total", "status"])
40
+ debug("count") <- single string also works, auto-wrapped
41
+ into a one-item list so it isn't split
42
+ into characters.
43
+
44
+ `color` picks the name/label color: "green", "red", or "yellow".
45
+ Defaults to "green". Raises ValueError if anything else is passed.
46
+
47
+ `display` toggles THIS SPECIFIC call. Defaults to True. Must be a
48
+ bool, or TypeError is raised.
49
+
50
+ Printing only happens if BOTH `display=True` for this call AND the
51
+ module-level global switch is enabled. Call `debug_off()` to
52
+ silence every debug() call in the file at once (e.g. before
53
+ sharing a notebook, to eliminate leakage), and `debug_on()` to
54
+ restore them — no need to touch individual call sites.
55
+
56
+ `orientation` picks the layout: "vertical" (default) prints one
57
+ "name: value" pair per line with a blank line between each pair.
58
+ "horizontal" prints all pairs on a single line, separated by ", ".
59
+ Raises ValueError if anything else is passed.
60
+
61
+ Looks up each name in the CALLER's local variables (via inspect) —
62
+ you don't need to pass the values yourself, just the names as
63
+ strings, in the order you want them printed.
64
+ `names` must be a string or a list/tuple of strings, or TypeError
65
+ is raised.
66
+ A name not found in the caller's locals prints as
67
+ "name: <not found>" (label still in the chosen color) instead of
68
+ raising, so one typo doesn't kill the whole debug block.
69
+ """
70
+ VALID_COLORS = {"green", "red", "yellow"}
71
+ VALID_ORIENTATIONS = {"vertical", "horizontal"}
72
+
73
+ if not isinstance(display, bool):
74
+ raise TypeError(f"display must be a bool, got {type(display).__name__}")
75
+
76
+ if color not in VALID_COLORS:
77
+ raise ValueError(f"color must be one of {sorted(VALID_COLORS)}, got {color!r}")
78
+
79
+ if orientation not in VALID_ORIENTATIONS:
80
+ raise ValueError(f"orientation must be one of {sorted(VALID_ORIENTATIONS)}, got {orientation!r}")
81
+
82
+ if isinstance(names, str):
83
+ names = [names]
84
+ elif isinstance(names, (list, tuple)):
85
+ if not all(isinstance(n, str) for n in names):
86
+ raise TypeError("all items in names must be strings")
87
+ else:
88
+ raise TypeError(f"names must be a str or list/tuple of str, got {type(names).__name__}")
89
+
90
+ if not display or not _DEBUG_GLOBAL_ENABLED:
91
+ return
92
+
93
+ COLORS = {
94
+ "green": "\033[1;32m",
95
+ "red": "\033[1;91m", # bright red
96
+ "yellow": "\033[1;93m", # bright yellow
97
+ }
98
+ NAME_COLOR = COLORS[color]
99
+ BLACK = "\033[30m"
100
+ RESET = "\033[0m"
101
+
102
+ caller_locals = inspect.currentframe().f_back.f_locals
103
+ lines = []
104
+ for name in names:
105
+ if name in caller_locals:
106
+ value = caller_locals[name]
107
+ lines.append(f"{NAME_COLOR}{name}{RESET}: {BLACK}{value}{RESET}")
108
+ else:
109
+ lines.append(f"{NAME_COLOR}{name}{RESET}: {BLACK}<not found>{RESET}")
110
+
111
+ if orientation == "horizontal":
112
+ print(", ".join(lines))
113
+ else:
114
+ print("\n\n".join(lines))
115
+
116
+
117
+ def debug_off():
118
+ """Silence ALL debug() calls in this module (global kill switch)."""
119
+ global _DEBUG_GLOBAL_ENABLED
120
+ _DEBUG_GLOBAL_ENABLED = False
121
+
122
+
123
+ def debug_on():
124
+ """Re-enable debug() calls after debug_off()."""
125
+ global _DEBUG_GLOBAL_ENABLED
126
+ _DEBUG_GLOBAL_ENABLED = True
127
+
128
+
129
+ """
130
+ if __name__ == "__main__":
131
+ count = 42
132
+ total = 137
133
+ status = "active"
134
+
135
+ print("--- default (vertical, green, display=True) ---")
136
+ debug(["count", "total", "status"])
137
+
138
+ print("\n--- single string, not a list ---")
139
+ debug("count")
140
+
141
+ print("\n--- color='red' ---")
142
+ debug(["count", "total"], color="red")
143
+
144
+ print("\n--- color='yellow' ---")
145
+ debug(["count", "total"], color="yellow")
146
+
147
+ print("\n--- orientation='horizontal' (comma-separated) ---")
148
+ debug(["count", "total", "status"], orientation="horizontal")
149
+
150
+ print("\n--- horizontal + color='red' ---")
151
+ debug(["count", "total", "status"], color="red", orientation="horizontal")
152
+
153
+ print("\n--- missing variable (typo) ---")
154
+ debug(["count", "totall", "status"])
155
+
156
+ print("\n--- display=False (should print nothing below this line) ---")
157
+ debug(["count", "total"], display=False)
158
+ print("(nothing printed above if display=False worked)")
159
+
160
+ print("\n--- global debug_off() silences everything, even display=True ---")
161
+ debug_off()
162
+ debug(["count", "total", "status"])
163
+ print("(nothing printed above if debug_off() worked)")
164
+
165
+ print("\n--- debug_on() restores normal behavior ---")
166
+ debug_on()
167
+ debug(["count", "total", "status"])
168
+
169
+ print("\n--- invalid color raises ValueError ---")
170
+ try:
171
+ debug(["count"], color="purple")
172
+ except ValueError as e:
173
+ print(f"Caught: {e}")
174
+
175
+ print("\n--- invalid orientation raises ValueError ---")
176
+ try:
177
+ debug(["count"], orientation="diagonal")
178
+ except ValueError as e:
179
+ print(f"Caught: {e}")
180
+
181
+ print("\n--- invalid display type raises TypeError ---")
182
+ try:
183
+ debug(["count"], display="yes")
184
+ except TypeError as e:
185
+ print(f"Caught: {e}")
186
+
187
+ print("\n--- invalid names type raises TypeError ---")
188
+ try:
189
+ debug(123)
190
+ """
191
+ except TypeError as e:
192
+ print(f"Caught: {e}")