extension.dispatcher

Extension Dispatcher for AxisFuzzy.

This module defines the machinery for building dynamic “proxy” callables that resolve and invoke the correct extension implementation at runtime based on the mtype of involved fuzzy objects.

It works in concert with:

  • axisfuzzy.extension.registry: Stores registered implementations and metadata.

  • axisfuzzy.extension.injector: Attaches dispatcher-built proxies to classes or the top-level namespace.

Design

The dispatcher is stateless and thread-safe. It builds three kinds of proxies:

  • Instance method proxies (callable as obj.fn(...)).

  • Instance property proxies (accessed as obj.prop).

  • Top-level function proxies (callable as axisfuzzy.fn(obj, ...)).

Each proxy performs a registry lookup by (name, mtype), falling back to a default implementation when a specialized one is not available.

Notes

  • Top-level proxy resolves mtype from one of: 1) explicit keyword argument mtype=..., 2) the first positional argument if it is a Fuzznum/Fuzzarray instance, 3) the library default (from config) otherwise.

  • Instance proxies read the mtype from the bound object.

  • Error messages include available specialized mtypes and whether a default implementation exists, aiding debugging.

Examples

Create and use a dispatched instance method:

from axisfuzzy.extension.dispatcher import get_extension_dispatcher
dispatcher = get_extension_dispatcher()
dist_method = dispatcher.create_instance_method('distance')

# Typically attached by the injector:
# Fuzznum.distance = dist_method
# x.distance(y) -> dispatches to ('distance', x.mtype)

Create and use a top-level function:

from axisfuzzy.extension.dispatcher import get_extension_dispatcher
dispatcher = get_extension_dispatcher()
dist_func = dispatcher.create_top_level_function('distance')

# Typically attached to `axisfuzzy` module:
# axisfuzzy.distance(x, y) -> dispatches using x.mtype, unless mtype='...' is passed.

Create and use a dispatched property:

score_prop = dispatcher.create_instance_property('score')
# Typically attached by injector:
# Fuzznum.score = score_prop
# x.score -> dispatches to ('score', x.mtype)
class axisfuzzy.extension.dispatcher.ExtensionDispatcher[source]

Bases: object

Factory for creating dispatching proxies for AxisFuzzy extensions.

The dispatcher generates closures and property descriptors that will resolve the correct extension implementation (specialized by mtype) at call time.

Notes

The dispatcher itself does not store function implementations; it exclusively queries the global ExtensionRegistry via get_registry_extension().

create_instance_method(func_name)[source]

Create an instance method proxy for an extension.

The returned function is intended to be bound as an instance method on Fuzznum/Fuzzarray. When invoked, it reads obj.mtype and resolves the implementation using the global extension registry.

Parameters:

func_name (str) – Logical extension name (e.g., ‘distance’, ‘score’).

Returns:

A callable suitable for binding as an instance method.

Return type:

Callable

Raises:
  • AttributeError – If the bound object has no mtype attribute.

  • NotImplementedError – If the registry does not have a specialized or default implementation.

Examples

from axisfuzzy.extension import get_extension_dispatcher
dispatcher = get_extension_dispatcher()
Fuzznum.distance = dispatcher.create_instance_method('distance')

d = x.distance(y)
create_instance_property(func_name)[source]

Create an instance property proxy for an extension.

The returned property, when accessed, reads obj.mtype and resolves a getter implementation from the global registry.

Parameters:

func_name (str) – Logical extension name for a read-only property (e.g., ‘score’).

Returns:

A read-only property whose getter dispatches to the registered implementation.

Return type:

property

Raises:
  • AttributeError – If the bound object has no mtype attribute.

  • NotImplementedError – If the registry does not have a specialized or default implementation.

Examples

from axisfuzzy.extension import get_extension_dispatcher
dispatcher = get_extension_dispatcher()
Fuzznum.score = dispatcher.create_instance_property('score')

s = x.score
create_top_level_function(func_name)[source]

Create a top-level function proxy for an extension.

The returned function expects a Fuzznum/Fuzzarray instance as the first positional argument (or an explicit mtype=... in kwargs). It then resolves and invokes the implementation.

Parameters:

func_name (str) – Logical extension name (e.g., ‘distance’, ‘read_csv’).

Returns:

A callable suitable for injection into the top-level module namespace.

Return type:

Callable

Raises:
  • ValueError – If an explicit mtype is invalid (not registered).

  • NotImplementedError – If the registry does not have a specialized or default implementation.

Notes

mtype resolution order: 1) kwargs['mtype'] if present (and removed before the final call), 2) args[0].mtype if the first argument is a Fuzznum/Fuzzarray, 3) config.DEFAULT_MTYPE otherwise.

Examples

from axisfuzzy.extension import get_extension_dispatcher
dispatcher = get_extension_dispatcher()
distance = dispatcher.create_top_level_function('distance')

# axisfuzzy.distance(x, y) -> dispatches using x.mtype
# axisfuzzy.distance(x, y, mtype='qrofn') -> forces 'qrofn'
axisfuzzy.extension.dispatcher.get_extension_dispatcher()[source]

Get the global singleton ExtensionDispatcher.

Returns:

The global dispatcher instance.

Return type:

ExtensionDispatcher

Examples

from axisfuzzy.extension.dispatcher import get_extension_dispatcher
dispatcher = get_extension_dispatcher()