-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there an easier way to pre-process incoming values for specific fields? #797
Comments
ok, came up with this in the meantime: E = TypeVar("E", bound=StrEnum)
class AlbumArtist(TaggedBase, dict=True, kw_only=True):
_categories: str = msgspec.field(name="categories")
_effective_roles: str = msgspec.field(name="effectiveRoles")
is_support: bool
name: str
roles: str
artist: Optional[Artist] = None
_SPLIT_PATTERN: ClassVar[re.Pattern[str]] = re.compile(r"\s*,\s*")
@cached_property
def categories(self) -> set[ArtistCategories]:
return self._parse_enum_set(self._categories, ArtistCategories)
@cached_property
def effective_roles(self) -> set[ArtistRoles]:
return self._parse_enum_set(self._effective_roles, ArtistRoles)
@classmethod
def _parse_enum_set(cls, value: str, enum_class: type[E]) -> set[E]:
"""Helper method to parse comma-separated string into set of enum values"""
return {
enum_class(item) for item in cls._SPLIT_PATTERN.split(value) if item
} Now, I have another problem: I use httpx in my project for api requests, and somehow need to pass specific keys and values to the |
@amogus07, yes there are some ways, but I'm sure you won't escape implementing custom logic in any of them. here's a way to achieve your goal different to your solution: from typing import Any
import msgspec
# data object
class CsvSet:
def __init__(self, raw_value: str):
self._values = set(raw_value.split(','))
def __eq__[T: set](self, other: T) -> bool:
return self._values == other
def __str__(self):
return ','.join(self._values)
class MyStruct(msgspec.Struct):
param: CsvSet
# custom hooks
def enc_hook(obj: Any) -> Any:
if isinstance(obj, CsvSet):
return str(obj)
def dec_hook(tp: type, obj: Any) -> Any:
if issubclass(tp, CsvSet):
return CsvSet(obj)
# tests
data = msgspec.convert({"param": "foo,bar"}, MyStruct, dec_hook=dec_hook)
assert data.param == {'foo', 'bar'}
serialized = msgspec.to_builtins(data, enc_hook=enc_hook)
assert serialized['param'] in ('foo,bar', 'bar,foo')
p.s.: adding generics support should not be too hard. at this moment, you can bring |
I should've probably mentioned that Python 3.9 needs to be supported, which doesn't support function type parameter syntax. Also, is it possible to get this to work without using |
Question
I want to convert an incoming comma-separated string to a set of enum members.
This is my current solution:
it's a snippet from https://github.com/prTopi/beets-vocadb/blob/2a2b3cca83449b26717ffff2a7bb085b26381d26/beetsplug/vocadb/requests_handler/models.py
Is there a more efficient way that doesn't involve additional attributes?
The text was updated successfully, but these errors were encountered: