Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate Selector's compute_default_fn slot and compute_default() method #1012

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions doc/user_guide/Parameter_Types.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -826,8 +826,6 @@
"\n",
"Because `Selector` is usually used to allow selection from a list of existing (instantiated) objects, `instantiate` is False by default, but you can specify `instantiate=True` if you want each copy of this Parameter value to be independent of other instances and superclasses.\n",
"\n",
"In cases where the objects in the list cannot be known when writing the Parameterized class but can be calculated at runtime, you can supply a callable (of no arguments) to `compute_default_fn`, and then ensure that at runtime you call `compute_default` on that Parameter to initialize the value.\n",
"\n",
"A `param.ListSelector` works just the same as a regular Selector, but the value is a _list_ of valid objects from the available objects, rather than just one. Each item in the list is checked against the `objects`, and thus the current value is thus a _subset_ of the `objects`, rather than just one of the objects.\n",
"\n",
"A `param.FileSelector` works like a regular Selector with the value being a filename and the `objects` being computed from files on a file system. The files are specified as a `path` [glob](https://docs.python.org/3/library/glob.html), and all filenames matching the glob are valid `objects` for the parameter.\n",
Expand Down
21 changes: 21 additions & 0 deletions param/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
)
from ._utils import (
ParamFutureWarning as _ParamFutureWarning,
ParamDeprecationWarning as _ParamDeprecationWarning,
_deprecate_positional_args,
_deprecated,
_validate_error_prefix,
Expand Down Expand Up @@ -1868,6 +1869,13 @@ def __init__(self, *, objects=Undefined, default=Undefined, instantiate=Undefine
compute_default_fn=Undefined, check_on_set=Undefined,
allow_None=Undefined, empty_default=False, **params):

if compute_default_fn is not Undefined:
warnings.warn(
'compute_default_fn has been deprecated and will be removed in a future version.',
_ParamDeprecationWarning,
stacklevel=3,
)

autodefault = Undefined
if objects is not Undefined and objects:
if isinstance(objects, dict):
Expand Down Expand Up @@ -1919,7 +1927,15 @@ def compute_default(self):

Also removes None from the list of objects (if the default is
no longer None).

.. deprecated:: 2.3.0
"""
warnings.warn(
'compute_default() has been deprecated and will be removed in a future version.',
_ParamDeprecationWarning,
stacklevel=2,
)

if self.default is None and callable(self.compute_default_fn):
self.default = self.compute_default_fn()
self._ensure_value_is_in_objects(self.default)
Expand Down Expand Up @@ -2063,6 +2079,11 @@ def __init__(self, default=Undefined, *, objects=Undefined, **kwargs):
objects=objects, default=default, empty_default=True, **kwargs)

def compute_default(self):
warnings.warn(
'compute_default() has been deprecated and will be removed in a future version.',
_ParamDeprecationWarning,
stacklevel=2,
)
if self.default is None and callable(self.compute_default_fn):
self.default = self.compute_default_fn()
for o in self.default:
Expand Down
20 changes: 20 additions & 0 deletions tests/testdeprecations.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,26 @@ class P(param.Parameterized):
with pytest.raises(param._utils.ParamFutureWarning):
p.n = 1

def test_deprecate_Selector_compute_default_fn(self):
with pytest.raises(param._utils.ParamDeprecationWarning):
param.Selector(compute_default_fn=lambda: 0)

def test_deprecate_Selector_compute_default(self):
class P(param.Parameterized):
s = param.Selector()

P.param['s'].compute_default_fn = lambda: 0
with pytest.raises(param._utils.ParamDeprecationWarning):
P().param['s'].compute_default()

def test_deprecate_ListSelector_compute_default(self):
class P(param.Parameterized):
ls = param.ListSelector()

P.param['ls'].compute_default_fn = lambda: [0]
with pytest.raises(param._utils.ParamDeprecationWarning):
P().param['ls'].compute_default()


class TestDeprecateInitModule:

Expand Down
23 changes: 16 additions & 7 deletions tests/testlistselector.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import re
import unittest
import warnings

import param
import pytest
Expand Down Expand Up @@ -197,20 +198,28 @@ class Q(param.Parameterized):
Q.r = 6

def test_compute_default(self):
class Q(param.Parameterized):
r = param.ListSelector(default=None, compute_default_fn=lambda: [1,2,3])
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='compute_default_fn', category=param._utils.ParamDeprecationWarning)
class Q(param.Parameterized):
r = param.ListSelector(default=None, compute_default_fn=lambda: [1,2,3])

self.assertEqual(Q.r, None)
Q.param['r'].compute_default()
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='compute_default', category=param._utils.ParamDeprecationWarning)
Q.param['r'].compute_default()
self.assertEqual(Q.r, [1,2,3])
self.assertEqual(Q.param['r'].objects, [1,2,3])

def test_bad_compute_default(self):
class Q(param.Parameterized):
r = param.ListSelector(default=None,compute_default_fn=lambda:1)
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='compute_default_fn', category=param._utils.ParamDeprecationWarning)
class Q(param.Parameterized):
r = param.ListSelector(default=None,compute_default_fn=lambda:1)

with self.assertRaises(TypeError):
Q.param['r'].compute_default()
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='compute_default', category=param._utils.ParamDeprecationWarning)
with self.assertRaises(TypeError):
Q.param['r'].compute_default()

def test_initialization_bad_iterable(self):
with self.assertRaises(ValueError):
Expand Down
21 changes: 15 additions & 6 deletions tests/testobjectselector.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import re
import unittest
import warnings

from collections import OrderedDict

Expand Down Expand Up @@ -550,12 +551,16 @@ class Q(param.Parameterized):
raise AssertionError("ObjectSelector created without range.")

def test_compute_default_fn_in_objects(self):
class P(param.Parameterized):
o = param.ObjectSelector(objects=[0, 1], compute_default_fn=lambda: 1)
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='compute_default_fn', category=param._utils.ParamDeprecationWarning)
class P(param.Parameterized):
o = param.ObjectSelector(objects=[0, 1], compute_default_fn=lambda: 1)

assert P.param.o.default is None

P.param.o.compute_default()
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='compute_default', category=param._utils.ParamDeprecationWarning)
P.param.o.compute_default()

assert P.param.o.default == 1

Expand All @@ -565,12 +570,16 @@ class P(param.Parameterized):


def test_compute_default_fn_not_in_objects(self):
class P(param.Parameterized):
o = param.ObjectSelector(objects=[0, 1], compute_default_fn=lambda: 2)
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='compute_default_fn', category=param._utils.ParamDeprecationWarning)
class P(param.Parameterized):
o = param.ObjectSelector(objects=[0, 1], compute_default_fn=lambda: 2)

assert P.param.o.default is None

P.param.o.compute_default()
with warnings.catch_warnings():
warnings.filterwarnings('ignore', message='compute_default', category=param._utils.ParamDeprecationWarning)
P.param.o.compute_default()

assert P.param.o.default == 2

Expand Down
Loading