Mv task UID formatting into `devx.pformat`

Add `pformat_task()` beside `pformat_task_uid()` so diagnostics can
inspect an explicit endpoint, sibling or nursery-owning `trio.Task`.
Keep the current-task default and decimal head/tail identity format.

Preserve the `tractor.log` entry point with lazy forwarding, avoiding
eager debugger initialization during logging imports. Move the
existing formatting TODOs with the implementation.

Exercise real parent/child tasks without an actor, including coroutine
identity, nursery ownership and equivalent log/tooling UID output.

Prompt-IO: ai/prompt-io/20261021T145344Z_0553fcf8_task_format_prompt_io.md
Prompt-IO: ai/prompt-io/20261021T151133Z_0553fcf8_uid_move_prompt_io.md

(this patch was generated in some part by `opencode` using
`gpt-6.1-sol` (`openai`))
piker_pin
Gud Boi 2026-10-21 11:29:32 -04:00
parent 0553fcf88c
commit bf2bb1c9a6
7 changed files with 327 additions and 16 deletions

View File

@ -0,0 +1,56 @@
---
created_at: 2026-10-21T14:53:44Z
generated_by:
harness: opencode
provider: openai
model: openai/gpt-6.1-sol
git_ref: 0553fcf8
scope: code
substantive: true
raw_file: 20261021T145344Z_0553fcf8_task_format_prompt_io.raw.md
---
## Prompt
The human requested moving the new regression-local Trio task formatter
into devx.pformat, scanning branches for earlier equivalents first, and
noted that log.pformat_task_uid already extracts the task ID. Follow-up:
the reviewed change was good enough apart from the function move; the
QA agent had already been alerted to the new order-bootstrap race.
## Response summary
Found no earlier detailed task formatter across 810 local refs and 18
worktrees. Extracted pformat_task into tooling and made the existing UID
helper accept an explicit task, preserving its established log output.
Added focused coverage that inspects a real child from its parent and
updated the cancellation regression to use the shared renderer.
## Files changed
- `tractor/devx/pformat.py`: reusable pformat_task.
- `tractor/log.py`: optional explicit task for pformat_task_uid.
- `tests/devx/test_pformat.py`: real task-selection/ownership coverage.
- `tests/test_context_final_return_disconnect.py`: shared-tool callers.
## Review boundary and verification
Pre-move tree: `27e75d8b1cdfec1d96284d993e55ad3c51c3804c`.
HEAD remains `0553fcf88cd37b4d487eafb992071d4d1cc6e06f`.
The real index was unchanged at extraction start. Existing final-send
work and provenance are retained, including the earlier review record
that documents the then-local helper. Original Tuicr replies were not
rewritten; this extraction supersedes their local-helper description.
See the raw partner for environment details and focused verification.
Final verification repeated after import/line-wrap adjustments: 75
formatter/logger tests and 10 final-Return/RPC tests passed; Ruff,
whitespace and added-source 69-column checks passed. A read-only Tuicr
comparison found the saved session now contains only the first original
comment/reply pair, unlike the earlier three-pair receipt. This extraction
did not write session state or recreate the absent comments.
## Human edits
This extraction follows the human's requested final placement. Existing
logging TODOs, pre-review changes and task/review states are preserved.

View File

@ -0,0 +1,49 @@
---
created_at: 2026-10-21T14:53:44Z
generated_by:
harness: opencode
provider: openai
model: openai/gpt-6.1-sol
git_ref: 0553fcf8
diff_cmd: git diff HEAD~1..HEAD
---
## Generated output
> `git diff HEAD~1..HEAD -- tractor/devx/pformat.py tractor/log.py`
Moved the regression-local task renderer into devx.pformat.pformat_task.
It accepts an explicit Trio task or defaults to the current task, and
reports identity, coroutine, parent nursery/owner and child nurseries.
The new renderer reuses log.pformat_task_uid for the short identity,
rather than independently extracting and slicing id(task).
Added a keyword-only optional task argument to that existing UID helper;
its current-task default, positional id_part and decimal head/tail output
remain unchanged. The full Task repr retains the full native identity.
Kept the UID import local to the richer renderer so log headers do not
gain a dependency on devx initialization. Existing UID/color TODOs remain.
> `git diff HEAD~1..HEAD -- tests/test_context_final_return_disconnect.py tests/devx/test_pformat.py`
Removed the local formatter and switched its three consumers to the
shared tooling function. Added an actor-free live parent/child task test
that checks explicit-task selection, default current-task selection,
nursery ownership, coroutine identity, and unchanged head/tail log IDs.
The accepted final-result send guard is untouched by this extraction.
## Existing-work discovery
Read-only scan: 810 local branch/remote-tracking refs, 18 worktree path
inventories and task-formatting definitions, plus relevant all-ref history.
Only log.pformat_task_uid and this session's regression helper were found.
The dirty pformat.py in wkt/tipc_backend_wg_stack contains an unrelated
comment spelling correction; no other worktree was modified.
## Verification
Worktree Python 3.13.13 / pytest 9.1.0 / Trio 0.29.0: formatter and logger
suites, 75 passed. Downstream Python 3.13.14 / pytest 9.0.2 / Trio 0.32.0:
final-Return regression and RPC suite, 10 passed. The older pytest in the
downstream environment remains below the current harness reference's
version bound; neither environment was changed. Ruff passed. A source
line-length check prompted wrapping before final verification.

