Skip to content

Commit 239d843

Browse files
Create debug file atomically instead of using tempfile.mktemp
tempfile.mktemp is deprecated since Python 2.3: it only returns a name, leaving a window where another process can create the file first. Use NamedTemporaryFile(delete=False) so the file is created atomically with the same prefix/suffix naming. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent b9c62e1 commit 239d843

2 files changed

Lines changed: 32 additions & 3 deletions

File tree

collagraph/sfc/__init__.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,15 @@ def _write_debug_file(tree, path): # pragma: no cover
101101

102102
# Create a meaningful filename based on the source .cgx file
103103
source_name = Path(path).stem if path else "template"
104-
debug_file = Path(tempfile.mktemp(prefix=f"cgx_{source_name}_", suffix=".py"))
105-
debug_file.write_text(formatted, encoding="utf-8")
104+
with tempfile.NamedTemporaryFile(
105+
mode="w",
106+
encoding="utf-8",
107+
prefix=f"cgx_{source_name}_",
108+
suffix=".py",
109+
delete=False,
110+
) as fh:
111+
fh.write(formatted)
112+
debug_file = Path(fh.name)
106113
logger.debug("CGX debug file written to: %s", debug_file)
107114

108115
try:

tests/test_sfc_debug.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
"""Tests for the CGX_DEBUG support code paths."""
22

3+
import tempfile
4+
35
import collagraph.sfc
4-
from collagraph.sfc.compiler import format_code
6+
from collagraph.sfc import _write_debug_file
7+
from collagraph.sfc.compiler import construct_ast, format_code
58

69
SIMPLE_TEMPLATE = """
710
<item />
@@ -42,3 +45,22 @@ def test_load_falls_back_when_debug_source_is_broken(monkeypatch, tmp_path):
4245

4346
component, _ = collagraph.sfc.load_from_string(SIMPLE_TEMPLATE)
4447
assert component.__name__ == "Item"
48+
49+
50+
def test_write_debug_file_avoids_mktemp(monkeypatch):
51+
# tempfile.mktemp is deprecated and racy (the file is created
52+
# after the name is picked); the debug file should be created
53+
# atomically instead.
54+
def forbidden(*args, **kwargs):
55+
raise AssertionError("tempfile.mktemp is deprecated and insecure")
56+
57+
monkeypatch.setattr(tempfile, "mktemp", forbidden)
58+
59+
tree, _ = construct_ast(path="example.cgx", template=SIMPLE_TEMPLATE)
60+
debug_file, source = _write_debug_file(tree, "example.cgx")
61+
62+
assert debug_file is not None
63+
assert debug_file.name.startswith("cgx_example_")
64+
assert debug_file.suffix == ".py"
65+
assert debug_file.read_text(encoding="utf-8") == source
66+
debug_file.unlink()

0 commit comments

Comments
 (0)