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.
enable_tpts
Tyler Goodlet 2025-06-22 22:09:37 -04:00
parent c559f80f08
commit e2b7924898
1 changed files with 45 additions and 26 deletions

View File

@ -20,6 +20,7 @@ Prettified version of `msgspec.Struct` for easier console grokin.
''' '''
from __future__ import annotations from __future__ import annotations
from collections import UserList from collections import UserList
import textwrap
from typing import ( from typing import (
Any, Any,
Iterator, Iterator,
@ -105,27 +106,11 @@ def iter_fields(struct: Struct) -> Iterator[
) )
def pformat( def iter_struct_ppfmt_lines(
struct: Struct, struct: Struct,
field_indent: int = 2, field_indent: int = 0,
indent: int = 0, ) -> Iterator[tuple[str, str]]:
) -> str:
'''
Recursion-safe `pprint.pformat()` style formatting of
a `msgspec.Struct` for sane reading by a human using a REPL.
'''
# global whitespace indent
ws: str = ' '*indent
# field whitespace indent
field_ws: str = ' '*(field_indent + indent)
# qtn: str = ws + struct.__class__.__qualname__
qtn: str = struct.__class__.__qualname__
obj_str: str = '' # accumulator
fi: structs.FieldInfo fi: structs.FieldInfo
k: str k: str
v: Any v: Any
@ -135,15 +120,18 @@ def pformat(
# ..]` over .__name__ == `Literal` but still get only the # ..]` over .__name__ == `Literal` but still get only the
# latter for simple types like `str | int | None` etc..? # latter for simple types like `str | int | None` etc..?
ft: type = fi.type ft: type = fi.type
typ_name: str = getattr(ft, '__name__', str(ft)) typ_name: str = getattr(
ft,
'__name__',
str(ft)
).replace(' ', '')
# recurse to get sub-struct's `.pformat()` output Bo # recurse to get sub-struct's `.pformat()` output Bo
if isinstance(v, Struct): if isinstance(v, Struct):
val_str: str = v.pformat( yield from iter_struct_ppfmt_lines(
indent=field_indent + indent, struct=v,
field_indent=indent + field_indent, field_indent=field_indent+field_indent,
) )
else: else:
val_str: str = repr(v) val_str: str = repr(v)
@ -161,8 +149,39 @@ def pformat(
# raise # raise
# return _Struct.__repr__(struct) # return _Struct.__repr__(struct)
# TODO: LOLOL use `textwrap.indent()` instead dawwwwwg! yield (
obj_str += (field_ws + f'{k}: {typ_name} = {val_str},\n') ' '*field_indent, # indented ws prefix
f'{k}: {typ_name} = {val_str},', # field's repr line content
)
def pformat(
struct: Struct,
field_indent: int = 2,
indent: int = 0,
) -> str:
'''
Recursion-safe `pprint.pformat()` style formatting of
a `msgspec.Struct` for sane reading by a human using a REPL.
'''
obj_str: str = '' # accumulator
for prefix, field_repr, in iter_struct_ppfmt_lines(
struct,
field_indent=field_indent,
):
obj_str += f'{prefix}{field_repr}\n'
# global whitespace indent
ws: str = ' '*indent
if indent:
obj_str: str = textwrap.indent(
text=obj_str,
prefix=ws,
)
# qtn: str = ws + struct.__class__.__qualname__
qtn: str = struct.__class__.__qualname__
return ( return (
f'{qtn}(\n' f'{qtn}(\n'