Ipywidgets: Add `titles` as a __init__ trait

Created on 17 May 2019  路  6Comments  路  Source: jupyter-widgets/ipywidgets

I find it quite unpythonic to have to write

tabs = w.Tab(children=outputs)
for i, title in enumerate(titles):
    tabs.set_title(i, title)

Where, we should just be able to write:

tabs = w.Tab(children=outputs, titles=titles)

Most helpful comment

Where, we should just be able to write:

tabs = w.Tab(children=outputs, titles=titles)

+1. It's bothered me for a long time that we have get_title and set_title.

Additionally, looking at the code, it's weird that titles is a dictionary indexed with integers, instead of just a tuple corresponding to the children. I think we could expose a tuple interface to users (along with constructor attribute) in a backwards-compatible way (i.e., changes to the tuple would change the dict that is synced), and we could eliminate the dict in 8.0.

All 6 comments

While I'm here, I'd also like to propose a Tab interface for capturing general output in a clean way (I also think this could apply to other containers such as Grid, etc.):

from IPython.display import display, Image

tabs = Tab()
for f in glob.glob('results/*.png'):
    with tabs.add_tab(title=f):
        print(f)
        display(Image(filename=f))


# Here it is implemented, but it would be great to have something like this 
# supported off the shelf
from contextlib import contextmanager
import ipywidgets.widgets as w

class Tab(w.Tab):
    @contextmanager
    def add_tab(self, title=None):
        out = w.Output()
        self.children += (out,)
        if title:
            self.set_title(len(self.children) - 1, title)

        with out:
            yield


Where, we should just be able to write:

tabs = w.Tab(children=outputs, titles=titles)

+1. It's bothered me for a long time that we have get_title and set_title.

Additionally, looking at the code, it's weird that titles is a dictionary indexed with integers, instead of just a tuple corresponding to the children. I think we could expose a tuple interface to users (along with constructor attribute) in a backwards-compatible way (i.e., changes to the tuple would change the dict that is synced), and we could eliminate the dict in 8.0.

Title assignment examples for Tab and Accordion from readthedocs are not working (at least in a lab notebook):

Summary:

  • Using a 'titles' parameter at instantiation time has these effects:

    • widget is rendered without raising an exception
    • widget does not have intended titles
    • widget does not have a titles attribute
  • Assigning a list of titles to widget.titles has these effects:

    • widget is rendered without raising an exception
    • widget does not have intended titles
    • widget has a titles attribute
  • Only widget.set_title method actually sets the titles to a widget with children, yet:

    • widget does not have a titles attribute
  • Environment:

Python ver: 3.7.6
OS:         win32 [MSC v.1916 64 bit (AMD64)]
ipywidgets: 7.5.1
JupyterLab: 2.2.6

Code showing the variations:

import ipywidgets as widgets

def prt_title_attr(obj, attr='titles'):
    print(attr + ' attribute:',
          getattr(obj,attr,'No such attribute!'),'\n')


# Tab widget:
tab_contents = ['P0', 'P1']
children = [widgets.Text(description=name) for name in tab_contents]

print("1.1 docstring_tab1: title list assigned to parameter `titles` at instantiation:")
docstring_tab1 = widgets.Tab(children = children,
                             titles = [str(i) for i in range(len(children))])
docstring_tab1
prt_title_attr(docstring_tab1)

print("1.2 docstring_tab2: title list assigned to `docstring_tab2.titles`:")
docstring_tab2 = widgets.Tab()
docstring_tab2.children = children
docstring_tab2.titles = [str(i) for i in range(len(children))]
docstring_tab2
prt_title_attr(docstring_tab2)

# Only the .set_title method produces expected results:
print("2. working_tab: tab title assigned via `.set_title()`:")
working_tab = ipw.Tab()
working_tab.children = children
for i in range(len(children)):
    working_tab.set_title(i, 'Tab ' + str(i))
working_tab
prt_title_attr(working_tab)

# Accordion widget:
print("3.1 docstring_acc1: title list assigned to parameter `titles` at instantiation:")
docstring_acc1 = widgets.Accordion(children=children, 
                                   titles=[str(i) for i in range(len(children))])
docstring_acc1
prt_title_attr(docstring_acc1)

print("3.2 docstring_acc2: title list assigned to `docstring_acc2.titles`:")
docstring_acc2 = widgets.Accordion()
docstring_acc2.children = children
docstring_acc2.titles = [str(i) for i in range(len(children))]
docstring_acc2
prt_title_attr(docstring_acc2)

print("4 working_acc: title list assigned via `.set_title()`:")
working_acc = widgets.Accordion()
working_acc.children = children
# or working_acc = widgets.Accordion(children = children)
for i in range(len(children)):
    working_acc.set_title(i, 'Acc ' + str(i))
working_acc
prt_title_attr(working_acc)
  • Output:
    ipw_Tab_Acc

The .titles attribute is in ipywidgets 8.0, which has not been released yet. ipywidgets 7.x still uses the set_title method.

This issue was fixed in https://github.com/jupyter-widgets/ipywidgets/pull/2746 and will be released with ipywidgets 8.

Title assignment examples for Tab and Accordion from readthedocs are not working

@CatChenal - make sure you are looking at the stable docs for ipywidgets 7.x. The development docs are for ipywidgets 8.

Was this page helpful?
0 / 5 - 0 ratings