Commit Graph

1266 Commits (29db08b37076d453e1e7b04926129b37796b9d78)

Author SHA1 Message Date
Tyler Goodlet 29db08b370 Use `nest_from_op()`/`pretty_struct` in `._rpc`
Again for nicer console logging. Also fix a double `req_chan` arg bug
when passed to `_invoke` in the `self.cancel()` rt-ep; don't update the
`kwargs: dict` just merge in `req_chan` input at call time.
2025-07-07 11:02:47 -04:00
Tyler Goodlet fe5e6e2ab0 Use `nest_from_op()` in actor-nursery shutdown
Including a new one-line `_shutdown_msg: str` which we mod-var-set for
testing usage and some denoising at `.info()` level. Adjust `Actor()`
instantiating input to the new `.registry_addrs` wrapped addrs property.
2025-07-07 10:59:00 -04:00
Tyler Goodlet ae91310b32 Use `Address` where possible in (root) actor boot
Namely inside various bootup-sequences in `._root` and `._runtime`
particularly in the root actor to support both better tpt-address
denoting in our logging and as part of clarifying logic around setting
the root's registry addresses which is soon to be much better factored
out of the core and into an explicit subsystem + API.

Some `_root.open_root_actor()` deats,
- set `registry_addrs` to a new `uw_reg_addrs` (uw: unwrapped) to be
  more explicit about wrapped addr types thoughout.
- instead ensure `registry_addrs` are the wrapped types and pass down
  into the root `Actor` singleton-instance.
- factor the root-actor check + rt-vars update (updating the `'_root_addrs'`)
  out of `._runtime.async_main()` into this fn.
- as previous, set `trans_bind_addrs = uw_reg_addrs` in unwrapped form since it will
  be passed down both through rt-vars as `'_root_addrs'` and to
  `._runtim.async_main()` as `accept_addrs` (which is then passed to the
  IPC server).
- adjust/simplify much logging.
- shield the `await actor.cancel(None)  # self cancel` to avoid any
  finally-footguns.
- as mentioned convert the

For `_runtime.async_main()` tweaks,
- expect `registry_addrs: list[Address]|None = None` with appropriate
  unwrapping prior to setting both `.reg_addrs` and the equiv rt-var.
- add a new `.registry_addrs` prop for the wrapped form.
- convert a final loose-eg for the `service_nursery` to use
  `collapse_eg()`.
- simplify teardown report logging.
2025-07-07 10:55:57 -04:00
Tyler Goodlet f86f4ae48d Facepalm, fix `raise from` in `collapse_eg()`
I dunno what exactly I was thinking but we definitely don't want to
**ever** raise from the original exc-group, instead always raise from
any original `.__cause__` to be consistent with the embedded src-error's
context.

Also, adjust `maybe_collapse_eg()` to return `False` in the non-single
`.exceptions` case, again don't know what I was trying to do but this
simplifies caller logic and the prior return-semantic had no real
value..

This fixes some final usage in the runtime (namely top level nursery
usage in `._root`/`._runtime`) which was previously causing test suite
failures prior to this fix.
2025-07-07 10:06:59 -04:00
Tyler Goodlet b244cf844d Add #TODO for `._context` to use `.msg.Aid` 2025-07-04 15:01:29 -04:00
Tyler Goodlet c0058024c2 Add todo for py3.13+ `.shared_memory`'s new `track=False` support.. finally they added it XD 2025-07-04 00:08:52 -04:00
Tyler Goodlet 065104401c Even more `.ipc.*` repr refinements
Mostly adjusting indentation, noise level, and clarity via `.pformat()`
tweaks more general use of `.devx.pformat.nest_from_op()`.

