From ac3ee581a868df734f106c4fb853b06827eefd01 Mon Sep 17 00:00:00 2001 From: Bowgo Tsai Date: Mon, 18 Dec 2017 01:22:10 +0800 Subject: [PATCH] gsi_util: adding file-related utilities (file_utils) The first function is UnopenedTemporaryFile, which is similar to tempfile.TemporaryFile, except an unopened file path is returned instead of an opened file-like object (fd). Bug: 70253882 Test: make gsi_util Test: ./run_test.py Change-Id: I11de6976a31d8612cb873212b31c3f13a79b1b3e --- gsi/gsi_util/gsi_util/utils/file_utils.py | 44 ++++++++++++++ .../utils/tests/file_utils_unittest.py | 57 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 gsi/gsi_util/gsi_util/utils/file_utils.py create mode 100755 gsi/gsi_util/gsi_util/utils/tests/file_utils_unittest.py 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()