mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-12 07:44:16 +00:00
Merge branch 'master' into 'master'
Move all uses of `pool` inside `run_parallel()`. Closes #410 See merge request pycqa/flake8!228
This commit is contained in:
commit
d0db8497b9
3 changed files with 38 additions and 34 deletions
|
|
@ -74,7 +74,6 @@ class Manager(object):
|
||||||
self.checks = checker_plugins
|
self.checks = checker_plugins
|
||||||
self.jobs = self._job_count()
|
self.jobs = self._job_count()
|
||||||
self.using_multiprocessing = self.jobs > 1
|
self.using_multiprocessing = self.jobs > 1
|
||||||
self.pool = None
|
|
||||||
self.processes = []
|
self.processes = []
|
||||||
self.checkers = []
|
self.checkers = []
|
||||||
self.statistics = {
|
self.statistics = {
|
||||||
|
|
@ -84,14 +83,6 @@ class Manager(object):
|
||||||
'tokens': 0,
|
'tokens': 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.using_multiprocessing:
|
|
||||||
try:
|
|
||||||
self.pool = multiprocessing.Pool(self.jobs, _pool_init)
|
|
||||||
except OSError as oserr:
|
|
||||||
if oserr.errno not in SERIAL_RETRY_ERRNOS:
|
|
||||||
raise
|
|
||||||
self.using_multiprocessing = False
|
|
||||||
|
|
||||||
def _process_statistics(self):
|
def _process_statistics(self):
|
||||||
for checker in self.checkers:
|
for checker in self.checkers:
|
||||||
for statistic in defaults.STATISTIC_NAMES:
|
for statistic in defaults.STATISTIC_NAMES:
|
||||||
|
|
@ -268,30 +259,40 @@ class Manager(object):
|
||||||
results_found += len(results)
|
results_found += len(results)
|
||||||
return (results_found, results_reported)
|
return (results_found, results_reported)
|
||||||
|
|
||||||
def _force_cleanup(self):
|
|
||||||
if self.pool is not None:
|
|
||||||
self.pool.terminate()
|
|
||||||
self.pool.join()
|
|
||||||
|
|
||||||
def run_parallel(self):
|
def run_parallel(self):
|
||||||
"""Run the checkers in parallel."""
|
"""Run the checkers in parallel."""
|
||||||
final_results = collections.defaultdict(list)
|
final_results = collections.defaultdict(list)
|
||||||
final_statistics = collections.defaultdict(dict)
|
final_statistics = collections.defaultdict(dict)
|
||||||
pool_map = self.pool.imap_unordered(
|
|
||||||
_run_checks,
|
try:
|
||||||
self.checkers,
|
pool = multiprocessing.Pool(self.jobs, _pool_init)
|
||||||
chunksize=calculate_pool_chunksize(
|
except OSError as oserr:
|
||||||
len(self.checkers),
|
if oserr.errno not in SERIAL_RETRY_ERRNOS:
|
||||||
self.jobs,
|
raise
|
||||||
),
|
self.using_multiprocessing = False
|
||||||
)
|
self.run_serial()
|
||||||
for ret in pool_map:
|
return
|
||||||
filename, results, statistics = ret
|
|
||||||
final_results[filename] = results
|
try:
|
||||||
final_statistics[filename] = statistics
|
pool_map = pool.imap_unordered(
|
||||||
self.pool.close()
|
_run_checks,
|
||||||
self.pool.join()
|
self.checkers,
|
||||||
self.pool = None
|
chunksize=calculate_pool_chunksize(
|
||||||
|
len(self.checkers),
|
||||||
|
self.jobs,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
for ret in pool_map:
|
||||||
|
filename, results, statistics = ret
|
||||||
|
final_results[filename] = results
|
||||||
|
final_statistics[filename] = statistics
|
||||||
|
pool.close()
|
||||||
|
pool.join()
|
||||||
|
pool = None
|
||||||
|
finally:
|
||||||
|
if pool is not None:
|
||||||
|
pool.terminate()
|
||||||
|
pool.join()
|
||||||
|
|
||||||
for checker in self.checkers:
|
for checker in self.checkers:
|
||||||
filename = checker.display_name
|
filename = checker.display_name
|
||||||
|
|
@ -328,8 +329,6 @@ class Manager(object):
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
LOG.warning('Flake8 was interrupted by the user')
|
LOG.warning('Flake8 was interrupted by the user')
|
||||||
raise exceptions.EarlyQuit('Early quit while running checks')
|
raise exceptions.EarlyQuit('Early quit while running checks')
|
||||||
finally:
|
|
||||||
self._force_cleanup()
|
|
||||||
|
|
||||||
def start(self, paths=None):
|
def start(self, paths=None):
|
||||||
"""Start checking files.
|
"""Start checking files.
|
||||||
|
|
|
||||||
|
|
@ -405,7 +405,6 @@ class Application(object):
|
||||||
print('... stopped')
|
print('... stopped')
|
||||||
LOG.critical('Caught keyboard interrupt from user')
|
LOG.critical('Caught keyboard interrupt from user')
|
||||||
LOG.exception(exc)
|
LOG.exception(exc)
|
||||||
self.file_checker_manager._force_cleanup()
|
|
||||||
self.catastrophic_failure = True
|
self.catastrophic_failure = True
|
||||||
except exceptions.ExecutionError as exc:
|
except exceptions.ExecutionError as exc:
|
||||||
print('There was a critical error during execution of Flake8:')
|
print('There was a critical error during execution of Flake8:')
|
||||||
|
|
|
||||||
|
|
@ -22,17 +22,23 @@ def test_oserrors_cause_serial_fall_back():
|
||||||
style_guide = style_guide_mock()
|
style_guide = style_guide_mock()
|
||||||
with mock.patch('_multiprocessing.SemLock', side_effect=err):
|
with mock.patch('_multiprocessing.SemLock', side_effect=err):
|
||||||
manager = checker.Manager(style_guide, [], [])
|
manager = checker.Manager(style_guide, [], [])
|
||||||
|
with mock.patch.object(manager, 'run_serial') as serial:
|
||||||
|
manager.run()
|
||||||
|
assert serial.call_count == 1
|
||||||
assert manager.using_multiprocessing is False
|
assert manager.using_multiprocessing is False
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('flake8.utils.is_windows', return_value=False)
|
@mock.patch('flake8.utils.is_windows', return_value=False)
|
||||||
def test_oserrors_are_reraised(is_windows):
|
def test_oserrors_are_reraised(is_windows):
|
||||||
"""Verify that OSErrors will cause the Manager to fallback to serial."""
|
"""Verify that unexpected OSErrors will cause the Manager to reraise."""
|
||||||
err = OSError(errno.EAGAIN, 'Ominous message')
|
err = OSError(errno.EAGAIN, 'Ominous message')
|
||||||
style_guide = style_guide_mock()
|
style_guide = style_guide_mock()
|
||||||
with mock.patch('_multiprocessing.SemLock', side_effect=err):
|
with mock.patch('_multiprocessing.SemLock', side_effect=err):
|
||||||
with pytest.raises(OSError):
|
with pytest.raises(OSError):
|
||||||
checker.Manager(style_guide, [], [])
|
manager = checker.Manager(style_guide, [], [])
|
||||||
|
with mock.patch.object(manager, 'run_serial') as serial:
|
||||||
|
manager.run()
|
||||||
|
assert serial.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
def test_multiprocessing_is_disabled():
|
def test_multiprocessing_is_disabled():
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue