Skip to content

Commit

Permalink
Fix depending on the method of a sub parameter object (#765)
Browse files Browse the repository at this point in the history
  • Loading branch information
maximlt authored Jun 19, 2023
1 parent 154cdbe commit 8759c1c
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 2 deletions.
4 changes: 2 additions & 2 deletions param/parameterized.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from functools import partial, wraps, reduce
from operator import itemgetter,attrgetter
from threading import get_ident
from types import FunctionType
from types import FunctionType, MethodType

import logging
from contextlib import contextmanager
Expand Down Expand Up @@ -2556,7 +2556,7 @@ def _spec_to_obj(self_, spec, dynamic=True, intermediate=True):
attr_obj = getattr(src, attr)
if isinstance(attr_obj, Parameterized):
return [], []
elif isinstance(attr_obj, FunctionType):
elif isinstance(attr_obj, (FunctionType, MethodType)):
info = MInfo(inst=inst, cls=cls, name=attr,
method=attr_obj)
else:
Expand Down
113 changes: 113 additions & 0 deletions tests/testparamdepends.py
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,119 @@ def cb(self):

assert not called

def test_param_depends_on_method(self):

method_count = 0

class A(param.Parameterized):
a = param.Integer()

@param.depends('a', watch=True)
def method1(self):
pass

@param.depends('method1', watch=True)
def method2(self):
nonlocal method_count
method_count += 1

inst = A()
pinfos = inst.param.method_dependencies('method2')
assert len(pinfos) == 1

pinfo = pinfos[0]
assert pinfo.cls is A
assert pinfo.inst is inst
assert pinfo.name == 'a'
assert pinfo.what == 'value'

inst.a = 2
assert method_count == 1

def test_param_depends_on_method_subparameter(self):

method1_count = 0
method2_count = 0

class Sub(param.Parameterized):
a = param.Integer()

@param.depends('a')
def method1(self):
nonlocal method1_count
method1_count += 1

class Main(param.Parameterized):
sub = param.Parameter()

@param.depends('sub.method1', watch=True)
def method2(self):
nonlocal method2_count
method2_count += 1

sub = Sub()
main = Main(sub=sub)
pinfos = main.param.method_dependencies('method2')
assert len(pinfos) == 1

pinfo = pinfos[0]
assert pinfo.cls is Sub
assert pinfo.inst is sub
assert pinfo.name == 'a'
assert pinfo.what == 'value'

sub.a = 2
assert method1_count == 0
assert method2_count == 1


def test_param_depends_on_method_subparameter_after_init(self):
# Setup inspired from https://github.com/holoviz/param/issues/764

method1_count = 0
method2_count = 0

class Controls(param.Parameterized):

explorer = param.Parameter()

@param.depends('explorer.method1', watch=True)
def method2(self):
nonlocal method2_count
method2_count += 1


class Explorer(param.Parameterized):

controls = param.Parameter()

x = param.Selector(objects=['a', 'b'])

def __init__(self, **params):
super().__init__(**params)
self.controls = Controls(explorer=self)

@param.depends('x')
def method1(self):
nonlocal method1_count
method1_count += 1

explorer = Explorer()

pinfos = explorer.controls.param.method_dependencies('method2')
assert len(pinfos) == 1

pinfo = pinfos[0]
assert pinfo.cls is Explorer
assert pinfo.inst is explorer
assert pinfo.name == 'x'
assert pinfo.what == 'value'

explorer.x = 'b'

assert method1_count == 0
assert method2_count == 1


class TestParamDependsFunction(unittest.TestCase):

Expand Down

0 comments on commit 8759c1c

Please sign in to comment.