Specific impl deats,
- use `pformat.ppfmt()/`nest_from_op()` more seriously throughout
  `._server`.
- add a `._server.Endpoint.pformat()`.
- add `._server.Server.len_peers()` and `.repr_state()`.
- polish `Server.pformat()`.
- drop some redundant `log.runtime()`s from `._serve_ipc_eps()` instead
  leaving-them-only/putting-them in the caller pub meth.
- `._tcp.start_listener()` log the bound addr, not the input (which may
  be the 0-port.
2025-07-03 23:33:02 -04:00
Tyler Goodlet 3201437f4e More `.ipc.Channel`-repr related tweaks
- only generate a repr in `.from_addr()` when log level is >= 'runtime'.
 |_ add a todo about supporting this optimization more generally on our
   adapter.
- fix `Channel.pformat()` to show unknown peer field line fmt correctly.
- add a `Channel.maddr: str` which just delegates directly to the
  `._transport` like other pass-thru property fields.
2025-06-29 15:47:42 -04:00
Tyler Goodlet a9da16892d Mk `Aid` hashable, use pretty-`.__repr__()`
Hash on the `.uuid: str` and delegate verbatim to
`msg.pretty_struct.Struct`'s equiv method.
2025-06-29 15:39:09 -04:00
Tyler Goodlet 1b609113c3 .trionics: link in `finally`-footgun `trio` GH ish 2025-06-29 15:34:10 -04:00
Tyler Goodlet 4a80cda841 .log: expose `at_least_level()` as `StackLevelAdapter` meth 2025-06-29 15:33:31 -04:00
Tyler Goodlet 131e2ee0a4 Drop `actor_info: str` from `._entry` logs 2025-06-29 14:59:50 -04:00
Tyler Goodlet 79ef973058 Try `nest_from_op()` in some `._rpc` spots
To start trying out,
- using in the `Start`-msg handler-block to repr the msg coming
  *from* a `repr(Channel)` using '<=)` sclang op.
- for a completed RPC task in `_invoke_non_context()`.
- for the msg loop task's termination report.
2025-06-29 14:47:03 -04:00
Tyler Goodlet c738492879 Hide more `Channel._transport` privates for repr
Such as the `MsgTransport.stream` and `.drain` attrs since they're
rarely that important at the chan level. Also start adopting
a `.<attr>=` style for actual attrs of the type versus a `<name>:
` style for meta-field info lines.
2025-06-29 13:41:10 -04:00
Tyler Goodlet a931274da6 Moar `nest_from_op()` tweaks..
- better `nest_indent` logic where we either get a non-zero value and
  apply it strictly to both the `nest_prefix` and `text`, OR we
  auto-calc it from any `nest_prefix`, NOT a conflation of both..
- add a `rm_from_first_ln: str` which allows removing chars from the
  first line of `text` after a `str.strip()` (handy for removing
  the '<Channel' first chevron from type-reprs).
2025-06-29 13:37:32 -04:00
Tyler Goodlet 49c61e40c7 Refine `Actor` status iface, use `Aid` throughout
To simplify `.pformat()` output when the new `privates: bool` is unset
(the default) this adds new public attrs to wrap an actor's
cancellation status as well as provide a `.repr_state: str` (similar to
our equiv on `Context`). Rework `.pformat()` to render a much simplified
repr using all these new refinements.

Further, port the `.cancel()` method to use `.msg.types.Aid` for all
internal `requesting_uid` refs (now renamed with `_aid`) and in all
called downstream methods.

New cancel-state iface deats,
- rename `._cancel_called_by_remote` -> `._cancel_called_by` and expect
  it to be set as an `Aid`.
- add `.cancel_complete: bool` which flags whether `.cancel()` ran to
  completion.
- add `.cancel_called: bool` which just wraps `._cancel_called` (and
  which likely will just be dropped since we already have
  `._cancel_called_by`).
- add `.cancel_caller: Aid|None` which wraps `._cancel_called_by`.

In terms of using `Aid` in cancel methods,
- rename vars with `_aid` suffix in `.cancel()` (and wherever else).
- change `.cancel_rpc_tasks()` input param to `req_aid: msgtypes.Aid`.
- do the same for `._cancel_task()` and (for now until we adjust its
  internals as well) use the `Aid.uid` remap property when assigning
  `Context._canceller`.
- adjust all log msg refs to match obvi.
2025-06-23 19:36:11 -04:00
Tyler Goodlet 25f3cf795d Add flag to toggle private vars in `Channel.pformat()`
Call it `privates: bool` and only show certain internal instance vars
when set in the `repr()` output.
2025-06-23 12:08:05 -04:00
Tyler Goodlet e2b7924898 Refactor `pretty_struct.pformat()` rendering
Adding an underlying `iter_struct_ppfmt_lines()` (which can also be
called directly) to iter-render field-lines-pairs; it's now called from
the top level `.pformat()`. The use case is to allow more granular
control for rendering runtime primitive (like `Actor.pformat()`) reprs
depending on log-level/config, oh and using `textwrap` for indenting.
2025-06-22 22:09:37 -04:00
Tyler Goodlet c559f80f08 Extend `.msg.types.Aid` method interface
Providing the legacy `.uid -> tuple` style id (since still used for the
`Actor._contexts` table) and a `repr-one-line` method `.reprol() -> str`
for rendering a compact unique actor ID summary (useful in
logging/.pformat()s at the least).
2025-06-22 21:55:37 -04:00
Tyler Goodlet 6a6f55cee0 Mv in `modden.repr` content, refine `nest_from_op()`
Since I'd like to use some `reprlib` formatting which `modden` already
implemented (and it's a main dependee project), figured I'd just bring
it all into `.devx.pformat` for now.

Also some more tweaks to `nest_from_op()` namely for correctness and
some additional paarams,
- an explicit `op_suffix: str = '\n'` (instead of always assuming
  `f'{input_op}\n'`).
- add `prefix_op: bool` so that, when unset, the `input_op` is instead
  used as a suffix to the first line of `text`.
- default `next_indent = None` such that when set (and not null) we use
  that exact ws-indent instead of calculating it from the
  `len(nest_prefix)` allowing for specifying a `0`-indent easily.
2025-06-22 20:57:51 -04:00
Tyler Goodlet bff32b0ad7 Drop 'IPC' prefix from `._server` types
We already have the `.ipc` sub-pkg name so it seems a bit
redundant/noisy for a namespace path Bp

Leave an alias for the `Server` rn since it's already used in a few
other internal mods.. will likely rename later if everyone is cool with
it..
2025-06-17 23:33:58 -04:00
Tyler Goodlet b71afdc615 Bah! just refine `devx.pformat.nest_from_op()`now!
Since we're gonna prolly start using it for serious..
- drop `back_from_op`.
- rename `tree_str` -> `text`
- move the huge comment-doc for "sclang" into the fn body.
- change all usage to reflect.
2025-06-17 18:11:33 -04:00
Tyler Goodlet 2bd8bf16d7 Re-impl `.devx.nest_from_op()` yet again XD
Apparently having lots of trouble getting the nested indenting
correct.. shh

This hopefully resolves it by doing the indent calcs incrementally
in the order of,
- `input_op: str` the "sclang" operator chars,
- `nest_prefix: str` the hierarchy chars, by def our
  little sub-tree L: '|_',
- finally the `tree_str` so there's no-overlap-/adjacency-to the
  `nest_prefix`.

Also deprecate (kinda) the `back_from_op` param, `nest_indent` is
more or less the replacement.
2025-06-17 17:02:21 -04:00
Tyler Goodlet 13dbd1d420 Enforce named-args only to `.open_nursery()` 2025-06-17 12:31:36 -04:00
Tyler Goodlet b2c415c4f6 Hide `._rpc._errors_relayed_via_ipc()` frame by def 2025-06-17 12:30:59 -04:00
Tyler Goodlet 93f70c63a4 Use `enable_transports: list[str]` parameter
Actually applying the input it in the root as well as all sub-actors by
passing it down to sub-actors through runtime-vars as delivered by the
initial `SpawnSpec` msg during child runtime init.

Impl deats,
- add a new `_state._runtime_vars['_enable_tpts']: list[str]` field set
  by the input param (if provided) to `.open_root_actor()`.
- mk `current_ipc_protos()` return the runtime-var entry with instead
  the default in the `_runtime_vars: dict` set to `[_def_tpt_proto]`.
- in `.open_root_actor()`, still error on this being a >1 `list[str]`
  until we have more testing infra/suites to audit multi-protos per
  actor.
- return the new value (as 3rd element) from `Actor._from_parent()` as
  per the todo note; means `_runtime.async_main()` will allocate
  `accept_addrs` as tpt-specific `Address` entries and pass them to
  `IPCServer.listen_on()`.

Also,
- also add a new `_state._runtime_vars['_root_addrs']: list = []` field
  with the intent of fully replacing the `'_root_mailbox'` field since,
  * it will need to be a collection to support multi-tpt,
  * it's a more cohesive field name alongside `_registry_addrs`,
  * the root actor of every tree needs to have a dedicated addr set
    (separate from any host-singleton registry actor) so that all its
    subs can contact it for capabilities mgmt including debugger
    access/locking.
- in the root, populate the field in `._runtime.async_main()` and for
  now just set '_root_mailbox' to the first entry in that list in
  anticipation of future multi-homing/transport support.
2025-06-17 11:33:36 -04:00
Tyler Goodlet 8c90521562 Just import `._runtime` ns in `._root`; be a bit more explicit 2025-06-16 15:37:21 -04:00
Tyler Goodlet f23ee3cd22 Use collapse in `._root.open_root_actor()` too
Seems to add one more cancellation suite failure as well as now cause
the discovery test to error instead of fail?
2025-06-16 15:34:06 -04:00
Tyler Goodlet 9295af929c Use collapser around root tn in `.async_main()`
Seems to cause the following test suites to fail however..

- 'test_advanced_faults.py::test_ipc_channel_break_during_stream'
- 'test_advanced_faults.py::test_ipc_channel_break_during_stream'
- 'test_clustering.py::test_empty_mngrs_input_raises'

Also tweak some ctxc request logging content.
2025-06-16 14:27:07 -04:00
Tyler Goodlet 9b3af1fa16 Switch to strict-eg nurseries almost everywhere
That is just throughout the core library, not the tests yet. Again, we
simply change over to using our (nearly equivalent?)
`.trionics.collapse_eg()` in place of the already deprecated
`strict_exception_groups=False` flag in the following internals,
- the conc-fan-out tn use in `._discovery.find_actor()`.
- `._portal.open_portal()`'s internal tn used to spawn a bg rpc-msg-loop
  task.
- the daemon and "run-in-actor" layered tn pair allocated in
  `._supervise._open_and_supervise_one_cancels_all_nursery()`.

The remaining loose-eg usage in `._root` and `._runtime` seem to be
necessary to keep the test suite green?? For the moment these are left
out.
2025-06-16 13:23:54 -04:00
Tyler Goodlet f8e4d12494 Use collapser in rent side of `Context` 2025-06-16 11:22:50 -04:00
Tyler Goodlet af3c14b250 Flip to `collapse_eg()` use in `.trionics.gather_contexts()` 2025-06-15 23:29:13 -04:00
Tyler Goodlet 7de7fd0afd Use `Channel.aid: Aid` throughout `.ipc._server` 2025-06-15 22:05:51 -04:00
Tyler Goodlet 79888a31a4 Report `enable_stack_on_sig` on `stackscope` import failure 2025-06-15 22:05:17 -04:00
Tyler Goodlet 4bc443ccae Always `Cancelled`-unmask ctx endpoint excs
To resolve the recently added and failing
`test_remote_exc_relay::test_unmasked_remote_exc`: never allow
`trio.Cancelled` to mask an underlying user-code exception, ever.

Our first real-world (runtime internal) use case for the new
`.trionics.maybe_raise_from_masking_exc()` such that the failing
test now passes with an properly relayed remote RTE unmasking B)

