Live data from Hacker News

Deprecations via warnings don't work for Python libraries

sethmlarson.dev

51–60 of 93 posts

Re: Deprecations via warnings don't work for Python libraries

#51

Wait, does urlib not use semvar? Don't remove APIs on minor releases people. A major release doesn't have to be a problem or a major redesign, you can do major release 400 for all I care, just don't break things on minor releases. Lots of things not using semvar that I always just assumed did.

This, I think, is the crux of the matter. As an example, I always knew urllib3 as one of the foundational packages that Requests uses. And I was curious, what versions of urllib3 does Requests pull in? Well, according to https://github.com/psf/requests/blob/main/setup.cfg , it's this: urllib3>=1.21.1, That is exactly the kind of dependency specification I would expect to see for a package that is using semver: The cu…

I would almost expect the 3 in urllib3 to be the major version and if something needed to break it would become urllib4. Which, I know, is terribly naive of me. But that is how psycopg does it.

Re: Deprecations via warnings don't work for Python libraries

#52

I think they are misreading the situation. The devil is in the details. It seems `getHeaders` v. `headers` is non-security, non-performance related issue. Why people should spend time fixing these?

Even if getHeaders() has security/performance concerns, the better solution is to make it an alias to the newer headers.get() in this case. Keeping the old API is a small hassle to a handful of developers but breaking existing code puts a much bigger burden on a lot more users.

Re: Deprecations via warnings don't work for Python libraries

#53

# Deprecated APIs resp.getheader("Content-Length") # Recommended APIs resp.headers.get("Content-Length") Why inflict this change on tens of millions of users? It's such a nonsense tiny busywork change. Let sleeping dogs lie.

This is exactly the sort of breaking change that I really struggle to see the value of — maintaining the deprecated method seems incredibly unlikely to be a notable maintenance burden when it is literally just:

    @deprecated("Use response.headers.get(name) instead")
    def getheader(self, name):
        return self.headers.get(name)
Like sure — deprecate it, which might have _some_ downstream cost, rather than having two non-deprecated ways to do the same thing, just to make it clear which one people should be using; but removing it has a much more significant cost on every downstream user, and the cost of maintenance of the old API seems like it should be almost nothing.

(I also don't hate the thought of having a `DeprecationWarning` subclass like `IndefiniteDeprecationWarning` to make it clear that there's no plan to remove the deprecated function, which can thus be ignored/be non-fatal in CI etc.)

Re: Deprecations via warnings don't work for Python libraries

#54

I think they are misreading the situation. The devil is in the details. It seems `getHeaders` v. `headers` is non-security, non-performance related issue. Why people should spend time fixing these?

Even if getHeaders() has security/performance concerns, the better solution is to make it an alias to the newer headers.get() in this case. Keeping the old API is a small hassle to a handful of developers but breaking existing code puts a much bigger burden on a lot more users.

Ya, why not just alias old api calls to the new if implementation details changed?

Re: Deprecations via warnings don't work for Python libraries

#55
post #41

Earlier quoted context omitted.

What does a good developer do when working in a codebase with hundreds of warnings? Or are you only considering a certain warnings?

Why does your codebase generate hundreds of warnings, given that every time one initially appeared, you should have stamped it out (or specifically marked that one warning to be ignored)? Start with one line of code that doesn't generate a warning. Add a second line of code that doesn't generate a warning...

Because most people are working at Failure/Feature factories where they might work on something and at last minute, they find out something is now warning. If they work on fixing it, the PM will screaming about time slippage and be like "I want you to work on X, not Y which can wait".

2 Years later, you have hundreds of warning.

Re: Deprecations via warnings don't work for Python libraries

#56

Wait, does urlib not use semvar? Don't remove APIs on minor releases people. A major release doesn't have to be a problem or a major redesign, you can do major release 400 for all I care, just don't break things on minor releases. Lots of things not using semvar that I always just assumed did.

semver is funny because it gives the illusion of working but does not work at all

Glory to 0ver: https://0ver.org/

Re: Deprecations via warnings don't work for Python libraries

#57
Deprecations don't work. Don't deprecate stuff without a really really good reason. The new API being cleaner is not a good reason. There are very few good reasons.

If you deprecate something in a popular library, you're forcing millions of people to do work. Waste time that could be used for something better, possibly at a time of your choice, not theirs. It was emitting warnings for 3 years... so you think everyone should have to rewrite their software every 3 years?

Especially for something like this. Only document it in a footnote, mark it as deprecated, etc - but don't remove the alias.

Don't break stuff, unless, to quote a famous work, you think your users are scum. Do you think your users are scum? Why do you hate your users?

Re: Deprecations via warnings don't work for Python libraries

#58
post #2

Deprecations via warnings don't reliably work anywhere, in general. If you are a good developer, you'll have extensive unit test coverage and CI. You never see the unit test output (unless they fail) - so warnings go unnoticed. If you are a bad developer, you have no idea what you are doing and you ignore all warnings unless program crashes.

You can turn warnings into errors with the `-Werror` option. I personally use that in CI runs, along with the `-X dev` option to enable additional runtime checks. Though that wont solve the author's problem, since most Python devs don't use either of those options

In PHP I don’t think there is a native way to convert E_DEPRECATED into E_ERROR, but the most common testing framework has a quick way of doing the same.

https://docs.phpunit.de/en/12.5/configuration.html#the-failo...

Re: Deprecations via warnings don't work for Python libraries

#59
post #2

Deprecations via warnings don't reliably work anywhere, in general. If you are a good developer, you'll have extensive unit test coverage and CI. You never see the unit test output (unless they fail) - so warnings go unnoticed. If you are a bad developer, you have no idea what you are doing and you ignore all warnings unless program crashes.

Why is it that CI tools don't make warnings visible? Why are they ignored by default in the first place? Seems like that should be a rather high priority.

> Why is it that CI tools don't make warnings visible?

A developer setting up CI decides to start an ubuntu 24.04 container and run 'apt-get install npm'

This produces 3,600 lines of logging (5.4 log lines per package, 668 packages) and 22 warnings (all warnings about man page creation being skipped)

Then they decide "Nobody's going to read all that, and the large volume might bury important information. I think I'll hide console output for processes that don't fail."

Now your CI doesn't show warnings.

Re: Deprecations via warnings don't work for Python libraries

#60

Earlier quoted context omitted.

It depends on how we define "worse." A breaking change causes a full-stop to a service. An intentional slowdown lets the service continue to operate at degraded performance. I concur that it's less clear for debugging purposes (although any reasonable debugging infrastructure should allow you to break and see what function you're in when the program hangs; definitely not as clear as the program crashing because the c…

A breaking change in a dependency doesn’t cause a full-stop to a service at all. The old version continues to work. Making subtly harmful changes so that new broken versions sneak in is just a bad idea and totally unnecessary.

> A breaking change in a dependency doesn’t cause a full-stop to a service at all

From the article:

"We still received feedback from users that this removal was unexpected and was breaking dependent libraries."

I think we may be assuming different floors on service maintainer competency; with so many users pulling in dependencies across an arbitrarily-wide version window with no testing, such changes do break services.

Post reply on HN