persist/util: add field helper
This commit is contained in:
@@ -452,3 +452,39 @@ def set_value_by_path(d: DictLike, path: str, content: Any) -> None:
|
||||
for key in keys[:-1]:
|
||||
current = current.setdefault(key, {})
|
||||
current[keys[-1]] = content
|
||||
|
||||
|
||||
from typing import NotRequired, Required, get_args, get_origin, get_type_hints
|
||||
|
||||
|
||||
def is_typeddict_class(obj: type) -> bool:
|
||||
"""Safely checks if a class is a TypedDict."""
|
||||
return (
|
||||
isinstance(obj, type)
|
||||
and hasattr(obj, "__annotations__")
|
||||
and obj.__class__.__name__ == "_TypedDictMeta"
|
||||
)
|
||||
|
||||
|
||||
def retrieve_typed_field_names(obj: type, prefix: str = "") -> set[str]:
|
||||
fields = set()
|
||||
hints = get_type_hints(obj, include_extras=True)
|
||||
|
||||
for field, field_type in hints.items():
|
||||
full_key = f"{prefix}.{field}" if prefix else field
|
||||
|
||||
origin = get_origin(field_type)
|
||||
args = get_args(field_type)
|
||||
|
||||
# Unwrap Required/NotRequired
|
||||
if origin in {NotRequired, Required}:
|
||||
field_type = args[0]
|
||||
origin = get_origin(field_type)
|
||||
args = get_args(field_type)
|
||||
|
||||
if is_typeddict_class(field_type):
|
||||
fields |= retrieve_typed_field_names(field_type, prefix=full_key)
|
||||
else:
|
||||
fields.add(full_key)
|
||||
|
||||
return fields
|
||||
|
||||
Reference in New Issue
Block a user