GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-131927: Prevent emitting optimizer warnings twice in the REPL by tomasr8 · Pull Request #131993 · python/cpython Conversation
|
| incomplete_input=False, | ||
| ) | ||
| with warnings.catch_warnings(record=True) as all_warnings: | ||
| warnings.simplefilter("always") |
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Can we use "default" instead of "always", and just one context manager that spans both compiler calls? I think that will do the de-duplication, if I understand the doc correctly.
https://docs.python.org/3/library/warnings.html#the-warnings-filter
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
From what I can tell it does not work in this case. The syntax warning uses _PyErr_EmitSyntaxWarning which in turn calls PyErr_WarnExplicitObject and sets the registry (last argument) to NULL. The registry is used to dedup the warnings so when it's not used, all warnings are emitted regardless of the filter setting.
Here's an example that shows that:
import warnings def _compile(): compile('1 is 1', 'input', 'eval') with warnings.catch_warnings(): warnings.simplefilter("default") _compile() _compile()
This is probably not something we want to change, so doing a manual deduplication in pyrepl seems like the way to go. What do you think?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can pass a registry?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Maybe, though the registry would have to persist between separate invocations of compile. I'll check if there's a nice way to do that.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Ok so I spent some time going over the warning code and this is my understanding so far. The warning registries are dictionaries that are inserted as __warningregistry__ into the globals of a Python frame. Which frame this is, is controlled by the stack level. The registries are created on demand in setup_context:
Lines 911 to 916 in 37bc386
| static int | |
| setup_context(Py_ssize_t stack_level, | |
| PyTupleObject *skip_file_prefixes, | |
| PyObject **filename, int *lineno, | |
| PyObject **module, PyObject **registry) | |
| { |
This function is pretty complex and depends on other pieces in the warnings module so we cannot construct a registry manually in _PyErr_EmitSyntaxWarning (which is the one responsible for emitting warnings from ast_opt and currently sets the registry to NULL):
Lines 1909 to 1910 in 37bc386
| if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, filename, | |
| lineno, NULL, NULL) < 0) |
One thing we could do, though I don't know how desirable it is, is to add a new private function akin to PyErr_WarnExplicitObject which sets up the registry for us. Basically something like this:
int - PyErr_WarnExplicitObject(PyObject *category, PyObject *message, - PyObject *filename, int lineno, - PyObject *module, PyObject *registry) + _PyErr_WarnExplicitObjectRegistry(PyObject *category, PyObject *message, + PyObject *filename, int lineno) { PyObject *res; if (category == NULL) category = PyExc_RuntimeWarning; PyThreadState *tstate = get_current_tstate(); if (tstate == NULL) { return -1; } + PyObject *unused_filename, *module, *registry; + int unused_lineno; + + if (!setup_context(1, NULL, + &unused_filename, &unused_lineno, &module, ®istry)) + return -1; warnings_lock(tstate->interp); res = warn_explicit(tstate, category, message, filename, lineno, module, registry, NULL, NULL); warnings_unlock(tstate->interp); if (res == NULL) return -1; Py_DECREF(res); return 0; }
This seems to eliminate the duplicated syntax warnings in the REPL. What do you think about this approach?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I like this. Can _PyErr_WarnExplicitObjectRegistry just create a registry and call PyErr_WarnExplicitObject with it?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I think so, basically something like this:
int _PyErr_WarnExplicitObjectRegistry(PyObject *category, PyObject *message, PyObject *filename, int lineno) { PyObject *unused_filename, *module, *registry; int unused_lineno; int stack_level = 1; if (!setup_context(stack_level, NULL, &unused_filename, &unused_lineno, &module, ®istry)) return -1; int rc = PyErr_WarnExplicitObject(category, message, filename, lineno, module, registry); Py_DECREF(module); return rc; }
I'll update the PR to see if everything still works with this change.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
tests are failing. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Yep, I suspect it's because |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
LGTM. @serhiy-storchaka what do you think? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Ok it seems some other test modified the warning filters so I just needed to add I have another question though, regarding the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
| warnings.simplefilter("default") | ||
| console.runsource(code) | ||
|
|
||
| count = sum("'return' in a 'finally' block" in str(w.message) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
You can use .count() here.
"'return' in a 'finally' block" may be an error in future versions. Maybe use some more long living warnings, like assert(1, 'message') or 1 is 1? BTW, they are currently emitted 3 times, not 2.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
You can use .count() here.
Hmm I don't think I can, unless I want to match the warning message exactly?
"'return' in a 'finally' block" may be an error in future versions. Maybe use some more long living warnings, like assert(1, 'message') or 1 is 1?
I can't if I want to test the new repl. The PEP 765 warning is the only one emitted from the ast optimizer which is needed to trigger this behaviour in the repl. However this does change the behaviour of all warnings that use _PyErr_EmitSyntaxWarning so I also added tests to test_compile for it.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| """) | ||
|
|
||
| with warnings.catch_warnings(record=True) as caught: | ||
| warnings.simplefilter("default") |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
What happens if set it to "always"?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
It emits twice, I added a test to test_compile for it
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
LGTM. 👍
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I'll take care of the backport |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…the REPL (pythonGH-131993) (cherry picked from commit 3d08c8a) Co-authored-by: Tomas R. <[email protected]>
…the REPL (pythonGH-131993) (cherry picked from commit 3d08c8a) Co-authored-by: Tomas R. <[email protected]>
…the REPL (pythonGH-131993) (cherry picked from commit 3d08c8a) Co-authored-by: Tomas R. <[email protected]>
|
GH-132463 is a backport of this pull request to the 3.13 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
GH-132463 is a backport of this pull request to the 3.13 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
GH-132463 is a backport of this pull request to the 3.13 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Revert pythonGH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line. ast.parse() no longer emits syntax warnings for return/break/continue in finally (see PEP-765) -- they are only emitted during compilation.
Revert pythonGH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line. ast.parse() no longer emits syntax warnings for return/break/continue in finally (see PEP-765) -- they are only emitted during compilation.
Revert pythonGH-131993. Explicitly silence the duplicated PEP 765 syntax warnings in the REPL. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line. Co-authored-by: Tomas R. <[email protected]>
Revert pythonGH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line.
Revert pythonGH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line.
…ythonGH-139755) Revert pythonGH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line. (cherry picked from commit 279db6b) Co-authored-by: Serhiy Storchaka <[email protected]>
…odules (pythonGH-139755) Revert pythonGH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line. (cherry picked from commit 279db6b) Co-authored-by: Serhiy Storchaka <[email protected]>
…odules (pythonGH-139755) Revert pythonGH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line. Fix duplicated warnings in the "finally" block. (cherry picked from commit 279db6b) Co-authored-by: Serhiy Storchaka <[email protected]>
…GH-139755) (GH-140119) Revert GH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line. Fix duplicated warnings in the "finally" block. (cherry picked from commit 279db6b)
…GH-139755) (GH-140117) Revert GH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line. Fix duplicated warnings in the "finally" block. (cherry picked from commit 279db6b) Co-authored-by: Serhiy Storchaka <[email protected]> * Update 2025-10-06-10-03-37.gh-issue-139640.gY5oTb.rst --------- Co-authored-by: Serhiy Storchaka <[email protected]>
…ythonGH-139755) Revert pythonGH-131993. Fix swallowing some syntax warnings in different modules if they accidentally have the same message and are emitted from the same line.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.