-
-
Notifications
You must be signed in to change notification settings - Fork 74
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 passing positional arguments to **some** Parameters #751
Conversation
Deprecating passing any additional arguments by position certainly doesn't seem like it would be a controversial change (to me at least!) and it makes it easier to make decisions about whether or not we want |
Thanks! I completely agree that we should limit the number of positional arguments to at most one; anything else is too fragile and hard to read. However, I guess I disagree about precisely what that positional argument should be. I think there should be one positional argument accepted if and only if there is a single meaningful value that would be sufficient to define that Parameter. To me, that's what positional arguments are best used for -- easily providing "the" argument that's needed. For the numeric and string types, the default value is that single, meaningful bit of configuration; Selector types also have one single meaningful bit of required configuration, but it isn't the default value, it's the range. If you specify the range (e.g. as a list), the default value can be implicit (currently the first item in the list). But if you specify the default value, then the range is still needed, and so I do not think it's appropriate to have the default value accepted as the single positional argument of a selector. For instance, you can currently write Whereas if a Selector had the default as a positional argument, the minimum sufficient specification for the parameter would be For a ClassSelector I don't think the situation is as clear. A ClassSelector also has only a single meaningful required value (the So that's what I think should happen: default as the one positional argument in nearly all cases, but the range as the one positional argument in the cases where the range is what's required. Of course, a counterargument would be that most users won't neccessarily stop to think deeply about what's most meaningful, and that those users would best be served by having one simple, easy-to-remember rule "all Parameters accept up to one positional argument, the default value". In this view, even if the resulting syntax is wordier, duplicative, and error prone for the specific case of Selector types, that's outweighed by having a syntax that is more guessable and less error prone for users as they switch between multiple Parameter types. If that's your argument, then I can grudgingly go along with it, if (a) you are very, very sure that the majority of our users would indeed make that guess, (b) the benefits outweigh the pain of having to deprecate the current behavior and move to the new behavior over several release cycles, and (c) we can realistically get to the point of realizing those benefits in a finite time. I'm dubious about all three, but especially (b) and (c). In any case, I'm very happy with the changes to remove all positional arguments other than the first one; my concern here is solely about which particular argument that single one is. |
Don't have a ton of time to write up my thoughts today but just want to say that we had a meeting where we basically all agreed (I believe at least @hoxbro, @maximlt, @jlstevens and myself were part of that discussion) and that it is impossible to actually reason about what the correct default argument for a parameter should be. I agree that in theory your proposal is reasonable, in practice though it is simply to error prone and even I find myself guessing frequently (I guess with your heuristic in mind I'd do better), but we can't expect new users to do so. The only real way forward is to disable positional arguments, and then eventually maybe reintroduce them for the |
I agree that is the right way to make use of positional arguments when developing an API! As said by Philipp, in practice we know that most Parameters accept I opened two PRs on HoloViews and Panel that were merged and passed
You can see from these PRs which don't touch that many lines that
@philippjfr what I've done in this PR, that is an alternative to #737, is to make a difference between the Parameters that had already I am suggesting this alternative as I found that updating HoloViews and Panel, many of the changes I made adding It's a suggestion for which I have a preference as I believe it'll cause less churn. Now that's just a suggestion! # No warning would be emitted for that code, which might be how users ended up writing Param code.
class P(Parameterized):
a = String('foo')
b = Selector(objects=['a', 'b', 'c'])
c = ClassSelector(default=foo(), class_=Foo)
I think that
I think the approach taken by this PR to deprecate the current behavior for only a couple of Parameters would cause less pain.
I am not sure what this means. If it's about Param 3.0 not happening in a reasonable time frame, I'd say we could start discussing that part of this PR. |
Definitely a tricky topic but my gut feeling is that the value of a parameter (as explicitly set with I see arguments both ways but I do think that having the This isn't a strong vote for changing things now, but I do think simple, consistent semantics here is a good API goal in the long term. |
Ok, here's a proposal that I think is compatible with everyone's position above, at least in spirit:
I.e., we'd remove all positional arguments unless the first positional argument was already I'm proposing this because then people can safely use the shorthand of assuming the first positional argument is What I do not think we should do is to accept a first positional argument of I think my proposal is the same as this PR implements, except without having any plan to ever add |
OK that's fine by me, as it's indeed what's been implemented in this PR. The only divergence with your plan and the one I suggested is on whether swapping the current first argument for
On 4) and as a side note, I already write it this way and will keep doing so: class P(Parameterized):
s = param.Selector(default=2, objects=[1, 2, 3])
c = param.ClassSelector(default=A(), class_=(A, B)) Thanks for unblocking this PR, merging! |
For what it is worth, the behavior Jim describes does make good sense to me. Glad to see this merged! |
Following the discussion in #730.
I opened first #737 where I deprecated passing any argument by position to any Parameter. Our ultimate goal being to allow to make
default
the only positional argument of all the Parameters.I felt #737 was going over the top, most Parameters already allowed passing
default
first by position, there's really no need to annoy users with deprecating that, and I have to admit that this is very practical when developing Param itself:What we needed to do was:
default
as their first argument, deprecate passing any additional arguments by positionClassSelector
hasclass_
first,Selector
hasobjects
first), deprecate passing any argument by positionSo effectively to avoid the deprecation warnings users will have to write code like below, which will in practice mostly affect
Selector
andClassSelector
:The plan suggested for the future:
ParamDeprecationWarning
toParamFutureWarning
so that it's visible to all users._deprecate_positional_args
decorator, so that an error is raised instead of a warningdefault
to be passed as the only positional argument toSelector
andClassSelector
I'd say there should be at least 6 months between 1. and 2., and 6 months between 2. and 3.
This PR also allows to pass
default
by position toDynamic
, while before it could only have been passed by keyword.