barflow 0.2.2__tar.gz → 0.3.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.
Files changed (39) hide show
  1. {barflow-0.2.2/src/barflow.egg-info → barflow-0.3.0}/PKG-INFO +7 -4
  2. {barflow-0.2.2 → barflow-0.3.0}/README.md +2 -2
  3. {barflow-0.2.2 → barflow-0.3.0}/pyproject.toml +13 -2
  4. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/__init__.py +1 -1
  5. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/_core.cpp +85 -5
  6. {barflow-0.2.2 → barflow-0.3.0/src/barflow.egg-info}/PKG-INFO +7 -4
  7. {barflow-0.2.2 → barflow-0.3.0}/LICENSE +0 -0
  8. {barflow-0.2.2 → barflow-0.3.0}/MANIFEST.in +0 -0
  9. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/bench.py +0 -0
  10. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/bench_first_frame.py +0 -0
  11. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/bench_import_to_iter.py +0 -0
  12. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/bench_memory.py +0 -0
  13. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/bench_metadata_churn.py +0 -0
  14. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/bench_multibar.py +0 -0
  15. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/bench_raw.md +0 -0
  16. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/bench_tail_latency.py +0 -0
  17. {barflow-0.2.2 → barflow-0.3.0}/benchmarks/results.md +0 -0
  18. {barflow-0.2.2 → barflow-0.3.0}/docs/DESIGN.md +0 -0
  19. {barflow-0.2.2 → barflow-0.3.0}/docs/FEATURE_REQUESTS.md +0 -0
  20. {barflow-0.2.2 → barflow-0.3.0}/docs/PUBLISHING.md +0 -0
  21. {barflow-0.2.2 → barflow-0.3.0}/examples/async_stream.py +0 -0
  22. {barflow-0.2.2 → barflow-0.3.0}/examples/gallery.py +0 -0
  23. {barflow-0.2.2 → barflow-0.3.0}/examples/parallel_presets.py +0 -0
  24. {barflow-0.2.2 → barflow-0.3.0}/examples/presets_gallery.py +0 -0
  25. {barflow-0.2.2 → barflow-0.3.0}/examples/showcase.py +0 -0
  26. {barflow-0.2.2 → barflow-0.3.0}/examples/themes_showcase.py +0 -0
  27. {barflow-0.2.2 → barflow-0.3.0}/setup.cfg +0 -0
  28. {barflow-0.2.2 → barflow-0.3.0}/setup.py +0 -0
  29. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/_progress.py +0 -0
  30. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/aio.py +0 -0
  31. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/bar_styles.py +0 -0
  32. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/columns.py +0 -0
  33. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/hooks.py +0 -0
  34. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/spinners.py +0 -0
  35. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/style.py +0 -0
  36. {barflow-0.2.2 → barflow-0.3.0}/src/barflow/themes.py +0 -0
  37. {barflow-0.2.2 → barflow-0.3.0}/src/barflow.egg-info/SOURCES.txt +0 -0
  38. {barflow-0.2.2 → barflow-0.3.0}/src/barflow.egg-info/dependency_links.txt +0 -0
  39. {barflow-0.2.2 → barflow-0.3.0}/src/barflow.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: barflow
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: Fast Python progress bars with a C++ core. Windows-first.
5
5
  Author: NevermindNilas
6
6
  License-Expression: MIT
@@ -20,13 +20,16 @@ Classifier: Programming Language :: C++
20
20
  Classifier: Programming Language :: Python
21
21
  Classifier: Programming Language :: Python :: 3
22
22
  Classifier: Programming Language :: Python :: 3 :: Only
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
23
26
  Classifier: Programming Language :: Python :: 3.13
24
27
  Classifier: Programming Language :: Python :: 3.14
25
28
  Classifier: Programming Language :: Python :: Implementation :: CPython
26
29
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
30
  Classifier: Topic :: Terminals
28
31
  Classifier: Topic :: Utilities
29
- Requires-Python: >=3.13
32
+ Requires-Python: >=3.10
30
33
  Description-Content-Type: text/markdown
31
34
  License-File: LICENSE
32
35
  Dynamic: license-file
