forked from goodboy/tractor
				
			Mk `.msg.pretty_struct.Struct.pformat()` a mod func
More along the lines of `msgspec.struct` and also far more useful internally for pprinting `MsgTypes`. Of course add method aliases.runtime_to_msgspec
							parent
							
								
									adba454d1d
								
							
						
					
					
						commit
						08fcd3fb03
					
				| 
						 | 
					@ -102,6 +102,59 @@ def iter_fields(struct: Struct) -> Iterator[
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    '''
 | 
				
			||||||
 | 
					    # 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
 | 
				
			||||||
 | 
					    k: str
 | 
				
			||||||
 | 
					    v: Any
 | 
				
			||||||
 | 
					    for fi, k, v in iter_fields(struct):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO: how can we prefer `Literal['option1',  'option2,
 | 
				
			||||||
 | 
					        # ..]` over .__name__ == `Literal` but still get only the
 | 
				
			||||||
 | 
					        # latter for simple types like `str | int | None` etc..?
 | 
				
			||||||
 | 
					        ft: type = fi.type
 | 
				
			||||||
 | 
					        typ_name: str = getattr(ft, '__name__', str(ft))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # recurse to get sub-struct's `.pformat()` output Bo
 | 
				
			||||||
 | 
					        if isinstance(v, Struct):
 | 
				
			||||||
 | 
					            val_str: str =  v.pformat(
 | 
				
			||||||
 | 
					                indent=field_indent + indent,
 | 
				
			||||||
 | 
					                field_indent=indent + field_indent,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:  # the `pprint` recursion-safe format:
 | 
				
			||||||
 | 
					            # https://docs.python.org/3.11/library/pprint.html#pprint.saferepr
 | 
				
			||||||
 | 
					            val_str: str = saferepr(v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO: LOLOL use `textwrap.indent()` instead dawwwwwg!
 | 
				
			||||||
 | 
					        obj_str += (field_ws + f'{k}: {typ_name} = {val_str},\n')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        f'{qtn}(\n'
 | 
				
			||||||
 | 
					        f'{obj_str}'
 | 
				
			||||||
 | 
					        f'{ws})'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Struct(
 | 
					class Struct(
 | 
				
			||||||
    _Struct,
 | 
					    _Struct,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,65 +193,12 @@ class Struct(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return sin_props
 | 
					        return sin_props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # TODO: make thisi a mod-func!
 | 
					    pformat = pformat
 | 
				
			||||||
    def pformat(
 | 
					    # __str__ = __repr__ = pformat
 | 
				
			||||||
        self,
 | 
					 | 
				
			||||||
        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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        '''
 | 
					 | 
				
			||||||
        # global whitespace indent
 | 
					 | 
				
			||||||
        ws: str = ' '*indent
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # field whitespace indent
 | 
					 | 
				
			||||||
        field_ws: str = ' '*(field_indent + indent)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # qtn: str = ws + self.__class__.__qualname__
 | 
					 | 
				
			||||||
        qtn: str = self.__class__.__qualname__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        obj_str: str = ''  # accumulator
 | 
					 | 
				
			||||||
        fi: structs.FieldInfo
 | 
					 | 
				
			||||||
        k: str
 | 
					 | 
				
			||||||
        v: Any
 | 
					 | 
				
			||||||
        for fi, k, v in iter_fields(self):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # TODO: how can we prefer `Literal['option1',  'option2,
 | 
					 | 
				
			||||||
            # ..]` over .__name__ == `Literal` but still get only the
 | 
					 | 
				
			||||||
            # latter for simple types like `str | int | None` etc..?
 | 
					 | 
				
			||||||
            ft: type = fi.type
 | 
					 | 
				
			||||||
            typ_name: str = getattr(ft, '__name__', str(ft))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # recurse to get sub-struct's `.pformat()` output Bo
 | 
					 | 
				
			||||||
            if isinstance(v, Struct):
 | 
					 | 
				
			||||||
                val_str: str =  v.pformat(
 | 
					 | 
				
			||||||
                    indent=field_indent + indent,
 | 
					 | 
				
			||||||
                    field_indent=indent + field_indent,
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            else:  # the `pprint` recursion-safe format:
 | 
					 | 
				
			||||||
                # https://docs.python.org/3.11/library/pprint.html#pprint.saferepr
 | 
					 | 
				
			||||||
                val_str: str = saferepr(v)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # TODO: LOLOL use `textwrap.indent()` instead dawwwwwg!
 | 
					 | 
				
			||||||
            obj_str += (field_ws + f'{k}: {typ_name} = {val_str},\n')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return (
 | 
					 | 
				
			||||||
            f'{qtn}(\n'
 | 
					 | 
				
			||||||
            f'{obj_str}'
 | 
					 | 
				
			||||||
            f'{ws})'
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # TODO: use a pprint.PrettyPrinter instance around ONLY rendering
 | 
					    # TODO: use a pprint.PrettyPrinter instance around ONLY rendering
 | 
				
			||||||
    # inside a known tty?
 | 
					    # inside a known tty?
 | 
				
			||||||
    # def __repr__(self) -> str:
 | 
					    # def __repr__(self) -> str:
 | 
				
			||||||
    #     ...
 | 
					    #     ...
 | 
				
			||||||
 | 
					 | 
				
			||||||
    # __str__ = __repr__ = pformat
 | 
					 | 
				
			||||||
    __repr__ = pformat
 | 
					    __repr__ = pformat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def copy(
 | 
					    def copy(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue