From a10d0eec4d7515e9eb506c3b3c7f593cdd5f81e4 Mon Sep 17 00:00:00 2001 From: Markus Lehtonen Date: Fri, 4 Apr 2014 09:00:02 +0300 Subject: [PATCH] utils: change fork_call() to return a callable Hopefully making its usage easier to read. Change-Id: I7facc91ace28b4e83783453d8f72ca14316b827a Signed-off-by: Markus Lehtonen --- obs_service_gbp/command.py | 4 +-- obs_service_gbp_utils/__init__.py | 8 +++-- tests/test_obs_service_gbp_utils.py | 55 +++++++++++++++-------------- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/obs_service_gbp/command.py b/obs_service_gbp/command.py index 41c8778..19fab5f 100644 --- a/obs_service_gbp/command.py +++ b/obs_service_gbp/command.py @@ -126,7 +126,7 @@ def gbp_export(repo, args, config): if args.rpm == 'yes' or (args.rpm == 'auto' and specs_found): LOGGER.info('Exporting RPM packaging files with GBP') LOGGER.debug('git-buildpackage-rpm args: %s', ' '.join(rpm_args)) - ret = fork_call(uid, gid, gbp_rpm, rpm_args) + ret = fork_call(uid, gid, gbp_rpm)(rpm_args) if ret: LOGGER.error('Git-buildpackage-rpm failed, unable to export ' 'RPM packaging files') @@ -134,7 +134,7 @@ def gbp_export(repo, args, config): if args.deb == 'yes' or (args.deb== 'auto' and os.path.isdir('debian')): LOGGER.info('Exporting Debian source package with GBP') LOGGER.debug('git-buildpackage args: %s', ' '.join(deb_args)) - ret = fork_call(uid, gid, gbp_deb, deb_args) + ret = fork_call(uid, gid, gbp_deb)(deb_args) if ret: LOGGER.error('Git-buildpackage failed, unable to export Debian ' 'sources package files') diff --git a/obs_service_gbp_utils/__init__.py b/obs_service_gbp_utils/__init__.py index b4b50ee..f41534a 100644 --- a/obs_service_gbp_utils/__init__.py +++ b/obs_service_gbp_utils/__init__.py @@ -96,8 +96,8 @@ def sanitize_uid_gid(user, group): raise GbpServiceError('Unable to find UID/GID: %s' % err) return (uid, gid) -def fork_call(user, group, func, *args, **kwargs): - """Fork and call a function. The function should return an integer""" +def _fork_call(user, group, func, *args, **kwargs): + """Wrapper for actual logic of fork_call()""" # Get numerical uid and gid uid, gid = sanitize_uid_gid(user, group) @@ -114,6 +114,10 @@ def fork_call(user, group, func, *args, **kwargs): else: raise ret_data +def fork_call(user, group, func): + """Fork and call a function. The function should return an integer. + Returns a callable that runs the function.""" + return partial(_fork_call, user, group, func) def _commit_info_in_json(repo, committish): """Get info about a committish in json-serializable format""" diff --git a/tests/test_obs_service_gbp_utils.py b/tests/test_obs_service_gbp_utils.py index 7f4e2df..972c0b2 100644 --- a/tests/test_obs_service_gbp_utils.py +++ b/tests/test_obs_service_gbp_utils.py @@ -48,19 +48,22 @@ class TestForkCall(object): self._group = grp.getgrgid(self._gid).gr_name @staticmethod - def _no_fork_call(uid, gid, func, *args, **kwargs): + def _no_fork_call(uid, gid, func): """For testing demoted call without actually forking""" - data_q = Queue() - try: - _demoted_child_call(uid, gid, data_q, - partial(func, *args, **kwargs)) - except SystemExit as err: - ret_code = err.code - ret_data = data_q.get() - if ret_code == _RET_FORK_OK: - return ret_data - else: - raise ret_data + def _no_fork_call_runner(uid, gid, func, *args, **kwargs): + """Actual workhorse""" + data_q = Queue() + try: + _demoted_child_call(uid, gid, data_q, + partial(func, *args, **kwargs)) + except SystemExit as err: + ret_code = err.code + ret_data = data_q.get() + if ret_code == _RET_FORK_OK: + return ret_data + else: + raise ret_data + return partial(_no_fork_call_runner, uid, gid, func) @staticmethod def _dummy_ok(): @@ -79,44 +82,44 @@ class TestForkCall(object): def test_success(self): """Basic test for successful call""" - eq_(fork_call(None, None, self._dummy_ok), 'ok') + eq_(fork_call(None, None, self._dummy_ok)(), 'ok') - eq_(fork_call(None, None, self._dummy_args, 1, '2', arg3='foo'), + eq_(fork_call(None, None, self._dummy_args)(1, '2', arg3='foo'), (1, '2', 'foo')) - ok_(os.getpid() != fork_call(None, None, os.getpid)) + ok_(os.getpid() != fork_call(None, None, os.getpid)()) def test_fail(self): """Tests for function call failures""" with assert_raises(GbpChildBTError) as exc: - fork_call(None, None, self._dummy_raise) + fork_call(None, None, self._dummy_raise)() eq_(exc.exception.typ, _DummyException) with assert_raises(GbpChildBTError) as exc: - fork_call(None, None, self._dummy_ok, 'unexptected_arg') + fork_call(None, None, self._dummy_ok)('unexptected_arg') eq_(exc.exception.typ, TypeError) def test_demoted_call_no(self): """Test running with different UID/GID""" - eq_(fork_call(self._name, self._group, self._dummy_ok), 'ok') - eq_(fork_call(self._uid, None, self._dummy_ok), 'ok') - eq_(fork_call(None, self._gid, self._dummy_ok), 'ok') + eq_(fork_call(self._name, self._group, self._dummy_ok)(), 'ok') + eq_(fork_call(self._uid, None, self._dummy_ok)(), 'ok') + eq_(fork_call(None, self._gid, self._dummy_ok)(), 'ok') - eq_(self._no_fork_call(self._uid, self._gid, self._dummy_ok), 'ok') + eq_(self._no_fork_call(self._uid, self._gid, self._dummy_ok)(), 'ok') def test_demoted_call_fail(self): """Test running with invalid UID/GID""" with assert_raises(GbpServiceError): - fork_call('_non_existent_user', None, self._dummy_ok) + fork_call('_non_existent_user', None, self._dummy_ok)() with assert_raises(GbpServiceError): - fork_call(None, '_non_existen_group', self._dummy_ok) + fork_call(None, '_non_existen_group', self._dummy_ok)() with assert_raises(GbpServiceError): - self._no_fork_call(99999, None, self._dummy_ok) + self._no_fork_call(99999, None, self._dummy_ok)() with assert_raises(GbpServiceError): - self._no_fork_call(None, 99999, self._dummy_ok) + self._no_fork_call(None, 99999, self._dummy_ok)() with assert_raises(GbpChildBTError) as exc: - self._no_fork_call(self._uid, self._gid, self._dummy_raise) + self._no_fork_call(self._uid, self._gid, self._dummy_raise)() eq_(exc.exception.typ, _DummyException) class TestGitMeta(UnitTestsBase): -- 2.34.1