File: test_factory.py

package info (click to toggle)
magicgui 0.9.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 21,796 kB
  • sloc: python: 11,202; makefile: 11; sh: 9
file content (147 lines) | stat: -rw-r--r-- 3,838 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import pytest
from psygnal import EmitLoopError

from magicgui import magic_factory
from magicgui.type_map._magicgui import MagicFactory
from magicgui.widgets import ComboBox, FunctionGui, Slider


def test_magic_factory():
    """Test basic magic_factory behavior."""

    @magic_factory(call_button=True)
    def factory(x: int = 1):
        return x

    assert isinstance(factory, MagicFactory)

    # factories make widgets that are FunctionGui instances
    widget1 = factory()
    assert isinstance(widget1, FunctionGui)
    assert widget1.call_button

    # You can call them repeatedly, and even override the initial kwargs
    # given to magic_factory (just like with functools.partial)
    widget2 = factory(call_button=False, x={"widget_type": "Slider"})
    assert widget1 is not widget2
    assert isinstance(widget2, FunctionGui)
    assert not widget2.call_button
    assert isinstance(widget2.x, Slider)

    # the widget, (like all FunctionGuis) is still callable and accepts args
    assert widget1() == 1
    assert widget1(3) == 3


def test_magic_factory_reuse():
    """Test magic_factory can be reused."""

    @magic_factory(x={"choices": ["a", "b"]})
    def factory(x="a"):
        return x

    # there was an earlier bug that overrode widget parameters.  this tests for that
    widget_a = factory()
    assert isinstance(widget_a.x, ComboBox)

    widget_b = factory()
    assert isinstance(widget_b.x, ComboBox)


def test_magic_factory_repr():
    """Test basic magic_factory behavior."""

    @magic_factory(labels=False)
    def factory(x: int = 1):
        return x

    rep = repr(factory)
    assert rep.startswith("MagicFactory(function=<function test_magic_factory_repr")
    assert rep.endswith("labels=False)")

    @magic_factory(labels=False, x={"widget_type": "Slider"})
    def factory2(x: int = 1):
        return x

    assert repr(factory2).endswith(
        "labels=False, param_options={'x': {'widget_type': 'Slider'}})"
    )


def test_magic_factory_only_takes_kwargs():
    @magic_factory(labels=False)
    def factory(x: int = 1):
        return x

    with pytest.raises(ValueError) as e:
        factory("positional")
        assert "only accept keyword arguments" in str(e)


@magic_factory
def self_referencing_factory(x: int = 1):
    """Function that refers to itself, and wants the FunctionGui instance."""
    return self_referencing_factory


def test_magic_factory_self_reference():
    """Test that self-referential factories work in global scopes."""
    widget = self_referencing_factory()
    assert isinstance(widget(), FunctionGui)


def test_magic_local_factory_self_reference():
    """Test that self-referential factories work in local scopes."""

    @magic_factory
    def local_self_referencing_factory(x: int = 1):
        return local_self_referencing_factory

    widget = local_self_referencing_factory()
    assert isinstance(widget(), FunctionGui)


def test_factory_init():
    def bomb():
        raise RuntimeError("boom")

    def widget_init(widget):
        widget.called.connect(bomb)

    @magic_factory(widget_init=widget_init)
    def factory(x: int = 1):
        pass

    widget = factory()

    with pytest.raises(EmitLoopError):
        widget()


def test_bad_value_factory_init():
    def widget_init():
        pass

    with pytest.raises(TypeError):

        @magic_factory(widget_init=widget_init)  # type: ignore
        def factory(x: int = 1):
            pass


def test_bad_type_factory_init():
    with pytest.raises(TypeError):

        @magic_factory(widget_init=1)  # type: ignore
        def factory(x: int = 1):
            pass


def test_none_defaults():
    """Make sure that an unannotated parameter with default=None is ok."""

    @magic_factory
    def factory(arg=None):
        return 1

    assert factory()() == 1