klogr 0.1.3__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.
- klogr-0.1.3/.github/workflows/publish.yml +41 -0
- klogr-0.1.3/.gitignore +30 -0
- klogr-0.1.3/.pre-commit-config.yaml +235 -0
- klogr-0.1.3/CHANGELOG.md +113 -0
- klogr-0.1.3/PKG-INFO +214 -0
- klogr-0.1.3/README.md +184 -0
- klogr-0.1.3/examples/01_basic_logger.py +29 -0
- klogr-0.1.3/examples/02_pretty_tables.py +30 -0
- klogr-0.1.3/examples/03_progress_tracking.py +41 -0
- klogr-0.1.3/examples/04_caching.py +43 -0
- klogr-0.1.3/examples/05_path_helpers.py +51 -0
- klogr-0.1.3/examples/README.md +15 -0
- klogr-0.1.3/klogr/__init__.py +31 -0
- klogr-0.1.3/klogr/cache.py +692 -0
- klogr-0.1.3/klogr/logger.py +802 -0
- klogr-0.1.3/klogr/path/__init__.py +107 -0
- klogr-0.1.3/klogr/path/env.py +43 -0
- klogr-0.1.3/klogr/path/io.py +299 -0
- klogr-0.1.3/klogr/path/ops.py +301 -0
- klogr-0.1.3/klogr/path/query.py +320 -0
- klogr-0.1.3/klogr/time.py +30 -0
- klogr-0.1.3/pyproject.toml +84 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Publish to PyPI
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- v*
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build-and-publish:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- name: Check out the code
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: |
|
|
24
|
+
python -m pip install --upgrade pip setuptools wheel build twine
|
|
25
|
+
|
|
26
|
+
- name: Build the package
|
|
27
|
+
run: python -m build
|
|
28
|
+
|
|
29
|
+
- name: Show wheel metadata (debug)
|
|
30
|
+
run: |
|
|
31
|
+
python -m twine check dist/*
|
|
32
|
+
for f in dist/*.whl; do
|
|
33
|
+
echo "===== $f ====="
|
|
34
|
+
python -c "import zipfile, sys; zf = zipfile.ZipFile(sys.argv[1]); [print(zf.read(n).decode()) for n in zf.namelist() if n.endswith('METADATA')]" "$f"
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
- name: Publish to PyPI
|
|
38
|
+
env:
|
|
39
|
+
TWINE_USERNAME: __token__
|
|
40
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
41
|
+
run: python -m twine upload --verbose --non-interactive dist/*
|
klogr-0.1.3/.gitignore
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
# Pretrained Torch
|
|
3
|
+
pretrained_models/
|
|
4
|
+
|
|
5
|
+
# PyCache
|
|
6
|
+
__pycache__
|
|
7
|
+
|
|
8
|
+
# VSCode
|
|
9
|
+
*.code-workspace
|
|
10
|
+
|
|
11
|
+
# Small Data/Videos
|
|
12
|
+
small_data/
|
|
13
|
+
data/
|
|
14
|
+
*.zip
|
|
15
|
+
|
|
16
|
+
# Outputs
|
|
17
|
+
outputs/
|
|
18
|
+
logs/
|
|
19
|
+
log/
|
|
20
|
+
.DS_Store
|
|
21
|
+
|
|
22
|
+
# builds
|
|
23
|
+
build/
|
|
24
|
+
dist/
|
|
25
|
+
.venv/
|
|
26
|
+
*.tar.gz
|
|
27
|
+
*.tar
|
|
28
|
+
|
|
29
|
+
# Lock file — managed by uv, regenerated per-environment
|
|
30
|
+
uv.lock
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
---
|
|
2
|
+
# $ pre-commit install --install-hooks
|
|
3
|
+
# See https://pre-commit.com for more information
|
|
4
|
+
# See https://pre-commit.com/hooks.html for more hooks
|
|
5
|
+
default_install_hook_types:
|
|
6
|
+
- pre-commit
|
|
7
|
+
- post-checkout
|
|
8
|
+
- post-merge
|
|
9
|
+
- post-rewrite
|
|
10
|
+
repos:
|
|
11
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
12
|
+
rev: v5.0.0
|
|
13
|
+
hooks:
|
|
14
|
+
- id: trailing-whitespace
|
|
15
|
+
|
|
16
|
+
- id: end-of-file-fixer
|
|
17
|
+
|
|
18
|
+
- id: mixed-line-ending
|
|
19
|
+
args: [--fix, lf]
|
|
20
|
+
|
|
21
|
+
- id: check-yaml
|
|
22
|
+
exclude: .pre-commit-config.yaml
|
|
23
|
+
|
|
24
|
+
- id: check-added-large-files
|
|
25
|
+
args: [--maxkb=2000]
|
|
26
|
+
|
|
27
|
+
- id: check-merge-conflict
|
|
28
|
+
- id: check-case-conflict
|
|
29
|
+
- id: check-json
|
|
30
|
+
- id: check-toml
|
|
31
|
+
exclude: uv\.lock
|
|
32
|
+
- id: pretty-format-json
|
|
33
|
+
args: [--autofix, --no-ensure-ascii, --no-sort-keys]
|
|
34
|
+
|
|
35
|
+
# - id: double-quote-string-fixer
|
|
36
|
+
# exclude: ^dependencies/|^experiments/dependencies/|^experiments/
|
|
37
|
+
|
|
38
|
+
# - repo: https://github.com/psf/black-pre-commit-mirror
|
|
39
|
+
# rev: 24.10.0
|
|
40
|
+
# hooks:
|
|
41
|
+
# - id: black
|
|
42
|
+
# # It is recommended to specify the latest version of Python
|
|
43
|
+
# # supported by your project here, or alternatively use
|
|
44
|
+
# # pre-commit's default_language_version, see
|
|
45
|
+
# # https://pre-commit.com/#top_level-default_language_version
|
|
46
|
+
# language_version: python3.10
|
|
47
|
+
# exclude: ^dependencies/|^experiments/dependencies/|^experiments/|uv\.lock|tools/generative/pipelines/|configs/hax_ml/|unittest_logs/
|
|
48
|
+
# args: [--line-length=79, --target-version=py310, --quiet]
|
|
49
|
+
|
|
50
|
+
# - repo: https://github.com/PyCQA/docformatter # there is an issue with the latest version and python_env - uncomment as soon as possible
|
|
51
|
+
# rev: v1.3.1
|
|
52
|
+
# hooks:
|
|
53
|
+
# - id: docformatter
|
|
54
|
+
# language: python
|
|
55
|
+
# exclude: ^dependencies/|^experiments/dependencies/|^experiments/|uv\.lock|tools/generative/pipelines/|configs/hax_ml/|unittest_logs/
|
|
56
|
+
# args: [--in-place, --wrap-descriptions, '120']
|
|
57
|
+
|
|
58
|
+
- repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt
|
|
59
|
+
rev: 0.2.3 # or other specific tag
|
|
60
|
+
hooks:
|
|
61
|
+
- id: yamlfmt
|
|
62
|
+
exclude: .pre-commit-config.yaml
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# - repo: https://github.com/asottile/pyupgrade
|
|
66
|
+
# rev: v3.3.1
|
|
67
|
+
# hooks:
|
|
68
|
+
# - id: pyupgrade
|
|
69
|
+
# args:
|
|
70
|
+
# # - --py36-plus
|
|
71
|
+
# # - --py37-plus
|
|
72
|
+
# # - --py38-plus
|
|
73
|
+
# - --py39-plus
|
|
74
|
+
# # # - --py311-plus
|
|
75
|
+
# exclude: ^dependencies/|^dependencies/|^experiments/dependencies/|^experiments/
|
|
76
|
+
|
|
77
|
+
- repo: https://github.com/lovesegfault/beautysh
|
|
78
|
+
rev: v6.2.1
|
|
79
|
+
hooks:
|
|
80
|
+
- id: beautysh
|
|
81
|
+
exclude: uv\.lock
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# - repo: https://github.com/pycqa/isort
|
|
86
|
+
# rev: 5.11.2
|
|
87
|
+
# hooks:
|
|
88
|
+
# - id: isort
|
|
89
|
+
# name: isort
|
|
90
|
+
# entry: isort
|
|
91
|
+
# language: python
|
|
92
|
+
# types: [python]
|
|
93
|
+
# exclude: ^^dependencies/|^experiments/|^cli/
|
|
94
|
+
# args: [--line-length=89, --multi-line=3, --force-grid-wrap=0, --trailing-comma, --use-parentheses, --ensure-newline-before-comments]
|
|
95
|
+
# # additional_dependencies: [isort>=5.12.0]
|
|
96
|
+
|
|
97
|
+
- repo: local
|
|
98
|
+
hooks:
|
|
99
|
+
- id: toml-sort-fix
|
|
100
|
+
name: toml-sort-fix
|
|
101
|
+
entry: toml-sort
|
|
102
|
+
args: [--in-place]
|
|
103
|
+
language: python
|
|
104
|
+
exclude: uv\.lock
|
|
105
|
+
types: [toml]
|
|
106
|
+
additional_dependencies: [toml-sort>=0.23.1]
|
|
107
|
+
|
|
108
|
+
- id: toml-sort
|
|
109
|
+
name: toml-sort
|
|
110
|
+
entry: toml-sort
|
|
111
|
+
args: [--check]
|
|
112
|
+
language: python
|
|
113
|
+
exclude: uv\.lock
|
|
114
|
+
types: [toml]
|
|
115
|
+
additional_dependencies: [toml-sort>=0.23.1]
|
|
116
|
+
|
|
117
|
+
- repo: https://github.com/pycqa/pylint
|
|
118
|
+
rev: v3.3.7
|
|
119
|
+
hooks:
|
|
120
|
+
- id: pylint
|
|
121
|
+
name: pylint
|
|
122
|
+
entry: pylint
|
|
123
|
+
language: system
|
|
124
|
+
types: [python]
|
|
125
|
+
exclude: uv\.lock
|
|
126
|
+
args: [
|
|
127
|
+
--disable=all, # disable all rules
|
|
128
|
+
--enable=E0401, # import-error
|
|
129
|
+
--enable=E1123, # unexpected-keyword-arg
|
|
130
|
+
--enable=E1125, # missing-kwoa
|
|
131
|
+
--enable=E1101, # no-member
|
|
132
|
+
]
|
|
133
|
+
stages: [manual]
|
|
134
|
+
# ruff is trying to include more of this: https://github.com/astral-sh/ruff/issues/970
|
|
135
|
+
|
|
136
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
137
|
+
# Ruff version.
|
|
138
|
+
rev: v0.12.7
|
|
139
|
+
hooks:
|
|
140
|
+
# Run the linter.
|
|
141
|
+
- id: ruff
|
|
142
|
+
args: [
|
|
143
|
+
--fix,
|
|
144
|
+
--unsafe-fixes,
|
|
145
|
+
--select,
|
|
146
|
+
ALL,
|
|
147
|
+
--ignore, C901, # class too complex # TODO: remove this at some point
|
|
148
|
+
--ignore, D203, # 1 blank line required before class docstring
|
|
149
|
+
--ignore, D211, # No blank lines allowed before class docstring
|
|
150
|
+
--ignore, D213, # Multi-line docstring summary should start at the second line
|
|
151
|
+
--ignore, F722, # jaxtyping annotations
|
|
152
|
+
--ignore, F821, # jaxtyping annotations with the name in strings
|
|
153
|
+
--ignore, E501, # Line too long ( > 79 characters)
|
|
154
|
+
--ignore, T201, # Checks for print statements and remove them
|
|
155
|
+
--ignore, COM812, # Missing trailing comma in a dictionary
|
|
156
|
+
--ignore, ISC001, # Checks for implicitly concatenated strings on a single line.
|
|
157
|
+
--ignore, G004, # Logging statement uses f-string
|
|
158
|
+
--ignore, ERA001, # Found commented-out code
|
|
159
|
+
--ignore, S607, # Starting a process with a partial executable path
|
|
160
|
+
--ignore, S603, # `subprocess` call: check for execution of untrusted input
|
|
161
|
+
--ignore, ANN401, # Dynamically typed expressions (typing.Any) are disallowed in `**kwargs`
|
|
162
|
+
--ignore, RUF012, # Mutable class attributes should be annotated with `typing.ClassVar
|
|
163
|
+
--ignore, PERF401, # Use a list comprehension to create a transformed list
|
|
164
|
+
--ignore, SIM115, # Use a context manager for opening files
|
|
165
|
+
--ignore, PERF203, # `try`-`except` within a loop incurs performance overhead
|
|
166
|
+
--ignore, PLW2901, # `for` loop variable overwritten by assignment target
|
|
167
|
+
--ignore, TCH010, # Invalid string member in `X | Y`-style union type
|
|
168
|
+
--ignore, N812, # Lowercase `functional` imported as non-lowercase `F`
|
|
169
|
+
--ignore, SLF001, # Private member accessed
|
|
170
|
+
--ignore, TRY301, # Abstract `raise` to an inner function
|
|
171
|
+
--ignore, NPY002, # Replace legacy `np.random.random` call with `np.random.Generator`
|
|
172
|
+
--ignore, TD003, # Missing issue link on the line following a TODO
|
|
173
|
+
--ignore, FIX002, # Line contains TODO, consider resolving the issue
|
|
174
|
+
--ignore, S311, # Standard pseudo-random generators are not suitable for cryptographic purposes
|
|
175
|
+
--ignore, TC006, # Add quotes to type expression in `typing.cast()`
|
|
176
|
+
--ignore, TRY401, # Redundant exception object included in `logging.exception` call
|
|
177
|
+
--ignore, BLE001, # Do not catch blind exception: `Exception`'
|
|
178
|
+
--ignore, PLR0911, # Too many return statements
|
|
179
|
+
--ignore, PLR0912, # Too many branches
|
|
180
|
+
--ignore, PLR0913, # Too many arguments in function definition
|
|
181
|
+
--ignore, PLR0915, # Too many statements
|
|
182
|
+
--ignore, PLR2004, # Magic value used in comparison, consider replacing `0.1` with a constant variable
|
|
183
|
+
--ignore, PLC0415, # `import` should be at the top-level of a file
|
|
184
|
+
--ignore, PT028, # Test function parameter `<>` has default argument
|
|
185
|
+
]
|
|
186
|
+
exclude: uv\.lock
|
|
187
|
+
# Run the formatter.
|
|
188
|
+
- id: ruff-format
|
|
189
|
+
exclude: uv\.lock
|
|
190
|
+
# - repo: https://github.com/jvllmr/poetry-types
|
|
191
|
+
# rev: v0.4.0
|
|
192
|
+
# hooks:
|
|
193
|
+
# - id: poetry-types
|
|
194
|
+
|
|
195
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
196
|
+
rev: v1.18.2
|
|
197
|
+
hooks:
|
|
198
|
+
- id: mypy
|
|
199
|
+
name: mypy
|
|
200
|
+
entry: mypy
|
|
201
|
+
language: python
|
|
202
|
+
types_or: [python, pyi]
|
|
203
|
+
exclude: uv\.lock
|
|
204
|
+
require_serial: true
|
|
205
|
+
# args: [--strict, --ignore-missing-imports]
|
|
206
|
+
args: [--ignore-missing-imports, --scripts-are-modules, --install-types, --non-interactive, --warn-unused-ignores, --show-error-codes, --check-untyped-defs,
|
|
207
|
+
--disallow-incomplete-defs, --explicit-package-bases, --warn-redundant-casts, --strict-equality, --strict-equality-for-none, --follow-untyped-imports]
|
|
208
|
+
additional_dependencies:
|
|
209
|
+
- pydantic
|
|
210
|
+
- types-requests
|
|
211
|
+
# mypy --install-types
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
215
|
+
# uv version.
|
|
216
|
+
rev: 0.8.3
|
|
217
|
+
hooks:
|
|
218
|
+
- id: uv-sync
|
|
219
|
+
stages: [pre-commit, pre-merge-commit, pre-push] # not run during manual. manual is run in Github, and this one is expensive
|
|
220
|
+
- id: uv-export
|
|
221
|
+
args: [--frozen, --output-file=requirements.txt, --no-hashes]
|
|
222
|
+
stages: [pre-commit, pre-merge-commit, pre-push]
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
# - repo: https://github.com/oxsecurity/megalinter # sudo apt install npm && sudo npm install mega-linter-runner -g
|
|
226
|
+
# # install docker https://docs.docker.com/engine/install/ubuntu/#set-up-the-repository
|
|
227
|
+
# # install with sudo once: sudo mega-linter-runner .
|
|
228
|
+
# rev: v6.8.0 # Git tag specifying the hook, not mega-linter-runner, version
|
|
229
|
+
# hooks:
|
|
230
|
+
# - id: megalinter-incremental # Faster, less thorough
|
|
231
|
+
# stages:
|
|
232
|
+
# - commit
|
|
233
|
+
# - id: megalinter-full # Slower, more thorough
|
|
234
|
+
# stages:
|
|
235
|
+
# - push
|
klogr-0.1.3/CHANGELOG.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to klogr are documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.3] — 2026-05-17
|
|
9
|
+
|
|
10
|
+
PyPI rejected the name `klog` with `400 The name 'klog' isn't allowed.`
|
|
11
|
+
(likely too close to existing Linux/Go-ecosystem names). Renamed to
|
|
12
|
+
`klogr` — same project, one letter different.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Package renamed `klog` → `klogr`. GitHub repo also renamed from
|
|
17
|
+
`affromero/klog` to `affromero/klogr`. Imports change accordingly:
|
|
18
|
+
`from klog import X` → `from klogr import X`.
|
|
19
|
+
- README install instructions, badges, and layout diagram updated for
|
|
20
|
+
the new name.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- README incorrectly claimed `get_cache_dir()` returns `~/.cache/klog`;
|
|
25
|
+
it actually returns the XDG cache root directly. Updated the comment.
|
|
26
|
+
|
|
27
|
+
## [0.1.2] — 2026-05-15
|
|
28
|
+
|
|
29
|
+
CI/workflow fixes after 0.1.1 also failed PyPI upload with the same
|
|
30
|
+
`400 Bad Request`. Local wheels build cleanly with the SPDX license
|
|
31
|
+
metadata — the failure is somewhere in the upload step. This release
|
|
32
|
+
adds `twine check` and `twine upload --verbose` to surface the actual
|
|
33
|
+
error.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- `.github/workflows/publish.yml`: bump `actions/checkout` to v4,
|
|
38
|
+
`actions/setup-python` to v5, pin Python to 3.12 (3.x picked 3.14
|
|
39
|
+
which prints deprecation noise).
|
|
40
|
+
- Add `twine check` and METADATA dump steps so we can see what's in
|
|
41
|
+
the wheel before upload.
|
|
42
|
+
- `twine upload --verbose --non-interactive` for actionable errors
|
|
43
|
+
when the upload step itself fails.
|
|
44
|
+
|
|
45
|
+
## [0.1.1] — 2026-05-15
|
|
46
|
+
|
|
47
|
+
First successful PyPI upload. Fixes the 0.1.0 build that PyPI rejected
|
|
48
|
+
with `400 Bad Request`.
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- `pyproject.toml` `license` field uses the SPDX expression
|
|
53
|
+
(`license = "MIT"` + `license-files = ["LICENSE.md"]`) instead of the
|
|
54
|
+
legacy `{text = "MIT"}` form that newer PyPI rejects.
|
|
55
|
+
- Drop redundant `License :: OSI Approved :: MIT License` classifier
|
|
56
|
+
(the SPDX expression replaces it; PyPI rejects both together).
|
|
57
|
+
- Project URLs in `pyproject.toml` corrected from `github.com/afromero/...`
|
|
58
|
+
to `github.com/affromero/...` (the actual GitHub handle).
|
|
59
|
+
- README ASCII diagram rewritten with ASCII-safe box characters
|
|
60
|
+
(`+--+`, `-->`) instead of Unicode box-drawing + `▶`. The previous
|
|
61
|
+
version rendered crooked in Markdown viewers that gave `▶` a wider
|
|
62
|
+
glyph than expected.
|
|
63
|
+
|
|
64
|
+
## [0.1.0] — 2026-05-15
|
|
65
|
+
|
|
66
|
+
First release under the new name `klogr`. Previously published as `difflogtest`.
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
|
|
70
|
+
- **Renamed package** from `difflogtest` to `klogr`. The old name described a snapshot-test framework that is no longer part of this package.
|
|
71
|
+
- **Flattened the module layout.** The old `difflogtest.logging.*` and `difflogtest.utils.*` sub-packages have been merged into top-level modules:
|
|
72
|
+
- `difflogtest.logging.core` → `klogr.logger`
|
|
73
|
+
- `difflogtest.logging.cache_tools` → `klogr.cache`
|
|
74
|
+
- `difflogtest.utils.strings` → `klogr.time`
|
|
75
|
+
- `difflogtest.utils.path` → `klogr.path/` (split into `ops`, `io`, `query`, `env`)
|
|
76
|
+
- `logger.info_json` now uses stdlib `json` instead of `json5` — Pydantic-emitted JSON doesn't need comment tolerance.
|
|
77
|
+
|
|
78
|
+
### Removed
|
|
79
|
+
|
|
80
|
+
- **Snapshot test framework** (`UnitTests`, `@register_unittest`, `LogReplacement`, `is_unittest_mode`, `run-unittests` CLI). Not maintained; rely on `pytest` directly.
|
|
81
|
+
- **`seed_everything`** — pixelcache ships its own; this one only existed for the snapshot framework.
|
|
82
|
+
- **`wait_seconds_bar`** — zero consumers.
|
|
83
|
+
- **`path_download_and_extract_tar`** — drops the `wget` dependency.
|
|
84
|
+
- **`is_file_changed`, `logfile_from_func`, `path_from_pattern`, `keep_local_data`** — snapshot-only path helpers.
|
|
85
|
+
|
|
86
|
+
### Dropped dependencies
|
|
87
|
+
|
|
88
|
+
- `tyro` (snapshot CLI)
|
|
89
|
+
- `pytz` (unused)
|
|
90
|
+
- `json5` (info_json rewritten to stdlib json)
|
|
91
|
+
- `torch`, `torchvision` (seed_everything was the only consumer)
|
|
92
|
+
- `wget` (download helper removed)
|
|
93
|
+
- `GitPython` (`is_file_changed` was the only consumer)
|
|
94
|
+
|
|
95
|
+
### Kept
|
|
96
|
+
|
|
97
|
+
- `get_logger`, `LoggingRich`, `LoggingTable`, `DEFAULT_VERBOSITY`
|
|
98
|
+
- `lru_cache`, `DisableableLRUCache`, `get_cache_dir`, `sha256sum`
|
|
99
|
+
- All path helpers consumed by Hax-CV (`path_join`, `path_exists`, `path_mkdir`, `path_open`, `path_glob`, `path_basename`, `path_dirname`, `path_stem`, `path_is_s3`, `path_absolute`, `path_abs`, `path_dotenv`, `path_home`, `path_expanduser`, `path_relative_to`, `path_resolve`, `path_replace_suffix`, `path_rstrip`, `path_write_text`, `path_read_text`, `path_listdir`, `path_remove`, `path_remove_dir`, `path_copy`, `path_copy_dir`, `path_move`, `path_rename`, `path_symlink`, `path_islink`, `path_lexists`, `path_is_dir`, `path_is_file`, `path_is_image_file`, `path_is_video_file`, `path_getmtime`, `path_stat`, `path_dir_empty`, `path_exists_and_not_empty`, `path_startswith`, `path_endswith`, `path_newest_dir`, `path_newest_file`, `path_rglob`, `path_s3_bucket_name`, `is_glob_pattern`, `expand_glob_to_temp_dir`)
|
|
100
|
+
- `get_elapsed_time`
|
|
101
|
+
|
|
102
|
+
### Migration
|
|
103
|
+
|
|
104
|
+
Replace every `from difflogtest...` import:
|
|
105
|
+
|
|
106
|
+
| Old | New |
|
|
107
|
+
|-----|-----|
|
|
108
|
+
| `from difflogtest import get_logger` | `from klogr import get_logger` |
|
|
109
|
+
| `from difflogtest import lru_cache, sha256sum` | `from klogr import lru_cache, sha256sum` |
|
|
110
|
+
| `from difflogtest.utils.path import path_X` | `from klogr.path import path_X` |
|
|
111
|
+
| `from difflogtest.logging.core import LoggingTable` | `from klogr import LoggingTable` |
|
|
112
|
+
|
|
113
|
+
If you depended on `@register_unittest`, `is_unittest_mode`, or `LogReplacement` — those are gone. Use `pytest` directly.
|
klogr-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: klogr
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Batteries-included structured logger for Python data/ML projects, built on Rich.
|
|
5
|
+
Project-URL: Changelog, https://github.com/affromero/klogr/blob/main/CHANGELOG.md
|
|
6
|
+
Project-URL: Homepage, https://github.com/affromero/klogr
|
|
7
|
+
Project-URL: Issues, https://github.com/affromero/klogr/issues
|
|
8
|
+
Author-email: Andres Romero <me@afromero.co>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: cache,logging,ml,path,rich,s3
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Topic :: System :: Logging
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: beartype>=0.21.0
|
|
23
|
+
Requires-Dist: jaxtyping>=0.3.2
|
|
24
|
+
Requires-Dist: natsort>=8.4.0
|
|
25
|
+
Requires-Dist: pydantic>=2.10.2
|
|
26
|
+
Requires-Dist: python-dotenv>=0.19.0
|
|
27
|
+
Requires-Dist: rich>=13.9.4
|
|
28
|
+
Requires-Dist: sha256sum>=2024.4.26
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
<div align="center">
|
|
32
|
+
|
|
33
|
+
# klogr
|
|
34
|
+
|
|
35
|
+
**Batteries-included structured logger for Python data/ML projects — built on [Rich](https://github.com/Textualize/rich).**
|
|
36
|
+
|
|
37
|
+
[](https://pypi.org/project/klogr/)
|
|
38
|
+
[](https://pypi.org/project/klogr/)
|
|
39
|
+
[](https://pypi.org/project/klogr/)
|
|
40
|
+
[](https://github.com/affromero/klogr/actions/workflows/publish.yml)
|
|
41
|
+
[](https://github.com/affromero/klogr/blob/main/LICENSE.md)
|
|
42
|
+
[](https://github.com/astral-sh/uv)
|
|
43
|
+
[](https://github.com/astral-sh/ruff)
|
|
44
|
+
[](http://mypy-lang.org/)
|
|
45
|
+
[](https://github.com/patrick-kidger/jaxtyping)
|
|
46
|
+
[](https://github.com/affromero/klogr/pulls)
|
|
47
|
+
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
get_logger()
|
|
52
|
+
|
|
|
53
|
+
v
|
|
54
|
+
+---------------------------+
|
|
55
|
+
| LoggingRich |
|
|
56
|
+
+---------------------------+
|
|
57
|
+
| .info .success .warning | --> Rich-formatted console
|
|
58
|
+
| .error .debug .rule | with auto file:line prefix
|
|
59
|
+
| .track .print .info_json|
|
|
60
|
+
+---------------------------+
|
|
61
|
+
|
|
62
|
+
plus, from the same package:
|
|
63
|
+
|
|
64
|
+
@lru_cache + DisableableLRUCache --> cached calls,
|
|
65
|
+
with a disable hook for tests
|
|
66
|
+
path_join / path_exists / path_open --> local + s3:// transparent
|
|
67
|
+
get_elapsed_time(seconds) --> "01d : 01h : 12m : 03s"
|
|
68
|
+
sha256sum(path) / get_cache_dir() --> stable on-disk caching
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`klogr` is what you reach for when stdlib `logging.basicConfig` doesn't cut it and `print()` feels gross. It wraps Python's `logging` module with `rich.logging.RichHandler` pre-configured, adds stacklevel awareness so every line shows where it came from, and ships a handful of helpers (caching, paths, timing) that show up in every ML/data project.
|
|
72
|
+
|
|
73
|
+
## Why use it
|
|
74
|
+
|
|
75
|
+
- **Drop-in `get_logger()`** — module-scoped, cached, zero setup. No `logging.basicConfig`, no handler wiring.
|
|
76
|
+
- **Stacklevel-aware** — every log line auto-prefixes with the caller's `file:line`. Stop hunting for which module shouted what.
|
|
77
|
+
- **`logger.track()`** — wraps `rich.progress.track()` and works inside `ThreadPoolExecutor` / `ProcessPoolExecutor` without going silent.
|
|
78
|
+
- **`logger.print()` / `logger.info_json()`** — pretty-print Pydantic models, dicts, JSON without piping through `print(json.dumps(..., indent=2))`.
|
|
79
|
+
- **`@lru_cache` with a disable hook** — flip an env var to bypass caching globally (handy for tests).
|
|
80
|
+
- **Path helpers that handle S3** — `path_join`, `path_exists`, `path_mkdir`, etc. work whether you pass `/tmp/foo` or `s3://bucket/foo`.
|
|
81
|
+
- **`get_elapsed_time(seconds)`** — formats float seconds as `00d : 01h : 12m : 03s`.
|
|
82
|
+
|
|
83
|
+
## Install
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
uv add klogr
|
|
87
|
+
# or
|
|
88
|
+
pip install klogr
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Requires Python ≥ 3.10. Runtime deps: `rich`, `pydantic`, `python-dotenv`, `beartype`, `jaxtyping`, `natsort`, `sha256sum`.
|
|
92
|
+
|
|
93
|
+
## Quickstart
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from klogr import get_logger
|
|
97
|
+
|
|
98
|
+
logger = get_logger()
|
|
99
|
+
|
|
100
|
+
logger.info("loaded %d samples", 1024) # auto file:line prefix
|
|
101
|
+
logger.success("training converged") # green check
|
|
102
|
+
logger.warning("validation loss plateaued")
|
|
103
|
+
logger.error("OOM on batch 42")
|
|
104
|
+
|
|
105
|
+
# Pretty-print structured data
|
|
106
|
+
logger.print({"epoch": 12, "lr": 3e-4, "loss": 0.21})
|
|
107
|
+
|
|
108
|
+
# Progress bar that works in parallel
|
|
109
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
110
|
+
with ThreadPoolExecutor(max_workers=8) as pool:
|
|
111
|
+
for result in logger.track(pool.map(process, items), total=len(items), description="batch"):
|
|
112
|
+
...
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## What's in the box
|
|
116
|
+
|
|
117
|
+
### Logger
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from klogr import get_logger, LoggingRich, DEFAULT_VERBOSITY
|
|
121
|
+
|
|
122
|
+
logger = get_logger() # default verbosity
|
|
123
|
+
quiet = get_logger({"info": False, "debug": False}) # custom
|
|
124
|
+
|
|
125
|
+
logger.info(msg) # cyan
|
|
126
|
+
logger.success(msg) # green check
|
|
127
|
+
logger.warning(msg) # yellow
|
|
128
|
+
logger.error(msg) # red
|
|
129
|
+
logger.rule(title) # horizontal divider
|
|
130
|
+
logger.print(any_object) # rich.print, soft-wrap aware
|
|
131
|
+
logger.info_json(json_str) # syntax-colored JSON
|
|
132
|
+
logger.track(iter, total, description) # progress bar
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Caching
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from klogr import lru_cache, DisableableLRUCache, get_cache_dir, sha256sum
|
|
139
|
+
|
|
140
|
+
@lru_cache(maxsize=128)
|
|
141
|
+
def expensive(key: str) -> bytes:
|
|
142
|
+
...
|
|
143
|
+
|
|
144
|
+
# Stable on-disk paths
|
|
145
|
+
cache_root = get_cache_dir() # XDG cache root
|
|
146
|
+
digest = sha256sum("/path/to/file.bin") # hex string
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Path helpers (local + S3 transparent)
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from klogr.path import (
|
|
153
|
+
path_join, path_exists, path_mkdir, path_dirname,
|
|
154
|
+
path_basename, path_glob, path_is_s3, path_open,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
path_exists("/tmp/local.bin") # True/False
|
|
158
|
+
path_exists("s3://bucket/key.bin") # True/False (same call)
|
|
159
|
+
path_mkdir("/tmp/nested/dir", parents=True, exist_ok=True)
|
|
160
|
+
for p in path_glob("/data/*.jpg"):
|
|
161
|
+
with path_open(p, "rb") as f:
|
|
162
|
+
...
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Timing
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from klogr import get_elapsed_time
|
|
169
|
+
|
|
170
|
+
print(get_elapsed_time(86400 + 3661)) # '01d : 01h : 01m : 01s'
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Examples
|
|
174
|
+
|
|
175
|
+
Runnable scripts live in [`examples/`](examples/):
|
|
176
|
+
|
|
177
|
+
- [`01_basic_logger.py`](examples/01_basic_logger.py) — log levels, formatting, file:line prefix
|
|
178
|
+
- [`02_pretty_tables.py`](examples/02_pretty_tables.py) — `LoggingTable` for tabular console output
|
|
179
|
+
- [`03_progress_tracking.py`](examples/03_progress_tracking.py) — `logger.track()` in parallel workers
|
|
180
|
+
- [`04_caching.py`](examples/04_caching.py) — `@lru_cache` with disable-hook
|
|
181
|
+
- [`05_path_helpers.py`](examples/05_path_helpers.py) — local + S3 path ops
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
uv run examples/01_basic_logger.py
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Layout
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
klogr/
|
|
191
|
+
├── __init__.py # public re-exports
|
|
192
|
+
├── logger.py # LoggingRich, LoggingTable, get_logger
|
|
193
|
+
├── cache.py # lru_cache, DisableableLRUCache, sha256sum, get_cache_dir
|
|
194
|
+
├── path/ # local + S3 path helpers
|
|
195
|
+
│ ├── __init__.py
|
|
196
|
+
│ ├── ops.py # pure ops (join, dirname, basename, suffix, …)
|
|
197
|
+
│ ├── env.py # path_dotenv, path_home, path_expanduser
|
|
198
|
+
│ ├── io.py # mkdir, remove, copy, move, read/write
|
|
199
|
+
│ └── query.py # exists, is_dir, glob, listdir, stat
|
|
200
|
+
└── time.py # get_elapsed_time
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Build & test
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
uv sync
|
|
207
|
+
.venv/bin/pre-commit run --all-files
|
|
208
|
+
.venv/bin/pytest
|
|
209
|
+
.venv/bin/mypy klogr/
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT — see [LICENSE.md](LICENSE.md).
|