View File

@ -0,0 +1,41 @@
---
created_at: 2026-10-21T15:11:33Z
generated_by:
harness: opencode
provider: openai
model: openai/gpt-6.1-sol
git_ref: 0553fcf8
scope: code
substantive: true
raw_file: 20261021T151133Z_0553fcf8_uid_move_prompt_io.raw.md
---
## Prompt
The human proposed moving pformat_task_uid into devx.pformat with the
new pformat_task and its unit test in a precursor commit, then placing
the final-result disconnect fix and matching tests in the next commit.
The request authorizes implementation and commit planning, not commits.
## Response summary
Moved the identity implementation into the formatting module, removed
the detailed formatter's reverse logging dependency, and preserved the
existing logging entry point through lazy forwarding. Retained the
existing TODO group and task-state markers. Extended focused identity
tests, verified the relocation and selected two dependency-ordered
whole-file commit boundaries with separate provenance.
## Files changed
- `tractor/devx/pformat.py`: canonical short and detailed task formatters.
- `tractor/log.py`: lazy forwarding entry point for existing log users.
- `tests/devx/test_pformat.py`: canonical/log entry-point equivalence.
## Verification and human edits
75 formatter/logger tests and 10 downstream final-Return/RPC tests passed.
Ruff and whitespace checks passed. Both existing environments are kept;
the downstream pytest-version caveat is disclosed in prior records.
Earlier raw prompt records are retained unchanged as generation history.
No staging, commits, history changes or Tuicr mutations were performed.

View File

@ -0,0 +1,33 @@
---
created_at: 2026-10-21T15:11:33Z
generated_by:
harness: opencode
provider: openai
model: openai/gpt-6.1-sol
git_ref: 0553fcf8
diff_cmd: git diff HEAD~1..HEAD
---
> `git diff HEAD~1..HEAD -- tractor/devx/pformat.py tractor/log.py tests/devx/test_pformat.py`
Moved pformat_task_uid's implementation into devx.pformat alongside
pformat_task. The detailed renderer now calls the UID renderer directly;
it no longer imports logging. Kept the tractor.log entry point as a
lazy forwarding function to avoid eagerly initializing devx/debugger
modules while logging itself is being imported. Preserved the existing
current-task default and decimal head/tail ID output, plus explicit-task
selection added in the preceding extraction. Moved the existing TODO
group verbatim and did not change its checklist markers.
Extended the task test to compare the logging entry point and canonical
tooling renderer for current and selected child tasks in both ID modes.
The existing tests/devx/test_pformat.py module is reused.
Verification: formatter/logger suites 75 passed in 0.16s on the worktree
environment; final-Return/RPC suites 10 passed in 1.76s on the downstream
evaluation environment. Ruff and git diff --check passed. The downstream
pytest version remains 9.0.2; its current harness-version gap is recorded
in the earlier review/extraction provenance. No environment was changed.
Prepared the requested tooling-first, disconnect-fix-second boundary
selection. Planning itself does not execute checks, stage or commit.

View File

