pm.depends(pn.state.param.busy) on a method
- Dominant language
- Python
- Stars
- 521
- Forks
- 86
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 35
Description
#### ALL software version info
* param 1.10.1
* panel 0.11.3
* python 3.7.10
#### Description of expected behavior and the observed behavior
I'm trying to use `@pm.depends(pn.state.param.busy, watch=True)` on an instance method of a class. When I modify a parameter, I expect the method to get called once with argument `busy=True` and once with argument `busy=False`.
Instead I'm seeing potentially 2 issues:
* Whenever I use `@pm.depends(pn.state.param.busy, watch=True)`, even on a normal function, the function or method gets called 4 times, with arguments busy = True/False/True/False. It doesn't seem to be due to the `watch` argument because when I remove it nothing gets called.
* In case of a method, every call gets duplicated (for a total of 8) and in half the calls the `self` argument is the boolean `busy`, in the other half it's the expected object instance. I never get both in the same call.
See example code and output below.
#### Complete, minimal, self-contained example code that reproduces the issue
```python
import panel as pn
import param as pm
from bokeh.server.server import Server
class A(pm.Parameterized):
value = pm.Integer()
def __init__(self):
super().__init__()
self.a = 1234
@pm.depends(pn.state.param.busy, watch=True)
def indicator_method(self, *args, **kwargs):
print("method", self, args, kwargs)
# @pm.depends(pn.state.param.busy, watch=True)
# def indicator_func(*args, **kwargs):
# print("func", args, kwargs)
def bkapp(doc):
a = A()
p = pn.Row(a.param)
doc.add_root(p.get_root())
if __name__ == '__main__':
port = 8901
server = Server({'/': bkapp}, num_procs=1, port=port)
server.start()
server.io_loop.add_callback(server.show, "/")
server.io_loop.start()
```
#### Output when changing value
Example as-is:
```
method True () {}
method () {}
method False () {}
method () {}
method True () {}
method () {}
method False () {}
method () {}
```
When commenting out the method and uncommenting the function:
```
func (True,) {}
func (False,) {}
func (True,) {}
func (False,) {}
```
#### Workaround for method vs function
Below two potential workarounds. The method still gets called 4 times though.
```python
class A(pm.Parameterized):
value = pm.Integer()
def __init__(self):
super().__init__()
self.a = 1234
# Workaround 1
f = functools.partial(self.indicator.__func__, self)
pm.depends(pn.state.param.busy, watch=True)(f)
# # Workaround 2
# pn.state.param.watch(self.indicator, 'busy')
def indicator(self, busy):
print(self.a, busy)
```
Output (workaround 1):
```
1234 True
1234 False
1234 True
1234 False
```
Output (workaround 2):
```
1234 Event(what='value', name='busy', obj=state(servers=[]), cls=, old=False, new=True, type='changed')
1234 Event(what='value', name='busy', obj=state(servers=[]), cls=, old=True, new=False, type='changed')
1234 Event(what='value', name='busy', obj=state(servers=[]), cls=, old=False, new=True, type='changed')
1234 Event(what='value', name='busy', obj=state(servers=[]), cls=, old=True, new=False, type='changed')
```
Contributor guide
Assessment
This issue has not been assessed yet.