devicectl-core 0.1.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.
Files changed (47) hide show
  1. devicectl/__init__.py +18 -0
  2. devicectl/cli/__init__.py +1 -0
  3. devicectl/cli/command.py +95 -0
  4. devicectl/cli/exits.py +32 -0
  5. devicectl/cli/fanout.py +142 -0
  6. devicectl/cli/main.py +69 -0
  7. devicectl/cli/output.py +299 -0
  8. devicectl/cli/parser.py +80 -0
  9. devicectl/cli/report.py +86 -0
  10. devicectl/cli/target.py +26 -0
  11. devicectl/clock.py +57 -0
  12. devicectl/devtools/__init__.py +6 -0
  13. devicectl/devtools/frontlint.py +935 -0
  14. devicectl/devtools/htmcheck.py +396 -0
  15. devicectl/devtools/rendercheck.py +384 -0
  16. devicectl/doctor.py +112 -0
  17. devicectl/errors.py +68 -0
  18. devicectl/fields.py +564 -0
  19. devicectl/meta.py +64 -0
  20. devicectl/paths.py +40 -0
  21. devicectl/progress.py +77 -0
  22. devicectl/report.py +67 -0
  23. devicectl/testing.py +199 -0
  24. devicectl/trace.py +333 -0
  25. devicectl/web/__init__.py +1 -0
  26. devicectl/web/agents.py +94 -0
  27. devicectl/web/events.py +171 -0
  28. devicectl/web/http.py +243 -0
  29. devicectl/web/progress.py +101 -0
  30. devicectl/web/server.py +1013 -0
  31. devicectl/web/static/core.css +3034 -0
  32. devicectl/web/static/js/api.js +198 -0
  33. devicectl/web/static/js/band.js +640 -0
  34. devicectl/web/static/js/chart.js +400 -0
  35. devicectl/web/static/js/drafts.js +312 -0
  36. devicectl/web/static/js/notify.js +272 -0
  37. devicectl/web/static/js/panels.js +432 -0
  38. devicectl/web/static/js/shell.js +672 -0
  39. devicectl/web/static/js/trace.js +133 -0
  40. devicectl/web/static/js/ui.js +1139 -0
  41. devicectl/web/static/vendor/preact-htm.module.js +27 -0
  42. devicectl/web/worker.py +697 -0
  43. devicectl_core-0.1.0.dist-info/METADATA +131 -0
  44. devicectl_core-0.1.0.dist-info/RECORD +47 -0
  45. devicectl_core-0.1.0.dist-info/WHEEL +4 -0
  46. devicectl_core-0.1.0.dist-info/licenses/LICENSE +287 -0
  47. devicectl_core-0.1.0.dist-info/licenses/NOTICE +13 -0
