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

EnumEditor unable to deduce allowed values from Enum trait #726

Open
kitchoi opened this issue Jan 21, 2020 · 4 comments
Open

EnumEditor unable to deduce allowed values from Enum trait #726

kitchoi opened this issue Jan 21, 2020 · 4 comments

Comments

@kitchoi
Copy link
Contributor

kitchoi commented Jan 21, 2020

To reproduce:

from traits.api import HasTraits, Enum

from traitsui.api import Item, View, EnumEditor


class EnumEditorDemo(HasTraits):
    """ Defines the main EnumEditor demo class. """

    name_list = Enum('A-495', 'A-498', 'R-1226', 'TS-17', 'TS-18',
                     'Foo', 12345, (11, 7), None)


    def default_traits_view(self):
        return View(
            Item(
                'name_list', style='simple',
                editor=EnumEditor(),
                label='Simple'
            ),
        )

if __name__ == '__main__':
    EnumEditorDemo().configure_traits()

We get this error:

Traceback (most recent call last):
  File "examples/demo/Standard_Editors/dummy.py", line 31, in <module>
    demo.configure_traits()
  File "/Users/kchoi/ETS/traits/traits/has_traits.py", line 2083, in configure_traits
    args,
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/toolkit.py", line 233, in view_application
    context, view, kind, handler, id, scrollable, args
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/view_application.py", line 85, in view_application
    context, view, kind, handler, id, scrollable, args
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/view_application.py", line 127, in __init__
    args=self.args,
  File "/Users/kchoi/ETS/traitsui/traitsui/view.py", line 463, in ui
    ui.ui(parent, kind)
  File "/Users/kchoi/ETS/traitsui/traitsui/ui.py", line 247, in ui
    self.rebuild(self, parent)
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/toolkit.py", line 163, in ui_live
    ui_live.ui_live(ui, parent)
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/ui_live.py", line 44, in ui_live
    _ui_dialog(ui, parent, BaseDialog.NONMODAL)
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/ui_live.py", line 66, in _ui_dialog
    BaseDialog.display_ui(ui, parent, style)
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/ui_base.py", line 285, in display_ui
    ui.owner.init(ui, parent, style)
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/ui_live.py", line 226, in init
    self.add_contents(panel(ui), bbox)
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/ui_panel.py", line 261, in panel
    panel = _GroupPanel(content[0], ui).control
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/ui_panel.py", line 603, in __init__
    layout = self._add_items(content, inner)
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/ui_panel.py", line 877, in _add_items
    editor.prepare(inner)
  File "/Users/kchoi/ETS/traitsui/traitsui/editor.py", line 241, in prepare
    self.init(parent)
  File "/Users/kchoi/ETS/traitsui/traitsui/qt4/enum_editor.py", line 168, in init
    control.addItems(self.names)
TypeError: addItems(self, Iterable[str]): argument 1 has unexpected type 'NoneType'

If I remove this line and let traitsui cleverly guess the editor:

                editor=EnumEditor(),    # remove this

Then the UI can be launched with the expected behaviour.

Similarly, if I have the allowed values in a separate trait, this raises the same error

    name_list = Enum(values="allowed_values")
    allowed_values = List(["A-495", "A-498"])

    def default_traits_view(self):
        return View(
            Item(
                'name_list', style='simple',
                editor=EnumEditor(),
                label='Simple'
            ),
        )

I need to do this instead:

                editor=EnumEditor(values="allowed_values"),

Given the name_list trait already specifies where the allowed values come from, it seems unnecessary to have to tell the editor again.

@corranwebster
Copy link
Contributor

corranwebster commented Jan 21, 2020

I think a lot of this is because the default EnumEditor created by the BaseEnum trait is fairly sophisticated:

https://github.com/enthought/traits/blob/master/traits/trait_types.py#L2016-L2022

You need to replicate a lot of that to get the same behaviour from a custom one; in particular, you can't assume that this EnumEditor will always be used with the same underlying Enum (or even have access to it at factory creation time).

@rkern
Copy link
Member

rkern commented Jan 21, 2020

The general rule is that when you specify the Item(name, editor=...), that editor doesn't inspect the trait for anything. It does no magic. editor=EnumEditor() means editor=EnumEditor(), no more. This is typically a good thing. If it did inspect the trait, it would be unclear when the arguments you passed to EnumEditor were meant to override what it could inspect from the trait and when they were expected to be left as what you specified (or deliberately omitted from the constructor).

The way that information gets transferred from the trait declaration to an editor is when no editor=... is specified in the Item. Then the trait is asked to create_editor() with the appropriate configuration.

@kitchoi
Copy link
Contributor Author

kitchoi commented Jan 21, 2020

I think a lot of this is because the default EnumEditor created by the BaseEnum trait is fairly sophisticated:
https://github.com/enthought/traits/blob/master/traits/trait_types.py#L2016-L2022

Interesting! For my understanding, may I ask where is this create_editor called? I have having difficulties finding it...

@corranwebster
Copy link
Contributor

It's called in the get_editor method of the BaseTraitHandler (which is the ABC of all TraitTypes): https://github.com/enthought/traits/blob/master/traits/base_trait_handler.py#L146

which is in turn called in the ui_panel.py module which is responsible for building the concrete UI:

editor_factory = trait.get_editor().trait_set(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants