summaryrefslogtreecommitdiff
path: root/lib/python/qmk/util.py
diff options
context:
space:
mode:
authorNick Brassel <nick@tzarc.org>2023-10-17 09:43:50 +1100
committerGitHub <noreply@github.com>2023-10-17 09:43:50 +1100
commitf6c70c40af502923594e76bf079f602ed88a2341 (patch)
treeda27fe0d9c8c4fa24e39afd82d1a479b02e06e60 /lib/python/qmk/util.py
parent81a3aa025cda52732e847af8db256cb132605ce0 (diff)
Allow for disabling of parallel processing of qmk find and `qmk mass-compile`. (#22160)
Co-authored-by: Duncan Sutherland <dunk2k_2000@hotmail.com>
Diffstat (limited to 'lib/python/qmk/util.py')
-rw-r--r--lib/python/qmk/util.py56
1 files changed, 56 insertions, 0 deletions
diff --git a/lib/python/qmk/util.py b/lib/python/qmk/util.py
new file mode 100644
index 0000000000..db7debd578
--- /dev/null
+++ b/lib/python/qmk/util.py
@@ -0,0 +1,56 @@
1"""Utility functions.
2"""
3import contextlib
4import multiprocessing
5
6from milc import cli
7
8
9@contextlib.contextmanager
10def parallelize():
11 """Returns a function that can be used in place of a map() call.
12
13 Attempts to use `mpire`, falling back to `multiprocessing` if it's not
14 available. If parallelization is not requested, returns the original map()
15 function.
16 """
17
18 # Work out if we've already got a config value for parallel searching
19 if cli.config.user.parallel_search is None:
20 parallel_search = True
21 else:
22 parallel_search = cli.config.user.parallel_search
23
24 # Non-parallel searches use `map()`
25 if not parallel_search:
26 yield map
27 return
28
29 # Prefer mpire's `WorkerPool` if it's available
30 with contextlib.suppress(ImportError):
31 from mpire import WorkerPool
32 from mpire.utils import make_single_arguments
33 with WorkerPool() as pool:
34
35 def _worker(func, *args):
36 # Ensure we don't unpack tuples -- mpire's `WorkerPool` tries to do so normally so we tell it not to.
37 for r in pool.imap_unordered(func, make_single_arguments(*args, generator=False), progress_bar=True):
38 yield r
39
40 yield _worker
41 return
42
43 # Otherwise fall back to multiprocessing's `Pool`
44 with multiprocessing.Pool() as pool:
45 yield pool.imap_unordered
46
47
48def parallel_map(*args, **kwargs):
49 """Effectively runs `map()` but executes it in parallel if necessary.
50 """
51 with parallelize() as map_fn:
52 # This needs to be enclosed in a `list()` as some implementations return
53 # a generator function, which means the scope of the pool is closed off
54 # before the results are returned. Returning a list ensures results are
55 # materialised before any worker pool is shut down.
56 return list(map_fn(*args, **kwargs))