diff --git a/gsi/gsi_util/gsi_util/utils/file_utils.py b/gsi/gsi_util/gsi_util/utils/file_utils.py new file mode 100644 index 000000000..0ebe6af66 --- /dev/null +++ b/gsi/gsi_util/gsi_util/utils/file_utils.py @@ -0,0 +1,44 @@ +# Copyright 2017 - The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""File-related utilities.""" + +import contextlib +import os +import tempfile + + +@contextlib.contextmanager +def UnopenedTemporaryFile(**kwargs): + """Creates and returns a unopened temprary file path. + + This function is similar to tempfile.TemporaryFile, except that an + unopened file path is returend instead of a file-like object. + The file will be deleted when the context manager is closed. + + Args: + **kwargs: Any keyward arguments passed to tempfile.mkstemp (e.g., dir, + prefix and suffix). + + Returns: + An unopened temporary file path. + """ + fd, path = tempfile.mkstemp(**kwargs) + os.close(fd) + + try: + yield path + finally: + if os.path.exists(path): + os.unlink(path) diff --git a/gsi/gsi_util/gsi_util/utils/tests/file_utils_unittest.py b/gsi/gsi_util/gsi_util/utils/tests/file_utils_unittest.py new file mode 100755 index 000000000..cf1c0af03 --- /dev/null +++ b/gsi/gsi_util/gsi_util/utils/tests/file_utils_unittest.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# Copyright 2017 - The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unit test for gsi_util.utils.file_utils.""" + +import os +import tempfile +import unittest + +from gsi_util.utils import file_utils + + +class UnopenedTemporaryFileTest(unittest.TestCase): + """Unit test for UnopenedTemporaryFile.""" + + def test_normal(self): + with file_utils.UnopenedTemporaryFile( + prefix='prefix', suffix='suffix') as f: + self.assertTrue(os.path.exists(f)) + self.assertEqual(0, os.path.getsize(f)) + self.assertRegexpMatches(os.path.basename(f), r'prefix.+suffix') + self.assertEqual(tempfile.gettempdir(), os.path.dirname(f)) + self.assertFalse(os.path.exists(f)) + + def test_remove_before_exit(self): + with file_utils.UnopenedTemporaryFile() as f: + self.assertTrue(os.path.exists(f)) + os.unlink(f) + self.assertFalse(os.path.exists(f)) + self.assertFalse(os.path.exists(f)) + + def test_rename_before_exit(self): + with file_utils.UnopenedTemporaryFile() as f: + self.assertTrue(os.path.exists(f)) + new_name = f + '.new' + os.rename(f, new_name) + self.assertFalse(os.path.exists(f)) + self.assertFalse(os.path.exists(f)) + self.assertTrue(os.path.exists(new_name)) + os.unlink(new_name) + + +if __name__ == '__main__': + unittest.main()