Source code for magicgui.widgets._bases.create_widget

from __future__ import annotations

import inspect
from typing import TYPE_CHECKING, Any

from magicgui.application import use_app
from magicgui.widgets import _bases, _protocols

from .widget import Widget

if TYPE_CHECKING:
    from magicgui.types import WidgetOptions


[docs]def create_widget( value: Any = _bases.value_widget.UNSET, annotation: Any = None, name: str = "", param_kind: str | inspect._ParameterKind = "POSITIONAL_OR_KEYWORD", label=None, gui_only=False, app=None, widget_type: str | type[_protocols.WidgetProtocol] | None = None, options: WidgetOptions = dict(), ): """Create and return appropriate widget subclass. This factory function can be used to create a widget appropriate for the provided ``value`` and/or ``annotation`` provided. Parameters ---------- value : Any, optional The starting value for the widget, by default ``None`` annotation : Any, optional The type annotation for the parameter represented by the widget, by default ``None`` name : str, optional The name of the parameter represented by this widget. by default ``""`` param_kind : str, optional The :attr:`inspect.Parameter.kind` represented by this widget. Used in building signatures from multiple widgets, by default "``POSITIONAL_OR_KEYWORD``" label : str A string to use for an associated Label widget (if this widget is being shown in a :class:`~magicgui.widgets.Container` widget, and labels are on). By default, ``name`` will be used. Note: ``name`` refers the name of the parameter, as might be used in a signature, whereas label is just the label for that widget in the GUI. gui_only : bool, optional Whether the widget should be considered "only for the gui", or if it should be included in any widget container signatures, by default False app : str, optional The backend to use, by default ``None`` widget_type : str or Type[WidgetProtocol] or None A class implementing a widget protocol or a string with the name of a magicgui widget type (e.g. "Label", "PushButton", etc...). If provided, this widget type will be used instead of the type autodetermined from ``value`` and/or ``annotation`` above. options : WidgetOptions, optional Dict of options to pass to the Widget constructor, by default dict() Returns ------- Widget An instantiated widget subclass Raises ------ TypeError If the provided or autodetected ``widget_type`` does not implement any known widget protocols from widgets._protocols. """ options = options.copy() kwargs = locals() _kind = kwargs.pop("param_kind", None) _app = use_app(kwargs.pop("app")) assert _app.native if isinstance(widget_type, _protocols.WidgetProtocol): wdg_class = kwargs.pop("widget_type") else: from magicgui.type_map import get_widget_class if widget_type: options["widget_type"] = widget_type wdg_class, opts = get_widget_class(value, annotation, options) if issubclass(wdg_class, Widget): opts.update(kwargs.pop("options")) kwargs.update(opts) kwargs.pop("widget_type", None) widget = wdg_class(**kwargs) if _kind: widget.param_kind = _kind return widget # pick the appropriate subclass for the given protocol # order matters for p in ("Categorical", "Ranged", "Button", "Value", ""): prot = getattr(_protocols, f"{p}WidgetProtocol") if isinstance(wdg_class, prot): options = kwargs.pop("options", {}) cls = getattr(_bases, f"{p}Widget") widget = cls(**{**kwargs, **options, "widget_type": wdg_class}) if _kind: widget.param_kind = _kind return widget raise TypeError(f"{wdg_class!r} does not implement any known widget protocols")