Source code for python_introspect.enableable

"""Nominal enable semantics as type-safe metadata.

This module provides a single, shared "axis" for objects and callables that
participate in enabled semantics.

Design goals:
- Nominal (not structural): only explicitly branded callables qualify.
- Dataclass-friendly: configs can inherit Enableable to get an enabled field.
- Callable-safe: branded callables must declare an `enabled` parameter.
"""

from __future__ import annotations

import inspect
from abc import ABC, ABCMeta
from dataclasses import dataclass
from typing import Any


ENABLED_FIELD = 'enabled'

_ENABLEABLE_TAG = object()


class EnableableMeta(ABCMeta):
    """Metaclass enabling nominal isinstance checks for branded callables."""

    def __instancecheck__(cls, instance: Any) -> bool:  # type: ignore[override]
        if getattr(instance, '__enableable_tag__', None) is _ENABLEABLE_TAG:
            return True
        return super().__instancecheck__(instance)


[docs] @dataclass(frozen=True) class Enableable(ABC, metaclass=EnableableMeta): """Mixin indicating an object participates in enabled semantics.""" enabled: bool = True
[docs] def is_enableable(obj: Any) -> bool: """Return True iff obj is nominally Enableable. Works for both instances (using isinstance) and classes (using issubclass). This is needed because widget creation code needs to check if a type (class) is enableable, not just instances. """ # Check if obj is a type/class if isinstance(obj, type): # obj is a class - check if it's a subclass of Enableable try: return issubclass(obj, Enableable) except TypeError: # obj is not a class or is not class-like (e.g., a generic type) return False else: # obj is an instance - use isinstance return isinstance(obj, Enableable)
[docs] def mark_enableable(obj: Any, *, enabled_default: bool = True) -> Any: """Nominally brand an object/callable as Enableable. This does not wrap and does not change call semantics. """ _ = enabled_default # reserved for future: default enabled semantics # If we're branding a callable, require the enabled kwarg to exist. if callable(obj) and not isinstance(obj, type): sig = inspect.signature(obj) if ENABLED_FIELD not in sig.parameters: raise TypeError( f"Enableable callable '{getattr(obj, '__name__', obj)}' must have an '{ENABLED_FIELD}' parameter" ) setattr(obj, '__enableable_tag__', _ENABLEABLE_TAG) return obj