extension.registry

Extension Registry for AxisFuzzy.

This module implements the extension registry that records and resolves “extensions” (external functions) by fuzzy-number type (mtype). It is the book-keeping backbone of the AxisFuzzy extension system and works together with:

  • axisfuzzy.extension.__init__ (activation entrypoint, apply_extensions)

  • axisfuzzy.extension.decorator (declarative registration via @extension, @batch_extension)

  • axisfuzzy.extension.dispatcher (runtime dispatch proxies: instance methods, properties, top-level)

  • axisfuzzy.extension.injector (binds proxies to Fuzznum/Fuzzarray classes and module namespace)

For a high-level overview of the extension architecture (Registration → Dispatch → Injection),

Notes

  • The registry is thread-safe and supports both specialized (mtype-specific) and default implementations for the same function name.

  • Implementations can specify how they should be exposed via injection_type: ‘instance_method’, ‘instance_property’, ‘top_level_function’, or ‘both’.

  • Priority values are used to prevent overwriting an existing implementation with an equal or lower priority.

Examples

Register a specialized instance method for ‘qrofn’:

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

@extension(name='distance', mtype='qrofn', target_classes=['Fuzznum'])
def qrofn_distance(x: Fuzznum, y: Fuzznum, p: int = 2) -> float:
    q = x.q
    return (((abs(x.md**q - y.md**q))**p + (abs(x.nmd**q - y.nmd**q))**p) / 2) ** (1/p)

Register a dispatched read-only property:

@extension(name='score', mtype='qrofn',
           target_classes=['Fuzznum', 'Fuzzarray'],
           injection_type='instance_property')
def qrofn_score(obj):
    return obj.md ** obj.q - obj.nmd ** obj.q

Register a default fallback exposed also as a top-level function:

@extension(name='normalize', is_default=True, target_classes=['Fuzznum'],
           injection_type='both')
def default_normalize(x):
    # generic fallback
    return x
class axisfuzzy.extension.registry.ExtensionRegistry[source]

Bases: object

Thread-safe registry for AxisFuzzy extension functions.

The registry stores multiple implementations per logical extension name: - at most one default (fallback) implementation - zero or more specialized implementations keyed by mtype

It provides: - A decorator factory (register()) to register implementations - Lookup by (name, mtype) with default fallback (get_function()) - Introspection helpers for documentation and injection

Notes

The registry does not perform injection itself. Injection happens later via axisfuzzy.extension.injector, which reads the metadata here and attaches dispatcher proxies created by axisfuzzy.extension.dispatcher.

See also

axisfuzzy.extension.decorator

User-facing decorators that call this registry.

axisfuzzy.extension.injector

Attaches proxies to classes or module.

axisfuzzy.extension.dispatcher

Builds dispatched proxies used at runtime.

get_function(name, mtype)[source]

Retrieve a function implementation for (name, mtype) with fallback.

The lookup algorithm is: 1) Try specialized implementation registered for this mtype. 2) If not found, return the default implementation for name (if any). 3) Otherwise return None.

Parameters:
  • name (str) – Extension name to look up.

  • mtype (str) – Fuzzy-number type for which to retrieve the specialized implementation.

Returns:

The resolved implementation function or None if not found.

Return type:

callable or None

Examples

reg = get_registry_extension()
fn = reg.get_function('distance', 'qrofn')  # specialized
if fn is None:
    raise RuntimeError('No distance registered')
get_metadata(name, mtype=None)[source]

Retrieve metadata for a registered function.

Parameters:
  • name (str) – Extension name to inspect.

  • mtype (str or None, optional) – If provided, returns specialized metadata for that mtype. Otherwise, returns default metadata when available.

Returns:

Stored metadata object or None if not present.

Return type:

FunctionMetadata or None

Examples

reg = get_registry_extension()
meta = reg.get_metadata('distance', 'qrofn')
if meta:
    print(meta.injection_type, meta.target_classes)
get_top_level_function_names()[source]

List function names that should be injected as top-level functions.

This scans both specialized and default registrations and collects any name whose injection_type is ‘top_level_function’ or ‘both’.

Returns:

Sorted unique function names requiring top-level injection.

Return type:

list of str

Examples

reg = get_registry_extension()
for fn_name in reg.get_top_level_function_names():
    print('top-level:', fn_name)
list_functions()[source]

List all registered names with their implementation summaries.

The result is a structured summary that groups specialized and default registrations per logical name. This is primarily intended for documentation, debugging, and injection planning.

Returns:

A dictionary with the following structure:

