backpack-backbone 0.2.0__py3-none-any.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.
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.4
2
+ Name: backpack-backbone
3
+ Version: 0.2.0
4
+ Summary: Shared code for the back* tools: terminal UI, prompt widgets, live views, logging, dates, settings plumbing and small file helpers, implemented once.
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/RedEraRrow/backbone
7
+ Project-URL: Issues, https://github.com/RedEraRrow/backbone/issues
8
+ Classifier: Environment :: Console :: Curses
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: MacOS
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Dynamic: license-file
18
+
19
+ # backbone
20
+
21
+ Everything the back* tools share, written once: colours, margins, box
22
+ drawing, meters, prompt widgets and a live-view loop, so a list in one tool
23
+ looks and behaves like a list in another, plus the plumbing underneath (logging,
24
+ dates, CLI output, atomic files, background processes, notifications). backtrack
25
+ and backcrack both build on it, and a new tool should too: anything that isn't
26
+ specific to one tool's job belongs here.
27
+
28
+ Python, stdlib only - no third-party packages at all. Requires Python 3.10+.
29
+
30
+ This is a library, not a tool. It has no entry points of its own; something
31
+ else imports it.
32
+
33
+ ## Install
34
+
35
+ On PyPI as `backpack-backbone` (the import name is still `backbone`).
36
+ backtrack and backcrack depend on it, so installing either one pulls it in;
37
+ there's no reason to install it on its own unless you're building a tool.
38
+
39
+ To work on it, install this checkout editable before the tools, so edits here
40
+ take effect immediately with no reinstall:
41
+
42
+ pip3 install -e .
43
+
44
+ pip then sees the requirement already satisfied and leaves it.
45
+
46
+ `backbone.deps` is how a tool says what it needs besides Python: each tool's
47
+ `doctor` command reports it, and `deps.require` stops a tool at startup with
48
+ how to install anything it can't run without.
49
+
50
+ ## What's in it
51
+
52
+ **`ui`** - the visual layer. `Colors` (honours `NO_COLOR=1`), the global
53
+ `MARGIN_H` / `MARGIN_V` inset every frame is drawn inside, `wrap_margins`,
54
+ `rule`, `bar`, `header_box`, `sparkline`, `spinner`, `rate_of_change`, and
55
+ the `SPIN` / `PARTS` / `SPARK` glyph sets. Also the ANSI-aware text
56
+ measuring (`visual_len`, `truncate_text`, `clip_ansi`, `strip_ansi`) that
57
+ makes any of that survive colour codes and wide characters, and small
58
+ formatters: `plural`, `human_gb`, `dir_size_kb`. The accent colour is chosen
59
+ with `set_accent` (an `ACCENT_PRESETS` key or `#RRGGBB`); a tool calls it once
60
+ at startup from its own settings, and `accent_code` / `accent_label` let a
61
+ settings screen check and name a value.
62
+
63
+ `from backbone import ...` exposes only a subset of `ui` (`Colors`, the
64
+ margins and glyph sets, `spinner`, `content_width`, `rule`, `bar`,
65
+ `header_box`, `wrap_margins`); import anything else from its module, e.g.
66
+ `from backbone.ui import human_gb`.
67
+
68
+ **`prompt`** - the widgets. `select` (single or multi), `confirm`, `text`,
69
+ `path`, `live_select`, `list_edit`, plus specialised editors for tag-style
70
+ values: `calendar_select`, `datetime_edit`, `time_edit`,
71
+ `fraction_edit`, `number_edit`, `rating_edit`, `equaliser_edit`, `rva2_edit`,
72
+ `system_editor_edit`. All resize-aware, all mouse-aware, all rendered through
73
+ the same painter.
74
+
75
+ **`prompt.core`** - the primitives underneath: the screen-diff painter, key
76
+ reading, the `Choice` and `Column` types, the footer hint bar (`hint`) and its
77
+ click mapping, and `run_dashboard`.
78
+
79
+ **`nav`** - `NAV_STACK`, the app-wide breadcrumb, and `QuitToTerminal`, which
80
+ derives from `BaseException` specifically so an editor's `except Exception`
81
+ can't swallow a quit.
82
+
83
+ **`datetime_parse`** - one date and time parser for everything that reads a
84
+ hand-typed date, keeping whatever precision was given and saying why when it
85
+ can't read something.
86
+
87
+ **`app`** - who is running. A tool calls `app.configure("name", config_dir)`
88
+ once at startup (from its config module); the log file and the hints toggle
89
+ are kept in that folder, named after the tool.
90
+
91
+ **`log`** - the diagnostics log, `<config_dir>/<name>.log`, off until the
92
+ tool calls `log.configure(True)`. `from backbone.log import log` to write to
93
+ it, and `with quietly():` to carry on past an error on purpose while still
94
+ logging it.
95
+
96
+ **`output`** - a CLI's one output path: `table`, `record`, `event`, `note`,
97
+ `fail`, drawn as human text on a terminal or JSON / NDJSON with `--json`, and
98
+ the exit codes that go with them.
99
+
100
+ **`files`** - `write_text_atomic`, `backup_copy`, `log_line` (a daemon's
101
+ timestamped line, printed and appended to its log), `disk_free`,
102
+ `count_entries`.
103
+
104
+ **`procs`** - a tool's own background processes: `spawn_module` starts one (`python -m`)
105
+ detached, `find_processes` / `stop_processes` find or SIGTERM them by name
106
+ however they were started (directly, through `python3`, or through a launcher
107
+ command given as `launcher=`), `ps_listing` for the raw process table.
108
+
109
+ **`notify`** - `ntfy(server, topic, title, message)` pushes to a phone in the
110
+ background, doing nothing without a topic; `chime()` plays a sound at the
111
+ machine.
112
+
113
+ **`timefmt`**, **`numbering`**, **`keyboard`**, **`terminal_input`** - clock
114
+ and SRT timestamps; arabic, roman or written-out numbers; the keyboard layout
115
+ family (for typo scoring); raw key reads and escape decoding.
116
+
117
+ **`prompt.timezone`** - a full-screen world-map timezone picker.
118
+
119
+ ## Live views
120
+
121
+ `run_dashboard(render, interval=..., on_key=...)` drives a tick-driven view
122
+ through the same `_Widget` machinery every prompt widget uses, rather than each
123
+ tool hand-rolling a redraw loop:
124
+
125
+ from backbone.prompt.core import run_dashboard
126
+
127
+ def render() -> list:
128
+ return [" line one", " line two"]
129
+
130
+ run_dashboard(render, interval=1.0, quit_key="q")
131
+
132
+ `render()` returns the whole frame as a list of lines, each carrying its own
133
+ left indent, and only runs once per `interval`. Keypresses and resizes are
134
+ checked every 50ms regardless, so a resize repaints and a `q` quits at once
135
+ instead of waiting out the data-refresh cadence. `on_key` handles anything
136
+ other than the quit key and is free to open a `select()` or `confirm()` of its
137
+ own; the dashboard repaints from scratch when it returns.
138
+
139
+ When stdin isn't a terminal (run from a script, or with input redirected),
140
+ it falls back to a plain sleep loop and never reads keys, so such a view has
141
+ to be stopped from outside.
142
+
143
+ ## Terminal size
144
+
145
+ Everything reads `get_terminal_width()`, one cached value invalidated by
146
+ SIGWINCH, rather than calling out to the OS per line. `consume_resize()` tells
147
+ a loop a resize has landed since it last asked, which is the signal to clear
148
+ and repaint rather than diff.
149
+
150
+ `content_width()` is that width minus the margins, with no artificial floor:
151
+ content is always sized against the real terminal, however narrow, so a hard
152
+ clip later can't cut an oversized frame apart mid-border.
153
+
154
+ ## Status bar and background work
155
+
156
+ `set_status(task_id, message)` registers running background work, which shows
157
+ in the status line as a pulsing beacon until the id is cleared. `show_status`
158
+ is the transient one-line toast. `set_footer_provider(fn)` registers a
159
+ persistent box drawn above the status line, such as backtrack's now-playing
160
+ bar; register nothing and no box is drawn. `prompt` also has optional hooks
161
+ for a host app's playback keys and player view (`set_transport_handler`,
162
+ `set_player_opener`), unused unless registered.
163
+
164
+ ## Self-checks
165
+
166
+ Two modules check their own pure logic, no terminal needed:
167
+
168
+ python3 -m backbone.ui
169
+ python3 -m backbone.prompt.core
170
+
171
+ Both print an OK line. They cover the parts that run without a terminal:
172
+ sizing, measuring, truncation, table widths, hint parsing. Raw mode,
173
+ key reading and screen painting need a real tty and are not covered.
174
+
175
+ The tests in `tests/` each run on their own:
176
+
177
+ for f in tests/test_*.py; do python3 "$f"; done
@@ -0,0 +1,32 @@
1
+ backbone/__init__.py,sha256=mgm36mKKetE4QnBR3adCDhx6OUFhzJAJpSNDNg42sEU,455
2
+ backbone/app.py,sha256=ptk3KNM6azVNz5cn4sQn-i3eztgV23hagvcmusdE6sQ,964
3
+ backbone/datetime_parse.py,sha256=Vj9hHfprrOVtFrZEqf7wsuAK6IZn1WNKs0hFimmXLAA,8976
4
+ backbone/deps.py,sha256=oH1UFo8-Zzx-KLyRBpsZ54DKi82bFpM_RhIAIRplAWM,3556
5
+ backbone/files.py,sha256=2nvhOCFon8zmMG18sBeYQvHOIUjIMh0gtVEi6_VPcto,2100
6
+ backbone/keyboard.py,sha256=qsnYxqeyqw4zhGkKfQAjZCJW2CdXmY9JyWIPODzfIKQ,6324
7
+ backbone/keys.py,sha256=LKq4MoKSCjdhI2F1FbEVxof0GYnlLphBevia5EHin0c,10095
8
+ backbone/log.py,sha256=RrNLdUVc2dLB7lyhMP89g1DQGD_gGvJ-U_q5RmzMihk,2187
9
+ backbone/nav.py,sha256=6RjZqzGzP7ktr5HSsOnoMfGE9mrVTijqaaRvoUdTCZI,760
10
+ backbone/notify.py,sha256=MU87rMLYiMQP-itBcfIVNZS1VDvyuVCkUlah6BOmhvQ,1288
11
+ backbone/numbering.py,sha256=vUM8ggvX1nFx4wHREUmJUuGgNzpNTPIic1xZkE_Es5E,6575
12
+ backbone/output.py,sha256=-2HYbUBxivoCDlXB4MGQF3xX75HEdtaF4JY4JlF9H1U,7704
13
+ backbone/procs.py,sha256=Q3ikR4lpGxuPhaNxrdLMvpuIpQZ2TgpXdCskVSRcNHE,2473
14
+ backbone/terminal_input.py,sha256=ycmvf23vC8UmByXtlpC5pUirrVum5WxGW4yUI5q2Ibs,1931
15
+ backbone/timefmt.py,sha256=l_pw87mz1SzSHrzrMUdOI1BMjzjD2bIzXhTVNgk4vyg,1043
16
+ backbone/ui.py,sha256=ScaBndBc3xRCiYqQPz-kc3zQehJQIkUl4ikVRw_H5E4,40224
17
+ backbone/prompt/__init__.py,sha256=i_b9GzrqHcVicgu4Smt2OYP0prZHAaMc8InvLCSNaPU,1257
18
+ backbone/prompt/audio.py,sha256=GhNS7izyySgAWXFmn7o978onGUYA-O-PI96ZpjSYfhg,20859
19
+ backbone/prompt/chrome.py,sha256=h0f6HF2_pWRAFiBGFnTopRyDsBN5WmPVLLuT9a4wHXI,9658
20
+ backbone/prompt/core.py,sha256=dQ7lgk8Cx1maoWKdUG2gHX7VLZxuZOenpy6g-nAnVbI,66766
21
+ backbone/prompt/dates.py,sha256=Ds_T7JzfNNmO1h10bGaKihN4Hy71JTGFidJJLnCF6_I,20935
22
+ backbone/prompt/keymap.py,sha256=pbd_fSJaN33-dGwIcmGm3aCLlCKrH0PrVW__Oh4Xzbs,5360
23
+ backbone/prompt/list_edit.py,sha256=B4z6UGUC6OJLOWvMtdJjZRCoY3kl5GA16pTqznzV_7M,44054
24
+ backbone/prompt/lists.py,sha256=uMMDzPk5BWNDMXNtdnlCnFuhbCaLKaXqBN7krmXDCBA,62294
25
+ backbone/prompt/text.py,sha256=T5uOZ5h0omGPG1ztyRJ3jY1USQdhR57YbqdvbRkcs70,14454
26
+ backbone/prompt/timezone.py,sha256=TI_-2MMHl4ZEpn-wWOZC8ONkonuvLpvNqRfK9j1FHPs,114806
27
+ backbone/prompt/values.py,sha256=83Yw7vmqirgthz7DNOQDPX7t_N6Q5rI4DrDZ8y519y4,22257
28
+ backpack_backbone-0.2.0.dist-info/licenses/LICENSE,sha256=GYuXCU6db-Xi7yUsUcRXZgYcfoe-Ss7NRcwhkZtWbhc,1067
29
+ backpack_backbone-0.2.0.dist-info/METADATA,sha256=_lK3YZSBY35JRJ2bxowIjTiA1dbFMuBA4UpwHM7s8JQ,7941
30
+ backpack_backbone-0.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
31
+ backpack_backbone-0.2.0.dist-info/top_level.txt,sha256=wcJ_vuPxKxasZ-47O-yKsFyJsJ2HS-ORXyzJz9qe7Vc,9
32
+ backpack_backbone-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 RedEraRrow
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 @@
1
+ backbone