ParamOverrides seem to be broken
Surely, ParamOverrides shouldn't be allow this?
import param
class Foo(param.ParameterizedFunction):
a = param.String('bar')
b = param.Boolean()
def __call__(self, **params):
print param.ParamOverrides(self,params)
>>> Foo(a=slice, b=3)
{'a': <type 'slice'>, 'b': 3} overriding params from Foo(a='bar', b=False, name='Foo')
Shouldn't the types be checked? Otherwise what is the point of ParamOverrides?
Maybe I am just getting confused and I just don't understand what ParamOverrides are for...
From the code, I don't see any type-checking done by ParamOverrides; it's only checking that there is a corresponding Parameter, not what its type or bounds are. That does seem like it opens up a lot of holes, and it doesn't seem like a good idea at all. It looks to me like it has access to the underlying Parameterized object overriden, and so it should be straightforward to call the checking methods on the data we have been supplied, so I don't know why it hasn't been done already. Seems unsafe to me! :-(
Oops.
How far do we want ParamOverrides to go in behaving like the overridden object?
For instance, should you be able to override a dynamic parameter with a function and have that function be transparently called when you request the parameter value from ParamOverrides? Right now, if someone overrides a dynamic parameter with a function, they'll get the function back rather than the result of calling that function (I think). So e.g. something like
class A(param.Parameterized):
a = param.String(default='hi')
b = param.Number(default=0.5, bounds=(0,1))
a = A()
po = param.ParamOverrides(a, dict(b=lambda:0.75))
print po.a
print po.b
gives something like
hi
(lambda function...)
instead of what I think someone would expect:
hi
0.75
So, apart from not checking types/values etc, I think ParamOverrides doesn't behave enough like the overridden object in this way too. What do you think?
If we want ParamOverrides to behave a lot like the overridden instance, then I guess I propose that instead of the current implementation, a ParamOverrides instance should basically be a Parameterized instance that shares the overridden Parameterized instance's parameters (i.e. the parameter objects) ;)
If someone supplies a function to ParamOverrides that would be called if it were set as a Parameter, then definitely it should be called in this case too. Your proposed implementation sounds like the right way to do it, to me.
Sounds good!
Although I approve having a unit test for this, I'm not sure I like seeing param tests fail while the fix is implemented. Hope the fix makes its way to master soon. :-)
Yeah, sorry about that. I had time to write the test, and was assuming the problem was just a bug/oversight, but then when I looked at the code for ParamOverrides I realized it would be a bigger job than I had time for at that point. I'll try to get it done by early next week.
ParamOverrides was probably one of those things that we did quickly to see if it was something we definitely wanted and if it would work, but then having established we did want it, never revisited.