{
    "distance": {
        "implementations": {
            "qrofn": {
                "priority": 0,
                "target_classes": ["Fuzznum", "Fuzzarray"],
                "injection_type": "both",
            }
        },
        "default": {
            "priority": 0,
            "target_classes": ["Fuzznum"],
            "injection_type": "instance_method",
        },
    },
    "_random": {
        "implementations": {
            "qrofn": {
                "priority": 0,
                "target_classes": ["Fuzznum"],
                "injection_type": "top_level_function",
            }
        },
        "default": None,
    },
}

Return type:

dict

Examples

reg = get_registry_extension()
summary = reg.list_functions()
for name, info in summary.items():
    print(name, '=>', info)
register(name, mtype=None, target_classes=None, injection_type='both', is_default=False, priority=0, **kwargs)[source]

Decorator factory to register an extension function.

This method is used by axisfuzzy.extension.decorator.extension() (or axisfuzzy.extension.decorator.batch_extension()) to declare a function as a dispatched extension. It records the function and its FunctionMetadata in a thread-safe manner.

Parameters:
  • name (str) – Extension name under which the function is registered.

  • mtype (str or None, optional) – Specialized fuzzy-number type. If None, registers as default implementation for name.

  • target_classes (str or list of str, optional) – Injection targets. If None, defaults to [‘Fuzznum’, ‘Fuzzarray’].

  • injection_type (Literal['instance_method', 'instance_property', 'top_level_function', 'both'], optional) – Exposure mode (method/property/top-level/both). Default is ‘both’.

  • is_default (bool, optional) – Register as default implementation. Default is False.

  • priority (int, optional) – Priority for conflict prevention. Existing entries with higher or equal priority block re-registration. Default is 0.

  • **kwargs – Additional metadata stored into FunctionMetadata.

Returns:

A decorator that takes the implementation function and registers it.

Return type:

callable

Raises:

ValueError – If attempting to re-register a default or specialized implementation when an existing one with higher or equal priority is already present.

Examples

Specialized method:

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

@extension(name='distance', mtype='qrofn', target_classes=['Fuzznum'])
def qrofn_distance(x: Fuzznum, y: Fuzznum) -> float:
    q = x.q
    return ((abs(x.md**q - y.md**q)**2 + abs(x.nmd**q - y.nmd**q)**2)/2) ** 0.5

Default top-level + instance:

@extension(name='normalize', is_default=True,
           target_classes=['Fuzznum'], injection_type='both')
def normalize_default(x): return x

Dispatched read-only property:

@extension(name='score', mtype='qrofn',
           target_classes=['Fuzznum','Fuzzarray'],
           injection_type='instance_property')
def qrofn_score(obj): return obj.md**obj.q - obj.nmd**obj.q
class axisfuzzy.extension.registry.FunctionMetadata(name, mtype, target_classes, injection_type, is_default=False, priority=0, description='')[source]

Bases: object

Metadata describing a registered extension function.

name

Logical extension name (e.g., ‘distance’, ‘score’, ‘_random’).

Type:

str

mtype

Target fuzzy-number type for the specialized implementation (e.g., ‘qrofn’). None indicates a default (fallback) implementation.

Type:

str or None

target_classes

Class names to inject into when exposed as instance members, typically a subset of [‘Fuzznum’, ‘Fuzzarray’].

Type:

list of str

injection_type

Exposure mode: - ‘instance_method’: dispatched bound method on target classes - ‘instance_property’: dispatched read-only property on target classes - ‘top_level_function’: function injected into the top-level module namespace - ‘both’: both instance method and top-level function

Type:

{‘instance_method’, ’instance_property’, ’top_level_function’, ’both’}

is_default

Whether this is a default (fallback) implementation for name. Defaults to False.

Type:

bool, optional

priority

Registration priority. Higher values take precedence when preventing re-registration with lower or equal priority. Defaults to 0.

Type:

int, optional

description

Short human-readable description for documentation. Defaults to “”.

Type:

str, optional

Notes

This metadata is consumed by the injector and dispatcher to determine how and where an extension should be exposed after registration.

description: str = ''
injection_type: Literal['instance_method', 'instance_property', 'top_level_function', 'both']
is_default: bool = False
mtype: Optional[str]
name: str
priority: int = 0
target_classes: List[str]
axisfuzzy.extension.registry.get_registry_extension()[source]

Get the global singleton ExtensionRegistry.

Implements double-checked locking to initialize the singleton in a thread-safe manner on first use.

Returns:

The global registry instance.

Return type:

ExtensionRegistry

Examples

reg = get_registry_extension()
# Use reg.register(...) via decorators in axisfuzzy.extension.decorator
# or call reg.get_function(...) during dispatch.