Merge pull request #525 from pikers/msgspec_struct_updates
`msgspec` struct derivative updatesmaster
commit
a12b008a15
|
@ -1,5 +1,7 @@
|
||||||
# piker: trading gear for hackers
|
# piker: trading gear for hackers
|
||||||
# Copyright (C) Guillermo Rodriguez (in stewardship for piker0)
|
# Copyright (C) (in stewardship for pikers)
|
||||||
|
# - Tyler Goodlet
|
||||||
|
# - Guillermo Rodriguez
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
@ -14,18 +16,22 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
Built-in (extension) types.
|
Extensions to built-in or (heavily used but 3rd party) friend-lib
|
||||||
|
types.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
import sys
|
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
|
|
||||||
import msgspec
|
from msgspec import (
|
||||||
|
msgpack,
|
||||||
|
Struct,
|
||||||
|
structs,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Struct(
|
class Struct(
|
||||||
msgspec.Struct,
|
Struct,
|
||||||
|
|
||||||
# https://jcristharif.com/msgspec/structs.html#tagged-unions
|
# https://jcristharif.com/msgspec/structs.html#tagged-unions
|
||||||
# tag='pikerstruct',
|
# tag='pikerstruct',
|
||||||
|
@ -36,22 +42,14 @@ class Struct(
|
||||||
|
|
||||||
'''
|
'''
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
'''
|
||||||
f: getattr(self, f)
|
Like it sounds.. direct delegation to:
|
||||||
for f in self.__struct_fields__
|
https://jcristharif.com/msgspec/api.html#msgspec.structs.asdict
|
||||||
}
|
|
||||||
|
|
||||||
# Lul, doesn't seem to work that well..
|
TODO: probably just drop this method since it's now a built-int method?
|
||||||
# def __repr__(self):
|
|
||||||
# # only turn on pprint when we detect a python REPL
|
|
||||||
# # at runtime B)
|
|
||||||
# if (
|
|
||||||
# hasattr(sys, 'ps1')
|
|
||||||
# # TODO: check if we're in pdb
|
|
||||||
# ):
|
|
||||||
# return self.pformat()
|
|
||||||
|
|
||||||
# return super().__repr__()
|
'''
|
||||||
|
return structs.asdict(self)
|
||||||
|
|
||||||
def pformat(self) -> str:
|
def pformat(self) -> str:
|
||||||
return f'Struct({pformat(self.to_dict())})'
|
return f'Struct({pformat(self.to_dict())})'
|
||||||
|
@ -60,30 +58,47 @@ class Struct(
|
||||||
self,
|
self,
|
||||||
update: dict | None = None,
|
update: dict | None = None,
|
||||||
|
|
||||||
) -> msgspec.Struct:
|
) -> Struct:
|
||||||
'''
|
'''
|
||||||
Validate-typecast all self defined fields, return a copy of us
|
Validate-typecast all self defined fields, return a copy of
|
||||||
with all such fields.
|
us with all such fields.
|
||||||
|
|
||||||
This is kinda like the default behaviour in `pydantic.BaseModel`.
|
NOTE: This is kinda like the default behaviour in
|
||||||
|
`pydantic.BaseModel` except a copy of the object is
|
||||||
|
returned making it compat with `frozen=True`.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
if update:
|
if update:
|
||||||
for k, v in update.items():
|
for k, v in update.items():
|
||||||
setattr(self, k, v)
|
setattr(self, k, v)
|
||||||
|
|
||||||
# roundtrip serialize to validate
|
# NOTE: roundtrip serialize to validate
|
||||||
return msgspec.msgpack.Decoder(
|
# - enode to msgpack binary format,
|
||||||
type=type(self)
|
# - decode that back to a struct.
|
||||||
).decode(
|
return msgpack.Decoder(type=type(self)).decode(
|
||||||
msgspec.msgpack.Encoder().encode(self)
|
msgpack.Encoder().encode(self)
|
||||||
)
|
)
|
||||||
|
|
||||||
# NOTE XXX: this won't work on frozen types!
|
|
||||||
# use ``.copy()`` above in such cases.
|
|
||||||
def typecast(
|
def typecast(
|
||||||
self,
|
self,
|
||||||
# fields: list[str] | None = None,
|
|
||||||
|
# TODO: allow only casting a named subset?
|
||||||
|
# fields: set[str] | None = None,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
for fname, ftype in self.__annotations__.items():
|
'''
|
||||||
setattr(self, fname, ftype(getattr(self, fname)))
|
Cast all fields using their declared type annotations
|
||||||
|
(kinda like what `pydantic` does by default).
|
||||||
|
|
||||||
|
NOTE: this of course won't work on frozen types, use
|
||||||
|
``.copy()`` above in such cases.
|
||||||
|
|
||||||
|
'''
|
||||||
|
# https://jcristharif.com/msgspec/api.html#msgspec.structs.fields
|
||||||
|
fi: structs.FieldInfo
|
||||||
|
for fi in structs.fields(self):
|
||||||
|
setattr(
|
||||||
|
self,
|
||||||
|
fi.name,
|
||||||
|
fi.type(getattr(self, fi.name)),
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue