Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit aa50a8c

Browse files
committed
Switch to using concurrent.futures
1 parent 231f601 commit aa50a8c

3 files changed

Lines changed: 42 additions & 25 deletions

File tree

pre_commit/xargs.py

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import contextlib
66
import math
7-
import multiprocessing.pool
87
import sys
98

109
import concurrent.futures
@@ -79,12 +78,12 @@ def partition(cmd, varargs, target_concurrency, _max_length=None):
7978

8079

8180
@contextlib.contextmanager
82-
def _threadpool(size):
83-
pool = multiprocessing.pool.ThreadPool(size)
84-
try:
85-
yield pool
86-
finally:
87-
pool.terminate()
81+
def _thread_mapper(maxsize):
82+
if maxsize == 1:
83+
yield map
84+
else:
85+
with concurrent.futures.ThreadPoolExecutor(maxsize) as ex:
86+
yield ex.map
8887

8988

9089
def xargs(cmd, varargs, **kwargs):
@@ -109,22 +108,24 @@ def xargs(cmd, varargs, **kwargs):
109108
def run_cmd_partition(run_cmd):
110109
return cmd_output(*run_cmd, encoding=None, retcode=None)
111110

112-
with _threadpool(min(len(partitions), target_concurrency)) as pool:
113-
results = pool.map(run_cmd_partition, partitions)
114-
115-
for proc_retcode, proc_out, proc_err in results:
116-
# This is *slightly* too clever so I'll explain it.
117-
# First the xor boolean table:
118-
# T | F |
119-
# +-------+
120-
# T | F | T |
121-
# --+-------+
122-
# F | T | F |
123-
# --+-------+
124-
# When negate is True, it has the effect of flipping the return code
125-
# Otherwise, the retuncode is unchanged
126-
retcode |= bool(proc_retcode) ^ negate
127-
stdout += proc_out
128-
stderr += proc_err
111+
with _thread_mapper(
112+
min(len(partitions), target_concurrency),
113+
) as thread_map:
114+
results = thread_map(run_cmd_partition, partitions)
115+
116+
for proc_retcode, proc_out, proc_err in results:
117+
# This is *slightly* too clever so I'll explain it.
118+
# First the xor boolean table:
119+
# T | F |
120+
# +-------+
121+
# T | F | T |
122+
# --+-------+
123+
# F | T | F |
124+
# --+-------+
125+
# When negate is True, it has the effect of flipping the return
126+
# code. Otherwise, the returncode is unchanged.
127+
retcode |= bool(proc_retcode) ^ negate
128+
stdout += proc_out
129+
stderr += proc_err
129130

130131
return retcode, stdout, stderr

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@
4747
'toml',
4848
'virtualenv',
4949
],
50-
extras_require={':python_version<"3.7"': ['importlib-resources']},
50+
extras_require={
51+
':python_version<"3.2"': ['futures'],
52+
':python_version<"3.7"': ['importlib-resources'],
53+
},
5154
entry_points={
5255
'console_scripts': [
5356
'pre-commit = pre_commit.main:main',

tests/xargs_test.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
import time
77

8+
import concurrent.futures
89
import mock
910
import pytest
1011
import six
@@ -180,3 +181,15 @@ def test_xargs_concurrency():
180181
# It would take 0.5*5=2.5 seconds ot run all of these in serial, so if it
181182
# takes less, they must have run concurrently.
182183
assert elapsed < 2.5
184+
185+
186+
def test_thread_mapper_concurrency_uses_threadpoolexecutor_map():
187+
with xargs._thread_mapper(10) as thread_map:
188+
assert isinstance(
189+
thread_map.__self__, concurrent.futures.ThreadPoolExecutor,
190+
) is True
191+
192+
193+
def test_thread_mapper_concurrency_uses_regular_map():
194+
with xargs._thread_mapper(1) as thread_map:
195+
assert thread_map is map

0 commit comments

Comments
 (0)