holoviz / holoviz/param

pm.depends(pn.state.param.busy) on a method

Open
#500 2 comments 0 reactions 1 assignee Claimed by @philippjfr View on GitHub
type-bug
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.