commit:     7b8f57335c43054fe4008b7401d6ac2b3f710c1a
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Wed Nov  6 08:03:36 2019 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Wed Nov  6 20:05:27 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=7b8f5733

FileCopier: capture exceptions

Use ForkExecutor to capture exceptions instead of showing
a full traceback. FileCopier callers will now be responsible
for displaying relevant exception messages.

Bug: https://bugs.gentoo.org/699400
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 lib/portage/tests/util/test_file_copier.py | 44 ++++++++++++++++++++++++++++++
 lib/portage/util/_async/FileCopier.py      | 16 ++++++-----
 2 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/lib/portage/tests/util/test_file_copier.py 
b/lib/portage/tests/util/test_file_copier.py
new file mode 100644
index 000000000..01dfba494
--- /dev/null
+++ b/lib/portage/tests/util/test_file_copier.py
@@ -0,0 +1,44 @@
+# Copyright 2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import errno
+import os
+import shutil
+import tempfile
+
+from portage.tests import TestCase
+from portage.util._async.FileCopier import FileCopier
+from portage.util._eventloop.global_event_loop import global_event_loop
+
+
+class FileCopierTestCase(TestCase):
+
+       def testFileCopier(self):
+               loop = global_event_loop()
+               tempdir = tempfile.mkdtemp()
+               try:
+
+                       # regular successful copy
+                       src_path = os.path.join(tempdir, 'src')
+                       dest_path = os.path.join(tempdir, 'dest')
+                       content = b'foo'
+                       with open(src_path, 'wb') as f:
+                               f.write(content)
+                       copier = FileCopier(src_path=src_path, 
dest_path=dest_path, scheduler=loop)
+                       copier.start()
+                       loop.run_until_complete(copier.async_wait())
+                       self.assertEqual(copier.returncode, 0)
+                       copier.future.result()
+                       with open(dest_path, 'rb') as f:
+                               self.assertEqual(f.read(), content)
+
+                       # failure due to nonexistent src_path
+                       src_path = os.path.join(tempdir, 'does-not-exist')
+                       copier = FileCopier(src_path=src_path, 
dest_path=dest_path, scheduler=loop)
+                       copier.start()
+                       loop.run_until_complete(copier.async_wait())
+                       self.assertEqual(copier.returncode, 1)
+                       self.assertEqual(copier.future.exception().errno, 
errno.ENOENT)
+                       self.assertEqual(copier.future.exception().filename, 
src_path.encode('utf8'))
+               finally:
+                       shutil.rmtree(tempdir)

diff --git a/lib/portage/util/_async/FileCopier.py 
b/lib/portage/util/_async/FileCopier.py
index 27e5ab4c0..3a0be4b63 100644
--- a/lib/portage/util/_async/FileCopier.py
+++ b/lib/portage/util/_async/FileCopier.py
@@ -1,17 +1,19 @@
-# Copyright 2013 Gentoo Foundation
+# Copyright 2013-2019 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-from portage import os
 from portage import shutil
-from portage.util._async.ForkProcess import ForkProcess
+from portage.util.futures import asyncio
+from portage.util.futures.executor.fork import ForkExecutor
+from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
 
-class FileCopier(ForkProcess):
+class FileCopier(AsyncTaskFuture):
        """
        Asynchronously copy a file.
        """
 
        __slots__ = ('src_path', 'dest_path')
 
-       def _run(self):
-               shutil.copy(self.src_path, self.dest_path)
-               return os.EX_OK
+       def _start(self):
+               self.future = 
asyncio.ensure_future(self.scheduler.run_in_executor(ForkExecutor(loop=self.scheduler),
+                       shutil.copy, self.src_path, self.dest_path))
+               super(FileCopier, self)._start()

Reply via email to