waitbus 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 (118) hide show
  1. waitbus/__init__.py +93 -0
  2. waitbus/__init__.pyi +38 -0
  3. waitbus/_broadcast_sub.py +737 -0
  4. waitbus/_cloudevents.py +164 -0
  5. waitbus/_columns.py +115 -0
  6. waitbus/_compose.py +129 -0
  7. waitbus/_config.py +359 -0
  8. waitbus/_db.py +698 -0
  9. waitbus/_doorbell.py +251 -0
  10. waitbus/_duration.py +33 -0
  11. waitbus/_emit.py +373 -0
  12. waitbus/_frame.py +332 -0
  13. waitbus/_http.py +40 -0
  14. waitbus/_log.py +34 -0
  15. waitbus/_mcp_constants.py +104 -0
  16. waitbus/_mcp_models.py +245 -0
  17. waitbus/_mcp_subscriptions.py +198 -0
  18. waitbus/_messaging.py +308 -0
  19. waitbus/_metrics.py +418 -0
  20. waitbus/_metrics_http.py +106 -0
  21. waitbus/_paths.py +187 -0
  22. waitbus/_peercred.py +72 -0
  23. waitbus/_predicate.py +390 -0
  24. waitbus/_protocols.py +24 -0
  25. waitbus/_sdnotify.py +37 -0
  26. waitbus/_secrets.py +125 -0
  27. waitbus/_subscribe.py +507 -0
  28. waitbus/_terminal.py +134 -0
  29. waitbus/_types.py +189 -0
  30. waitbus/_ulid.py +107 -0
  31. waitbus/_untrusted.py +109 -0
  32. waitbus/_version.py +11 -0
  33. waitbus/broadcast.py +1816 -0
  34. waitbus/broadcast_tap.py +131 -0
  35. waitbus/cli/__init__.py +67 -0
  36. waitbus/cli/_exit_codes.py +81 -0
  37. waitbus/cli/_shared.py +906 -0
  38. waitbus/cli/allowlist.py +353 -0
  39. waitbus/cli/daemons/__init__.py +20 -0
  40. waitbus/cli/daemons/broadcast.py +73 -0
  41. waitbus/cli/daemons/etag_poll.py +39 -0
  42. waitbus/cli/daemons/listener.py +39 -0
  43. waitbus/cli/daemons/mcp.py +50 -0
  44. waitbus/cli/daemons/pr_monitor.py +38 -0
  45. waitbus/cli/daemons/read_events.py +49 -0
  46. waitbus/cli/daemons/watchdog_check.py +38 -0
  47. waitbus/cli/db/__init__.py +8 -0
  48. waitbus/cli/db/migrate.py +113 -0
  49. waitbus/cli/db/prune.py +317 -0
  50. waitbus/cli/demo.py +593 -0
  51. waitbus/cli/doctor.py +55 -0
  52. waitbus/cli/emit.py +114 -0
  53. waitbus/cli/init.py +97 -0
  54. waitbus/cli/install/__init__.py +9 -0
  55. waitbus/cli/install/credentials.py +111 -0
  56. waitbus/cli/install/launchd.py +136 -0
  57. waitbus/cli/install/systemd.py +122 -0
  58. waitbus/cli/main.py +150 -0
  59. waitbus/cli/on.py +25 -0
  60. waitbus/cli/query/__init__.py +5 -0
  61. waitbus/cli/query/events.py +145 -0
  62. waitbus/cli/replay.py +21 -0
  63. waitbus/cli/serve.py +603 -0
  64. waitbus/cli/sources.py +460 -0
  65. waitbus/cli/stats.py +131 -0
  66. waitbus/cli/status.py +109 -0
  67. waitbus/cli/stress.py +49 -0
  68. waitbus/cli/swarm_demo.py +291 -0
  69. waitbus/cli/top.py +25 -0
  70. waitbus/cli/verify_plugin.py +59 -0
  71. waitbus/cli/wait.py +24 -0
  72. waitbus/coalesce.py +196 -0
  73. waitbus/config_validate.py +359 -0
  74. waitbus/etag_poll.py +718 -0
  75. waitbus/events_analyze.py +140 -0
  76. waitbus/events_query.py +363 -0
  77. waitbus/listener.py +731 -0
  78. waitbus/mcp.py +1463 -0
  79. waitbus/migrations/0001_initial_schema.sql +87 -0
  80. waitbus/migrations/0002_add_daemon_sequence.sql +94 -0
  81. waitbus/migrations/__init__.py +401 -0
  82. waitbus/on.py +730 -0
  83. waitbus/pr_monitor.py +405 -0
  84. waitbus/py.typed +0 -0
  85. waitbus/read_events.py +545 -0
  86. waitbus/replay.py +295 -0
  87. waitbus/schema.sql +130 -0
  88. waitbus/sources/__init__.py +83 -0
  89. waitbus/sources/_attestation.py +379 -0
  90. waitbus/sources/_config.py +446 -0
  91. waitbus/sources/_protocol.py +324 -0
  92. waitbus/sources/_registry.py +806 -0
  93. waitbus/sources/docker_watch.py +492 -0
  94. waitbus/sources/fs_watch.py +307 -0
  95. waitbus/sources/pytest_emit.py +330 -0
  96. waitbus/stats.py +492 -0
  97. waitbus/top.py +256 -0
  98. waitbus/wait.py +713 -0
  99. waitbus/watchdog_check.py +225 -0
  100. waitbus-0.1.0.data/data/share/launchd/MANIFEST.txt +11 -0
  101. waitbus-0.1.0.data/data/share/launchd/dev.waitbus.broadcast.plist +43 -0
  102. waitbus-0.1.0.data/data/share/launchd/dev.waitbus.etag-poll.plist +34 -0
  103. waitbus-0.1.0.data/data/share/launchd/dev.waitbus.listener.plist +44 -0
  104. waitbus-0.1.0.data/data/share/launchd/dev.waitbus.watchdog.plist +32 -0
  105. waitbus-0.1.0.data/data/share/systemd/user/waitbus-broadcast.service +50 -0
  106. waitbus-0.1.0.data/data/share/systemd/user/waitbus-broadcast.socket +18 -0
  107. waitbus-0.1.0.data/data/share/systemd/user/waitbus-etag-poll.service +36 -0
  108. waitbus-0.1.0.data/data/share/systemd/user/waitbus-etag-poll.timer +11 -0
  109. waitbus-0.1.0.data/data/share/systemd/user/waitbus-forward@.service +46 -0
  110. waitbus-0.1.0.data/data/share/systemd/user/waitbus-listener.service +53 -0
  111. waitbus-0.1.0.data/data/share/systemd/user/waitbus-watchdog.service +53 -0
  112. waitbus-0.1.0.data/data/share/systemd/user/waitbus-watchdog.timer +14 -0
  113. waitbus-0.1.0.data/data/share/systemd/user/waitbus.MANIFEST.txt +16 -0
  114. waitbus-0.1.0.dist-info/METADATA +758 -0
  115. waitbus-0.1.0.dist-info/RECORD +118 -0
  116. waitbus-0.1.0.dist-info/WHEEL +4 -0
  117. waitbus-0.1.0.dist-info/entry_points.txt +2 -0
  118. waitbus-0.1.0.dist-info/licenses/LICENSE +21 -0
