コード例 #1
0
def test_forward_refs_return_annotation():
    """Test that forward refs return annotations get resolved."""

    @magicgui
    def testA() -> int:
        return 1

    @magicgui
    def testB() -> "tests.MyInt":  # type: ignore  # noqa
        return 1

    from tests import MyInt

    results = []
    register_type(MyInt, return_callback=lambda *x: results.append(x))

    testA()
    assert not results

    testB()
    gui, result, return_annotation = results[0]
    assert isinstance(gui, widgets.FunctionGui)
    assert result == 1
    # the forward ref has been resolved
    assert return_annotation is MyInt
コード例 #2
0
def test_register_return_callback():
    """Test that registering a return callback works."""
    def check_value(gui, value, rettype):
        assert value == 1

    class Base:
        pass

    class Sub(Base):
        pass

    register_type(int, return_callback=check_value)
    register_type(Base, return_callback=check_value)

    @magicgui
    def func(a=1) -> int:
        return a

    func()
    with pytest.raises(AssertionError):
        func(3)

    @magicgui
    def func2(a=1) -> Sub:
        return a

    func2()
コード例 #3
0
ファイル: _magicgui.py プロジェクト: lukasz-migas/napari
def register_types_with_magicgui():
    """Register napari types with magicgui.

    Parameter Annotations -> Widgets:
        napari.layers.Layer, will be rendered as a ComboBox.
            if a parameter is annotated as a subclass Layer type, then the
            combobox options will be limited to that layer type.
        napari.Viewer, will be rendered as a ComboBox, with the current viewer
            as the only choice.

    Return Annotations -> Widgets:
        napari.layers.Layer will add a new layer to the Viewer.
            if a return is annotated as a subclass of Layer, then the
            corresponding layer type will be added.  As of 0.4.3, the user
            must return an actual layer instance
            see `add_layer_to_viewer` for detail
        napari.types.<layer_type>Data will add a new layer to the Viewer.
            using a bare data array (e.g. numpy array) as a return value.
        napari.types.LayerDataTuple will add a new layer to the Viewer.
            and expects the user to return a single layer data tuple
        List[napari.types.LayerDataTuple] will add multiple new layer to the
            Viewer. And expects the user to return a list of layer data tuples.

    """
    # only run this function once
    if getattr(register_types_with_magicgui, '_called', False):
        return
    register_types_with_magicgui._called = True

    from magicgui.widgets import FunctionGui

    # the widget field in `_source.py` was defined with a forward reference
    # to avoid having to import magicgui when we define the layer `Source` obj.
    # Now that we know we have imported magicgui, we update that forward ref
    # https://pydantic-docs.helpmanual.io/usage/postponed_annotations/
    Source.update_forward_refs(FunctionGui=FunctionGui)

    register_type(layers.Layer,
                  choices=get_layers,
                  return_callback=add_layer_to_viewer)
    register_type(Viewer, bind=find_viewer_ancestor)
    register_type(
        types.LayerDataTuple,
        return_callback=add_layer_data_tuples_to_viewer,
    )
    register_type(
        List[types.LayerDataTuple],
        return_callback=add_layer_data_tuples_to_viewer,
    )
    for layer_name in layers.NAMES:
        data_type = getattr(types, f'{layer_name.title()}Data')
        register_type(
            data_type,
            choices=get_layers_data,
            return_callback=add_layer_data_to_viewer,
        )
コード例 #4
0
ファイル: types.py プロジェクト: tlambert03/napari
def _register_types_with_magicgui():
    """Register ``napari.types`` objects with magicgui."""
    import sys
    from concurrent.futures import Future

    from magicgui import register_type

    from . import layers
    from .utils import _magicgui as _mgui

    for _type in (LayerDataTuple, List[LayerDataTuple]):
        register_type(
            _type,
            return_callback=_mgui.add_layer_data_tuples_to_viewer,
        )
        if sys.version_info >= (3, 9):
            future_type = Future[_type]  # type: ignore
            register_type(future_type, return_callback=_mgui.add_future_data)

    for layer_name in layers.NAMES:
        data_type = globals().get(f'{layer_name.title()}Data')
        register_type(
            data_type,
            choices=_mgui.get_layers_data,
            return_callback=_mgui.add_layer_data_to_viewer,
        )
        if sys.version_info >= (3, 9):
            register_type(
                Future[data_type],  # type: ignore
                choices=_mgui.get_layers_data,
                return_callback=partial(
                    _mgui.add_future_data, _from_tuple=False
                ),
            )
