Re: Deprecating positional arguments for functions whose signatures are being already

Adrin <[email protected]> Mon, 23 Oct 2023 13:43:58 +0200
Newsgroups gmane.comp.python.scientific.devel
Message-ID <CAEOrW4-YOvSOqDm2qCG9Ez_PHwmekn_-7T1N0TViizQ+hMOwOA@mail.gmail.com>
As the person who championed the SLEP on the scikit-learn side, I can only
say that we're very happy this happened, and it has made life much easier
in terms of certain API changes, as well as removing hidden bugs from
users' codes due to mistaken argument orders.

As a user, I personally would be very happy to see this in scipy.

On Mon, Oct 23, 2023 at 1:00 PM h.vetinari--- via SciPy-Dev <
[email protected]> wrote:

> Dear all,
>
> In the context of maintaining our APIs, previous discussions recognized
> the advantages of using keyword-only arguments where appropriate, but it
> was decided that a "big bang" change of all our APIs is not desired, and so
> the current policy [1] states that this should only be done where APIs are
> already being changed _anyway_, for example because a certain argument in
> the signature is being removed (which would make positional-only use of all
> following arguments invalid).
>
> In the context of the ongoing deprecation work, we (meaning mainly myself
> and @j-bowhay) have taken this to mean "introduce the keyword-only cut-off
> at the _natural_ point in the signature". Obviously there is some degree of
> subjectivity in that, but I consider it strictly worse than doing nothing
> to introduce the cut-off between positional-or-keyword and keyword-only at
> exactly the point where a given deprecated argument gets removed. To me it
> is a binary choice "whether to make a function keyword-only at its natural
> point or not".
>
> To illustrate this distinction, let's imagine a function
>
> def func(x, y, z, option_A=..., option_B=..., option_C=...): ...
>
> Let's assume that option_B has become obsolete, or gets renamed, then -
> strictly speaking - only option_C would need to become keyword-only, and
> not option_A. However, I would argue that the only reasonable point to make
> this function keyword only is as follows:
>
> def func(x, y, z, *, option_A=..., option_C=...): ...
>
> This results in a "net additional deprecation" of positional usage of
> option_A vis-à-vis the most minimal deprecation to keep things working as
> before that would look as follows:
>
> def func(x, y, z, option_A=..., *, option_C=...): ...
>
> This is worse IMO because it creates an inconsistency in how conceptually
> equivalent arguments are treated in the API (one can be used positionally,
> one cannot), and risks having to _again_ deprecate something in the
> function if anything about option_A changes in the future.
>
> Obviously, not all examples are as clear-cut, and more than that,
> sometimes a given deprecation only affects a subset of functions that
> belong to an interrelated family, where the API should be consistent
> overall. More context and discussion about this can be found in [2].
>
> For 1.12, we have taken all the functions being touched by deprecations
> and handled them accordingly (in accordance with their respective owners,
> in case the question about where to place the cut-off wasn't self-evident),
> which happened early in 1.12 development. Currently, the affected functions
> are (see also release notes):
> * linalg.{eigh, eigvalsh, pinv}
> * integrate.simpson
> * signal.{firls, firwin, firwin2, remez}
> * sparse.linalg.{bicg, bicgstab, cg, cgs, gcrotmk, gmres, lgmres, minres,
> qmr, tfqmr}
> * special.comb
> * stats.kendalltau
>
> It's worth noting that in some cases we delayed signature changes already
> announced for 1.12 or 1.13 to 1.14, in order to give people time to _also_
> react to the fact that they now need to change away from positional usage
> of some keyword arguments in those functions.
>
> There was some discussion in [2] about these additional deprecations (e.g.
> the option_A case in the example above), resp. whether we should revisit
> the choice about doing a wholesale change of our APIs like e.g.
> scikit-learn did with SLEP009 [3].
>
> I agreed to bring up this topic on the mailing list - please let us know
> your thoughts. The three broad choices (as far as I can tell) are:
> 1. wholesale change à la SLEP009 (this will need more discussion and a
> concrete plan of action IMO)
> 2. keep doing incremental changes as currently present in main (but
> changing over individual functions wholesale and not piecemeal w.r.t. their
> signature)
> 3. revert the change to keyword-only arguments for the above-mentioned
> functions
>
> Option 2. represents the status quo of both the current documented policy
> and the state of the repo on main.
>
> Best regards
> H.
>
> [1]
> https://docs.scipy.org/doc/scipy/dev/missing-bits.html#required-keyword-names
> [2] https://github.com/scipy/scipy/issues/18703
> [3] https://github.com/scikit-learn/scikit-learn/issues/15005
> _______________________________________________
> SciPy-Dev mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> https://mail.python.org/mailman3/lists/scipy-dev.python.org/
> Member address: [email protected]
>

_______________________________________________
SciPy-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/scipy-dev.python.org/
Member address: [email protected]