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`