Skip to content

Commit 502eee7

Browse files
NamedTemporaryFile delete_on_close for python 3.10 and 3.11
1 parent fa1fcbf commit 502eee7

2 files changed

Lines changed: 39 additions & 8 deletions

File tree

‎src/buildstream/_loader/loader.py‎

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# Authors:
1515
# Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
1616

17+
import sys
1718
import tempfile
1819
from typing import Callable, Generator
1920
import os
@@ -264,7 +265,9 @@ def foreach_parent(parent):
264265
# modify_element_function (Callable[[CommentedMap],None]): A function to modify a given CommentedMap
265266
#
266267
@contextmanager
267-
def temporary_modified_element(self,target:str,modify_element_function:Callable[[CommentedMap],None]) -> Generator[None, None, None]:
268+
def temporary_modified_element(
269+
self, target: str, modify_element_function: Callable[[CommentedMap], None]
270+
) -> Generator[None, None, None]:
268271

269272
_, target_name, target_loader = self._parse_name(target, MappingNode.from_dict({}))
270273

@@ -273,16 +276,18 @@ def temporary_modified_element(self,target:str,modify_element_function:Callable[
273276

274277
modify_element_function(target_node)
275278

276-
with tempfile.NamedTemporaryFile(
279+
# FIXME When 3.12 hits EOL, replace this with tempfile.NamedTemporaryFile itself.
280+
with _legacy_named_temporary_file_delete_on_close(
277281
delete_on_close=False, prefix=f"{target_name.replace('/','_')}_temp", suffix=".bst"
278282
) as temp_target_file:
279283
_yaml.roundtrip_dump(target_node, temp_target_file)
280284
temp_target_file.close() # delete_on_close is false so this doesn't remove the file, but delete is True(default) so we delete the file when we leave the context manager.
281285
target_loader._set_fullpath_override(target_name, temp_target_file.name)
282286

283-
yield
284-
285-
target_loader._set_fullpath_override(target_name,None)
287+
try:
288+
yield
289+
finally:
290+
target_loader._set_fullpath_override(target_name, None)
286291

287292
###########################################
288293
# Private Methods #
@@ -1141,3 +1146,30 @@ def _clean_caches(self):
11411146

11421147
self._meta_elements = {}
11431148
self._elements = {}
1149+
1150+
1151+
# _legacy_named_temporary_file_delete_on_close()
1152+
#
1153+
# Helper for python 3.10 and 3.11 support
1154+
#
1155+
# NamedTemporaryFile attribute `delete_on_close=False` was not added until 3.12
1156+
#
1157+
# FIXME: When 3.11 hits end of life remove this function.
1158+
#
1159+
@contextmanager
1160+
def _legacy_named_temporary_file_delete_on_close(delete_on_close=False, prefix=None, suffix=None):
1161+
1162+
assert not delete_on_close, "Don't use this function unless you explicitly need delete_on_close set to false"
1163+
if sys.version_info >= (3, 12):
1164+
# Use the `delete_on_close` attribute if it's available
1165+
yield tempfile.NamedTemporaryFile(delete_on_close=delete_on_close, prefix=prefix, suffix=suffix)
1166+
else:
1167+
# Otherwise implement it for ourselves.
1168+
file = tempfile.NamedTemporaryFile(prefix=prefix, suffix=suffix, delete=False)
1169+
try:
1170+
yield file
1171+
finally:
1172+
try:
1173+
os.unlink(file.name)
1174+
except OSError:
1175+
pass

‎src/buildstream/_stream.py‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333

3434
from ._context import Context
35-
from .node import MappingNode
3635
from ._artifactelement import verify_artifact_ref, ArtifactElement
3736
from ._artifactproject import ArtifactProject
3837
from ._exceptions import StreamError, ImplError, BstError, ArtifactElementError, ArtifactError
@@ -282,9 +281,9 @@ def add_deps_to_element(target_node: CommentedMap):
282281
"Only BUILD and RUN scopes are supported",
283282
detail="Use the --build and --use-buildtree options to shell into a build tree",
284283
reason="only-build-run-supported",
285-
)
284+
)
286285

287-
with self._project.loader.temporary_modified_element(target,add_deps_to_element):
286+
with self._project.loader.temporary_modified_element(target, add_deps_to_element):
288287
self.build([target])
289288
return self.shell(target, scope, *args, **kwargs)
290289

0 commit comments

Comments
 (0)