Source code for axisfuzzy.extension.decorator

#  Copyright (c) yibocat 2025 All Rights Reserved
#  Python: 3.12.7
#  Date: 2025/8/18 18:23
#  Author: yibow
#  Email: yibocat@yeah.net
#  Software: AxisFuzzy

"""
Decorators for registering axisfuzzy extension functions.

Provides the `extension` and `batch_extension` decorators which register
callables into the ExtensionRegistry. Registered callables are later injected
into target classes (e.g. ``Fuzznum``, ``Fuzzarray``) or the top-level axisfuzzy
namespace by the injector at library initialization.

Examples
--------
Simple specialized extension registration:

.. code-block:: python

    from axisfuzzy.extension import extension
    from axisfuzzy.core import Fuzznum

    @extension('distance', mtype='qrofn', target_classes=['Fuzznum'])
    def qrofn_distance(f1: Fuzznum, f2: Fuzznum, p: int = 2) -> float:
        # qrofn-specific implementation
        ...
"""

from typing import Optional, Union, List, Literal

from .registry import get_registry_extension


[docs] def extension(name: str, mtype: Optional[str] = None, target_classes: Union[str, List[str]] = None, injection_type: Literal[ 'instance_method', 'top_level_function', 'instance_property', 'both'] = 'both', is_default: bool = False, priority: int = 0, **kwargs): """ Register an extension function in the ExtensionRegistry. This decorator simplifies the process of adding new functionalities to FuzzLab's ``Fuzznum`` and ``Fuzzarray`` objects, or as top-level functions. It acts as a wrapper around ``ExtensionRegistry.register()``, providing a declarative way to define extension properties. Parameters ---------- name : str Extension name (e.g. ``distance``). mtype : str or None, optional Target fuzzy-number type (e.g. ``qrofn``). If None the registration is considered a general/default implementation. target_classes : str or list of str or None, optional Class name or list of class names to inject into (e.g. ``Fuzznum`` or ``["Fuzznum", "Fuzzarray"]``). If None, library conventions are used. injection_type : {``instance_method``, ``top_level_function``, ``instance_property``, ``both``}, optional Injection mode. Default is ``both``. is_default : bool, optional Whether this registration is a fallback when no mtype-specific implementation exists. Default is ``False``. priority : int, optional Resolution priority when multiple candidates match. Higher values take precedence. Default is 0. **kwargs Additional metadata forwarded to the registry. Returns ------- callable A decorator that accepts the implementation function and registers it. Examples -------- Specialized distance for qrofn: .. code-block:: python from axisfuzzy.extension import extension from axisfuzzy.core import Fuzznum @extension('distance', mtype='qrofn', target_classes=['Fuzznum']) def qrofn_distance(f1: Fuzznum, f2: Fuzznum, p: int = 2) -> float: # qrofn-specific implementation ... Default distance fallback: .. code-block:: python from axisfuzzy.extension import extension from axisfuzzy.core import Fuzznum @extension('distance', is_default=True, target_classes=['Fuzznum']) def default_distance(f1: Fuzznum, f2: Fuzznum) -> float: # generic fallback implementation ... """ registry = get_registry_extension() return registry.register( name=name, mtype=mtype, target_classes=target_classes, injection_type=injection_type, is_default=is_default, priority=priority, **kwargs )
[docs] def batch_extension(registrations: List[dict]): """ Decorator to register a single function with multiple extension configurations. This is useful when a single function needs to serve different roles or be registered under various conditions (e.g., as a specialized implementation for one `mtype` and a default for another, or with different injection types). Parameters ---------- registrations : list of dict Each dict supplies keyword arguments for the `extension` decorator, e.g. ``{'name': 'normalize', 'mtype': 'qrofn', 'target_classes': ['Fuzznum']}``. Returns ------- callable A decorator which registers the decorated function multiple times. Examples -------- Registering a function that serves as a specialized 'normalize' for 'qrofn' and a default 'normalize' for other types: .. code-block:: python # In axisfuzzy/fuzzy/qrofs/_func.py from axisfuzzy.extension import batch_extension from axisfuzzy.core import Fuzznum @batch_extension([ {'name': 'normalize', 'mtype': 'qrofn', 'target_classes': ['Fuzznum']}, {'name': 'normalize', 'is_default': True, 'target_classes': ['Fuzznum']} ]) def qrofn_normalize(fuzz: Fuzznum) -> Fuzznum: # QROFN specific normalization logic # ... return fuzz """ def decorator(func): registry = get_registry_extension() for reg in registrations: registry.register(**reg)(func) return func return decorator