@@ -302,7 +305,7 @@ pip install barflow
302
305
  ```
303
306
 
304
307
  Wheels are published for Windows (AMD64), Linux (x86_64, aarch64), and
305
- macOS (x86_64, arm64) for CPython 3.13 and 3.14, including the
308
+ macOS (x86_64, arm64) for CPython 3.10 through 3.14, including the
306
309
  free-threaded `cp313t` / `cp314t` builds.
307
310
 
308
311
  ## Features
@@ -418,7 +421,7 @@ and the benchmarks methodology.
418
421
  ## Build from source
419
422
 
420
423
  Requires Visual Studio 2022+ (Windows) or GCC/Clang + Python headers
421
- (POSIX) and Python ≥ 3.13.
424
+ (POSIX) and Python ≥ 3.10.
422
425
 
423
426
  ```
424
427
  # Windows
@@ -269,7 +269,7 @@ pip install barflow
269
269
  ```
270
270
 
271
271
  Wheels are published for Windows (AMD64), Linux (x86_64, aarch64), and
272
- macOS (x86_64, arm64) for CPython 3.13 and 3.14, including the
272
+ macOS (x86_64, arm64) for CPython 3.10 through 3.14, including the
273
273
  free-threaded `cp313t` / `cp314t` builds.
274
274
 
275
275
  ## Features
@@ -385,7 +385,7 @@ and the benchmarks methodology.
385
385
  ## Build from source
386
386
 
387
387
  Requires Visual Studio 2022+ (Windows) or GCC/Clang + Python headers
388
- (POSIX) and Python ≥ 3.13.
388
+ (POSIX) and Python ≥ 3.10.
389
389
 
390
390
  ```
391
391
  # Windows
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "barflow"
7
- version = "0.2.2"
7
+ version = "0.3.0"
8
8
  description = "Fast Python progress bars with a C++ core. Windows-first."
9
9
  readme = "README.md"
10
- requires-python = ">=3.13"
10
+ requires-python = ">=3.10"
11
11
  license = "MIT"
12
12
  license-files = ["LICENSE"]