waitbus/__init__.py ADDED
@@ -0,0 +1,93 @@
1
+ """waitbus: report GitHub Actions CI status from locally-cached webhook events.
2
+
3
+ Package providing the listener, ETag-poll fallback, query CLI, watchdog
4
+ absence-detector, and the broadcast daemon. Each module is invocable as
5
+ `python -m waitbus.<module>` or via its installed console-script
6
+ (`waitbus-listener`, `waitbus-broadcast`, etc.). The systemd units
7
+ shipped under `share/systemd/user/` dispatch to the console-script paths.
8
+
9
+ Library-mode usage: `import waitbus.<x>` is import-side-effect-free.
10
+ The `ensure_state_dirs()` helper in `waitbus._paths` is invoked only
11
+ from entry-point `main()` functions, never at import.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import logging
17
+ from typing import Any
18
+
19
+ # Re-export the predicate-engine plugin hooks so Layer-2 extras packages
20
+ # (e.g. waitbus-cel, waitbus-jmespath) can register from a single, stable
21
+ # import path that the rest of the predicate machinery uses. The full module
22
+ # is private (_predicate); only the hook surface is re-exported here.
23
+ # These are cheap to import eagerly.
24
+ from ._predicate import (
25
+ EvaluatorUnavailableError,
26
+ Predicate,
27
+ register_condition,
28
+ register_evaluator,
29
+ )
30
+
31
+ # PEP 282 best practice: library/package root logger gets a NullHandler
32
+ # so consumers who don't configure logging don't see leaked records.
33
+ # Entry-point `main()` functions (listener, broadcast, etc.) call
34
+ # `logging.basicConfig(...)` themselves to install a real handler.
35
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
36
+
37
+ # --- Public Python API: producer (emit) + consumer (subscribe/wait_for) ---
38
+ # `emit` / `register_source` (producer side) and `subscribe` / `wait_for` /
39
+ # `asubscribe` (consumer side) + the frozen wire `EventFrame` form one
40
+ # coherent, symmetric public surface. The subscriber engine and `emit()` form
41
+ # the public API contract. Their implementations live in PRIVATE modules (`_emit`,
42
+ # `_subscribe`) -- matching the `_predicate` / `_broadcast_sub` / `_frame`
43
+ # convention -- and the curated public symbols are re-exported HERE at the
44
+ # package root. The canonical public import is `from waitbus import emit`.
45
+ # Resolution is LAZY (PEP 562 `__getattr__`) so the bare `import waitbus`
46
+ # stays side-effect-free and cheap: it pulls only the light predicate hooks
47
+ # above, NOT msgspec or the broadcast/registry machinery, which load only when
48
+ # a consumer first touches `emit` / `subscribe`. Static type-checkers read the
49
+ # committed `__init__.pyi` stub (which mirrors this map), so the public function
50
+ # names do not collide with any submodule.
51
+ _LAZY_EXPORTS: dict[str, str] = {
52
+ "subscribe": "waitbus._subscribe",
53
+ "wait_for": "waitbus._subscribe",
54
+ "asubscribe": "waitbus._subscribe",
55
+ "EventFrame": "waitbus._subscribe",
56
+ "emit": "waitbus._emit",
57
+ "register_source": "waitbus.sources._registry",
58
+ "request": "waitbus._messaging",
59
+ "respond": "waitbus._messaging",
60
+ }
61
+
62
+
63
+ def __getattr__(name: str) -> Any:
64
+ """PEP 562 lazy attribute resolution for the public API surface."""
65
+ target = _LAZY_EXPORTS.get(name)
66
+ if target is None:
67
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
68
+ import importlib
69
+
70
+ return getattr(importlib.import_module(target), name)
71
+
72
+
73
+ def __dir__() -> list[str]:
74
+ return [*globals(), *_LAZY_EXPORTS]
75
+
76
+
77
+ # Eager: predicate-engine plugin hooks. Lazy (via __getattr__): the producer
78
+ # API (emit, register_source) + consumer SDK (subscribe, wait_for, asubscribe,
79
+ # EventFrame). __all__ is sorted (RUF022); the grouping is documented above.
80
+ __all__ = (
81
+ "EvaluatorUnavailableError",
82
+ "EventFrame",
83
+ "Predicate",
84
+ "asubscribe",
85
+ "emit",
86
+ "register_condition",
87
+ "register_evaluator",
88
+ "register_source",
89
+ "request",
90
+ "respond",
91
+ "subscribe",
92
+ "wait_for",
93
+ )
waitbus/__init__.pyi ADDED
@@ -0,0 +1,38 @@
1
+ # Type stub for the waitbus package root. Single source of truth for the public
2
+ # API that static type-checkers see (mypy consults this stub instead of the
3
+ # runtime ``__init__.py`` ``__getattr__``). It mirrors ``_LAZY_EXPORTS`` + the
4
+ # eager predicate hooks; the drift-guard test ``tests/test_init_pyi_drift.py``
5
+ # pins the two in lockstep. Public functions live in PRIVATE impl modules
6
+ # (``_emit`` / ``_subscribe``) re-exported here, so no public name collides with
7
+ # a submodule. ``as`` aliasing is required for re-export under
8
+ # ``--no-implicit-reexport`` (PEP 484).
9
+ from ._emit import emit as emit
10
+ from ._messaging import request as request
11
+ from ._messaging import respond as respond
12
+ from ._predicate import EvaluatorUnavailableError as EvaluatorUnavailableError
13
+ from ._predicate import Predicate as Predicate
14
+ from ._predicate import register_condition as register_condition
15
+ from ._predicate import register_evaluator as register_evaluator
16
+ from ._subscribe import EventFrame as EventFrame
17
+ from ._subscribe import asubscribe as asubscribe
18
+ from ._subscribe import subscribe as subscribe
19
+ from ._subscribe import wait_for as wait_for
20
+ from .sources._registry import register_source as register_source
21
+
22
+ # Runtime-only internals the test suite / drift-guard reference (not public API).
23
+ _LAZY_EXPORTS: dict[str, str]
24
+
25
+ __all__ = (
26
+ "EvaluatorUnavailableError",
27
+ "EventFrame",
28
+ "Predicate",
29
+ "asubscribe",
30
+ "emit",
31
+ "register_condition",
32
+ "register_evaluator",
33
+ "register_source",
34
+ "request",
35
+ "respond",
36
+ "subscribe",
37
+ "wait_for",
38
+ )