From 03eeeb9d92e3821611931d9fa259811d95b646e8 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Thu, 16 Apr 2026 20:38:08 -0700 Subject: [PATCH] Docs: auto-close plugin now handles function-scoped fixtures Describe the updated scoping rule: instances from test bodies and function-scoped fixtures are closed automatically; session-, module-, class- and package-scoped fixtures are exempt. Refs #2692 --- docs/testing_plugins.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/testing_plugins.rst b/docs/testing_plugins.rst index 070ab6cf..b82a6e0c 100644 --- a/docs/testing_plugins.rst +++ b/docs/testing_plugins.rst @@ -87,9 +87,18 @@ If you are using ``await datasette.client.get()`` and similar methods then you d Automatic cleanup of Datasette instances ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Installing Datasette also installs a small pytest plugin that automatically calls :ref:`datasette_close` on any ``Datasette()`` instance constructed inside the body of a test function. This helps prevent large test suites from running out of file descriptors or leaking background threads from the hundreds of instances they may build up across a session. +Installing Datasette also installs a small pytest plugin that automatically calls :ref:`datasette_close` on any ``Datasette()`` instance constructed during a test. This helps prevent large test suites from running out of file descriptors or leaking background threads from the hundreds of instances they may build up across a session. -Instances created inside a pytest fixture are **not** closed by this plugin — pytest fixtures often create a single ``Datasette`` that is shared across many tests, and closing it automatically would break those tests. If you need a per-test instance and want to share it between multiple tests, create it inside a fixture rather than at the top level of a test function. +The plugin closes: + +- Instances created in the body of a test function. +- Instances created inside **function-scoped** pytest fixtures (the default scope — ``@pytest.fixture`` with no ``scope=`` argument, or ``scope="function"``). + +The plugin deliberately does **not** close: + +- Instances created inside higher-scoped fixtures (``scope="session"``, ``"module"``, ``"class"`` or ``"package"``). Those fixtures are typically designed to produce a single ``Datasette`` that is shared across many tests, and closing it automatically would break the tests that run after the first. + +In practice this means downstream projects rarely need to call ``ds.close()`` themselves — function-scoped fixtures and inline test code are both covered automatically, while long-lived shared fixtures keep working as before. If you need to opt out of this behavior, add the following to your ``pytest.ini`` (or equivalent):