コード例 #5
0
def register_types_with_magicgui():
    """Register napari types with magicgui.

    Parameter Annotations -> Widgets:
        napari.layers.Layer, will be rendered as a ComboBox.
            if a parameter is annotated as a subclass Layer type, then the
            combobox options will be limited to that layer type.

    Return Annotations -> Widgets:
        napari.layers.Layer will add a new layer to the Viewer.
            if a return is annotated as a subclass of Layer, then the
            corresponding layer type will be added.
            see `show_layer_result` for detail
    """
    register_type(Layer, choices=get_layers, return_callback=show_layer_result)
    register_type(Viewer, choices=get_viewers)
コード例 #6
0
def _register():
    from functools import partial

    import magicgui

    from .. import layers, types
    from ..types import LayerDataTuple
    from ..utils import _magicgui as _mgui

    for _type in (LayerDataTuple, List[LayerDataTuple]):
        magicgui.register_type(FunctionWorker[_type],
                               return_callback=_mgui.add_worker_data)
    for layer_name in layers.NAMES:
        _type = getattr(types, f'{layer_name.title()}Data')
        magicgui.register_type(
            FunctionWorker[_type],
            return_callback=partial(_mgui.add_worker_data, _from_tuple=False),
        )
コード例 #7
0
ファイル: _magicgui.py プロジェクト: wadhikar/napari
def register_types_with_magicgui():
    """Register napari types with magicgui.

    Parameter Annotations -> Widgets:
        napari.layers.Layer, will be rendered as a ComboBox.
            if a parameter is annotated as a subclass Layer type, then the
            combobox options will be limited to that layer type.
        napari.Viewer, will be rendered as a ComboBox, with the current viewer
            as the only choice.

    Return Annotations -> Widgets:
        napari.layers.Layer will add a new layer to the Viewer.
            if a return is annotated as a subclass of Layer, then the
            corresponding layer type will be added.  As of 0.4.3, the user
            must return an actual layer instance
            see `add_layer_to_viewer` for detail
        napari.types.<layer_type>Data will add a new layer to the Viewer.
            using a bare data array (e.g. numpy array) as a return value.
        napari.types.LayerDataTuple will add a new layer to the Viewer.
            and expects the user to return a single layer data tuple
        List[napari.types.LayerDataTuple] will add multiple new layer to the
            Viewer. And expects the user to return a list of layer data tuples.

    """
    register_type(layers.Layer,
                  choices=get_layers,
                  return_callback=add_layer_to_viewer)
    register_type(Viewer, bind=find_viewer_ancestor)
    register_type(
        types.LayerDataTuple,
        return_callback=add_layer_data_tuples_to_viewer,
    )
    register_type(
        List[types.LayerDataTuple],
        return_callback=add_layer_data_tuples_to_viewer,
    )
    for layer_name in layers.NAMES:
        data_type = getattr(types, f'{layer_name.title()}Data')
        register_type(
            data_type,
            choices=get_layers_data,
            return_callback=add_layer_data_to_viewer,
        )
