enthought / enthought/traitsui

Non-live contexts problematic with Controllers and ModelViews

Open
#464 1 comment 0 reactions 0 assignees View on GitHub
type: bug
Dominant language
Python
Stars
306
Forks
99
PR merge metrics
No merged PRs in 30d

Description

Because `Controller`s and `ModelView`s hold state and non-live contexts call clone traits on each and every value in the context, you can end up with multiple independent copies of both the model and the handler, and which one is being accessed at any given time is not at all clear.

See the following code, for example:
```

from traits.api import HasTraits, Int, Property, Unicode, cached_property
from traitsui.api import Controller, ModelView, View, Item

class MyModel(HasTraits):

value = Unicode

class MyModelView(ModelView):

another_value = Unicode

length = Property(Int, depends_on=['another_value', 'model.value'])

def init(self, info):
print(self, info.handler, info.object)
print(self.model, info.model, info.object.model, info.handler.model)

@cached_property
def _get_length(self):
return len(self.another_value) + len(self.model.value)

view = View(
Item('another_value'),
Item('model.value'),
Item('length', style='readonly'),
)

class MyController(Controller):

another_value = Unicode

length = Property(Int, depends_on=['another_value', 'model.value'])

def init(self, info):
print(self, info.handler, info.controller)
print(self.model, info.object, info.controller.model, info.handler.model)

@cached_property
def _get_length(self):
return len(self.another_value) + len(self.model.value)

view = View(
Item('controller.another_value'),
Item('value'),
Item('controller.length', style='readonly'),
)

m = MyModelView(model=MyModel())
m.configure_traits(kind='modal')

m = MyController(model=MyModel())
m.configure_traits(kind='modal')
```

Note that you end up with no less than 4 copies of the model object; also note that the `length` property does not respond to changes in the model's `value` as expected.

This is not a problem for `Handlers` as they don't have any state, so even if a cloned handler gets invoked, you have to go through the context to get any actual values.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the reproduced MyModelView and MyController examples and their configure_traits(kind='modal') entry points. Trace how non-live contexts clone values and compare the model, handler, controller, and object references shown by init. Done means the context has consistent model and handler state and the length property responds to model.value changes.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
desktop
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.