11# piker: trading gear for hackers
2- # Copyright (C) Guillermo Rodriguez (in stewardship for piker0)
2+ # Copyright (C) (in stewardship for pikers)
3+ # - Tyler Goodlet
4+ # - Guillermo Rodriguez
35
46# This program is free software: you can redistribute it and/or modify
57# it under the terms of the GNU Affero General Public License as published by
1416# You should have received a copy of the GNU Affero General Public License
1517# along with this program. If not, see <https://www.gnu.org/licenses/>.
1618
17- """
18- Built-in (extension) types.
19+ '''
20+ Extensions to built-in or (heavily used but 3rd party) friend-lib
21+ types.
1922
20- """
21- import sys
23+ '''
2224from pprint import pformat
2325
24- import msgspec
26+ from msgspec import (
27+ msgpack ,
28+ Struct ,
29+ structs ,
30+ )
2531
2632
2733class Struct (
28- msgspec . Struct ,
34+ Struct ,
2935
3036 # https://jcristharif.com/msgspec/structs.html#tagged-unions
3137 # tag='pikerstruct',
@@ -36,22 +42,14 @@ class Struct(
3642
3743 '''
3844 def to_dict (self ) -> dict :
39- return {
40- f : getattr (self , f )
41- for f in self .__struct_fields__
42- }
43-
44- # Lul, doesn't seem to work that well..
45- # def __repr__(self):
46- # # only turn on pprint when we detect a python REPL
47- # # at runtime B)
48- # if (
49- # hasattr(sys, 'ps1')
50- # # TODO: check if we're in pdb
51- # ):
52- # return self.pformat()
53-
54- # return super().__repr__()
45+ '''
46+ Like it sounds.. direct delegation to:
47+ https://jcristharif.com/msgspec/api.html#msgspec.structs.asdict
48+
49+ TODO: probably just drop this method since it's now a built-int method?
50+
51+ '''
52+ return structs .asdict (self )
5553
5654 def pformat (self ) -> str :
5755 return f'Struct({ pformat (self .to_dict ())} )'
@@ -60,30 +58,47 @@ def copy(
6058 self ,
6159 update : dict | None = None ,
6260
63- ) -> msgspec . Struct :
61+ ) -> Struct :
6462 '''
65- Validate-typecast all self defined fields, return a copy of us
66- with all such fields.
63+ Validate-typecast all self defined fields, return a copy of
64+ us with all such fields.
6765
68- This is kinda like the default behaviour in `pydantic.BaseModel`.
66+ NOTE: This is kinda like the default behaviour in
67+ `pydantic.BaseModel` except a copy of the object is
68+ returned making it compat with `frozen=True`.
6969
7070 '''
7171 if update :
7272 for k , v in update .items ():
7373 setattr (self , k , v )
7474
75- # roundtrip serialize to validate
76- return msgspec . msgpack . Decoder (
77- type = type ( self )
78- ).decode (
79- msgspec . msgpack .Encoder ().encode (self )
75+ # NOTE: roundtrip serialize to validate
76+ # - enode to msgpack binary format,
77+ # - decode that back to a struct.
78+ return msgpack . Decoder ( type = type ( self ) ).decode (
79+ msgpack .Encoder ().encode (self )
8080 )
8181
82- # NOTE XXX: this won't work on frozen types!
83- # use ``.copy()`` above in such cases.
8482 def typecast (
8583 self ,
86- # fields: list[str] | None = None,
84+
85+ # TODO: allow only casting a named subset?
86+ # fields: set[str] | None = None,
87+
8788 ) -> None :
88- for fname , ftype in self .__annotations__ .items ():
89- setattr (self , fname , ftype (getattr (self , fname )))
89+ '''
90+ Cast all fields using their declared type annotations
91+ (kinda like what `pydantic` does by default).
92+
93+ NOTE: this of course won't work on frozen types, use
94+ ``.copy()`` above in such cases.
95+
96+ '''
97+ # https://jcristharif.com/msgspec/api.html#msgspec.structs.fields
98+ fi : structs .FieldInfo
99+ for fi in structs .fields (self ):
100+ setattr (
101+ self ,
102+ fi .name ,
103+ fi .type (getattr (self , fi .name )),
104+ )
0 commit comments