RFC 010: Python-style tempfile standard library¶
- Status: Draft
- Created: 2024-12-11
- Author(s): Danny Meijer (@dannymeijer)
- Related: RFC 019 (runner testing), RFC 023 (stdlib namespacing and compiler handoff)
- Issue: #79
- RFC PR: —
- Written against: v0.1
- Shipped in: —
Summary¶
This RFC adds a Python-style std.tempfile module to the Incan standard library so programs can create scratch files, staging directories, and short-lived test fixtures that are cleaned up automatically unless explicitly persisted. The naming direction is settled: the public surface follows Python's tempfile family rather than abbreviated Rust-style type names.
Motivation¶
Temporary filesystem objects are a basic systems-programming need:
- tests need isolated scratch space;
- safe file updates often write to a temporary path and rename into place;
- data-processing pipelines frequently need short-lived intermediate files;
- cleanup should happen reliably even on early returns or errors.
Python solves this with tempfile, while Rust commonly uses the tempfile crate. Incan should provide an equally explicit story rather than forcing users into manual create -> remember path -> remember cleanup patterns.
Goals¶
- Provide first-class temporary files and directories with automatic cleanup.
- Use Python-style
tempfilenaming for the public surface. - Make persistence explicit so authors can keep a temp artifact intentionally.
- Support both default system temp locations and caller-provided parent directories.
- Keep the feature ergonomic for tests and ordinary application code.
Non-Goals¶
- Requiring an exact one-to-one clone of every Python
tempfilebehavior in the first version. - Context-manager syntax just for temporary resources.
- Defining every possible OS-specific temporary-file flag or security knob in the initial RFC.
- Replacing ordinary
Pathand filesystem APIs.
Guide-level explanation (how users think about it)¶
Named temporary files¶
from std.tempfile import NamedTemporaryFile
temp = NamedTemporaryFile()?
temp.write_text("some data")?
process_file(temp.path())
# file is deleted when `temp` goes out of scope unless it is persisted
Temporary directories¶
from std.tempfile import TemporaryDirectory
temp_dir = TemporaryDirectory()?
config = temp_dir.path() / "config.toml"
config.write_text(default_config)?
data_dir = temp_dir.path() / "data"
data_dir.mkdir()?
When the TemporaryDirectory value is dropped, the temporary directory tree is removed.
Keeping a result¶
from std.tempfile import NamedTemporaryFile
temp = NamedTemporaryFile(suffix=".json")?
temp.write_text(data)?
final_path = temp.persist()?
println(f"saved to {final_path}")
persist() converts a temporary resource into an ordinary path that will no longer be auto-deleted by the temp handle.
Reference-level explanation (precise rules)¶
Surface¶
The stdlib provides temporary filesystem types through std.tempfile. The naming direction is part of the contract:
NamedTemporaryFileTemporaryDirectoryTemporaryFileSpooledTemporaryFile
Not every member of that family must land with identical maturity on day one, but the public naming should align with that Python-style vocabulary.
Required capabilities¶
- Create a named temporary file in the system temp directory.
- Create a temporary directory in the system temp directory.
- Create either one under a caller-provided parent directory.
- Expose the realized
Pathwhere applicable. - Persist the resource so automatic cleanup no longer runs.
Cleanup semantics¶
- A non-persisted temporary file must be removed when its owning temp handle is dropped.
- A non-persisted temporary directory must remove its directory tree when its owning handle is dropped.
- Cleanup failures must surface as diagnostics or documented runtime errors; the language must not silently claim successful cleanup if the underlying filesystem rejected it.
Filesystem interaction¶
- Temporary resources are ordinary filesystem entries while they exist.
- Existing path-based APIs can consume
temp.path()without any special cases. - Persisting a resource yields a normal path that remains after the temp handle is gone.
Design details¶
Why Python-style naming¶
The naming question is settled in favor of Python's tempfile family. The public stdlib should optimize for familiarity at the Incan layer even if the backing implementation uses shorter or differently named runtime types underneath.
Why types instead of bare helper functions¶
Using dedicated temp-handle types keeps lifetime and cleanup tied together. A raw helper like create_temp_file() -> Path would push the burden back onto callers, who would then need to remember cleanup manually.
Interaction with existing features¶
- Testing benefits immediately because scratch files and directories are a common fixture pattern.
- Error handling composes naturally because cleanup should still happen when functions return early with
?. - The backend can map the feature to a Rust temp-resource implementation, but the language contract is about lifecycle and behavior, not about a specific Rust crate.
Compatibility / migration¶
This feature is additive. Existing Path and filesystem APIs keep their meaning.
Alternatives considered¶
- Manual create-and-delete helpers
-
Too easy to misuse, especially on error paths.
-
Context-manager-only surface
-
Incan does not need a new control-flow surface just to make temporary resources safe.
-
Abbreviated names such as
TempFile/TempDir - Shorter, but they give up the Python-aligned naming that this RFC explicitly wants for the Incan stdlib surface.
Drawbacks¶
- Temporary-resource cleanup semantics vary subtly across operating systems, especially around open handles.
- The Python-style surface may not map one-to-one onto the backing runtime's naming or exact semantics, so the docs must be explicit about where Incan intentionally differs.
- Users may overuse temp files where in-memory buffers would be simpler or faster.
Layers affected¶
- Stdlib: must define the temporary-resource surface and document cleanup semantics.
- Typechecker / docs: must treat temp resources as ordinary typed values with path-returning methods.
- Lowering / runtime: must preserve cleanup and persistence behavior across success and error paths.
- Testing / tooling: should make examples and diagnostics around temporary resources easy to discover.
Design Decisions¶
- Construction follows ordinary direct Incan construction rather than
.new()-style factory calls. - Python-style type names such as
NamedTemporaryFileandTemporaryDirectoryare part of the intended public surface. - Temporary resources remain path-usable filesystem entries while they exist; this RFC does not invent a separate non-
Pathinteraction model for them.
Unresolved questions¶
- Is
TemporaryFilewithout a durable path in scope for the initial version, or is path-addressable temporary storage the only guaranteed surface? - Should
SpooledTemporaryFilebe part of the initial RFC, or explicitly deferred? - What are the exact cross-platform guarantees when a temp file is still open elsewhere at drop time?