Details,
- flip the `Context._scope_nursery` to the default strict-eg behaviour
  and instead stack its outer scope with a `.trionics.collapse_eg()`.
- wrap the inner-most scope (after `msgops.maybe_limit_plds()`) with
  a `maybe_raise_from_masking_exc()` to ensure user-code errors are
  never masked by `trio.Cancelled`s.

Some err-reporting refinement,
- always capture any `scope_err` from the entire block for debug
  purposes; report it in the `finally` block's log.
- always capture any suppressed `maybe_re`, output from
  `ctx.maybe_raise()`, and `log.cancel()` report it.
2025-06-15 21:40:28 -04:00
Tyler Goodlet 86346c27e8 Extend `._taskc.maybe_raise_from_masking_exc()`
To handle captured non-egs (when the now optional `tn` isn't provided)
as well as yield up a `BoxedMaybeException` which contains any detected
and un-masked `exc_ctx` as its `.value`.

Also add some additional tooling,
- a `raise_unmasked: bool` toggle for when the caller just wants to
  report the masked exc and not raise-it-in-place of the masker.
- `extra_note: str` which by default is tuned to the default
  `unmask_from = (trio.Cancelled,)` but which can be used to deliver
  custom exception msg content.
- `always_warn_on: tuple[BaseException]` which will always emit
  a warning log of what would have been the raised-in-place-of
  `ctx_exc`'s msg for special cases where you want to report
  a masking case that might not be otherwise noticed by the runtime
  (cough like a `Cancelled` masking another `Cancelled) but which
  you'd still like to warn the caller about.
- factor out the masked-`ext_ctx` predicate logic into
  a `find_masked_excs()` and also use it for non-eg cases.

Still maybe todo?
- rewrapping multiple masked sub-excs in an eg back into an eg? left in
  #TODOs and a pause-point where applicable.
2025-06-15 18:28:20 -04:00
Tyler Goodlet 0687f1aaa6 Mv `maybe_raise_from_masking_exc()` to `.trionics`
Factor the `@acm`-closure it out of the
`test_trioisms::test_acm_embedded_nursery_propagates_enter_err` suite
for real use internally.
2025-06-15 13:29:34 -04:00
Tyler Goodlet 6c46882545 Add some tooling params to `collapse_eg()` 2025-06-13 22:06:55 -04:00
Tyler Goodlet 00583b7671 Use `nest_from_op()` in some runtime logs for actor-state-repring 2025-06-12 23:26:38 -04:00
Tyler Goodlet 78beeebe8f Augment `nest_from_op()` with a `nest_prefix: str`
Such that the caller can pass chars they'd like to prefix the first line
of the (indented) `tree_str`, commonly we use '|_' for "obj fields".
2025-06-12 23:22:46 -04:00
Tyler Goodlet 333fde39ad Detail the docs on `Context._maybe_raise_remote_err()` 2025-06-12 23:22:16 -04:00
Tyler Goodlet 502c7a1dc6 Move `.is_multi_cancelled()` to `.trioniics._beg`
Since it's for beg filtering, the current impl should be renamed anyway;
it's not just for filtering cancelled excs.

Deats,
- added a real doc string, links to official eg docs and fixed the
  return typing.
- adjust all internal imports to match.
2025-06-12 23:16:29 -04:00
Tyler Goodlet 7b05547fcc Reapply `.devx.debug` mod-name change to ipc-server lost during rebase.. 2025-06-11 22:09:04 -04:00
Tyler Goodlet 4185661c2e Drop "
" from tail of `BoxedMaybeException.pformat()`
2025-06-11 21:42:02 -04:00
Tyler Goodlet cc7bee683f Drop `.to_asyncio`s usage-of-`greenback`-reporting to `log.devx()` 2025-06-11 21:42:02 -04:00
Tyler Goodlet 2ed811fa0d Disable `greenback` sync fn breakpointing by def
Opting for performance over broad multi-actor "debug-ability" from
sync-function-contexts when `debug_mode=True` is set;
IOW prefer no behind-the-scenes `greenlet` perf impact over being
able to use an actor-safe `breakpoint()` wherever as per,
https://greenback.readthedocs.io/en/latest/principle.html#performance

Adjust the breakpoint restore ex script to match.
2025-06-11 21:42:02 -04:00
Tyler Goodlet 084d750604 Re-impl as `DebugStatus.maybe_enter_repl_fixture()`
Dropping the `_maybe_open_repl_fixture()` approach and instead using
a `DebugStatus._fixture_stack = ExitStack()` which provides for much
simpler support around both sync and async pausing APIs thanks to only
invoking `repl_fixture.__exit__()` on actual `PdbREPL` interaction being
complete!

Deats,
- all `repl_fixture` detection logic still happens in one place (the new
  method) but we aren't limited to closing it via an immediate post REPL
  `.__exit__()` call which instead is triggered by,
- `DebugStatus.release()` which now calls `._fixture_stack.close()` and
  thus only invokes `repl_fixture.__exit__()` when user REPL-ing is
  **actually complete** an arbitrary amount of debugging time later.
- include the notes for `@acm` support above the new method, though not
  sure if they're as relevant any more?

Benefits,
- we can drop the previously added indent levels from
  `_enter_repl_sync()` and `_post_mortem()`.
- now we automatically have support for the `.pause_from_sync()` API
  since `_enter_repl_sync()` doesn't close the prior
  `_maybe_open_repl_fixture()` immediately when `debug_func=None`; the
  user's `__exit__()` is only ever called once `.release()` is.

Other,
- add big 'CASE' comments around the various blocks in
  `.pause_from_sync()`, i was having trouble figuring out which i was
  using from a `breakpoint()` in a dependent app..
2025-06-11 21:42:02 -04:00
Tyler Goodlet de7ba6b1f4 Always pass `repl: PdbREPL` as first param to fixture 2025-06-11 21:42:02 -04:00
Tyler Goodlet 145c44ce44 Add `typing_extensions`, it's a sub-dep of `stackscope`?
Oddly my env was borked bc this (apparently missed by `uv`?) sub-dep
wasn't installed and then `stackscope` was silently failing import and
caused the shield-pause test to also fail (since it couldn't match the
expected `log.devx()` on console). The import failure is not very
explanatory due to the `log.warning()`; change it to `.error()` level.

Also, explicitly import `_sync_pause_from_builtin` in
`examples/debugging/restore_builtin_breakpoint.py` to ensure the ref is
exported properly from `.devx.debug` (which it wasn't during dev of the
prior commit Bp).
2025-06-11 21:42:02 -04:00
Tyler Goodlet 16dbf8fbca Reorg `.devx.debug` into sub-mods!
Which cleans out the pkg-mod to just the expected exports with (its
longstanding todo comment list) and thus a separation-of-concerns
and smaller mod-file sizes via the following new sub-mods:
- `._trace` for the `.pause()`/`breakpoint()`/`pdb.set_trace()`-style
  APIs including all sync-caller variants.
- `._post_mortem` to contain our async `.post_mortem()` and all other
  public crash handling APIs for use from sync callers.
- `._sync` for the high-level syncing helper-routines used throughout the
  runtime to avoid multi-proc TTY use collisions.

And also,
- remove `hide_runtime_frames()` since moved to `.devx._frame_stack`.
2025-06-11 21:42:02 -04:00