From 49c37345260e9873c1e387bbc7c15f1ed3bc36b8 Mon Sep 17 00:00:00 2001 From: Kur01234 Date: Tue, 4 Jun 2024 10:11:46 +0200 Subject: [PATCH] feat: added hooks for collection on append --- music_kraken/objects/collection.py | 48 ++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/music_kraken/objects/collection.py b/music_kraken/objects/collection.py index f1d7e75..0296c70 100644 --- a/music_kraken/objects/collection.py +++ b/music_kraken/objects/collection.py @@ -1,16 +1,44 @@ from __future__ import annotations -from collections import defaultdict -from typing import TypeVar, Generic, Dict, Optional, Iterable, List, Iterator, Tuple, Generator, Union, Any, Set import copy +from collections import defaultdict +from dataclasses import dataclass +from typing import (Any, Callable, Dict, Generator, Generic, Iterable, + Iterator, List, Optional, Set, Tuple, TypeVar, Union) -from .parents import OuterProxy -from ..utils import object_trace -from ..utils import output, BColors +from ..utils import BColors, object_trace, output +from .parents import InnerData, OuterProxy T = TypeVar('T', bound=OuterProxy) +@dataclass +class AppendHookArguments: + """ + This class is used to store the arguments for the append hook. + The best explanation is with an examples: + + ``` + # this is the action that triggers the append hook + album = Album() + song = Song() + album.song_collection.append(song) + ``` + + In this case, the append hook is triggered with the following arguments: + ``` + AppendHookArguments( + collection=album.song_collection, + new_object=song, + collection_root_objects=[album] + ) + ``` + """ + + collection: Collection + new_object: T + collection_root_objects: Set[InnerData] + class Collection(Generic[T]): __is_collection__ = True @@ -27,6 +55,7 @@ class Collection(Generic[T]): sync_on_append: Dict[str, Collection] = None, append_object_to_attribute: Dict[str, T] = None, extend_object_to_attribute: Dict[str, Collection] = None, + append_callbacks: List[Callable[[AppendHookArguments], None]] = None, ) -> None: self._collection_for: dict = dict() @@ -41,6 +70,7 @@ class Collection(Generic[T]): self.sync_on_append: Dict[str, Collection] = sync_on_append or {} self.pull_from: List[Collection] = [] self.push_to: List[Collection] = [] + self.append_callbacks: List[Callable[[AppendHookArguments], None]] = append_callbacks or [] # This is to cleanly unmap previously mapped items by their id self._indexed_from_id: Dict[int, Dict[str, Any]] = defaultdict(dict) @@ -141,6 +171,14 @@ class Collection(Generic[T]): for attribute, new_object in self.append_object_to_attribute.items(): other.__getattribute__(attribute).append(new_object, **kwargs) + append_hook_args = AppendHookArguments( + collection=self, + new_object=other, + collection_root_objects=self._collection_for.keys(), + ) + for callback in self.append_callbacks: + callback(append_hook_args) + def append(self, other: Optional[T], **kwargs): """ If an object, that represents the same entity exists in a relevant collection,