### Install abc-delegation Source: https://context7.com/monomonedula/abc-delegation/llms.txt Install the library using pip. ```bash pip install abc-delegation ``` -------------------------------- ### Create Single-Delegate Metaclass with delegation_metaclass Source: https://context7.com/monomonedula/abc-delegation/llms.txt Use delegation_metaclass to create a metaclass for single-delegate classes. This example demonstrates defining an abstract base class, a concrete delegate, and a delegating class that overrides one method and automatically delegates others. ```python from abc import ABCMeta, abstractmethod from abc_delegation import delegation_metaclass # Define an abstract base class with required methods class FileHandler(metaclass=ABCMeta): @abstractmethod def read(self, path): pass @abstractmethod def write(self, path, content): pass @abstractmethod def delete(self, path): pass # Concrete implementation that will be used as delegate class LocalFileSystem: def read(self, path): return f"Reading from {path}" def write(self, path, content): return f"Writing '{content}' to {path}" def delete(self, path): return f"Deleting {path}" # Delegating class with custom delegate attribute name class CachedFileHandler(FileHandler, metaclass=delegation_metaclass("_fs")): def __init__(self, filesystem): self._fs = filesystem self._cache = {} # Override read to add caching behavior def read(self, path): if path not in self._cache: self._cache[path] = self._fs.read(path) return f"[CACHED] {self._cache[path]}" # write and delete are automatically delegated to self._fs # Usage fs = LocalFileSystem() handler = CachedFileHandler(fs) print(handler.read("/data/file.txt")) # Output: [CACHED] Reading from /data/file.txt print(handler.write("/data/file.txt", "Hello")) # Output: Writing 'Hello' to /data/file.txt print(handler.delete("/data/old.txt")) # Output: Deleting /data/old.txt ``` -------------------------------- ### Use UnsafeDelegatingMeta to Disable Validation Source: https://context7.com/monomonedula/abc-delegation/llms.txt Employ UnsafeDelegatingMeta when runtime validation of delegate attributes should be disabled. This can improve performance or be used when delegate method presence is guaranteed. The example defines an abstract DataStore and a partial implementation. ```python from abc import ABCMeta, abstractmethod from abc_delegation import UnsafeDelegatingMeta class DataStore(metaclass=ABCMeta): @abstractmethod def get(self, key): pass @abstractmethod def set(self, key, value): pass class PartialStore: """A store that only implements get - validation would fail""" def get(self, key): return f"Value for {key}" ``` -------------------------------- ### Use Pre-configured DelegatingMeta for Default Delegate Source: https://context7.com/monomonedula/abc-delegation/llms.txt Utilize DelegatingMeta as a shortcut when using '_delegate' as the default delegate attribute name with validation enabled. This example shows a logger class that automatically delegates methods to a provided logger instance. ```python from abc import ABCMeta, abstractmethod from abc_delegation import DelegatingMeta class Logger(metaclass=ABCMeta): @abstractmethod def info(self, message): pass @abstractmethod def error(self, message): pass @abstractmethod def debug(self, message): pass class ConsoleLogger: def info(self, message): return f"INFO: {message}" def error(self, message): return f"ERROR: {message}" def debug(self, message): return f"DEBUG: {message}" # Uses _delegate as the attribute name by default class TimestampedLogger(Logger, metaclass=DelegatingMeta): def __init__(self, logger): self._delegate = logger def info(self, message): return f"[2024-01-15 10:30:00] {self._delegate.info(message)}" # error and debug are automatically delegated logger = TimestampedLogger(ConsoleLogger()) print(logger.info("Application started")) # Output: [2024-01-15 10:30:00] INFO: Application started print(logger.error("Connection failed")) # Output: ERROR: Connection failed print(logger.debug("Variable x = 42")) # Output: DEBUG: Variable x = 42 ``` -------------------------------- ### Basic Delegation with Metaclass Source: https://github.com/monomonedula/abc-delegation/blob/master/README.md Demonstrates how to use `delegation_metaclass` to create a class `C` that delegates methods to an instance of class `B`. The `foo` method is overridden in `C`, while `bar` is delegated. ```python from abc import ABCMeta from abc_delegation import delegation_metaclass class A(metaclass=ABCMeta): @abstractmethod def bar(self): pass @abstractmethod def foo(self): pass class B: def bar(self): return "B bar" def foo(self): return "B foo" class C(A, metaclass=delegation_metaclass("my_delegate")): def __init__(self, b): self.my_delegate = b def foo(self): return "C foo" c = C(B()) assert c.foo() == "C foo" assert c.bar() == "B bar" ``` -------------------------------- ### Unified Player with multi_delegation_metaclass Source: https://context7.com/monomonedula/abc-delegation/llms.txt Compose a `MediaPlayer` from multiple delegates (AudioEngine, VideoEngine, StreamingService) using `multi_delegation_metaclass`. Methods are dispatched to the first delegate that implements them. ```python from abc import ABCMeta, abstractmethod from abc_delegation import multi_delegation_metaclass class MediaPlayer(metaclass=ABCMeta): @abstractmethod def play_audio(self, file): pass @abstractmethod def play_video(self, file): pass @abstractmethod def stream(self, url): pass @abstractmethod def get_metadata(self, file): pass class AudioEngine: def play_audio(self, file): return f"Playing audio: {file}" def get_metadata(self, file): return f"Audio metadata for {file}: duration=3:45" class VideoEngine: def play_video(self, file): return f"Playing video: {file}" def get_metadata(self, file): return f"Video metadata for {file}: 1920x1080" class StreamingService: def stream(self, url): return f"Streaming from {url}" # Compose from three different delegates class UnifiedPlayer( MediaPlayer, metaclass=multi_delegation_metaclass("_audio", "_video", "_streaming") ): def __init__(self, audio, video, streaming): self._audio = audio self._video = video self._streaming = streaming player = UnifiedPlayer(AudioEngine(), VideoEngine(), StreamingService()) print(player.play_audio("song.mp3")) # Output: Playing audio: song.mp3 print(player.play_video("movie.mp4")) # Output: Playing video: movie.mp4 print(player.stream("https://example.com/live")) # Output: Streaming from https://example.com/live # get_metadata is found on the first delegate (AudioEngine) print(player.get_metadata("media.file")) # Output: Audio metadata for media.file: duration=3:45 ``` -------------------------------- ### Lazy Data Store with UnsafeDelegatingMeta Source: https://context7.com/monomonedula/abc-delegation/llms.txt Use `UnsafeDelegatingMeta` to create a data store that allows instantiation even if the delegate object is incomplete. Errors will occur at runtime if a method is called that the delegate does not implement. ```python class LazyDataStore(DataStore, metaclass=UnsafeDelegatingMeta): def __init__(self, store): self._delegate = store # This works with UnsafeDelegatingMeta (would raise TypeError with DelegatingMeta) store = LazyDataStore(PartialStore()) print(store.get("user:123")) # Output: Value for user:123 # Calling set would raise AttributeError at runtime since delegate doesn't have it # store.set("key", "value") # AttributeError: 'PartialStore' object has no attribute 'set' ``` -------------------------------- ### Multiple Delegates with Metaclass Source: https://github.com/monomonedula/abc-delegation/blob/master/README.md Shows how to use `multi_delegation_metaclass` to delegate methods to multiple delegate objects (`_delegate1`, `_delegate2`). Class `C` overrides `foo` and delegates `bar` to `_delegate1` and `baz` to `_delegate2`. ```python from abc import ABCMeta from abc_delegation import multi_delegation_metaclass class A(metaclass=ABCMeta): @abstractmethod def bar(self): pass @abstractmethod def foo(self): pass @abstractmethod def baz(self): pass class B: def bar(self): return "B bar" def foo(self): return "B foo" class X: def baz(self): return "X baz" class C(A, metaclass=multi_delegation_metaclass("_delegate1", "_delegate2")): def __init__(self, d1, d2): self._delegate1 = d1 self._delegate2 = d2 def foo(self): return "C foo" c = C(B(), X()) assert c.bar() == "B bar" assert c.foo() == "C foo" assert c.baz() == "X baz" ``` -------------------------------- ### Multi-delegate Repository with validation Source: https://context7.com/monomonedula/abc-delegation/llms.txt Demonstrates validation with `multi_delegation_metaclass`. The metaclass checks if all required abstract methods are present across the specified delegates. ```python # Validation also works with multi_delegation_metaclass class MultiRepository( Repository, metaclass=multi_delegation_metaclass("_primary", "_fallback", validate=True) ): def __init__(self, primary, fallback): self._primary = primary self._fallback = fallback class FindOnlyStore: def find(self, id): return f"Found {id}" class SaveOnlyStore: def save(self, entity): return f"Saved {entity}" # Fails because delete is missing from both delegates try: multi_repo = MultiRepository(FindOnlyStore(), SaveOnlyStore()) except TypeError as e: print(f"Multi-delegate validation error: {e}") # Output: Multi-delegate validation error: Can't instantiate MultiRepository: missing attribute delete in the delegate attributes ('_primary', '_fallback') ``` -------------------------------- ### Repository with delegation_metaclass and validation Source: https://context7.com/monomonedula/abc-delegation/llms.txt Use `delegation_metaclass` to delegate methods to a store. By default, validation is enabled, ensuring the delegate has all required abstract methods at instantiation time. ```python from abc import ABCMeta, abstractmethod from abc_delegation import delegation_metaclass, multi_delegation_metaclass class Repository(metaclass=ABCMeta): @abstractmethod def find(self, id): pass @abstractmethod def save(self, entity): pass @abstractmethod def delete(self, id): pass class IncompleteStore: """Missing the delete method""" def find(self, id): return f"Found {id}" def save(self, entity): return f"Saved {entity}" class DelegatedRepository(Repository, metaclass=delegation_metaclass("_store")): def __init__(self, store): self._store = store # Validation catches missing methods at instantiation try: repo = DelegatedRepository(IncompleteStore()) except TypeError as e: print(f"Validation error: {e}") # Output: Validation error: Can't instantiate DelegatedRepository: missing attribute delete in the delegate attribute _store ``` -------------------------------- ### Unsafe Repository with validation disabled Source: https://context7.com/monomonedula/abc-delegation/llms.txt Disable validation in `delegation_metaclass` by setting `validate=False`. This allows instantiation with incomplete delegates, deferring errors to runtime. ```python # To disable validation, pass validate=False class UnsafeRepository(Repository, metaclass=delegation_metaclass("_store", validate=False)): def __init__(self, store): self._store = store # This succeeds even with incomplete delegate unsafe_repo = UnsafeRepository(IncompleteStore()) print(unsafe_repo.find("123")) # Output: Found 123 ``` -------------------------------- ### Delegate Validation with Metaclass Source: https://github.com/monomonedula/abc-delegation/blob/master/README.md Illustrates the default validation behavior of `delegation_metaclass`. When a delegate object (`B`) is missing a required method (`bar`) defined in the abstract base class (`A`), instantiation of the delegating class (`C`) raises a `TypeError`. ```python class A(metaclass=ABCMeta): @abstractmethod def bar(self): pass @abstractmethod def foo(self): pass class B: pass # validation is on by default class C(A, metaclass=delegation_metaclass("_delegate")): def __init__(self, b): self._delegate = b def foo(self): return "C foo" C(B()) # Trying to instantiate C class with B delegate which is missing 'bar' method # Validation raises an error: # TypeError: Can't instantiate bar: missing attribute bar in the delegate attribute _delegate ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.