Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH 1/2] FileCopier: capture exceptions
Date: Wed, 06 Nov 2019 08:08:41
Message-Id: 20191106080818.7972-2-zmedico@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH 0/2] emaint: clean up FileCopier exception logging by Zac Medico
1 Use ForkExecutor to capture exceptions instead of showing
2 a full traceback. FileCopier callers will now be responsible
3 for displaying relevant exception messages.
4
5 Bug: https://bugs.gentoo.org/699400
6 Signed-off-by: Zac Medico <zmedico@g.o>
7 ---
8 lib/portage/tests/util/test_file_copier.py | 44 ++++++++++++++++++++++
9 lib/portage/util/_async/FileCopier.py | 16 ++++----
10 2 files changed, 53 insertions(+), 7 deletions(-)
11 create mode 100644 lib/portage/tests/util/test_file_copier.py
12
13 diff --git a/lib/portage/tests/util/test_file_copier.py b/lib/portage/tests/util/test_file_copier.py
14 new file mode 100644
15 index 000000000..01dfba494
16 --- /dev/null
17 +++ b/lib/portage/tests/util/test_file_copier.py
18 @@ -0,0 +1,44 @@
19 +# Copyright 2019 Gentoo Authors
20 +# Distributed under the terms of the GNU General Public License v2
21 +
22 +import errno
23 +import os
24 +import shutil
25 +import tempfile
26 +
27 +from portage.tests import TestCase
28 +from portage.util._async.FileCopier import FileCopier
29 +from portage.util._eventloop.global_event_loop import global_event_loop
30 +
31 +
32 +class FileCopierTestCase(TestCase):
33 +
34 + def testFileCopier(self):
35 + loop = global_event_loop()
36 + tempdir = tempfile.mkdtemp()
37 + try:
38 +
39 + # regular successful copy
40 + src_path = os.path.join(tempdir, 'src')
41 + dest_path = os.path.join(tempdir, 'dest')
42 + content = b'foo'
43 + with open(src_path, 'wb') as f:
44 + f.write(content)
45 + copier = FileCopier(src_path=src_path, dest_path=dest_path, scheduler=loop)
46 + copier.start()
47 + loop.run_until_complete(copier.async_wait())
48 + self.assertEqual(copier.returncode, 0)
49 + copier.future.result()
50 + with open(dest_path, 'rb') as f:
51 + self.assertEqual(f.read(), content)
52 +
53 + # failure due to nonexistent src_path
54 + src_path = os.path.join(tempdir, 'does-not-exist')
55 + copier = FileCopier(src_path=src_path, dest_path=dest_path, scheduler=loop)
56 + copier.start()
57 + loop.run_until_complete(copier.async_wait())
58 + self.assertEqual(copier.returncode, 1)
59 + self.assertEqual(copier.future.exception().errno, errno.ENOENT)
60 + self.assertEqual(copier.future.exception().filename, src_path.encode('utf8'))
61 + finally:
62 + shutil.rmtree(tempdir)
63 diff --git a/lib/portage/util/_async/FileCopier.py b/lib/portage/util/_async/FileCopier.py
64 index 27e5ab4c0..3a0be4b63 100644
65 --- a/lib/portage/util/_async/FileCopier.py
66 +++ b/lib/portage/util/_async/FileCopier.py
67 @@ -1,17 +1,19 @@
68 -# Copyright 2013 Gentoo Foundation
69 +# Copyright 2013-2019 Gentoo Authors
70 # Distributed under the terms of the GNU General Public License v2
71
72 -from portage import os
73 from portage import shutil
74 -from portage.util._async.ForkProcess import ForkProcess
75 +from portage.util.futures import asyncio
76 +from portage.util.futures.executor.fork import ForkExecutor
77 +from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
78
79 -class FileCopier(ForkProcess):
80 +class FileCopier(AsyncTaskFuture):
81 """
82 Asynchronously copy a file.
83 """
84
85 __slots__ = ('src_path', 'dest_path')
86
87 - def _run(self):
88 - shutil.copy(self.src_path, self.dest_path)
89 - return os.EX_OK
90 + def _start(self):
91 + self.future = asyncio.ensure_future(self.scheduler.run_in_executor(ForkExecutor(loop=self.scheduler),
92 + shutil.copy, self.src_path, self.dest_path))
93 + super(FileCopier, self)._start()
94 --
95 2.21.0