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

Discussion: Backward compatibility apocalypse #569

Open
akx opened this issue Apr 3, 2018 · 4 comments
Open

Discussion: Backward compatibility apocalypse #569

akx opened this issue Apr 3, 2018 · 4 comments

Comments

@akx
Copy link
Member

akx commented Apr 3, 2018

Hey all,

So as you may have noticed, development on Babel has been a teensy weensy slow as of late, with just minor bugfixes and so on happening. Partially it's due to personal stuff on my side, but there's also something I dread (and if you read the title, you may already be guessing what it'll be).

As you may know, Babel is actually a pretty popular package – according to the PyPI download stats that are available on Google BigQuery, various versions of Babel have been downloaded over 800,000 times in March 2018 (3,060,694 times since the start of 2018); that means, uh, 26 900 times a day, so 1 100 times per hour, 19 times per minute... so, uh, someone downloads Babel once every 3 seconds. 😅 That means we have quite a bit of responsibility in trying to make sure Babel is stable and usable – or at least that's how it feels to me.

As you may know, the Python community at large isn't that good at pinning their dependency versions, not even loosely. Granted, many Python packages don't follow any specific versioning structure like Semantic Versioning – not even Babel does at present – so that's probably part of the reason; secondly, I suppose it's just not been traditional to do so in the Python ecosystem.

There's another dataset on BigQuery that I used to dig deeper into Babel's unpinning situation, by analyzing requirements.txt and setup.py files that seem to be referring to Babel. I'm sure I missed a lot of repos and my methodology is flawed, but the bottom line is this: there are tons of packages that depend on "practically any version of Babel since 2013, I don't care" (Babel>=1.3) or "just give me that Babel juice" (Babel), or whatever. There are lots of fairly prominent projects in that list (unless they're false positives), such as Odoo, Invenio, WTForms, Sentry, some Openshift components...

By this point, you're probably seeing where I'm going with this.

You know what happens when we start, say, adhering to Semver (which has been in the cards if you ask me), bump up to 3.0 with some backwards-incompatible changes (such as some of those in master at present!) and publish a new version, and it starts getting a thousand downloads per hour? Lots and lots and lots of suddenly-broken CI builds (and more likely than not, production services), confused users around the world, that's what. 😖

Honestly I'm not sure what to do here. I don't think letting Babel stagnate (even more) is an option, but on the other hand I don't want the figurative pixel blood of the compatibility apocalypse described above on my hands.

Some avenues to resolving this problem that do come to mind are:

  • Just throw caution to the wind, start following semver at babel==3.0.0 and watch the world burn? Feels bad, but I'm sure the pins would start appearing pretty quickly.
  • Figure out which are the most popular projects depending on Babel and ask them to add a <3.0 pin to their Babel dependency. This will take some time (especially considering the downstream users of those projects will need to update too) and we'll probably end up missing some obvious project anyway, and this will not be very nice to the projects we can't directly reach out to.
  • "Internally fork" Babel to, say, babel2 (like jinja2, eh), publishing new versions under that name on PyPI (and to avoid conflicts within a requirement set, the Python package could maybe be called babel2 too) and start with semver there. This feels messy codebase-wise, but would be a very clean migration option.

Other ideas? What do you guys think? Pinging @python-babel/babel-developers.

@MythicManiac
Copy link

How about scanning the user's requirements and using a form of AGRESSIVE DEPRECATION if they're not pinned?

image

@erickwilder
Copy link
Contributor

I really like how Django deals with this problem and I think it's a good example of how to deal with this. If there are features and/or Python versions to be deprecated, then a patch version should be release adding warnings everywhere to start to annoy people (like me, I hate all Django deprecation warnings 😄 ) and this will give people the opportunity to start patching their code base to pin Babel to the version they want to use.

Another project that I like how they deal with this is React:

  • They also start with deprecation warnings in a patch release;
  • Then, they introduce aliases for soon to be deprecated functions with something weird like, UNSAFE_soonToBeDeprecatedFunction().
  • At a third release cycle, they remove the unaliased versions and if you really want to keep using the deprecated behavior, the UNSAFE_ prefix becomes also annoying just to look at it on your editor.
  • The final release cycle is basically dropping all prefixed functions and no deprecated code is available.

Finally, if you want to deprecate anything I also would recommend pointing people to some sort of migration guide/instructions in the context of the deprecation warning messages. Something I see on Homebrew whenever a package has some caveats after an upgrade. I don't use Babel for quite some time now but I would not like to see projects I worked in the past to burn in a leftpady way.

@etanol
Copy link
Contributor

etanol commented Apr 4, 2018

I personally don't believe in semantic versioning, the way I see it is that it has more failure stories than successes.

So, if I were to make a decision, I would take a more radical approach: split Babel into two separate packages. Babel currently provides a CLDR commodity as well as some improvements over gettext catalogs. I think those are differentiated enough to live in their own package. But I could be an interesting idea to spawn a cldr package that only deals with locale data and another gettext package to provide the translation catalog functionality.

This way there is no backwards compatibility to break and some things can be restarted.

But don't take this too seriously, given the irony of my comment; as I can no longer dedicate time to the project.

akx added a commit to akx/babel that referenced this issue May 7, 2018
This retains backwards compatibility (at least as far as the function's
signature is concerned) with users that are using NumberPattern.apply()
directly.

See: python-babel#550
See: python-babel#569
@lnielsen
Copy link

I'm just seen this old issue and that it mentions Invenio of which I'm the project lead.

From Invenio's point of view we are very grateful for the work going into maintaining Babel. It's one of the few packages that's been rock solid and didn't cause issues.

Perhaps, let me shed some light on why we're not pinning. Invenio is a fairly large project support several large services such as e.g. Zenodo. Being fairly large projects means we have lots of dependencies (about 230 packages), and we're seeing that many of our dependencies are shifting to a very aggressive versioning strategy that doesn't provide backward compatibility with deprecation warnings. We've tried several strategies and e.g. pining often fixes the problem in the short term, but in the long term the pins often means that we'll require package X in version >=1,<2, and then another of our dependencies will require the same package X with version >=3 thus leading to conflicting requirements. Either way, pinning or no-pinning leads to making it very hard with the Python ecosystem for a large project like ours to find the right alignment of all packages.

The packages that cause us the most issues when using aggressive strategies is core packages that many depends on. Therefore any effort going into making upgrading from major version to major version as easy as possible, and providing deprecation warnings is highly appreciated.

Again, thanks for all the effort spend on this package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants