toga
toga copied to clipboard
Write a backwards-compatibility policy
What is the problem or limitation you are having?
Toga's release notes contain a backwards incompatibility section; however, that doesn't provide any guarantees about what is and isn't considered to be part of the public API, and what level of compatibility users can expect.
#2302 identified a minor backwards compatibility issue that stemmed from this ambiguity.
Describe the solution you'd like
A formal backwards compatibility policy, describing what is and what isn't part of the public API surface.
It should cover how stable and beta APIs can be identified, and how Toga will address issues as they arise. It should also highlight what Toga's version numbers "mean" - specifically:
- We're pre v1.0 so there will be sharp edges
- The closer we get to v1.0, the less sharp edges there should be
- Once we're "stable", we'll jump to calendar versioning.
As part of this change, we may also want to audit the APIs to enforce the use of keyword arguments in more locations. The issue in #2302 arose because an argument that should almost always be used as a positional argument had a change in name. Most widget arguments should be keyword arguments, rather than relying on position (with some possible exceptions like the label on Buttons and Labels); explicitly calling out that the name of positional arguments isn't guaranteed would make renaming positional argument a lot easier.
Describe alternatives you've considered
There isn't really an alternative - this is something we need to write.
Additional context
No response
Since Python 3.8 there is now a syntax for positional-only arguments.
That's what I was referring to by "enforcing keyword arguments" - sorry if that wasn't clear.
We're already using keyword-only arguments in a few places, but positional-only arguments are a more recent addition to the language which I don't think we've ever used before.
My apologies - I misread what you wrote.
I'm not sure if the API rigour of positional-only arguments is worth it. We certainly could use /
to enforce that positional arguments be positional, but I'm not sure that's actually much of a quality-of-developer-life improvement.
AIUI, the /
operator was primarily added to aid C-API developers, where arguments must be positional and in order. In that context, it makes sense to me that you would hard-enforce positional arguments; but for general Python, I'm not sure it's as useful. For example - toga.Button()
takes the button label as the first argument, but saying toga.Button(label="foo")
isn't a bad idea (and, given the discussion around #2293, might be required to make a markup language easy to implement).
My inclination would be to handle this at the policy level, backed up by the *
required keyword operator. We would document that the name of any argument occurring before an *
operator is not part of the API guarantee.
That said, I guess we could do both, and just be judicious around where we introduce the /
operator. We might introduce it for APIs like the append()
call that triggered this issue, but only use *
for widget constructors like toga.Button()
.
Is there any particular rule, of thumb or otherwise, about how long to deprecate things before removing them? If not, it would be a good thing to include in such a policy.
In our pre-1.0 phase, the rule of thumb is "at least one release"; which means a couple of months in practice. However, unless there's a compelling reason to finalise the deprecation, the deprecation warning/shim will likely remain in place until the next minor version bump.
Once we hit "1.0", we're be moving to calver, and we'll likely pick either a time-based interval, or nominate formal "long term support" versions between which there won't be any removals.