From 10cfd3434e82ae56c8387f86ea32f15da2b552bb Mon Sep 17 00:00:00 2001 From: Stuart Young Date: Mon, 1 Oct 2018 10:58:56 -0400 Subject: [PATCH] remove paver timeout decorator --- pavelib/paver_tests/test_decorators.py | 29 ------------- pavelib/paver_tests/test_prereqs.py | 29 +++++-------- pavelib/prereqs.py | 25 ++++------- pavelib/utils/decorators.py | 58 -------------------------- 4 files changed, 17 insertions(+), 124 deletions(-) delete mode 100644 pavelib/paver_tests/test_decorators.py delete mode 100644 pavelib/utils/decorators.py diff --git a/pavelib/paver_tests/test_decorators.py b/pavelib/paver_tests/test_decorators.py deleted file mode 100644 index 456323dc96..0000000000 --- a/pavelib/paver_tests/test_decorators.py +++ /dev/null @@ -1,29 +0,0 @@ -""" Tests for the utility decorators for Paver """ -import time - -import pytest - -from pavelib.utils.decorators import ( - timeout, TimeoutException -) - - -def test_function_under_timeout(): - - @timeout(2) - def sample_function_1(): - return "sample text" - - value = sample_function_1() - assert value == "sample text" - - -def test_function_over_timeout(): - - @timeout(0.1) - def sample_function_2(): - time.sleep(1) - return "sample text" - - with pytest.raises(TimeoutException): - sample_function_2() diff --git a/pavelib/paver_tests/test_prereqs.py b/pavelib/paver_tests/test_prereqs.py index 14919f14f5..41a299c870 100644 --- a/pavelib/paver_tests/test_prereqs.py +++ b/pavelib/paver_tests/test_prereqs.py @@ -92,13 +92,10 @@ class TestPaverNodeInstall(PaverTestCase): an npm install error ("cb() never called!"). Test that we can handle this kind of failure. For more info see TE-1767. """ - with patch('pavelib.utils.decorators.timeout') as _timeout_patch: - _timeout_patch.return_value = lambda x: x - reload(pavelib.prereqs) - with patch('subprocess.Popen') as _mock_popen: - _mock_popen.side_effect = fail_on_npm_install - with self.assertRaises(BuildFailure): - pavelib.prereqs.node_prereqs_installation() + with patch('subprocess.Popen') as _mock_popen: + _mock_popen.side_effect = fail_on_npm_install + with self.assertRaises(BuildFailure): + pavelib.prereqs.node_prereqs_installation() # npm install will be called twice self.assertEquals(_mock_popen.call_count, 2) @@ -106,11 +103,8 @@ class TestPaverNodeInstall(PaverTestCase): """ Vanilla npm install should only be calling npm install one time """ - with patch('pavelib.utils.decorators.timeout') as _timeout_patch: - _timeout_patch.return_value = lambda x: x - reload(pavelib.prereqs) - with patch('subprocess.Popen') as _mock_popen: - pavelib.prereqs.node_prereqs_installation() + with patch('subprocess.Popen') as _mock_popen: + pavelib.prereqs.node_prereqs_installation() # when there's no failure, npm install is only called once self.assertEquals(_mock_popen.call_count, 1) @@ -118,11 +112,8 @@ class TestPaverNodeInstall(PaverTestCase): """ If there's some other error, only call npm install once, and raise a failure """ - with patch('pavelib.utils.decorators.timeout') as _timeout_patch: - _timeout_patch.return_value = lambda x: x - reload(pavelib.prereqs) - with patch('subprocess.Popen') as _mock_popen: - _mock_popen.side_effect = unexpected_fail_on_npm_install - with self.assertRaises(BuildFailure): - pavelib.prereqs.node_prereqs_installation() + with patch('subprocess.Popen') as _mock_popen: + _mock_popen.side_effect = unexpected_fail_on_npm_install + with self.assertRaises(BuildFailure): + pavelib.prereqs.node_prereqs_installation() self.assertEquals(_mock_popen.call_count, 1) diff --git a/pavelib/prereqs.py b/pavelib/prereqs.py index aeba209b4a..e519adb667 100644 --- a/pavelib/prereqs.py +++ b/pavelib/prereqs.py @@ -14,7 +14,6 @@ from paver.easy import BuildFailure, sh, task from .utils.envs import Env from .utils.timer import timed -from .utils.decorators import timeout, TimeoutException PREREQS_STATE_DIR = os.getenv('PREREQ_CACHE_DIR', Env.REPO_ROOT / '.prereqs_cache') NO_PREREQ_MESSAGE = "NO_PREREQ_INSTALL is set, not installing prereqs" @@ -129,17 +128,6 @@ def node_prereqs_installation(): Configures npm and installs Node prerequisites """ - @timeout(limit=600) - def _run_npm_command(npm_command, npm_log_file): - """ - helper function for running the npm installation with a timeout. - The implementation of Paver's `sh` function returns before the forked - actually returns. Using a Popen object so that we can ensure that - the forked process has returned - """ - proc = subprocess.Popen(npm_command, stderr=npm_log_file) - proc.wait() - # NPM installs hang sporadically. Log the installation process so that we # determine if any packages are chronic offenders. shard_str = os.getenv('SHARD', None) @@ -156,15 +144,16 @@ def node_prereqs_installation(): # evinces itself as `cb_error_text` and it ought to disappear when we upgrade # npm to 3 or higher. TODO: clean this up when we do that. try: - _run_npm_command(npm_command, npm_log_file) - except TimeoutException: - print "NPM installation took too long. Exiting..." - print "Check {} for more information".format(npm_log_file_path) - sys.exit(1) + # The implementation of Paver's `sh` function returns before the forked + # actually returns. Using a Popen object so that we can ensure that + # the forked process has returned + proc = subprocess.Popen(npm_command, stderr=npm_log_file) + proc.wait() except BuildFailure, error_text: if cb_error_text in error_text: print "npm install error detected. Retrying..." - _run_npm_command(npm_command, npm_log_file) + proc = subprocess.Popen(npm_command, stderr=npm_log_file) + proc.wait() else: raise BuildFailure(error_text) print "Successfully installed NPM packages. Log found at {}".format( diff --git a/pavelib/utils/decorators.py b/pavelib/utils/decorators.py deleted file mode 100644 index c47c65850a..0000000000 --- a/pavelib/utils/decorators.py +++ /dev/null @@ -1,58 +0,0 @@ -""" a collection of utililty decorators for paver tasks """ - -import multiprocessing -from functools import wraps - -import psutil - - -def timeout(limit=60): - """ - kill a function if it has not completed within a specified timeframe - """ - - def _handle_function_process(*args, **kwargs): - """ helper function for running a function and getting its output """ - queue = kwargs['queue'] - function = kwargs['function_to_call'] - function_args = args - function_kwargs = kwargs['function_kwargs'] - function_output = function(*function_args, **function_kwargs) - queue.put(function_output) - - def decorated_function(function): - """ the time-limited function returned by the timeout decorator """ - - def function_wrapper(*args, **kwargs): - """ - take a function and run it on a separate process, forcing it to - either give up its return value or throw a TimeoutException with - a specified timeframe (in seconds) - """ - queue = multiprocessing.Queue() - args_tuple = tuple(a for a in args) - meta_kwargs = { - 'function_to_call': function, 'queue': queue, - 'function_kwargs': kwargs - } - function_proc = multiprocessing.Process( - target=_handle_function_process, args=args_tuple, kwargs=meta_kwargs - ) - function_proc.start() - function_proc.join(float(limit)) - if function_proc.is_alive(): - pid = psutil.Process(function_proc.pid) - for child in pid.get_children(recursive=True): - child.terminate() - function_proc.terminate() - raise TimeoutException - function_output = queue.get() - return function_output - - return wraps(function)(function_wrapper) - - return decorated_function - - -class TimeoutException(Exception): - pass