humanlog 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.
humanlog-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 srichs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,263 @@
1
+ Metadata-Version: 2.4
2
+ Name: humanlog
3
+ Version: 0.1.0
4
+ Summary: One-line progress + logging for humans.
5
+ Author-email: srichs <srichs@pm.me>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/srichs/humanlog
8
+ Project-URL: Repository, https://github.com/srichs/humanlog
9
+ Project-URL: Issues, https://github.com/srichs/humanlog/issues
10
+ Project-URL: Changelog, https://github.com/srichs/humanlog/blob/main/CHANGELOG.md
11
+ Keywords: logging,cli,progress,terminal,developer-tools
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: System :: Logging
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: black>=24.0; extra == "dev"
28
+ Requires-Dist: mypy>=1.0; extra == "dev"
29
+ Requires-Dist: pytest>=8.0; extra == "dev"
30
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
31
+ Requires-Dist: ruff>=0.5; extra == "dev"
32
+ Requires-Dist: sphinx>=7.0; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # humanlog
36
+
37
+ [![CI](https://github.com/srichs/humanlog/actions/workflows/ci.yml/badge.svg)](https://github.com/srichs/humanlog/actions/workflows/ci.yml)
38
+ [![PyPI](https://img.shields.io/pypi/v/humanlog.svg)](https://pypi.org/project/humanlog/)
39
+
40
+ One-line logging + progress for humans.
41
+ Works in terminals, CI, and Jupyter — no setup, no configuration.
42
+
43
+ ```python
44
+ from humanlog import log
45
+
46
+ log.step("Downloading data")
47
+ ...
48
+ log.done(rows=120_000)
49
+
50
+ log.info("Cleaning finished")
51
+ log.warn("Missing values detected", cols=3)
52
+ ```
53
+
54
+ ## Why humanlog?
55
+
56
+ Most logging tools are either:
57
+
58
+ - too low-level (stdlib logging),
59
+ - too heavy (structured logging frameworks),
60
+ - or great at one thing (progress bars) but awkward for everything else.
61
+
62
+ `humanlog` is opinionated and small:
63
+
64
+ - readable output
65
+ - automatic timing
66
+ - graceful behavior everywhere
67
+ - zero configuration
68
+
69
+ It’s for applications, scripts, CLIs, and data workflows.
70
+
71
+ ## Install
72
+
73
+ ```bash
74
+ pip install humanlog
75
+ ```
76
+
77
+ Python 3.9+ (no dependencies).
78
+
79
+ ## The core idea
80
+
81
+ ### Steps feel like steps
82
+
83
+ ```python
84
+ log.step("Training model")
85
+ train()
86
+ log.done(loss=0.031)
87
+ ```
88
+
89
+ Output (terminal):
90
+
91
+ ```text
92
+ → Training model …
93
+ ✓ Training model (loss=0.031, time=2.41s)
94
+ ```
95
+
96
+ No manual timers. No formatting. No state.
97
+
98
+ ### Informational messages
99
+
100
+ ```python
101
+ log.info("Loading dataset", rows=120_000)
102
+ log.warn("Missing values detected", cols=3)
103
+ log.error("Failed to connect to database")
104
+ ```
105
+
106
+ Output:
107
+
108
+ ```text
109
+ [12:40:03] ℹ Loading dataset (rows=120000)
110
+ [12:40:04] ⚠ Missing values detected (cols=3)
111
+ [12:40:05] ✖ Failed to connect to database
112
+ ```
113
+
114
+ ## Works everywhere
115
+
116
+ ### Terminal (TTY)
117
+
118
+ - Animated steps
119
+ - Clean overwrite
120
+ - Human-friendly symbols
121
+
122
+ ### CI (GitHub Actions, GitLab, etc.)
123
+
124
+ - No carriage-return garbage
125
+ - Timestamped, line-by-line logs
126
+
127
+ ### Jupyter notebooks
128
+
129
+ - No broken progress bars
130
+ - Clean output cells
131
+
132
+ `humanlog` automatically detects where it’s running and adapts.
133
+
134
+ Set `HUMANLOG_NO_ANIMATE=1` (or `NO_COLOR=1`) to force non-animated output.
135
+
136
+ ## Zero configuration
137
+
138
+ No handlers.
139
+ No log levels to wire up.
140
+ No global logging side effects.
141
+
142
+ Just import and go.
143
+
144
+ ## API
145
+
146
+ ### `log.step(message: str)`
147
+
148
+ Start a timed step.
149
+
150
+ If another step is already active, `humanlog` automatically finishes it first so
151
+ you never end up with overlapping step state.
152
+
153
+ You can also use it as a context manager to auto-complete the step:
154
+
155
+ ```python
156
+ with log.step("Training model"):
157
+ train()
158
+ ```
159
+
160
+ If an exception escapes the block, the step is automatically closed as failed:
161
+
162
+ ```text
163
+ [12:40:05] ✖ Training model (error=RuntimeError, time=0.73s)
164
+ ```
165
+
166
+ ### `log.done(**info)`
167
+
168
+ Finish the current step and print timing + optional key/value info.
169
+
170
+ ### `log.info(message: str, **info)`
171
+
172
+ Print an informational message.
173
+
174
+ If a step is active, it is automatically completed before the info line is
175
+ printed.
176
+
177
+ ### `log.warn(message: str, **info)`
178
+
179
+ Print a warning (to stderr).
180
+
181
+ If a step is active, it is automatically completed before the warning is
182
+ printed.
183
+
184
+ ### `log.error(message: str, **info)`
185
+
186
+ Print an error (to stderr).
187
+
188
+ If a step is active, it is automatically completed before the error is printed.
189
+
190
+ Key/value info is always optional and rendered inline:
191
+
192
+ ```python
193
+ log.info("Loaded batch", batch=3, rows=1024)
194
+ ```
195
+
196
+ ## Example: a real script
197
+
198
+ ```python
199
+ from humanlog import log
200
+
201
+ log.step("Downloading data")
202
+ download()
203
+ log.done(rows=120_000)
204
+
205
+ log.step("Cleaning data")
206
+ clean()
207
+ log.done(dropped=341)
208
+
209
+ log.step("Training model")
210
+ train()
211
+ log.done(epochs=10, loss=0.031)
212
+
213
+ log.info("All done")
214
+ ```
215
+
216
+ Readable. Intentional. Calm.
217
+
218
+ ## Non-goals (by design)
219
+
220
+ `humanlog` is not:
221
+
222
+ - a replacement for structured logging
223
+ - a metrics system
224
+ - a tracing framework
225
+ - a progress-bar DSL
226
+
227
+ If you need JSON logs or OpenTelemetry, use those tools.
228
+
229
+ If you want pleasant, readable output, use `humanlog`.
230
+
231
+ ## Roadmap (likely, but optional)
232
+
233
+ - `log.track(iterable, label="Processing")`
234
+ - optional Rich-powered rendering
235
+ - stdlib logging bridge (opt-in)
236
+
237
+ The core will stay small.
238
+
239
+ ## Philosophy
240
+
241
+ `humanlog` optimizes for:
242
+
243
+ - clarity over flexibility
244
+ - defaults over configuration
245
+ - humans over machines
246
+
247
+ Logs are for people first.
248
+
249
+ ## Contributing
250
+
251
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup and quality checks.
252
+
253
+ ## Changelog
254
+
255
+ Release history is tracked in [CHANGELOG.md](CHANGELOG.md).
256
+
257
+ ## Releasing
258
+
259
+ Maintainers can follow [RELEASE.md](RELEASE.md) for packaging, verification, and publish steps.
260
+
261
+ ## License
262
+
263
+ MIT
@@ -0,0 +1,229 @@
1
+ # humanlog
2
+
3
+ [![CI](https://github.com/srichs/humanlog/actions/workflows/ci.yml/badge.svg)](https://github.com/srichs/humanlog/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/humanlog.svg)](https://pypi.org/project/humanlog/)
5
+
6
+ One-line logging + progress for humans.
7
+ Works in terminals, CI, and Jupyter — no setup, no configuration.
8
+
9
+ ```python
10
+ from humanlog import log
11
+
12
+ log.step("Downloading data")
13
+ ...
14
+ log.done(rows=120_000)
15
+
16
+ log.info("Cleaning finished")
17
+ log.warn("Missing values detected", cols=3)
18
+ ```
19
+
20
+ ## Why humanlog?
21
+
22
+ Most logging tools are either:
23
+
24
+ - too low-level (stdlib logging),
25
+ - too heavy (structured logging frameworks),
26
+ - or great at one thing (progress bars) but awkward for everything else.
27
+
28
+ `humanlog` is opinionated and small:
29
+
30
+ - readable output
31
+ - automatic timing
32
+ - graceful behavior everywhere
33
+ - zero configuration
34
+
35
+ It’s for applications, scripts, CLIs, and data workflows.
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ pip install humanlog
41
+ ```
42
+
43
+ Python 3.9+ (no dependencies).
44
+
45
+ ## The core idea
46
+
47
+ ### Steps feel like steps
48
+
49
+ ```python
50
+ log.step("Training model")
51
+ train()
52
+ log.done(loss=0.031)
53
+ ```
54
+
55
+ Output (terminal):
56
+
57
+ ```text
58
+ → Training model …
59
+ ✓ Training model (loss=0.031, time=2.41s)
60
+ ```
61
+
62
+ No manual timers. No formatting. No state.
63
+
64
+ ### Informational messages
65
+
66
+ ```python
67
+ log.info("Loading dataset", rows=120_000)
68
+ log.warn("Missing values detected", cols=3)
69
+ log.error("Failed to connect to database")
70
+ ```
71
+
72
+ Output:
73
+
74
+ ```text
75
+ [12:40:03] ℹ Loading dataset (rows=120000)
76
+ [12:40:04] ⚠ Missing values detected (cols=3)
77
+ [12:40:05] ✖ Failed to connect to database
78
+ ```
79
+
80
+ ## Works everywhere
81
+
82
+ ### Terminal (TTY)
83
+
84
+ - Animated steps
85
+ - Clean overwrite
86
+ - Human-friendly symbols
87
+
88
+ ### CI (GitHub Actions, GitLab, etc.)
89
+
90
+ - No carriage-return garbage
91
+ - Timestamped, line-by-line logs
92
+
93
+ ### Jupyter notebooks
94
+
95
+ - No broken progress bars
96
+ - Clean output cells
97
+
98
+ `humanlog` automatically detects where it’s running and adapts.
99
+
100
+ Set `HUMANLOG_NO_ANIMATE=1` (or `NO_COLOR=1`) to force non-animated output.
101
+
102
+ ## Zero configuration
103
+
104
+ No handlers.
105
+ No log levels to wire up.
106
+ No global logging side effects.
107
+
108
+ Just import and go.
109
+
110
+ ## API
111
+
112
+ ### `log.step(message: str)`
113
+
114
+ Start a timed step.
115
+
116
+ If another step is already active, `humanlog` automatically finishes it first so
117
+ you never end up with overlapping step state.
118
+
119
+ You can also use it as a context manager to auto-complete the step:
120
+
121
+ ```python
122
+ with log.step("Training model"):
123
+ train()
124
+ ```
125
+
126
+ If an exception escapes the block, the step is automatically closed as failed:
127
+
128
+ ```text
129
+ [12:40:05] ✖ Training model (error=RuntimeError, time=0.73s)
130
+ ```
131
+
132
+ ### `log.done(**info)`
133
+
134
+ Finish the current step and print timing + optional key/value info.
135
+
136
+ ### `log.info(message: str, **info)`
137
+
138
+ Print an informational message.
139
+
140
+ If a step is active, it is automatically completed before the info line is
141
+ printed.
142
+
143
+ ### `log.warn(message: str, **info)`
144
+
145
+ Print a warning (to stderr).
146
+
147
+ If a step is active, it is automatically completed before the warning is
148
+ printed.
149
+
150
+ ### `log.error(message: str, **info)`
151
+
152
+ Print an error (to stderr).
153
+
154
+ If a step is active, it is automatically completed before the error is printed.
155
+
156
+ Key/value info is always optional and rendered inline:
157
+
158
+ ```python
159
+ log.info("Loaded batch", batch=3, rows=1024)
160
+ ```
161
+
162
+ ## Example: a real script
163
+
164
+ ```python
165
+ from humanlog import log
166
+
167
+ log.step("Downloading data")
168
+ download()
169
+ log.done(rows=120_000)
170
+
171
+ log.step("Cleaning data")
172
+ clean()
173
+ log.done(dropped=341)
174
+
175
+ log.step("Training model")
176
+ train()
177
+ log.done(epochs=10, loss=0.031)
178
+
179
+ log.info("All done")
180
+ ```
181
+
182
+ Readable. Intentional. Calm.
183
+
184
+ ## Non-goals (by design)
185
+
186
+ `humanlog` is not:
187
+
188
+ - a replacement for structured logging
189
+ - a metrics system
190
+ - a tracing framework
191
+ - a progress-bar DSL
192
+
193
+ If you need JSON logs or OpenTelemetry, use those tools.
194
+
195
+ If you want pleasant, readable output, use `humanlog`.
196
+
197
+ ## Roadmap (likely, but optional)
198
+
199
+ - `log.track(iterable, label="Processing")`
200
+ - optional Rich-powered rendering
201
+ - stdlib logging bridge (opt-in)
202
+
203
+ The core will stay small.
204
+
205
+ ## Philosophy
206
+
207
+ `humanlog` optimizes for:
208
+
209
+ - clarity over flexibility
210
+ - defaults over configuration
211
+ - humans over machines
212
+
213
+ Logs are for people first.
214
+
215
+ ## Contributing
216
+
217
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup and quality checks.
218
+
219
+ ## Changelog
220
+
221
+ Release history is tracked in [CHANGELOG.md](CHANGELOG.md).
222
+
223
+ ## Releasing
224
+
225
+ Maintainers can follow [RELEASE.md](RELEASE.md) for packaging, verification, and publish steps.
226
+
227
+ ## License
228
+
229
+ MIT
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "humanlog"
7
+ version = "0.1.0"
8
+ description = "One-line progress + logging for humans."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ authors = [
12
+ {name = "srichs", email = "srichs@pm.me"},
13
+ ]
14
+ license = {text = "MIT"}
15
+ keywords = ["logging", "cli", "progress", "terminal", "developer-tools"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
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 :: Libraries :: Python Modules",
27
+ "Topic :: System :: Logging",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/srichs/humanlog"
32
+ Repository = "https://github.com/srichs/humanlog"
33
+ Issues = "https://github.com/srichs/humanlog/issues"
34
+ Changelog = "https://github.com/srichs/humanlog/blob/main/CHANGELOG.md"
35
+
36
+ [tool.setuptools]
37
+ package-dir = {"" = "src"}
38
+ packages = ["humanlog"]
39
+
40
+
41
+ [project.optional-dependencies]
42
+ dev = [
43
+ "black>=24.0",
44
+ "mypy>=1.0",
45
+ "pytest>=8.0",
46
+ "pytest-cov>=5.0",
47
+ "ruff>=0.5",
48
+ "sphinx>=7.0",
49
+ ]
50
+
51
+ [tool.pytest.ini_options]
52
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,7 @@
1
+ """humanlog: one-line progress + logging for humans."""
2
+
3
+ from .core import HumanLog
4
+
5
+ __all__ = ["HumanLog", "log"]
6
+
7
+ log = HumanLog()