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

Drop support for Mapping types as Selection options #2679

Merged
merged 6 commits into from
Feb 3, 2020

Conversation

jtpio
Copy link
Member

@jtpio jtpio commented Jan 7, 2020

Fixes #1958.
Continuation of #2130.

Breaking change

  • This removes support for Mapping types when constructing a new Dropdown.

@pbugnion
Copy link
Member

pbugnion commented Jan 7, 2020

Thanks!

Currently, the options traitlet has type Any(). I wonder if we can change it to a traitlets.List or some such?

I think we can probably cut more code from _Selection in general.

@jtpio
Copy link
Member Author

jtpio commented Jan 8, 2020

That's a good point, let's specify the type even more.

@jtpio
Copy link
Member Author

jtpio commented Jan 8, 2020

Currently, the options traitlet has type Any(). I wonder if we can change it to a traitlets.List or some such?

traitlets.List might be slightly too specific, since options should also support other iterables such as Tuple.

@jtpio jtpio force-pushed the remove-mutable-dropdown branch from e84be23 to f8347f5 Compare January 8, 2020 10:43
@pbugnion
Copy link
Member

pbugnion commented Jan 8, 2020

There is no reasonable traitlet supertype that includes general Python iterables, as far as I can see.

For instance, the following currently works:

import numpy as np
options = np.array(['hello', 'world'])
widgets.Dropdown(options=options)

As far as I can tell, no refinement of Any would let us keep this behaviour, so I vote in favour of keeping Any.

@pbugnion
Copy link
Member

pbugnion commented Jan 8, 2020

I think some of the entries in doc_snippets also need updating (e.g. multiple_selection_params).

@SylvainCorlay SylvainCorlay added this to the 8.0 milestone Jan 8, 2020
@jtpio jtpio force-pushed the remove-mutable-dropdown branch 2 times, most recently from 23c6b56 to db67be3 Compare January 8, 2020 13:29
@jtpio
Copy link
Member Author

jtpio commented Jan 8, 2020

I think some of the entries in doc_snippets also need updating (e.g. multiple_selection_params).

For the _MultipleSelection, don't we want to keep support for Mapping / dict? At least for now, and potentially drop it in a separate PR.

@pbugnion
Copy link
Member

pbugnion commented Jan 9, 2020

For the _MultipleSelection, don't we want to keep support for Mapping / dict? At least for now, and potentially drop it in a separate PR.

Ah yes, you're completely right, sorry.

Maybe we should introduce a deprecation ahead of 8?

@pbugnion
Copy link
Member

pbugnion commented Jan 9, 2020

Actually, since _MultipleSelection also relies on _make_options, doesn't this PR break support for dict-like objects in widgets that inherit from _MultipleSelection?

For instance, unless I'm missing something, the following is broken:

import ipywidgets.widgets.widget_selection as iws
s2 = iws._MultipleSelection(options={'a': 52, 'b': 62}, value=[62])

This works on master, but fails on your branch. AFAICT, on your branch, _make_options converts options to [('a', 'a'), ('b', 'b')].

Happy to look into this together -- I've found the logic in _MultipleSelection very difficult to follow.

@pbugnion
Copy link
Member

pbugnion commented Jan 9, 2020

Somewhat unexpectedly, for a dictionary d = { "a": 5, "b": 8}, tuple(d) returns the dictionary keys:

>>> d = {"a": 5, "b": 6}
>>> tuple(d)
#=> ("a", "b")

This means that, for someone who's not paid attention to the deprecation warning and still has a dict, their widget won't crash -- it'll just behave really unexpectedly: the dropdown entries will be the same, but the values will just be ignored. I think this is going to be really surprising.

We can either:

  1. not care
  2. keep the if isinstance(x, Mapping): in _make_options but raise a TypeError if x is a Mapping.

@jasongrout
Copy link
Member

keep the if isinstance(x, Mapping): in _make_options but raise a TypeError if it's x is a Mapping.

I'm fine with this, say for one more version.

@jtpio
Copy link
Member Author

jtpio commented Jan 10, 2020

Thanks @pbugnion for investigating this further.

Actually, since _MultipleSelection also relies on _make_options, doesn't this PR break support for dict-like objects in widgets that inherit from _MultipleSelection?

It looks like it does yes. We should be able to catch that in the tests though.

In the long run we'll probably want to drop support for mutable types for MultipleSelection widgets too. But it would be better to introduce a DeprecationWarning first.

  1. keep the if isinstance(x, Mapping): in _make_options but raise a TypeError if x is a Mapping.

This could be a good compromise in the meantime.

@jtpio jtpio changed the title Drop support for mutable types as Dropdown options [WIP] Drop support for mutable types as Dropdown options Jan 10, 2020
@jasongrout
Copy link
Member

Just to be clear here - we are talking about dropping support for mapping types, not mutable types.

@jasongrout jasongrout changed the title [WIP] Drop support for mutable types as Dropdown options [WIP] Drop support for mapping types as Dropdown options Jan 14, 2020
@jasongrout
Copy link
Member

@jtpio - what is the current status of this PR?

@jtpio
Copy link
Member Author

jtpio commented Jan 22, 2020

It was changed back to a "WIP" to check the points raised by @pbugnion above and see if they can be covered in the tests too:

Actually, since _MultipleSelection also relies on _make_options, doesn't this PR break support for dict-like objects in widgets that inherit from _MultipleSelection?

@jtpio jtpio force-pushed the remove-mutable-dropdown branch from db67be3 to a498a2d Compare January 22, 2020 13:26
@jtpio
Copy link
Member Author

jtpio commented Jan 22, 2020

We can indeed see that with a SelectMultiple widget:

from ipywidgets import SelectMultiple

options = {'a': 'Apples', 'o': 'Oranges', 'p': 'Pears'}

select = SelectMultiple(
    options=options,
    description='Fruits'
)
select

Which gives back the list of keys as values:

image

We might then want to drop support for Mapping types as _MultipleSelectionoptions too. The DeprecationWarning added in #2130 should also be triggered when using a SelectMultiple widget in 7.5:

image

@jtpio
Copy link
Member Author

jtpio commented Jan 22, 2020

keep the if isinstance(x, Mapping): in _make_options but raise a TypeError if x is a Mapping.

This would at least make the change more visible instead of silently converting the Mapping to a tuple.

@jtpio
Copy link
Member Author

jtpio commented Jan 22, 2020

Currently, the options traitlet has type Any(). I wonder if we can change it to a traitlets.List or some such?

We can also follow this approach and be explicit about the types being accepted. For example with Union([Tuple(), Set()]).

Edit: although we might want to keep support for the numpy case: #2679 (comment)

@jtpio jtpio force-pushed the remove-mutable-dropdown branch from a498a2d to 4e2b528 Compare January 28, 2020 17:12
@jtpio jtpio force-pushed the remove-mutable-dropdown branch from 4e2b528 to 28877f9 Compare January 28, 2020 17:15
@jtpio
Copy link
Member Author

jtpio commented Jan 28, 2020

The last commit implements the ideas mentioned above:

  • raise a TypeError for Mapping types, since the DeprecationWarning was already given on other selection widgets
  • this prevents implicit casts to a tuple
  • numpy arrays are still supported

@jtpio jtpio changed the title [WIP] Drop support for mapping types as Dropdown options Drop support for Mapping types as Selection options Jan 28, 2020
@jasongrout
Copy link
Member

@jtpio - thanks! @pbugnion - do you have time to review the current changes?

@pbugnion
Copy link
Member

pbugnion commented Feb 2, 2020

Great, thank you!

I'll review this in the next couple of days.

@pbugnion pbugnion force-pushed the remove-mutable-dropdown branch 3 times, most recently from 0b4abe3 to 5a73074 Compare February 3, 2020 07:34
@pbugnion
Copy link
Member

pbugnion commented Feb 3, 2020

I added a couple of tests to verify the behaviour when setting .options, clarified a docstring, and added a note on changes in ipywidgets 8.

RTD is failing because of #2768, but the rest looks good. I'm going to merge this.

Thank you!

@pbugnion pbugnion merged commit 7258f03 into jupyter-widgets:master Feb 3, 2020
@jtpio jtpio deleted the remove-mutable-dropdown branch February 3, 2020 08:30
@jtpio
Copy link
Member Author

jtpio commented Feb 3, 2020

Thanks @pbugnion!

@lock lock bot added the resolved-locked Closed issues are locked after 30 days inactivity. Please open a new issue for related discussion. label May 20, 2020
@lock lock bot locked as resolved and limited conversation to collaborators May 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
backwards-incompatible resolved-locked Closed issues are locked after 30 days inactivity. Please open a new issue for related discussion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Drop support for mutable types as dropdown options
4 participants