barflow 0.6.2__cp315-cp315-win_amd64.whl
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.
- barflow/__init__.py +180 -0
- barflow/_core.cp315-win_amd64.pyd +0 -0
- barflow/_core.cpp +3207 -0
- barflow/_progress.py +85 -0
- barflow/_wrap.py +199 -0
- barflow/aio.py +126 -0
- barflow/bar_styles.py +506 -0
- barflow/columns.py +201 -0
- barflow/hooks.py +140 -0
- barflow/spinners.py +176 -0
- barflow/style.py +178 -0
- barflow/themes.py +975 -0
- barflow-0.6.2.dist-info/DELVEWHEEL +2 -0
- barflow-0.6.2.dist-info/METADATA +481 -0
- barflow-0.6.2.dist-info/RECORD +19 -0
- barflow-0.6.2.dist-info/WHEEL +5 -0
- barflow-0.6.2.dist-info/licenses/LICENSE +201 -0
- barflow-0.6.2.dist-info/top_level.txt +1 -0
- barflow.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
barflow/__init__.py
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""BarFlow — fast Python progress bars with a C++ core.
|
|
2
|
+
|
|
3
|
+
Top-level imports are kept minimal so `from barflow import track` stays
|
|
4
|
+
cold-startup-cheap (~1 ms). Columns, themes, spinners, hooks, and the
|
|
5
|
+
asyncio wrapper are lazy-loaded via `__getattr__` on first access.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# start delvewheel patch
|
|
10
|
+
def _delvewheel_patch_1_13_2():
|
|
11
|
+
import os
|
|
12
|
+
if os.path.isdir(libs_dir := os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, 'barflow.libs'))):
|
|
13
|
+
os.add_dll_directory(libs_dir)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_delvewheel_patch_1_13_2()
|
|
17
|
+
del _delvewheel_patch_1_13_2
|
|
18
|
+
# end delvewheel patch
|
|
19
|
+
|
|
20
|
+
from . import _core
|
|
21
|
+
from ._core import Tracker
|
|
22
|
+
|
|
23
|
+
__version__ = "0.6.2"
|
|
24
|
+
__all__ = ["Progress", "Tracker", "track", "wrap_file", "wrapattr", "__version__"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# ---- Fast path -------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
def _auto_disable():
|
|
30
|
+
"""True when stderr is not an interactive terminal. BarFlow renders to
|
|
31
|
+
stderr, so on a pipe/file/redirect we suppress the bar (tqdm's
|
|
32
|
+
`disable=None` behavior) rather than spraying ANSI frames into the sink."""
|
|
33
|
+
import sys
|
|
34
|
+
stream = sys.stderr
|
|
35
|
+
try:
|
|
36
|
+
return not (stream is not None and stream.isatty())
|
|
37
|
+
except Exception:
|
|
38
|
+
return True
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _build_progress(total, desc, columns, theme, disable, min_interval,
|
|
42
|
+
capture_output, smoothing, leave, unit, unit_scale,
|
|
43
|
+
unit_divisor, initial, delay):
|
|
44
|
+
"""Construct the Progress backing a track()/atrack() call.
|
|
45
|
+
|
|
46
|
+
Fast path: no columns, no theme, no capture_output → straight to
|
|
47
|
+
`_core.Progress` (one C-extension construction, no Python subclass).
|
|
48
|
+
Slow path: any decoration → route through the Python `Progress` class,
|
|
49
|
+
which resolves themes/columns before calling into the core.
|
|
50
|
+
"""
|
|
51
|
+
if columns or theme or capture_output:
|
|
52
|
+
from . import _progress
|
|
53
|
+
return _progress.Progress(
|
|
54
|
+
*(columns or ()),
|
|
55
|
+
total=total,
|
|
56
|
+
desc=desc,
|
|
57
|
+
theme=theme,
|
|
58
|
+
disable=disable,
|
|
59
|
+
min_interval=min_interval,
|
|
60
|
+
capture_output=capture_output,
|
|
61
|
+
smoothing=smoothing,
|
|
62
|
+
leave=leave,
|
|
63
|
+
unit=unit,
|
|
64
|
+
unit_scale=unit_scale,
|
|
65
|
+
unit_divisor=unit_divisor,
|
|
66
|
+
initial=initial,
|
|
67
|
+
delay=delay,
|
|
68
|
+
)
|
|
69
|
+
return _core.Progress(
|
|
70
|
+
total=total,
|
|
71
|
+
desc=desc,
|
|
72
|
+
min_interval=min_interval,
|
|
73
|
+
disable=disable,
|
|
74
|
+
smoothing=smoothing,
|
|
75
|
+
leave=leave,
|
|
76
|
+
unit=unit,
|
|
77
|
+
unit_scale=unit_scale,
|
|
78
|
+
unit_divisor=float(unit_divisor),
|
|
79
|
+
initial=initial,
|
|
80
|
+
delay=delay,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def track(iterable, total=None, desc=None, *, columns=None, theme=None,
|
|
85
|
+
task_id=0, disable=False, min_interval=0.05, capture_output=False,
|
|
86
|
+
smoothing=0.0, leave=True, unit="it", unit_scale=False,
|
|
87
|
+
unit_divisor=1000, initial=0, delay=0.0):
|
|
88
|
+
"""Wrap `iterable` in a live progress bar. Returns an iterator.
|
|
89
|
+
|
|
90
|
+
Fast path: no columns, no theme, no capture_output → goes straight to
|
|
91
|
+
`_core.Progress` (one C-extension construction, no Python subclass).
|
|
92
|
+
Slow path: any decoration → route through the Python `Progress` class.
|
|
93
|
+
|
|
94
|
+
`disable` False (default) always shows; True hides; None auto-disables
|
|
95
|
+
when stderr is not a TTY (tqdm's `disable=None` semantics).
|
|
96
|
+
`smoothing` 0 = whole-run average rate (default); (0,1] = EMA weight on
|
|
97
|
+
the most recent interval for a responsive it/s and ETA.
|
|
98
|
+
`leave` False clears the bar on completion instead of leaving it.
|
|
99
|
+
`unit` noun in the rate suffix ("it" → "N it/s", "B" → "N B/s").
|
|
100
|
+
`unit_scale` humanize counts/rates with SI-style k/M/G scaling.
|
|
101
|
+
`unit_divisor` scaling base — 1000 (SI) or 1024 (binary/bytes).
|
|
102
|
+
`initial` count already done (resume); shown but excluded from rate.
|
|
103
|
+
`delay` seconds to wait before showing the bar (hide fast jobs).
|
|
104
|
+
"""
|
|
105
|
+
if task_id != 0:
|
|
106
|
+
# track() always builds a single-task (task 0) bar; a non-zero
|
|
107
|
+
# task_id would otherwise reach the C Tracker bounds check and raise
|
|
108
|
+
# an opaque "task_id out of range". Fail fast with guidance instead.
|
|
109
|
+
raise ValueError(
|
|
110
|
+
"track() creates a single-task bar, so task_id must be 0. "
|
|
111
|
+
"For multiple bars use barflow.Progress + add_task()."
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
if disable is None:
|
|
115
|
+
disable = _auto_disable()
|
|
116
|
+
|
|
117
|
+
if total is None:
|
|
118
|
+
try:
|
|
119
|
+
total = len(iterable)
|
|
120
|
+
except TypeError:
|
|
121
|
+
total = 0
|
|
122
|
+
|
|
123
|
+
progress = _build_progress(
|
|
124
|
+
total, desc, columns, theme, disable, min_interval, capture_output,
|
|
125
|
+
smoothing, leave, unit, unit_scale, unit_divisor, initial, delay,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
progress.__enter__()
|
|
129
|
+
tracker = Tracker(iter(iterable), progress, task_id=task_id, owns_progress=True)
|
|
130
|
+
if capture_output:
|
|
131
|
+
# The C Tracker tears the progress down via close(), which bypasses
|
|
132
|
+
# the Python __exit__ that uninstalls stdout/stderr capture — so an
|
|
133
|
+
# exhausted track(capture_output=True) would otherwise leave sys.stdout
|
|
134
|
+
# permanently replaced. Guard the iteration so __exit__ always runs.
|
|
135
|
+
return _capture_guard(tracker, progress)
|
|
136
|
+
return tracker
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _capture_guard(tracker, progress):
|
|
140
|
+
"""Yield from `tracker`, guaranteeing `progress.__exit__` runs on
|
|
141
|
+
exhaustion, early break (generator close), or exception — so the
|
|
142
|
+
stdout/stderr capture is always uninstalled."""
|
|
143
|
+
try:
|
|
144
|
+
yield from tracker
|
|
145
|
+
finally:
|
|
146
|
+
progress.__exit__(None, None, None)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# ---- Lazy layer ------------------------------------------------------------
|
|
150
|
+
|
|
151
|
+
def __getattr__(name):
|
|
152
|
+
# Lazy-load the Progress Python subclass on first access.
|
|
153
|
+
if name == "Progress":
|
|
154
|
+
from . import _progress
|
|
155
|
+
Progress = _progress.Progress
|
|
156
|
+
globals()["Progress"] = Progress
|
|
157
|
+
return Progress
|
|
158
|
+
# File-object progress wrapping (barflow.wrap_file / .wrapattr) is lazy so
|
|
159
|
+
# the byte-humanization import cost is only paid by callers that use it.
|
|
160
|
+
if name in ("wrap_file", "wrapattr"):
|
|
161
|
+
from . import _wrap
|
|
162
|
+
globals()["wrap_file"] = _wrap.wrap_file
|
|
163
|
+
globals()["wrapattr"] = _wrap.wrapattr
|
|
164
|
+
return globals()[name]
|
|
165
|
+
# Hand-rolled dispatch avoids importing `importlib` and building a dict
|
|
166
|
+
# at module-load time. Each branch resolves to a single __import__ call.
|
|
167
|
+
if name == "columns":
|
|
168
|
+
mod = __import__("barflow.columns", fromlist=("columns",))
|
|
169
|
+
elif name == "themes":
|
|
170
|
+
mod = __import__("barflow.themes", fromlist=("themes",))
|
|
171
|
+
elif name == "spinners":
|
|
172
|
+
mod = __import__("barflow.spinners", fromlist=("spinners",))
|
|
173
|
+
elif name == "aio":
|
|
174
|
+
mod = __import__("barflow.aio", fromlist=("aio",))
|
|
175
|
+
elif name == "hooks":
|
|
176
|
+
mod = __import__("barflow.hooks", fromlist=("hooks",))
|
|
177
|
+
else:
|
|
178
|
+
raise AttributeError(f"module 'barflow' has no attribute {name!r}")
|
|
179
|
+
globals()[name] = mod
|
|
180
|
+
return mod
|
|
Binary file
|