@@ -0,0 +1,133 @@
1
+ /* A failure that the device caused, turned into a recording of the next one.
2
+ *
3
+ * When a write to a device fails, the one thing that would tell anybody why
4
+ * -- the frames that went over the wire and what came back -- is only there
5
+ * if somebody had thought to start recording beforehand, which nobody ever
6
+ * has. So the first such failure starts the recording itself and says so:
7
+ * the page asks for the same thing again, and this time it is on tape. A
8
+ * failure while a recording is already running offers the recording there
9
+ * and then, from the notice that reported it.
10
+ *
11
+ * Which failures count is the server's to say, not the page's: an error
12
+ * reply carries `traceable` when it came from the device or the link to it
13
+ * -- no answer, a refusal, a checksum -- or from a bug in the program while
14
+ * it was talking to one. A value out of range, a port nobody has chosen, a
15
+ * request the server was too busy for: none of those is in a trace, and
16
+ * none of them starts one.
17
+ *
18
+ * Whether it does this at all is a choice kept per browser, beside the
19
+ * theme and the bell, and on until somebody turns it off -- from the notice
20
+ * itself, or from the program's Tools tab. Turning it off also stops a
21
+ * recording it started (the server marks those `automatic`): a switch
22
+ * labelled "record on failure" that is off beside a card still saying
23
+ * "recording" leaves nobody sure which of the two to believe. A recording
24
+ * somebody started by hand is theirs, and runs on. Nothing here knows
25
+ * what the recording is of; the program hands in the three calls that
26
+ * start, stop and download it, and `start` is asked for an automatic one.
27
+ */
28
+
29
+ import { html, useRef, useState } from '/core/vendor/preact-htm.module.js';
30
+
31
+ let program = 'devicectl';
32
+
33
+ export function configure({ name }) {
34
+ program = name;
35
+ }
36
+
37
+ const key = () => `${program}-auto-trace`;
38
+
39
+ function stored() {
40
+ try {
41
+ return localStorage.getItem(key()) !== 'off';
42
+ } catch {
43
+ return true;
44
+ }
45
+ }
46
+
47
+ function store(on) {
48
+ try {
49
+ if (on) localStorage.removeItem(key());
50
+ else localStorage.setItem(key(), 'off');
51
+ } catch {
52
+ /* A browser that keeps nothing keeps the default, which is on. */
53
+ }
54
+ }
55
+
56
+ /* The behaviour, and the preference behind it.
57
+ *
58
+ * `recording` is whether the server says a recording is running, and
59
+ * `automatic` whether this started it; both are read through a ref when a
60
+ * failure lands rather than from the render that wired the handler up.
61
+ * `start`, `stop` and `download` are the program's own calls.
62
+ * `failed(what, err)` is what the program's error path calls in place of a
63
+ * plain error toast; it returns true when it has said something itself.
64
+ */
65
+ export function useAutoTrace({ toast, recording, automatic, start, stop, download }) {
66
+ const [enabled, setEnabled] = useState(stored);
67
+ const live = useRef({ recording, automatic });
68
+ live.current = { recording, automatic };
69
+
70
+ const set = async (on) => {
71
+ store(on);
72
+ setEnabled(on);
73
+ if (on || !live.current.recording || !live.current.automatic) return;
74
+ await stop();
75
+ toast.info('Stopped the recording a failure started. It is kept, to download or throw away.');
76
+ };
77
+
78
+ const actions = () => [
79
+ { label: 'Download trace', onClick: () => download(), dismiss: false },
80
+ { label: 'Stop recording', onClick: () => stop() },
81
+ {
82
+ label: 'Stop recording automatically',
83
+ onClick: async () => {
84
+ await set(false);
85
+ toast.info('Failures will no longer start a recording. The Tools tab turns it back on.');
86
+ },
87
+ },
88
+ ];
89
+
90
+ const failed = (what, err) => {
91
+ if (!err?.traceable || !stored()) return false;
92
+ const said = what ? `${what}: ${err.message}` : err.message;
93
+ if (live.current.recording) {
94
+ toast.error(
95
+ `${said}. The serial trace was recording while it happened, so what went over ` +
96
+ 'the wire is in it.',
97
+ { actions: actions() }
98
+ );
99
+ return true;
100
+ }
101
+ Promise.resolve()
102
+ .then(start)
103
+ .then(
104
+ () =>
105
+ toast.error(
106
+ `${said}. That came from the device, so a serial trace is recording now: ` +
107
+ 'try it again, and the trace will have every frame of it.',
108
+ { actions: actions() }
109
+ ),
110
+ () => toast.error(said)
111
+ );
112
+ return true;
113
+ };
114
+
115
+ return { enabled, set, failed };
116
+ }
117
+
118
+ /* The preference, as a row for a program's Tools tab. */
119
+ export function AutoTraceToggle({ auto }) {
120
+ return html`<div class="row" title="when the device fails a request, start recording the trace and offer it">
121
+ <div class="k">Record on failure</div>
122
+ <div class="v">
123
+ <label class="toggle">
124
+ <span class="muted">${auto.enabled ? 'on' : 'off'}</span>
125
+ <input
126
+ type="checkbox"
127
+ checked=${auto.enabled}
128
+ onChange=${(e) => auto.set(e.target.checked)}
129
+ />
130
+ </label>
131
+ </div>
132
+ </div>`;
133
+ }