From 12172cc5cd8be52bfdb330457aa58c173664a4c6 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Fri, 9 Jun 2023 14:40:30 -0400 Subject: [PATCH 1/4] Make `.data.types.Struct.typecast()` work via type lookup from `builtins` --- piker/data/types.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/piker/data/types.py b/piker/data/types.py index 7a3bc6bb..620182fc 100644 --- a/piker/data/types.py +++ b/piker/data/types.py @@ -18,7 +18,8 @@ Built-in (extension) types. """ -import sys +import builtins +# import sys from pprint import pformat import msgspec @@ -85,5 +86,11 @@ class Struct( self, # fields: list[str] | None = None, ) -> None: - for fname, ftype in self.__annotations__.items(): - setattr(self, fname, ftype(getattr(self, fname))) + for fname, ftype_str in self.__annotations__.items(): + ftype = getattr(builtins, ftype_str) + attr = getattr(self, fname) + setattr( + self, + fname, + ftype(attr), + ) From 994564f923da93d4ad765248b0954226af3c3dc0 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 20 Jun 2023 13:25:01 -0400 Subject: [PATCH 2/4] Just warn-print when annots are str values? --- piker/data/types.py | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/piker/data/types.py b/piker/data/types.py index 620182fc..2155788b 100644 --- a/piker/data/types.py +++ b/piker/data/types.py @@ -42,18 +42,6 @@ class Struct( for f in self.__struct_fields__ } - # Lul, doesn't seem to work that well.. - # 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__() - def pformat(self) -> str: return f'Struct({pformat(self.to_dict())})' @@ -63,31 +51,46 @@ class Struct( ) -> msgspec.Struct: ''' - Validate-typecast all self defined fields, return a copy of us - with all such fields. + Validate-typecast all self defined fields, return a copy of + 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: for k, v in update.items(): setattr(self, k, v) - # roundtrip serialize to validate + # NOTE: roundtrip serialize to validate + # - enode to msgpack binary format, + # - decode that back to a struct. return msgspec.msgpack.Decoder( type=type(self) ).decode( msgspec.msgpack.Encoder().encode(self) ) - # NOTE XXX: this won't work on frozen types! - # use ``.copy()`` above in such cases. def typecast( self, # fields: list[str] | None = None, + ) -> None: - for fname, ftype_str in self.__annotations__.items(): - ftype = getattr(builtins, ftype_str) + ''' + 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. + + ''' + annots: dict = self.__annotations__ + for fname, ftype in annots.items(): + if isinstance(ftype, str): + print(f'{self} has `str` annotations!?\n{annots}\n') + ftype = getattr(builtins, ftype) + attr = getattr(self, fname) setattr( self, From 00a51c02882d96854d44bbf810074fcee3715acb Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 20 Jun 2023 13:51:37 -0400 Subject: [PATCH 3/4] Use new `msgspec.structs` api for `.typecast()` --- piker/data/types.py | 46 ++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/piker/data/types.py b/piker/data/types.py index 2155788b..4587f77e 100644 --- a/piker/data/types.py +++ b/piker/data/types.py @@ -22,11 +22,15 @@ import builtins # import sys from pprint import pformat -import msgspec +from msgspec import ( + msgpack, + Struct, + structs, +) class Struct( - msgspec.Struct, + Struct, # https://jcristharif.com/msgspec/structs.html#tagged-unions # tag='pikerstruct', @@ -37,10 +41,14 @@ class Struct( ''' def to_dict(self) -> dict: - return { - f: getattr(self, f) - for f in self.__struct_fields__ - } + ''' + Like it sounds.. direct delegation to: + https://jcristharif.com/msgspec/api.html#msgspec.structs.asdict + + TODO: probably just drop this method since it's now a built-int method? + + ''' + return structs.asdict(self) def pformat(self) -> str: return f'Struct({pformat(self.to_dict())})' @@ -49,7 +57,7 @@ class Struct( self, update: dict | None = None, - ) -> msgspec.Struct: + ) -> Struct: ''' Validate-typecast all self defined fields, return a copy of us with all such fields. @@ -66,15 +74,15 @@ class Struct( # NOTE: roundtrip serialize to validate # - enode to msgpack binary format, # - decode that back to a struct. - return msgspec.msgpack.Decoder( - type=type(self) - ).decode( - msgspec.msgpack.Encoder().encode(self) + return msgpack.Decoder(type=type(self)).decode( + msgpack.Encoder().encode(self) ) def typecast( self, - # fields: list[str] | None = None, + + # TODO: allow only casting a named subset? + # fields: set[str] | None = None, ) -> None: ''' @@ -85,15 +93,11 @@ class Struct( ``.copy()`` above in such cases. ''' - annots: dict = self.__annotations__ - for fname, ftype in annots.items(): - if isinstance(ftype, str): - print(f'{self} has `str` annotations!?\n{annots}\n') - ftype = getattr(builtins, ftype) - - attr = getattr(self, fname) + # https://jcristharif.com/msgspec/api.html#msgspec.structs.fields + fi: structs.FieldInfo + for fi in structs.fields(self): setattr( self, - fname, - ftype(attr), + fi.name, + fi.type(getattr(self, fi.name)), ) From ae8358a5e73a56db4fdc22d3f3296fb282e00d51 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 27 Jun 2023 13:32:18 -0400 Subject: [PATCH 4/4] Tidy up unused imports and doc string --- piker/data/types.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/piker/data/types.py b/piker/data/types.py index 4587f77e..596195cc 100644 --- a/piker/data/types.py +++ b/piker/data/types.py @@ -1,5 +1,7 @@ # 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 # it under the terms of the GNU Affero General Public License as published by @@ -14,12 +16,11 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -""" -Built-in (extension) types. +''' +Extensions to built-in or (heavily used but 3rd party) friend-lib +types. -""" -import builtins -# import sys +''' from pprint import pformat from msgspec import (