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

ListSelector default #817

Merged
merged 7 commits into from
Aug 17, 2023
Merged
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
10 changes: 5 additions & 5 deletions numbergen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ class TimeAwareRandomState(TimeAware):
random_generator = param.Parameter(
default=random.Random(c_size_t(hash((500,500))).value), doc=
"""
Random state used by the object. This may may be an instance
Random state used by the object. This may be an instance
of random.Random from the Python standard library or an
instance of numpy.random.RandomState.

Expand Down Expand Up @@ -458,9 +458,9 @@ class UniformRandom(RandomDistribution):
See the random module for further details.
"""

lbound = param.Number(default=0.0,doc="inclusive lower bound")
lbound = param.Number(default=0.0,doc="Inclusive lower bound.")

ubound = param.Number(default=1.0,doc="exclusive upper bound")
ubound = param.Number(default=1.0,doc="Exclusive upper bound.")


def __call__(self):
Expand Down Expand Up @@ -500,8 +500,8 @@ class UniformRandomInt(RandomDistribution):
See the randint function in the random module for further details.
"""

lbound = param.Number(default=0,doc="inclusive lower bound")
ubound = param.Number(default=1000,doc="inclusive upper bound")
lbound = param.Number(default=0,doc="Inclusive lower bound.")
ubound = param.Number(default=1000,doc="Inclusive upper bound.")


def __call__(self):
Expand Down
47 changes: 30 additions & 17 deletions param/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1666,7 +1666,7 @@ def sig(self):


class _SignatureSelector(Parameter):

# Needs docstring; why is this a separate mixin?
_slot_defaults = _dict_update(
SelectorBase._slot_defaults, _objects=_compute_selector_default,
compute_default_fn=None, check_on_set=_compute_selector_checking_default,
Expand Down Expand Up @@ -1748,17 +1748,13 @@ def __init__(self, *, objects=Undefined, default=Undefined, instantiate=Undefine
self.allow_None = self._slot_defaults['allow_None']
else:
self.allow_None = allow_None
if self.default is not None and self.check_on_set is True:
self._validate(self.default)
if self.default is not None:
self._validate_value(self.default)
self._update_state()

def _update_state(self):
if (
self.check_on_set is False
and self.default is not None
and self.default not in self.objects
):
self.objects.append(self.default)
if self.check_on_set is False and self.default is not None:
self._ensure_value_is_in_objects(self.default)

@property
def objects(self):
Expand Down Expand Up @@ -1786,18 +1782,17 @@ def compute_default(self):
"""
if self.default is None and callable(self.compute_default_fn):
self.default = self.compute_default_fn()
if self.default not in self.objects:
self.objects.append(self.default)
self._ensure_value_is_in_objects(self.default)

def _validate(self, val):
"""
val must be None or one of the objects in self.objects.
"""
if not self.check_on_set:
self._ensure_value_is_in_objects(val)
return

if not (val in self.objects or (self.allow_None and val is None)):
self._validate_value(val)

def _validate_value(self, val):
if self.check_on_set and not (self.allow_None and val is None) and val not in self.objects:
items = []
limiter = ']'
length = 0
Expand Down Expand Up @@ -2623,16 +2618,34 @@ def compute_default(self):
self.objects.append(o)

def _validate(self, val):
self._validate_type(val)

if self.check_on_set:
self._validate_value(val)
else:
self._ensure_value_is_in_objects(val)


def _validate_type(self, val):
if (val is None and self.allow_None):
return

if not isinstance(val, list):
raise ValueError(
f"{_validate_error_prefix(self)} only takes list types, "
f"not {val!r}."
)
for o in val:
super()._validate(o)

def _validate_value(self, val):
self._validate_type(val)
if val is not None:
for o in val:
super()._validate_value(o)

def _update_state(self):
if self.check_on_set is False and self.default is not None:
for o in self.default:
self._ensure_value_is_in_objects(o)


class MultiFileSelector(ListSelector):
Expand Down
15 changes: 8 additions & 7 deletions tests/testlistselector.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def setUp(self):
super().setUp()
class P(param.Parameterized):
e = param.ListSelector(default=[5],objects=[5,6,7])
f = param.ListSelector(default=10)
f = param.ListSelector(default=[10])
jbednar marked this conversation as resolved.
Show resolved Hide resolved
h = param.ListSelector(default=None)
g = param.ListSelector(default=None,objects=[7,8])
i = param.ListSelector(default=[7],objects=[9],check_on_set=False)
Expand Down Expand Up @@ -173,16 +173,17 @@ class Q(param.Parameterized):
r = param.ListSelector(default=[6])

##########################
# CEBALERT: not sure it makes sense for ListSelector to be set to
# a non-iterable value (except None). I.e. I think this first test
# should fail.
def test_default_not_checked_to_be_iterable(self):
class Q(param.Parameterized):
r = param.ListSelector(default=6)
with pytest.raises(
ValueError,
match=re.escape("ListSelector parameter 'r' only takes list types, not 6."),
):
class Q(param.Parameterized):
r = param.ListSelector(default=6)

def test_set_checked_to_be_iterable(self):
class Q(param.Parameterized):
r = param.ListSelector(default=6,check_on_set=False)
r = param.ListSelector(default=[6],check_on_set=False)
jbednar marked this conversation as resolved.
Show resolved Hide resolved

with self.assertRaises(ValueError):
Q.r = 6
Expand Down