From 417531885ad25154bb7efce47cbf8443c91f3b51 Mon Sep 17 00:00:00 2001 From: Grada Date: Thu, 17 Sep 2026 17:24:48 +0800 Subject: [PATCH] Document wrap_file lifecycle and shared state --- newsfragments/3379.doc.rst | 1 + src/trio/_file_io.py | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 newsfragments/3379.doc.rst diff --git a/newsfragments/3379.doc.rst b/newsfragments/3379.doc.rst new file mode 100644 index 0000000000..28f0951f85 --- /dev/null +++ b/newsfragments/3379.doc.rst @@ -0,0 +1 @@ +Document how :func:`trio.wrap_file` shares ownership, close behavior, and state with the synchronous file object it wraps. diff --git a/src/trio/_file_io.py b/src/trio/_file_io.py index d9305ef4ff..383d47b26b 100644 --- a/src/trio/_file_io.py +++ b/src/trio/_file_io.py @@ -487,6 +487,16 @@ def wrap_file(file: FileT) -> AsyncIOWrapper[FileT]: """This wraps any file object in a wrapper that provides an asynchronous file object interface. + The wrapper and ``file`` refer to the same underlying object. Calling + :meth:`~trio.abc.AsyncResource.aclose` on the wrapper closes ``file`` as + well. Discarding the wrapper does not explicitly close ``file``; use + ``aclose`` or an async context manager when the wrapper owns its lifetime. + + You may continue to use ``file`` directly until it is closed, but both + references share the same file position and buffers. Since the wrapper + runs blocking operations in worker threads, simultaneous access through + both references is safe only when the underlying object is thread-safe. + Args: file: a :term:`file object`