test: turn unexpected warnings into errors - #2480
Merged
Merged
Conversation
The unit suite emitted 7 warnings. Rather than let them accumulate, set `filterwarnings = error` in pytest.ini so a stray warning fails the suite, and clear out the existing ones: * `test_renderer.py` used the deprecated `render.download` for three validation tests; they now use `render.download_button`. The deprecation itself is still covered by `test_render_download_is_deprecated`. * The two anonymous-panel `show_offcanvas()` tests legitimately trigger the accessibility warning (there is no way to give an anonymous panel a title), so they now assert it with `pytest.warns()`. The one remaining warning is not ours to fix: narwhals passes `cat.get_categories()` straight through to polars, where it is deprecated. Filed upstream as narwhals-dev/narwhals#3895 and ignored by message in pytest.ini until that lands.
A leaked `TemporaryDirectory` is finalized whenever the collector runs, so as an error it fails whichever test happens to be running at that moment (in CI, `test_theme_css_compiles_and_is_cached` on the oldest-deps job) rather than the test that leaked it. Under `error` the warning is raised inside the finalizer, becomes an unraisable exception, and pytest reports it as a `PytestUnraisableExceptionWarning`.
The 3.12/macOS job hit the same GC-attribution problem from a different angle: a `ValueError` from an abandoned `ExtendedTask._done_callback` coroutine, which pytest surfaces as `PytestUnraisableExceptionWarning` against whichever test was running at collection time (`test_otel_reactive_execution.py` here). Warnings raised from finalizers can't be attributed to the code at fault, so as errors they make the suite flaky rather than strict.
This was referenced Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The unit suite was emitting 7 warnings. This clears them and adds
filterwarnings = errortopytest.iniso new ones fail the suite instead ofscrolling past.
What was warning
render.downloaddeprecation (3 tests). Threetest_renderer.pyvalidation tests still decorated with the deprecated
render.download; theynow use
render.download_button. The deprecation itself is still covered bytest_render_download_is_deprecated.show_offcanvas()tests legitimately trigger the "should have anaria-label" warning —show_offcanvas()on bare content has no way to seta title — so they now assert it with
pytest.warns()rather than leak it.cat.get_categories()(2 tests). Not ours to fix — see below.The narwhals bug this turned up
Chasing the last warning found a real upstream problem, filed as
narwhals-dev/narwhals#3895.
serialize_dtype()inshiny/render/_data_frame_utils/_tbl_data.pycallscol.cat.get_categories()to send a categorical column's levels to the client.narwhals' polars cat namespace is a pure passthrough —
class PolarsSeriesCatNamespace(PolarsSeriesNamespace, PolarsCatNamespace): ..., anempty body dispatching via
__getattr__— so that lands verbatim on polars'own
Series.cat.get_categories(), deprecated as of polars 1.44 and documentedfor removal in polars 2.0. It isn't only test noise: any app rendering a
polars categorical column prints this
DeprecationWarningto its user'sconsole, and there's nothing the app author can do about it.
I prototyped a fix in
_tbl_data.pyand then threw it away, because everyversion of it was polars-specific, which defeats the point of going through
narwhals at all:
col.implementation.is_polars()to read the native series works,but puts backend-specific code in a module whose whole job is being
backend-agnostic.
col.unique(maintain_order=True)is backend-agnostic but wrong: pandascategoricals carry declared categories, including unused ones and in
declared order, and two existing test cases cover exactly that.
dtype.categories— what polars' own deprecation message recommends — raisesAttributeError: 'narwhals.stable.v1._dtypes.Enum' object has no attribute '_cached_categories', becausenarwhals/stable/v1/_dtypes.pyskipsNwEnum.__init__. We importnarwhals.stable.v1, so the documentedworkaround is unavailable to us. That's noted as a secondary item on the
issue.
So the upstream issue is the fix, with a scoped ignore in
pytest.iniholdingthe line until it lands. It carries a runnable reprex, its real output, a
suggested implementation for the polars backend (Enum →
pl.Series(dtype.categories),Categorical →
unique(maintain_order=True).drop_nulls().cast(pl.String), bothverified to return today's values), and an offer to send the PR.
Note on
filterwarnings = errorThe tradeoff: a new pandas/polars/starlette release that adds a
DeprecationWarningwill turn CI red on an unrelated PR. The fix is one ignoreline, and the red is usually a real signal — as the narwhals case shows, a
warning in our test output was a warning in users' app consoles. Every ignore
carries a comment so the list stays prunable.
CI turned up a second, more awkward class, which the later commits here ignore:
ResourceWarningfrom a leakedTemporaryDirectory(failed the oldest-depsjob, blamed on
test_theme_css_compiles_and_is_cached).PytestUnraisableExceptionWarningwrappingValueError: <Token ...> was created in a different Contextfrom an abandonedExtendedTask._done_callbackcoroutine (failed 3.12/macOS, blamed ontest_otel_reactive_execution.py).Both are raised from finalizers at GC time, so they fail whichever test happens
to be running when the collector fires rather than the test at fault — flaky
rather than strict, so they're ignored as a class. Warnings raised on a real
call stack are still fatal, which is where the value is.
The
ExtendedTaskone looks like a genuine latent bug (a context token resetfrom the wrong context during teardown), currently invisible because it only
happens in an abandoned coroutine. Out of scope here; worth its own issue.
No library code changes; test config and tests only.