| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| from functools import partial |
| from typing import Any, Callable, TypeVar |
|
|
| import fiddle as fdl |
|
|
| T = TypeVar("T") |
|
|
|
|
| class PredicateDispatch: |
| """A dispatcher that routes values to handlers based on predicates. |
| |
| This class implements a predicate-based dispatch system where handlers are registered |
| with conditions that determine when they should be used. When called, it tries each |
| predicate in order until it finds a match. |
| |
| Example: |
| ```python |
| dispatcher = PredicateDispatch() |
| |
| @dispatcher.register(lambda x: isinstance(x, str)) |
| def handle_strings(s): |
| return f"String: {s}" |
| |
| result = dispatcher("hello") # Returns "String: hello" |
| ``` |
| """ |
|
|
| def __init__(self): |
| """Initialize an empty handler registry.""" |
| self.handlers = [] |
|
|
| def register(self, predicate: Callable[[Any], bool]): |
| """Register a new handler with a predicate. |
| |
| Args: |
| predicate: A callable that takes a value and returns True if the handler |
| should process this value. |
| |
| Returns: |
| A decorator function that registers the handler. |
| """ |
|
|
| def decorator(func: Callable[[T], Any]): |
| self.handlers.append((predicate, func)) |
| return func |
|
|
| return decorator |
|
|
| def __call__(self, value): |
| """Process a value through the registered handlers. |
| |
| Args: |
| value: The value to be processed. |
| |
| Returns: |
| The processed value from the first matching handler, or the original value |
| if no handlers match. |
| """ |
| for predicate, handler in self.handlers: |
| if predicate(value): |
| return handler(value) |
| return value |
|
|
| def register_class(self, cls: type): |
| """Register a handler for instances of a specific class. |
| |
| A convenience method that automatically creates an isinstance predicate. |
| |
| Args: |
| cls: The class to check instances against. |
| |
| Returns: |
| A decorator function that registers the handler. |
| """ |
| return self.register(lambda v: isinstance(v, cls)) |
|
|
|
|
| """Global dispatcher for converting Python objects to Fiddle configurations. |
| |
| This dispatcher is used by Fiddle's serialization system to handle special cases |
| during configuration serialization. When Fiddle encounters an object it doesn't |
| know how to serialize, it will pass it through this dispatcher to convert it |
| into a serializable Fiddle configuration. |
| |
| Example use cases: |
| - Converting functools.partial to fdl.Partial |
| - Converting HuggingFace models to their from_pretrained configurations |
| - Handling custom classes with special serialization needs |
| |
| The dispatcher is extended by registering new handlers with predicates that |
| determine when they should be used. See PredicateDispatch for more details. |
| """ |
| to_config = PredicateDispatch() |
|
|
|
|
| @to_config.register_class(partial) |
| def handle_partial(value: partial): |
| """Convert functools.partial objects to Fiddle Partial configurations. |
| |
| This handler enables serialization of partial function applications by converting |
| them to Fiddle's equivalent representation. |
| |
| Args: |
| value: A functools.partial object. |
| |
| Returns: |
| A Fiddle Partial configuration representing the same partial application. |
| """ |
| return fdl.Partial(value.func, *value.args, **value.keywords) |
|
|