From 36dc58bf3501990d9ffa12f2bccfdd83b889c140 Mon Sep 17 00:00:00 2001 From: Nils Philippsen Date: Aug 20 2018 10:54:05 +0000 Subject: [PATCH 1/3] catch errno == ENOENT if mbs-manager is missing Sometimes a missing mbs-manager will cause exceptions that don't have the exact same error message. Additionally, test for wrapped exceptions with an errno set to ENOENT. Signed-off-by: Nils Philippsen --- diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py index c094e8a..a32c920 100644 --- a/pyrpkg/__init__.py +++ b/pyrpkg/__init__.py @@ -3155,7 +3155,11 @@ class Commands(object): try: self._run_command(command, env=env) except rpkgError as e: - if str(e) == '[Errno 2] No such file or directory': + e_errno = None + if e.args and isinstance(e.args[0], Exception): + e_errno = getattr(e.args[0], 'errno', None) + if (e_errno == errno.ENOENT + or str(e) == '[Errno 2] No such file or directory'): raise rpkgError('mbs-manager is missing. Please install ' 'module-build-service.') else: From 049a53497023bb6e2388936373c7837f89228d8f Mon Sep 17 00:00:00 2001 From: Nils Philippsen Date: Aug 20 2018 10:54:05 +0000 Subject: [PATCH 2/3] test for missing mbs-manager with errno set Signed-off-by: Nils Philippsen --- diff --git a/tests/test_cli.py b/tests/test_cli.py index b5939a6..ea35afe 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -10,6 +10,7 @@ import subprocess import sys import tempfile import koji_cli.lib +import errno try: import unittest2 as unittest @@ -2625,6 +2626,37 @@ State: failed six.assertRaisesRegex(self, rpkgError, r'mbs-manager is missing.+', cli.module_build_local) + @patch.object(Commands, '_run_command') + def test_module_build_local_mbs_manager_is_missing_with_errno( + self, mock_run): + """ + Test submitting a local module build with mbs-manager missing #2. + """ + try: + exc = FileNotFoundError + except NameError: + exc = IOError + + mock_run.side_effect = rpkgError(exc( + errno.ENOENT, + "[Errno 2] No such file or directory:" + " 'mbs-manager': 'mbs-manager'")) + + cli_cmd = [ + 'rpkg', '--path', self.cloned_repo_path, 'module-build-local' + ] + with patch('sys.argv', new=cli_cmd): + cli = self.new_cli() + + # we create an empty file for the purpose of this test so we don't + # raise an exception + modulemd_yml = os.path.join(self.cloned_repo_path, + cli.cmd.repo_name + '.yaml') + self.write_file(modulemd_yml) + + six.assertRaisesRegex(self, rpkgError, r'mbs-manager is missing.+', + cli.module_build_local) + class TestOptionNameAndNamespace(CliTestCase): """Test CLI option --name and --namespace""" From c80daf69204b0cc44789427ce13a9e0864a0a4d6 Mon Sep 17 00:00:00 2001 From: Nils Philippsen Date: Aug 20 2018 11:42:30 +0000 Subject: [PATCH 3/3] explain mbs-manager exception handling Signed-off-by: Nils Philippsen --- diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py index a32c920..57c2169 100644 --- a/pyrpkg/__init__.py +++ b/pyrpkg/__init__.py @@ -3155,6 +3155,13 @@ class Commands(object): try: self._run_command(command, env=env) except rpkgError as e: + # If the exception wraps another one which has .errno == ENOENT + # this indicates that the file (mbs-manager executable) wasn't + # found. This works in both Python 2 and 3 which throw different + # types of exceptions in this case. We use duck-typing rather than + # checking for the respective specific exception types because the + # Python 3 FileNotFoundError exception isn't known in Python 2 and + # special casing this makes the code unnecessarily complicated. e_errno = None if e.args and isinstance(e.args[0], Exception): e_errno = getattr(e.args[0], 'errno', None)