13
13
  authors = [
@@ -28,6 +28,9 @@ classifiers = [
28
28
  "Programming Language :: Python",
29
29
  "Programming Language :: Python :: 3",
30
30
  "Programming Language :: Python :: 3 :: Only",
31
+ "Programming Language :: Python :: 3.10",
32
+ "Programming Language :: Python :: 3.11",
33
+ "Programming Language :: Python :: 3.12",
31
34
  "Programming Language :: Python :: 3.13",
32
35
  "Programming Language :: Python :: 3.14",
33
36
  "Programming Language :: Python :: Implementation :: CPython",
@@ -53,3 +56,11 @@ where = ["src"]
53
56
  build-verbosity = 1
54
57
  test-command = 'python -c "import barflow; list(barflow.track(range(1000)))"'
55
58
  skip = ["*-musllinux_i686", "*-win32"]
59
+
60
+ [tool.cibuildwheel.macos]
61
+ # The C++17 core uses aligned new/delete, which Clang only emits for a
62
+ # deployment target of macOS 10.13+. CPython 3.12+ already defaults the
63
+ # x86_64 target high enough, but 3.10/3.11 default to 10.9 and fail to
64
+ # compile. Pin the floor to 10.13 for every macOS build (arm64 is always
65
+ # 11.0+ regardless, so this only lifts the x86_64 leg).
66
+ environment = { MACOSX_DEPLOYMENT_TARGET = "10.13" }
@@ -8,7 +8,7 @@ asyncio wrapper are lazy-loaded via `__getattr__` on first access.
8
8
  from . import _core
9
9
  from ._core import Tracker
10
10
 
11
- __version__ = "0.2.2"
11
+ __version__ = "0.3.0"
12
12
  __all__ = ["Progress", "Tracker", "track", "__version__"]
13
13
 
14
14
 
@@ -244,6 +244,14 @@ struct ProgressState {
244
244
  std::thread render_thread;
245
245
  std::once_flag close_once;
246
246
 
247
+ // pause()/resume() let an external writer (e.g. an output redirector)
248
+ // suspend the render thread, emit lines on the cleared bar area, and
249
+ // then have the bar repainted below. `paused` is checked by the render
250
+ // loop on every wakeup; `force_render` makes the first frame after
251
+ // resume repaint even if no counter moved while paused.
252
+ std::atomic<bool> paused{false};
253
+ bool force_render{false}; // guarded by render_mtx
254
+
247
255
  double min_interval{0.05};
248
256
  bool disable{false};
249
257
  bool vt_enabled{false};
@@ -1340,11 +1348,17 @@ void render_loop(ProgressState* st) {
1340
1348
  st->render_cv.wait_for(lock, interval);
1341
1349
  if (!st->running.load(std::memory_order_acquire)) break;
1342
1350
 
1351
+ // Suspended for external writing: do not touch the terminal until
1352
+ // resume() clears the flag. pause() already erased the bar area, so
1353
+ // the external writer owns the screen meanwhile.
1354
+ if (st->paused.load(std::memory_order_acquire)) continue;
1355
+
1343
1356
  // Render unconditionally if there is a spinner (it animates even
1344
- // with no producer progress); otherwise only if counters moved.
1345
- // The spinner flag is cached at column setup so we don't re-scan
1346
- // the column vector on every wakeup (every `min_interval`).
1347
- bool any_dirty = st->has_spinner_col;
1357
+ // with no producer progress) or if a resume forced a repaint;
1358
+ // otherwise only if counters moved. The spinner flag is cached at
1359
+ // column setup so we don't re-scan the column vector on every
1360
+ // wakeup (every `min_interval`).
1361
+ bool any_dirty = st->has_spinner_col || st->force_render;
1348
1362
  if (!any_dirty) {
1349
1363
  for (auto& t : st->tasks) {
1350
1364
  if (t->completed.load(std::memory_order_acquire) != t->last_snapshot) {
@@ -1353,7 +1367,10 @@ void render_loop(ProgressState* st) {
1353
1367
  }
1354
1368
  }
1355
1369
  }
1356
- if (any_dirty) render_frame(st);
1370
+ if (any_dirty) {
1371
+ render_frame(st);
1372
+ st->force_render = false;
1373
+ }
1357
1374
  }
1358
1375
  // Final frame, still under the lock.
1359
1376
  render_frame(st);
@@ -1948,6 +1965,65 @@ PyObject* Progress_write_above(PyProgress* self, PyObject* text_obj) {
1948
1965
  Py_RETURN_NONE;
1949
1966
  }
1950
1967
 
1968
+ // pause() — suspend the render thread and erase the bar area, leaving the
1969
+ // cursor at column 0 of the cleared region so an external writer can emit
1970
+ // lines there without the bar repainting on top. Mirrors the walk-back +
1971
+ // erase that write_above performs. Idempotent and safe to call when the bar
1972
+ // is disabled or closed (no-op). Pairs with resume().
1973
+ PyObject* Progress_pause(PyProgress* self, PyObject* /*args*/) {
1974
+ auto* st = self->state;
1975
+ if (st->disable || st->closed) Py_RETURN_NONE;
1976
+ {
1977
+ std::lock_guard<std::mutex> lg(st->render_mtx);
1978
+ // Acquiring render_mtx guarantees no frame is mid-flight: the render
1979
+ // loop only holds the lock outside its cv wait, so once we hold it
1980
+ // the last frame is fully written.
1981
+ st->paused.store(true, std::memory_order_release);
1982
+
1983
+ if (st->vt_enabled) {
1984
+ std::string& buf = st->scratch;
1985
+ buf.clear();
1986
+ int term_w = query_terminal_width(st);
1987
+ if (!st->last_task_cells.empty()) {
1988
+ int total_rows = 0;
1989
+ for (int c : st->last_task_cells) {
1990
+ int r = (term_w > 0) ? ((c + term_w - 1) / term_w) : 1;
1991
+ if (r < 1) r = 1;
1992
+ total_rows += r;
1993
+ }
1994
+ if (total_rows > 0) {
1995
+ buf.append("\x1b[", 2);
1996
+ char tmp[20];
1997
+ size_t n = u64_to_chars(tmp, static_cast<uint64_t>(total_rows));
1998
+ buf.append(tmp, n);
1999
+ buf.push_back('A');
2000
+ }
2001
+ }
2002
+ buf.push_back('\r');
2003
+ buf.append("\x1b[J", 3); // erase from cursor to end of screen
2004
+ write_bytes(st, buf.data(), buf.size());
2005
+ st->last_rendered_lines = 0;
2006
+ st->last_task_cells.clear();
2007
+ st->delta_valid = false; // resume repaints from scratch
2008
+ }
2009
+ }
2010
+ Py_RETURN_NONE;
2011
+ }
2012
+
2013
+ // resume() — undo pause(): clear the suspend flag and force the next render
2014
+ // loop wakeup to repaint the bar below whatever the external writer emitted.
2015
+ PyObject* Progress_resume(PyProgress* self, PyObject* /*args*/) {
2016
+ auto* st = self->state;
2017
+ if (st->disable || st->closed) Py_RETURN_NONE;
2018
+ {
2019
+ std::lock_guard<std::mutex> lg(st->render_mtx);
2020
+ st->paused.store(false, std::memory_order_release);
2021
+ st->force_render = true;
2022
+ }
2023
+ st->render_cv.notify_one();
2024
+ Py_RETURN_NONE;
2025
+ }
2026
+
1951
2027
  PyObject* Progress_get_completed(PyProgress* self, void* /*closure*/) {
1952
2028
  Task* t = self->state->task0.load(std::memory_order_acquire);
1953
2029
  uint64_t v = t ? t->completed.load(std::memory_order_relaxed) : 0;
@@ -1989,6 +2065,10 @@ PyMethodDef Progress_methods[] = {
1989
2065
  "Force an immediate render frame."},
1990
2066
  {"write_above",reinterpret_cast<PyCFunction>(Progress_write_above),
1991
2067
  METH_O, "Emit text above the bar area without tearing."},
2068
+ {"pause", reinterpret_cast<PyCFunction>(Progress_pause), METH_NOARGS,
2069
+ "Suspend the render thread and clear the bar so external writes are clean."},
2070
+ {"resume", reinterpret_cast<PyCFunction>(Progress_resume), METH_NOARGS,
2071
+ "Resume rendering after pause(), repainting the bar."},
1992
2072
  {nullptr, nullptr, 0, nullptr}
1993
2073
  };
1994
2074
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: barflow
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: Fast Python progress bars with a C++ core. Windows-first.
5
5
  Author: NevermindNilas
6
6
  License-Expression: MIT
@@ -20,13 +20,16 @@ Classifier: Programming Language :: C++
20
20
  Classifier: Programming Language :: Python
21
21
  Classifier: Programming Language :: Python :: 3
22
22
  Classifier: Programming Language :: Python :: 3 :: Only
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
23
26
  Classifier: Programming Language :: Python :: 3.13
24
27
  Classifier: Programming Language :: Python :: 3.14
25
28
  Classifier: Programming Language :: Python :: Implementation :: CPython
26
29
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
30
  Classifier: Topic :: Terminals
28
31
  Classifier: Topic :: Utilities
29
- Requires-Python: >=3.13
32
+ Requires-Python: >=3.10
30
33
  Description-Content-Type: text/markdown
31
34
  License-File: LICENSE
32
35
  Dynamic: license-file
@@ -302,7 +305,7 @@ pip install barflow
302
305
  ```
303
306
 
304
307
  Wheels are published for Windows (AMD64), Linux (x86_64, aarch64), and
305
- macOS (x86_64, arm64) for CPython 3.13 and 3.14, including the
308
+ macOS (x86_64, arm64) for CPython 3.10 through 3.14, including the
306
309
  free-threaded `cp313t` / `cp314t` builds.
307
310
 
308
311
  ## Features
@@ -418,7 +421,7 @@ and the benchmarks methodology.
418
421
  ## Build from source
419
422
 
420
423
  Requires Visual Studio 2022+ (Windows) or GCC/Clang + Python headers
421
- (POSIX) and Python ≥ 3.13.
424
+ (POSIX) and Python ≥ 3.10.
422
425
 
423
426
  ```
424
427
  # Windows
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes