Speaking of that, flask 2 was released in May 21. I can't really complain about some breaking changes every 2 years or so. That's almost like a linux distribution.
A change that brings new added value to users is a case where the change needs to be made, yes.
But the article's point is that the Flask changes don't seem to be doing that. They're not making breaking changes in order to introduce new features that add value for users. They're making breaking changes just because they feel like it, giving users no added value to compensate for the time and effort required to deal with the change. That's not respecting users.
At a first glance, you might think "but where is the shiny carrot that makes me upgrade?" But the thing is - we have dealt with major upgrades at work which broke many things, added many features, changed things in undocumented ways, turned the whole dependency inside out.
That's a horrible experience. You end up running after ghosts: Is it the breaking change, is it a change due to a feature, what is even going on!
Looking at it, Flask 3 seems to be a simple batch of several breaking changes on the roadmap for quite some time. This is good - they thought about batching these breaking changes together to have one big bad one, opposed to like 6 of them over the 2 years. And you can upgrade, and you can clearly see if one of the breaking changes causes harm to your application, without having to worry about hundreds of other changes within the same major release.
What I am asking is, why did there even need to be a breaking change in the case of the function discussed in the article? No functionality changed; the Python standard library function was identical to the former Flask function. So why couldn't the Python standard library function have been imported into the Flask namespace to replace the former Flask function? Why force every user to do that manually?
> giving users no added value to compensate for the time and effort required to deal with the change
... the users of free software. That didn't bother to find&replace one method in their plugin code.
Learn to read before throwing dictionary definitions at people
Providing method now-provided by standard libs is by definition unnecessary cruft. Nobody wants that in their codebase. They warned people for 2 years.
But apparently basic competence is too hard requirement in software ecosystems.
I don't think your sweeping claims here are justified. Importing the function from the standard library into the same namespace in your library where the function you previously implemented was is not "cruft". It's helping your users by not making a breaking change when you don't actually need to--no actual functionality changed.
> apparently basic competence is too hard requirement in software ecosystems
Your snark here is even less justified IMO than your sweeping claims above.
So they should tie the development to an extension that isn't in further development?
A better solution for a case like this would be to import the function from the Python standard library into the Flask namespace, so old code would still work. Then it wouldn't matter that Flask-Login is no longer actively maintained.
Also, as the article notes, Flask-Login is by no means the only Flask-using Python package that was broken by this change. Are all of those other packages no longer actively maintained? I doubt it.
Package maintenance also means to keep up with changes in the packages dependencies. If I don't do that, that's my problem, not the dependencies.
If I want to fix a certain version as my requirement, I can do so. Every major package system, including the ones used in Python, allow this. If I don't want that, then I need to keep my package maintained, and that means keeping an eye on what my dependencies do. That's part of package maintenance, simple as that.
There is no onus on the dependencies maintainers to care about whether I do my maintenance or not.
There's no "onus" on Flask to do anything they don't want to do. But if Flask forces every package that depends on them to fix a breaking change that they could have avoided with a one-line import statement, I would argue that is not very respectful of all those other package maintainers.
The reverse would be that every package that depends on flask forces it to make all future changes dependent on whether or not they break someones code. Which obviously isn't a sustainable model for software development.
> I would argue that is not very respectful of all those other package maintainers.
Define what is "respectful" then?
The flask team announces changes. They deprecate things. They use deprecation warnings. They use major versions correctly. They honor well established good practices in software development, to give package maintainers the opportunity to react to changes early.
Please, do explain: What else is required to meet whatever definition of "respectful" we are talking about here?
There’s also the option of releasing a package called something like flask2_compatibility that monkeypatches flask3 to work with flask2
Exactly.
Forever?
More net lines removed too.
But hey, it annoyed Man That Is Bad At Dependency Management and Wrote A Book About It so it must be bad!
Which, as the GP of my original post in this subthread argued, and I agree, is not respectful to your users. Importing the function from the Python standard library is a one-liner, hardly an arduous burden.
Open source is supposed to be a community. Forcing a breaking change like this on all their dependencies that they could have avoided with a one-line import statement is, IMO, not very good behavior as a community member.
No one is forcing a breaking change on anyone.
a) PIP usually retains past versions
b) A python package can specify it's dependencies, including their version, as hard requirements
c) virtualenvs exist
If a packages maintainer doesn't want to change his code to support some changes in some_dependency-v4.2, he can specify that the package requires some_dependency-v2.1 or whatever other existing version he is happy with.If he doesn't do that, and instead specifies only `some_dependency`, that signals to the package management software that the package works with the `@latest` version of that dependency. The onus to make sure that is, and continues to be, the case in code, is on the maintainer of the package, not the maintainer of the dependency, period.
And no, this is not "disrespectful". This doesn't go against any sense of community in FOSS. This is established practice in software development and package maintenance.
... would lead to even more outrage, because we tried that in the past. And the result were "rotting libraries", that became unmaintainable, incomprehensible, and riddled with hard to track and harder to fix bugs, because they had to drag along code that was often more than a decade old, kicking and screaming, just so libadbandonedsincebronzeage.so wouldn't have to issue an update.
So no, we should have breaking changes.
We should keep libraries vital and get rid of old code. We shouldn't drag along stuff just because we can. We have established procedures to deal with this, and with good reason.
- It's a significant piece of functionality.
- The change is trivial, not worth the cost of losing login.
In some instances Python deprecates something for six years, Flask six months.
That would break every single module that is compliant with flask 3.x and imports it with `import flask`. This simply isn't justified by the "benefit" of some old packages not having to change a single line of code.
Yes, maybe in hindsight it would have been beneficial to put the major version of some packages (flask is far from the only one) directly into the package name, as a workaround for pythons inability to deal with multiple versions of the same module under the same name in one environment. But python works as it does, `import flask` is how god-knows how many projects use it, so that's how the show runs, period.
If some package requires a certain version, it can pin that version in its `setup.py`. If a project requires a certain version it can pin that version in it's `requirements.txt`. If an environment requires a certain version, the admin can create a virtualenv.
Almost every practice in software development is a compromise that wouldn't be necessary if some decision in the past were different.
I think I agreed with you somewhere in this thread, that version-names (flask1, flask2, ...) are a better solution than major versions.
However, `flask` as an import name isn't going to go away. That is simply a reality and we have to work with it, because alot of projects rely on this. The same is true for tens of thousands of important software packages all over the OSS landscape.
So we can argue all day and then some over "what if"s...it won't change the status quo that exists, and in that state, semver is a good compromise that solves way more problems than it introduces.
So if you want any of the Flask 3.0 features you have to take the new Werkzeug, and see Flask-Login break.
If you're frequently updating to latest, you're on the bleeding edge; sometimes things will bleed more than others.
If you're stable, you might not have the latest and greatest all the time.
The attitude of expecting to always have the latest and greatest, but never have anything break, all while not paying for the effort, seems absurd to me.
Anyways, in my experience, if you routinely use the latest and greatest versions of dependencies, over time you find that you stop using dependencies that make this painful.
Anyways, I’m fine with accidental breakage. Deliberately choosing instability in the form of a major version release seems irresponsible for packages at the base of an entire ecosystem. (Absent some critical security issue that your users would have to address anyways as happened with log4j)
No they are not.
The flask team announces changes, deprecates things and uses major versions correctly. The major version change also doesn't happen frequently.
If a package absolutely requires a certain version, IT CAN SPECIFY AS MUCH in its requirements. If it doesn't, tough luck.