コード例 #8
0
ファイル: test_magicgui.py プロジェクト: ruhmamehek/magicgui
def test_register_types(qtbot):
    """Test that we can register custom widget classes for certain types."""
    # must provide a non-None choices or widget_type
    with pytest.raises(ValueError):
        register_type(str, choices=None)

    register_type(int, widget_type=QtW.QLineEdit)

    # this works, but choices overrides widget_type, and warns the user
    with pytest.warns(UserWarning):
        register_type(str,
                      choices=["works", "cool", "huh"],
                      widget_type=QtW.QLineEdit)

    class Main:
        pass

    class Sub(Main):
        pass

    class Main2:
        pass

    class Sub2(Main2):
        pass

    register_type(Main, choices=[1, 2, 3])
    register_type(Main2, widget_type=QtW.QLineEdit)

    @magicgui
    def func(a: str = "works", b: int = 3, c: Sub = None, d: Sub2 = None):
        return a

    gui = func.Gui()
    assert isinstance(gui.get_widget("a"), QtW.QComboBox)
    assert isinstance(gui.get_widget("b"), QtW.QLineEdit)
    assert isinstance(gui.get_widget("c"), QtW.QComboBox)
    assert isinstance(gui.get_widget("d"), QtW.QLineEdit)

    core.reset_type(str)
    core.reset_type(int)
コード例 #9
0
def test_register_types():
    """Test that we can register custom widget classes for certain types."""
    # must provide a non-None choices or widget_type
    with pytest.raises(ValueError):
        register_type(str, choices=None)

    register_type(int, widget_type="LineEdit")

    # this works, but choices overrides widget_type, and warns the user
    with pytest.warns(UserWarning):
        register_type(str,
                      choices=["works", "cool", "huh"],
                      widget_type="LineEdit")

    class Main:
        pass

    class Sub(Main):
        pass

    class Main2:
        pass

    class Sub2(Main2):
        pass

    register_type(Main, choices=[1, 2, 3])
    register_type(Main2, widget_type="LineEdit")

    @magicgui
    def func(a: str = "works", b: int = 3, c: Sub = None, d: Sub2 = None):
        return a

    assert isinstance(func.a, widgets.ComboBox)
    assert isinstance(func.b, widgets.LineEdit)
    assert isinstance(func.c, widgets.ComboBox)
    assert isinstance(func.d, widgets.LineEdit)

    del type_map._TYPE_DEFS[str]
    del type_map._TYPE_DEFS[int]
コード例 #10
0
def register_type(type_: type, **kwargs) -> type:
    """Decorator to register a type with magicgui."""
    import magicgui

    magicgui.register_type(type_, **kwargs)
    return type_
コード例 #11
0
ファイル: napari_viewer.py プロジェクト: ruhmamehek/magicgui
import skimage.filters

import napari
from magicgui import magicgui, register_type


def get_viewers(gui, *args):
    """Get the viewer that the magicwidget is in."""
    try:
        return (gui.parent().qt_viewer.viewer, )
    except AttributeError:
        return tuple(v for v in globals().values()
                     if isinstance(v, napari.Viewer))


register_type(napari.Viewer, choices=get_viewers)

with napari.gui_qt():
    # create a viewer and add some images
    viewer = napari.Viewer(title="Viewer A")
    viewer.add_image(skimage.data.astronaut(), name="astronaut")

    @magicgui(call_button="call", viewer={"visible": False})
    def takes_viewer(viewer: napari.Viewer):
        """Just print the viewer."""
        print(viewer)

    # instantiate the widget
    gui = takes_viewer.Gui()
    # Add it to the napari viewer
    viewer.window.add_dock_widget(gui)
コード例 #12
0
                            paint_new_label, _save_labels)

#
# additional gui elements
#


def get_viewers(gui, *args):
    try:
        viewer = gui.parent().qt_viewer.viewer
        return (viewer, )
    except AttributeError:
        return tuple(v for v in globals().values() if isinstance(v, Viewer))


register_type(Viewer, choices=get_viewers)


# TODO expose the partial parameter to the gui
@magicgui(call_button='save annotations [shfit + s]',
          viewer={'visible': False})
def save_gui(viewer: Viewer):
    _save_labels(viewer)


@magicgui(call_button='update layers [u]', viewer={"visible": False})
def update_layers_gui(viewer: Viewer):
    update_layers(viewer)


@magicgui(call_button='hide annotated cells [h]', viewer={"visible": False})