@ -5,15 +5,82 @@ Unit tests for the `tractor.devx.pformat` render helpers.
from __future__ import annotations
import pytest
import trio
from tractor._exceptions import _mk_send_mte
from tractor.log import pformat_task_uid as log_task_uid
from tractor.devx.pformat import (
pformat_boxed_tb,
pformat_caller_frame,
pformat_task,
pformat_task_uid,
)
from tractor.msg._codec import _def_tractor_codec
def test_pformat_task_selects_another_tasks_identity() -> None:
'''
Describe the selected task rather than the diagnostic caller.
The final-Return regression needs to snapshot an endpoint and its
nursery owner from another task. Hold a real child in an active
nursery and inspect it from its parent, checking both identities
and public nursery relationships without requiring an actor.
Preserve the log header's decimal head/tail ID convention while
allowing that existing helper to select an explicit task too.
'''
async def main() -> None:
'''
Keep the inspected child alive through all report assertions.
'''
async def child(
task_status: trio.TaskStatus[trio.lowlevel.Task],
) -> None:
'''
Publish the real task before waiting for cancellation.
'''
task_status.started(trio.lowlevel.current_task())
await trio.sleep_forever()
owner: trio.lowlevel.Task = trio.lowlevel.current_task()
owner_id: str = str(id(owner))
assert pformat_task_uid() == f'{owner.name}[{owner_id[-6:]}]'
assert pformat_task_uid('head') == (
f'{owner.name}[{owner_id[:6]}]'
)
assert log_task_uid() == pformat_task_uid()
assert log_task_uid('head') == pformat_task_uid('head')
async with trio.open_nursery() as nursery:
task: trio.lowlevel.Task = await nursery.start(child)
task_id: str = str(id(task))
task_uid: str = f'{task.name}[{task_id[-6:]}]'
report: str = pformat_task(task)
assert pformat_task_uid(task=task) == task_uid
assert pformat_task_uid('head', task=task) == (
f'{task.name}[{task_id[:6]}]'
)
assert log_task_uid(task=task) == task_uid
assert log_task_uid('head', task=task) == (
pformat_task_uid('head', task=task)
)
assert f'uid={task_uid!r}' in report
assert f'task={task!r}' in report
assert f'coro={task.coro!r}' in report
assert f'parent_nursery: {nursery!r}' in report
assert f'parent_task={owner!r}' in report
assert 'child_nurseries: ()' in report
assert f'child_nurseries: ({nursery!r},)' in (
pformat_task(owner)
)
assert pformat_task() == pformat_task(owner)
nursery.cancel_scope.cancel()
trio.run(main)
@pytest.mark.parametrize(
'box_tb',
[True, False],

View File

@ -25,7 +25,14 @@ import sys
import textwrap
import traceback
from trio import CancelScope
from trio import (
CancelScope,
Nursery,
)
from trio.lowlevel import (
Task,
current_task,
)
def add_div(
@ -219,6 +226,70 @@ def pformat_caller_frame(
return tb_str
# TODO IDEAs:
# -[ ] move to `.devx.pformat`?
# -[ ] do per task-name and actor-name color coding
# -[ ] unique color per task-id and actor-uuid
def pformat_task_uid(
id_part: str = 'tail',
*,
task: Task|None = None,
) -> str:
'''
Render a task's name and a decimal head/tail slice of its ID.
Default to the current task, or select an explicit `task` when
rendering another task's identity from diagnostic tooling.
'''
if task is None:
task = current_task()
tid: str = str(id(task))
if id_part == 'tail':
tid_part: str = tid[-6:]
else:
tid_part: str = tid[:6]
return f'{task.name}[{tid_part}]'
def pformat_task(
task: Task|None = None,
) -> str:
'''
Render a Trio task's identity, execution and nursery ownership.
Default to the current task. An explicit `task` lets a caller
inspect a sibling or nursery owner without selecting itself.
Capture the report while that task is alive to retain its active
`Task.parent_nursery` and `Task.child_nurseries` relationships.
'''
if task is None:
task = current_task()
task_uid: str = pformat_task_uid(task=task)
nursery: Nursery|None = task.parent_nursery
parent_task: Task|None = (
nursery.parent_task if nursery is not None else None
)
child_nurseries: tuple[Nursery, ...] = tuple(
task.child_nurseries,
)
return (
f'<Task(\n'
f' |_name: {task.name!r}\n'
f' uid={task_uid!r}\n'
f' task={task!r}\n'
f' coro={task.coro!r}\n'
f' |_parent_nursery: {nursery!r}\n'
f' parent_task={parent_task!r}\n'
f' |_child_nurseries: {child_nurseries!r}\n'
f')>\n'
)
def pformat_cs(
cs: CancelScope,
var_name: str = 'cs',

View File

@ -332,26 +332,20 @@ def add_log_level(
add_log_level('IO', 21, 'purple')
# TODO IDEAs:
# -[ ] move to `.devx.pformat`?
# -[ ] do per task-name and actor-name color coding
# -[ ] unique color per task-id and actor-uuid
def pformat_task_uid(
id_part: str = 'tail'
):
id_part: str = 'tail',
*,
task: trio.lowlevel.Task|None = None,
) -> str:
'''
Return `str`-ified unique for a `trio.Task` via a combo of its
`.name: str` and `id()` truncated output.
Forward the logging entry point to devx.pformat's UID renderer.
'''
task: trio.Task = trio.lowlevel.current_task()
tid: str = str(id(task))
if id_part == 'tail':
tid_part: str = tid[-6:]
else:
tid_part: str = tid[:6]
# Import lazily: devx initialization itself imports tractor.log.
from .devx.pformat import pformat_task_uid as render_task_uid
return f'{task.name}[{tid_part}]'
return render_task_uid(id_part, task=task)
_curr_actor_no_exc = partial(