From 6ca21a633c802d364f0a769435f7a37e2fac041c Mon Sep 17 00:00:00 2001 From: rus07tam Date: Sun, 23 Nov 2025 10:14:12 +0000 Subject: [PATCH] feat: add get_attrs, get_or_set_attr --- src/snakia/utils/__init__.py | 3 +++ src/snakia/utils/attr.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/snakia/utils/attr.py diff --git a/src/snakia/utils/__init__.py b/src/snakia/utils/__init__.py index db30b42..6b52dbc 100644 --- a/src/snakia/utils/__init__.py +++ b/src/snakia/utils/__init__.py @@ -1,3 +1,4 @@ +from .attr import get_attrs, get_or_set_attr from .frame import frame from .inherit import inherit from .nolock import nolock @@ -6,6 +7,8 @@ from .throw import throw from .to_async import to_async __all__ = [ + "get_or_set_attr", + "get_attrs", "frame", "inherit", "nolock", diff --git a/src/snakia/utils/attr.py b/src/snakia/utils/attr.py new file mode 100644 index 0000000..643181c --- /dev/null +++ b/src/snakia/utils/attr.py @@ -0,0 +1,28 @@ +from typing import Any, TypeVar + +T = TypeVar("T") + + +def get_or_set_attr(obj: Any, name: str, default: T) -> T: + if not hasattr(obj, name): + setattr(obj, name, default) + attr = getattr(obj, name) + if not isinstance(attr, type(default)): + setattr(obj, name, default) + return default + return attr + + +def get_attrs( + obj: Any, *, use_dir: bool = False, of_class: bool = False +) -> dict[str, Any]: + if of_class and not isinstance(obj, type): + obj = obj.__class__ + if not use_dir: + if hasattr(obj, "__dict__"): + return obj.__dict__ # type: ignore + if hasattr(obj, "__slots__"): + return {k: getattr(obj, k) for k in obj.__slots__} + raise NotImplementedError("Unknown layout") + else: + return {k: getattr(obj, k) for k in dir(obj)}