traitlet-widgets

A library which provides the ability to create widget views for traitlet `HasTraits` models, and also to observe changes in a model


Keywords
jupyter, mvc, traitlets, ui, widgets, ipywidgets, notebook
License
MIT
Install
pip install traitlet-widgets==5.5.1

Documentation

Traitlet Widgets

pypi-badge

Examples

Model View

For a given model:

from traitlets import HasTraits, Integer, Unicode

class Model(HasTraits):
    age = Integer(min=0)
    name = Unicode()

We can create a view using model_view

from traitlet_widgets import model_view

model = Model()
view = model_view(model)

which gives
Screenshot of result of model_view

UI Customisation

The UI can be customised through the use of TraitType.tag() or a custom transformer function.

Metadata

Any tag set on a trait will be trialed as a widget attribute. If the attribute does not exist on the widget then it will not be set. For example:

from traitlets import HasTraits, Integer, Unicode
from traitlet_widgets import model_view

class Model(HasTraits):
    age = Integer(min=0)
    name = Unicode().tag(description="A girl has no name")

model = Model()

model_view(model)

Screenshot of result of model_view

The same metadata that can be provided using tags can also be provided through a hierarchical metadata dictionary:

model_view(model, metadata={"name": {"description": "Model name meta"}})

This may be desired if it is important to hide UI details from the model.

Variants

It is possible to override the variant used for a particular trait, provided it is compatible with the underlying trait:

from traitlets import HasTraits, Integer, Unicode
from traitlet_widgets import  model_view

class Model(HasTraits):
    age = Integer(min=0, max=10)
    name = Unicode()

model_view(Model())

Screenshot of result of model_view

Let's create a bounded integer text view for the age field:

from traitlets import HasTraits, Integer, Unicode
from traitlet_widgets import  model_view
import ipywidgets as widgets

class Model(HasTraits):
    age = Integer(min=0, max=10).tag(variant=widgets.BoundedIntText)
    name = Unicode()

model_view(Model())

Screenshot of result of model_view

Advanced Usage

To further control how a view is generated from a model, you can subclass the view factory. For example, given this model

from traitlets import HasTraits, Integer, Unicode
from traitlet_widgets import  model_view
import ipywidgets as widgets

class Model(HasTraits):
    age = Integer(min=0, max=10).tag(variant=widgets.BoundedIntText)
    name = Unicode()

model_view(Model())

we can create a custom view factory:

from traitlet_widgets import ViewFactory

class CustomFactory(ViewFactory):

    def create_trait_view(self, trait, ctx):
        default_widget = super().create_trait_view(trait, ctx)

        if ctx.name == "name":
            default_widget.description = "A girl has no name"
            default_widget.style = {"description_width": "initial"}

        return default_widget

f = CustomFactory()
f.create_root_view(Model())

Screenshot of result of model_view

Adding custom widgets

With the trait_view_variants decorator, it is possible to register custom view variants for a particular trait type, for example:

from traitlet_widgets import trait_view_variants
import ipywidgets as widgets
import traitlets

@trait_view_variants(traitlets.Bool)
def bool_view_factory(trait, ctx):
    yield widgets.ToggleButton, ctx.metadata
    ...

But sometimes you might wish to forgo the metadata-driven UI, and directly specify the factory and its arguments. For this, you can use the factory metadata field:

from traitlets import HasTraits, Integer, Unicode
from traitlet_widgets import model_view
import ipywidgets as widgets


class Model(HasTraits):
    age = Integer(min=0, max=10)
    name = Unicode()


def play_factory(trait, ctx):
    return widgets.Play, {
        "min": trait.get("min", 0),
        "max": trait.get("max", 100),
        **ctx.metadata,
    }


model_view(Model(), metadata={"age": {"factory": play_factory}})

Further Customisation

Although this library is driven by metadata, it is possible to modify this behaviour by overriding the appropriate methods on the view factory. These methods govern the trait discovery, view creation, and trait filtering.