The error traceback indicates that there is a problem with the pn.widgets.Select widget if your object list contains actual param.Parameterized objects.
In that case the Select widget contains 2 pieces encapsulated in a “Row”, the actual Selector + the nice little BLUE box […] to drill-down into the parameterized object selected.
when you update the self.param.rooms.object, this triggers the watchers that have been registered by the pn.widgets.Select to get informed of the change. But it can’t handle it correctly, because the top-level ‘Row’ doesn’t have an “options” parameter, only one of the widgets sub-objects, the selector has one.
So currently it looks like there is a bug when trying to update a selector list that contains parameterized-objects after the Select-widget has been instantiated. Or it’s just not supported ?
Anyway, well above my expertise level ,one of the usual suspects like @Marc or @philippjfr may be able to help.
Below some debugging:
I basically broke out the rooms-widget manually to be able to inspect it:
import param
import panel as pn
pn.extension()
class A(param.Parameterized):
val = param.Integer()
class ObjSelect(param.Parameterized):
a=A()
rooms = param.ObjectSelector(default=a, objects=[a])
action = param.Action(lambda self: self.update_obj_list(), label='Update')
i = param.Integer(2, precedence=-2)
def update_obj_list(self):
print("update")
l = self.param.rooms.objects.copy()
new_obj = A()
l.append(new_obj)
self.param.rooms.objects = l
print(id(self.param.rooms.objects))
self.rooms = new_obj
self.i += 1
print("updated")
o = ObjSelect()
w_rooms = pn.widgets.Select.from_param(o.param.rooms)
pn.Column(o.param.action, w_rooms)
The error message:
File "C:\Users\jogri\AppData\Local\Temp\ipykernel_868\2998770942.py", line 11, in <lambda>
action = param.Action(lambda self: self.update_obj_list(), label='Update')
^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\jogri\AppData\Local\Temp\ipykernel_868\2998770942.py", line 19, in update_obj_list
self.param.rooms.objects = l
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python311\Lib\site-packages\param\parameterized.py", line 1141, in __setattr__
self.owner.param._call_watcher(watcher, event)
File "C:\Python311\Lib\site-packages\param\parameterized.py", line 2043, in _call_watcher
self_._execute_watcher(watcher, (event,))
File "C:\Python311\Lib\site-packages\param\parameterized.py", line 2025, in _execute_watcher
watcher.fn(*args, **kwargs)
File "C:\Python311\Lib\site-packages\panel\param.py", line 594, in link
widget.param.update(**updates)
File "C:\Python311\Lib\site-packages\param\parameterized.py", line 1893, in update
raise ValueError("'%s' is not a parameter of %s" % (k, self_or_cls.name))
ValueError: 'options' is not a parameter of Row02287
Now checking the watcher that gets actually triggered:
print(o.param.rooms.watchers)
{'constant': [Watcher(inst=ObjSelect(action=<function ObjSelect.<lambda> at 0x000001BEC3BA5580>, i=2, name='ObjSelect02270', rooms=A(name='A02269', val=0)), cls=<class '__main__.ObjSelect'>, fn=<function Param.widget.<locals>.link at 0x000001BEC3C5CB80>, mode='args', onlychanged=True, parameter_names=('rooms',), what='constant', queued=False, precedence=0)],
'precedence': [Watcher(inst=ObjSelect(action=<function ObjSelect.<lambda> at 0x000001BEC3BA5580>, i=2, name='ObjSelect02270', rooms=A(name='A02269', val=0)), cls=<class '__main__.ObjSelect'>, fn=<function Param.widget.<locals>.link at 0x000001BEC3C5CB80>, mode='args', onlychanged=True, parameter_names=('rooms',), what='precedence', queued=False, precedence=0)],
'label': [Watcher(inst=ObjSelect(action=<function ObjSelect.<lambda> at 0x000001BEC3BA5580>, i=2, name='ObjSelect02270', rooms=A(name='A02269', val=0)), cls=<class '__main__.ObjSelect'>, fn=<function Param.widget.<locals>.link at 0x000001BEC3C5CB80>, mode='args', onlychanged=True, parameter_names=('rooms',), what='label', queued=False, precedence=0)],
'objects': [Watcher(inst=ObjSelect(action=<function ObjSelect.<lambda> at 0x000001BEC3BA5580>, i=2, name='ObjSelect02270', rooms=A(name='A02269', val=0)), cls=<class '__main__.ObjSelect'>, fn=<function Param.widget.<locals>.link at 0x000001BEC3C5CB80>, mode='args', onlychanged=True, parameter_names=('rooms',), what='objects', queued=False, precedence=0)]}
And here the widget details:
print(w_rooms)
display(w_rooms.param.values())
print(w_rooms.param.objects)
Row(width=300)
[0] Select(margin=(5, 0, 5, 10), name='Rooms', options=OrderedDict([('A02269', ...]), sizing_mode='stretch_width', value=A)
[1] Toggle(align='end', button_type='primary', height_policy='fit', margin=(0, 0, 5, 10), max_height=30, max_width=20, name='⋮')
{'align': 'start',
'aspect_ratio': None,
'background': None,
'css_classes': [],
'design': None,
'height': None,
'height_policy': 'auto',
'loading': False,
'margin': 0,
'max_height': None,
'max_width': None,
'min_height': None,
'min_width': None,
'name': 'Row02287',
'objects': [Select(margin=(5, 0, 5, 10), name='Rooms', options=OrderedDict([('A02269', ...]), sizing_mode='stretch_width', value=A),
Toggle(align='end', button_type='primary', height_policy='fit', margin=(0, 0, 5, 10), max_height=30, max_width=20, name='⋮')],
'scroll': False,
'sizing_mode': None,
'styles': {},
'stylesheets': [],
'tags': [],
'visible': True,
'width': 300,
'width_policy': 'auto'}
<bound method Parameters.objects of <param.parameterized.Parameters object at 0x000001BEC3C79550>>