$ python -Werror -Wdefault::SyntaxWarning -c "1 is 1; import warnings as w; w.warn('?')"
<string>:1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="?
Traceback (most recent call last):
File "<string>", line 1, in <module>
1 is 1; import warnings as w; w.warn('?')
~~~~~~^^^^^
UserWarning: ?
A very reasonable request. Perhaps we can redirect this discussion towards figuring out what is missing in warnings filtering.
It sounds like you want warnings restricted to only those things that can only be reliably diagnosed at runtime, and therefore cannot be caught by static checkers. So, basically, no SyntaxWarnings of any kind.
If that is how you see it, then disabling all SyntaxWarning’s with -Wignore::SyntaxWarning should work for you. Or what am I missing?
It’s the worst option on that list, and I regret including it after thinking about it more. It would still require either running a linter on your entire dependency tree or parsing stdout for all of the actually useful syntax warnings. Without a guarantee that warnings other than syntax warnings won’t become unfilterable in the future, it also doesn’t address what this thread is actually about: the future
I don’t actually want to disable all syntax warnings. As I mentioned,allof the prior syntax warnings have always caught real problems reliably.
This also isn’t just about what happened with 765. If it was, the damage is already done, and libraries already had to make changes to unblock CI pipelines for people because of the lack of proper filtering. What happens if in 3.15 someone makes an unfilterable runtime warning for some reason?
I’m not asking for a solution for 765 and my use case, This thread is about having clear and dependable expectations for the ongoing future of warnings and either preventing a similar situation from reoccurring, or making it clear that those who care about this aren’t going to find support for it from the language, and need to transition their tooling.
So if I’m understanding you correctly, you don’t mind if your application produces warnings in production. But you want to limit which warnings it produces to be only those which you consider to be false positives (i.e. warning about something that isn’t actually a problem), after having reviewed them as part of your CI process.
Is that a correct statement of your position?
I ask because my experience of using “warnings as errors” is that I’m developing something where any sort of unhandled message from the runtime is bad, and therefore it doesn’t really matter whether I agree with a warning or not, I need to find a way to avoid triggering it[1]. So I’m curious about how your situation differs from mine.
Which may just mean disabling the warning in the application code - but this obviously isn’t possible for syntax warnings. ↩︎
Close to that. Depending on how you define “actually a problem”, maybe exactly that. I do view some things as problems surfaced by warnings that don’t require blocking CI, and can be filtered on a temporary basis (judgement of severity and impact).
Maybe it would help if I detailed some facts about the use I care about
In at least one CI job per python version we support, we run with -Werror, in production we don’t.
These CI jobs block internal library PRs and production application version upgrades.
We have an internal wheelhouse, so but we do not want to maintain patches for most external dependencies, as this would complicate usability of SBOMs (we would prefer to PR upstream or change code we maintain when possible).
-Werror is not in use when building external libraries for our internal wheelhouse: if an error can’t surface in our code paths, it is a tree with no one to hear it fall.
We utilize warning filters in top level entrypoints prior to the majority of imports. I know in some cases we have to import sys and os prior to warnings, and we always have to import warnings to install a warning filter.
These entrypoints are not special cased for CI, and are also in use in production.
While not all filter entries are permanent, each gets a justification and is tracked. Some are intentionally temporary.
We are conservative with code changes, up until 765, code other than filter entries hasn’t be changed if it was working as intended..
1 & 2 are more bug fixing and resolution of limitations in existing features than anything that needs a PEP.
For 3 & 4, is there any compelling reason for not making a pitch for SyntaxWarning itself being the “lint-like” error category that is excluded from -Werror by default?
Alternatively, rather than making the distinction based on the warning category, we could instead introduce a separate “compilation warnings filter” which takes precedence over the main runtime warnings filter when the AST compilation and code generation specifically is emitting a warning.
The default state of the compilation warnings filter could then be set to default::SyntaxWarning (giving the effect that even with -Werror set, syntax warnings wouldn’t be turned into runtime exceptions unless the compilation warnings filter was also overridden)
The way I see it, the main thing we’d be aiming to achieve would be to make it so that running implicitly compiled code under -Werror would become much closer in behaviour to running the same code from a precompiled code cache (the above proposal wouldn’t make it completely identical, though, as the only way to make it identical is to set the warning filter to -Werror -Wignore::SyntaxWarning and hence turn off syntax warnings completely)
Hmm, for backwards compatibility reasons, a better default compilation warning filter (in order of precedence) might look like the default runtime warning filter settings for DeprecationWarning:
A compilation warning filter along those lines would also cover making the runtime handling of precompiled and implicitly compiled third party packages consistent (their syntax warnings get ignored either way)
For me, it’s that python seems to be going in a new direction in terms of what it is willing to warn for. I don’t view any of the other syntax warnings as even possible to be spurious. The newest addition is always spurious for those who actually know what the language does or even give a brief thought to “functions can’t return or raise exiting the function more than once, what’s going to happen when I’ve told it to return again in finally?”. The steering council made it clear that they have no intent to remove this syntax from the language, so it also doesn’t fit into warn prior to deprecation (though if it did, syntax warning would still be the wrong warning type)
If some people want the interpreter to start acting on things with less confidence, I’d want that set of things handled differently, and it certainly shouldn’t feel worse than prior existing tools. Linters already exist; why are we replicating their work in a less expressive manner?
I’m a bit more cynical here. These issues were raised when it was pointed out that those existing bugs and limitations would cause 765 to be more disruptive, and a PR was available to remedy the worst of it in time for inclusion 3.14. Instead, people were told their existing use cases being disrupted wasn’t a big deal. The technical answer is clearly that we improve the situation, but there’s something else here beyond a technical issue.
I guess I should ask if you really need to avoid triggering it, or is it fine if there was a reliable way for applications to supress such warnings in such use cases?
I have a feeling that these posts indicate the best way forward is to stop using warnings as errors, but give an option likely to help the most people who have a current reason to use warnings as errors. The only problem with that would be the timescale on being able to switch, but as the current situation already has some holes for existing users, maybe it’s okay if those advanced cases need to branch on python version for 2-5 years to get them to a better solution.
If we made the warnings module more configurable on how they were emitted:
If it were possible redirect warnings to any file or stream (including use of None saying done send them anywhere, rather than requiring use of /dev/null)
Choose whether or not to emit as human readable or machine parseable[1]
That such redirection would also capture warnings accumulated while parsing
Suppressing all warnings from being emitted in production assists @pf_moore 's case
Giving a structured file that can be parsed gives a more powerful option to CI pipelines than just promoting any warning to an error.
And it being something applications that have more advanced cases would set, leaves the warnings visible by default, which was something people in favor of 765 clearly value.
My own personal use case is closer to that which @Liz expressed, but we’re a bit more willing to maintain internal patches for libraries at my work. This would cover my use better than trying to mandate behavior about what warnings could be added in the future.
ad 3 and 4. IMHO, not worth the effort and the creation of extra types/categories – once we agree on 1 and 2.
I understand the decision by SC in a slightly different way: that the syntax is considered misfeature and if not certain backward-compatibility issues it should be removed from the language. SyntaxWarning was a compromise (necessary because of those backward-compatibility issues).
IMHO the real problem is the inability to filter SyntaxWarnings individually. Once it is fixed, other PEP-765-related problems seem to have sensible solutions for all interested parties.
In hindsight, I agree it would have been better if the fix had become a prerequisite for implementing the PEP.
If precompilation didn’t silence all syntax warnings, I strongly doubt the SC would have accepted PEP 765 without requiring that the syntax warning location reporting issues be fixed first (and I would have agreed with them imposing that requirement).
So the “something else” (as I see it) is folks not considering precompilation (without -Werror) an acceptable mechanism for silencing syntax warnings (including when running with -Werror).
That just circles back around to the issue that people actually wanted to get the warnings, but then selectively silence any that weren’t an issue. Silencing all syntax warnings still subverts part of why people were using it without actually providing an alternative.
It also turned caching into no longer being transparent to users. It’s a behavioral change, rather than just a performance tradeoff, and didn’t work as the authors expected for default visibility because uv isn’t caching by default, nor is there a standard that says they should.
The caching bit is actually the part that’s probably most agreed upon as not working as presented. Others chimed in on that detail as well, and these are among the most agreed with posts about the actual behavior of the pep in the entire thread, by the measure discourse gives, for whatever that’s worth.
Long story short, no, I don’t count that as fufilling the ability to filter warnings, the pep doesn’t present it that way either. the pep never even made that argument, and prior to people coming in with actual issues once implemented, it was only presented in discussion of the pep as a way to claim only the library authors would see it by default, without taking the full ecosystem into account.
To whatever extent is possible, I’d appreciate if people would stop writing other people’s existing processes off and focus on the future.
I’m open to changing my processes here if something better comes along, but I don’t want this to be something that is recurring with less than a single version’s notice.
I think the choice to rely on the cache was a miss (), but it wasn’t the critical failure. The critical failure was a combination of a preexisting issue with warning filtering, and that preexisting issue not being addressed and written off as unimportant, even when a new interaction was significantly changing how it surfaced, and even with a fix available.
I’m trying to figure out what’s needed to have something I can rely upon here going forward, but I also want to prevent the general case from happening again too.
That requires more than technical change, it requires discussion about processes and how to ensure other issues that come to light after a change is implemented are addressed when possible.
The reason I bring up the caching issue is because that (in combination with linters being able to find syntax errors without running the code) is the workaround that was seen as making the syntax warning more acceptable than the previous syntax error proposal, despite the issues with syntax warning filtering.
Folks have since made it clear they’re not happy with that decision, and quite reasonably requested that those filtering issues be resolved. The PSF (by way of Serhiy’s time as a developer in residence) are specifically investing in solving those technical problems.
That’s why I don’t see a big process change being needed for that part of things - it was a judgement call about the kinds of changes affected users would need to make, and the combined population of “uses uv”, “isn’t willing to turn on precompilation at installation time”, and “has a dependency that provokes this warning” turned out to be both larger and more concerned about the new warning than we expected.
I do think there are some interesting design questions around how we handle compile time warnings in general, though, which is why I highlighted those as the area where I believe a PEP could be most helpful.
Some concrete ideas for a compile time warnings filter design:
Python API: new boolean compiling keyword argument to warnings.warn and the filter adjustment APIs
C API: new public API function to emit compile time warnings. TBD for other C APIs.
CLI option: new trailing @compiling phase specifier to indicate when a filter should be added to the compile time filter instead of the default runtime filter (for example, -Wignore@compiling). The part before the @ may contain multiple : separated subfields as usual.
This design allows compile time syntax warnings and compile time deprecation warnings to optionally be handled differently from each other, as well as allowing compile time deprecations to potentially be handled differently from runtime deprecations.
The compile time filter would be applied in addition to the regular warnings filter, so it would only need to be adjusted when compile time specific filtering was desired.
The default compile time filtering would hide library level syntax warnings, while leaving deprecation warnings and top level syntax warnings visible:
With that approach, turning compile time syntax warnings into runtime errors would require specifying -Werror@compiling in addition to -Werror (and avoiding precompilation)
I think this turns the runtime vs compile time distinction into a part of the public API of the language in an undesirable way. Reasoning about this should be an exotic case, so it doesn’t belong in the filter DSL.
I prefer that we close the hole around SyntaxWarning being unfilterable without making significant new API decisions. We can then take more time to debate
new warning classes or categories
some opt-in way of making SyntaxWarning appear at runtime (so that you can eliminate the asymmetry)
additional filter mechanisms
etc
There’s agreement in this thread that the warning escaping filters is a real, practical issue. I’d like to focus on the points of agreement rather than points of disagreement – I think we have enough of both to get somewhere positive, but only if we try!
This is not the usergroup that is complaining in this thread.
The actual usergroup that is complaining:
has an existing, perfectly functioning and well tested usecase of return-in-finally
runs their own code in their own CI with Werror
doesn’t want to change their own working code because of a spurious warning by CPython
For this usergroup there just isn’t a viable workaround. Precompiling your own code is not a sensible solution since it suppress all SyntaxWarnings.
This usergroup was evidently overlooked when the SC accepted the PEP. Which is fine, mistakes happen, tradeoffs are made.
But this repeated gaslighting that this situation was actually considered and the users just aren’t willing to use the perfectly functioning workaround is honestly rude.
Hmm, true, -e installs don’t precompile (for any installer), and there are projects that aren’t installed as Python packages at all, but are still tested with -Werror.
OK, that makes the objections much more comprehensible to me, thanks.
Edit: I realised after posting that I’m still confused (since this “checking your own code” scenario is describing the case where linting makes compile time syntax warnings redundant), but as @Liz already pointed out, we don’t need another discussion delving into how we got here, so I’ll refrain from any further exploration of that question in this thread.
This is the thing that I think was the key mistake in deciding that fixing the filtering problems wasn’t critical. By taking the view that precompiling is the recommended approach, we are effectively saying that for some users, the “correct” way of testing their Python code is with an edit-compile-run cycle, which is fundamentally at odds with how people think of (and develop) Python applications.
In the abstract sense, the existence of a compiler and a bytecode interpreter and all such machinery is an implementation detail that shouldn’t change how we think about our code.
At this point, though, this is a digression from the key question in this thread, which is how we ensure that future syntax warnings can be effectively managed under -Werror. So I think we should probably focus on that question, and work out what we need to do now. It may be that what @storchaka is doing to fix the technical issues is enough, but there seem to be enough people unhappy with the fact that this problem wasn’t identified (or wasn’t considered sufficiently bad) for the return-in-finally warning, that there’s also a “people” issue and we need to come to a better understanding of how the community, core devs, and SC should view workflows based on -Werror when evaluating future proposals.
Part of why I used “to the extent possible” when re-expressing wanting to move on from 765 is that to some extent, it may not be possible to completely move on from what happened without discussion of why it wasn’t enough. There seems to be a disconnect in understanding of existing use cases, and that may significantly contribute to why things played out this way. It’s hard to design to keep existing use cases working if those uses cases aren’t well understood.
This is a case where the strictly linear discussion flow of platforms like discourse is really a limitation, because a tangent within this thread on simply getting people on the same page about the various ways people want to use warnings is relevant, yet not the main focus.
I’d also like to take a moment to reiterate that while I have my frustrations with what happened, I don’t think there’s really any single issue or person at fault or to place blame with here. This one’s a complicated intersection of problems both technical and social, and a lot of natural reactions happened within non-ideal circumstances.
It’s been brought up by many people that the tone of some of these discussions has felt acidic. I haven’t felt that way about most of it, even while feeling like some of my concerns were brushed off as unimportant because I understand that the various perspectives people have are different enough to make it hard to weigh impacts, I’ve tried to argue for my use case, but yet another issue (in how much I can disclose about work) limits some of what I can even effectively convey.