Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Mappings to be given as the options in a selection widget again. #3557

Merged
merged 5 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions python/ipywidgets/ipywidgets/widgets/tests/test_interaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,17 +187,33 @@ def test_dict():
dict(a=5),
dict(a=5, b='b', c=dict),
]:
with pytest.raises(TypeError):
c = interactive(f, d=d)

c = interactive(f, d=d)
w = c.children[0]
check = dict(
cls=widgets.Dropdown,
description='d',
value=next(iter(d.values())),
options=d,
_options_labels=tuple(d.keys()),
_options_values=tuple(d.values()),
)
check_widget(w, **check)

def test_ordereddict():
from collections import OrderedDict
items = [(3, 300), (1, 100), (2, 200)]
first = items[0][1]
values = OrderedDict(items)
with pytest.raises(TypeError):
c = interactive(f, lis=values)
c = interactive(f, lis=values)
assert len(c.children) == 2
d = dict(
cls=widgets.Dropdown,
value=first,
options=values,
_options_labels=("3", "1", "2"),
_options_values=(300, 100, 200),
)
check_widgets(c, lis=d)
jasongrout marked this conversation as resolved.
Show resolved Hide resolved

def test_iterable():
def yield_values():
Expand Down Expand Up @@ -566,15 +582,14 @@ def test_multiple_selection():
check_widget(w, value=(1, 2))

# dict style
with pytest.raises(TypeError):
w = smw(options={1: 1})
w.options = {1: 1}
check_widget(w, options={1:1})

# updating
w.options = (1,)
with pytest.raises(TraitError):
w.value = (2,)
check_widget(w, options=(1,))

check_widget(w, options=(1,) )

def test_interact_noinspect():
a = 'hello'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ class TestDropdown(TestCase):
def test_construction(self):
Dropdown()

def test_raise_mapping_options(self):
with pytest.raises(TypeError):
Dropdown(options={'One': 1, 'Two': 2, 'Three': 3})
def test_dict_mapping_options(self):
d = Dropdown(options={'One': 1, 'Two': 2, 'Three': 3})
assert d.get_state('_options_labels') == {'_options_labels': ('One', 'Two', 'Three')}

def test_setting_options_from_list(self):
d = Dropdown()
Expand All @@ -37,8 +37,10 @@ def test_setting_options_from_list_tuples(self):
def test_setting_options_from_dict(self):
d = Dropdown()
assert d.options == ()
with pytest.raises(TypeError):
d.options = {'One': 1}
d.options = {'One': 1, 'Two': 2, 'Three': 3}
assert d.get_state('_options_labels') == {'_options_labels': ('One', 'Two', 'Three')}




class TestSelectionSlider(TestCase):
Expand Down
15 changes: 9 additions & 6 deletions python/ipywidgets/ipywidgets/widgets/widget_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
_doc_snippets['selection_params'] = """
options: list
The options for the dropdown. This can either be a list of values, e.g.
``['Galileo', 'Brahe', 'Hubble']`` or ``[0, 1, 2]``, or a list of
``['Galileo', 'Brahe', 'Hubble']`` or ``[0, 1, 2]``, a list of
(label, value) pairs, e.g.
``[('Galileo', 0), ('Brahe', 1), ('Hubble', 2)]``.
``[('Galileo', 0), ('Brahe', 1), ('Hubble', 2)]``, or a Mapping between
labels and values, e.g., ``{'Galileo': 0, 'Brahe': 1, 'Hubble': 2}``.

index: int
The index of the current selection.
Expand Down Expand Up @@ -55,7 +56,8 @@
The options for the dropdown. This can either be a list of values, e.g.
``['Galileo', 'Brahe', 'Hubble']`` or ``[0, 1, 2]``, or a list of
(label, value) pairs, e.g.
``[('Galileo', 0), ('Brahe', 1), ('Hubble', 2)]``.
``[('Galileo', 0), ('Brahe', 1), ('Hubble', 2)]``, or a Mapping between
labels and values, e.g., ``{'Galileo': 0, 'Brahe': 1, 'Hubble': 2}``.
The labels are the strings that will be displayed in the UI,
representing the actual Python choices, and should be unique.

Expand Down Expand Up @@ -110,9 +112,10 @@ def _make_options(x):
The input can be
* an iterable of (label, value) pairs
* an iterable of values, and labels will be generated
* a Mapping between labels and values
"""
if isinstance(x, Mapping):
raise TypeError("options must be a iterable of values or of (label, value) pairs. If x is your Mapping, use x.items() for the options.")
x = x.items()

# only iterate once through the options.
xlist = tuple(x)
Expand Down Expand Up @@ -151,7 +154,7 @@ class _Selection(DescriptionWidget, ValueWidget, CoreWidget):
index = Int(None, help="Selected index", allow_none=True).tag(sync=True)

options = Any((),
help="""Iterable of values or (label, value) pairs that the user can select.
help="""Iterable of values, (label, value) pairs, or Mapping between labels and values that the user can select.

The labels are the strings that will be displayed in the UI, representing the
actual Python choices, and should be unique.
Expand Down Expand Up @@ -298,7 +301,7 @@ class _MultipleSelection(DescriptionWidget, ValueWidget, CoreWidget):
index = TypedTuple(trait=Int(), help="Selected indices").tag(sync=True)

options = Any((),
help="""Iterable of values or (label, value) pairs that the user can select.
help="""Iterable of values, (label, value) pairs, or Mapping between labels and values that the user can select.

The labels are the strings that will be displayed in the UI, representing the
actual Python choices, and should be unique.
Expand Down