1 | # Licensed to the Apache Software Foundation (ASF) under one |
||
2 | # or more contributor license agreements. See the NOTICE file |
||
3 | # distributed with this work for additional information |
||
4 | # regarding copyright ownership. The ASF licenses this file |
||
5 | # to you under the Apache License, Version 2.0 (the |
||
6 | # "License"); you may not use this file except in compliance |
||
7 | # with the License. You may obtain a copy of the License at |
||
8 | # |
||
9 | # http://www.apache.org/licenses/LICENSE-2.0 |
||
10 | # |
||
11 | # Unless required by applicable law or agreed to in writing, |
||
12 | # software distributed under the License is distributed on an |
||
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||
14 | # KIND, either express or implied. See the License for the |
||
15 | # specific language governing permissions and limitations |
||
16 | # under the License. |
||
17 | |||
18 | import multiprocessing as mp |
||
19 | import os |
||
20 | from fnmatch import fnmatch |
||
21 | from subprocess import Popen |
||
22 | |||
23 | |||
24 | View Code Duplication | def chunk(seq, n): |
|
0 ignored issues
–
show
Duplication
introduced
by
![]() |
|||
25 | """ |
||
26 | divide a sequence into equal sized chunks |
||
27 | (the last chunk may be smaller, but won't be empty) |
||
28 | """ |
||
29 | chunks = [] |
||
30 | some = [] |
||
31 | for element in seq: |
||
32 | if len(some) == n: |
||
33 | chunks.append(some) |
||
34 | some = [] |
||
35 | some.append(element) |
||
36 | if len(some) > 0: |
||
37 | chunks.append(some) |
||
38 | return chunks |
||
39 | |||
40 | |||
41 | def dechunk(chunks): |
||
42 | "flatten chunks into a single list" |
||
43 | seq = [] |
||
44 | for chunk in chunks: |
||
45 | seq.extend(chunk) |
||
46 | return seq |
||
47 | |||
48 | |||
49 | View Code Duplication | def run_parallel(cmds, **kwargs): |
|
0 ignored issues
–
show
|
|||
50 | """ |
||
51 | Run each of cmds (with shared **kwargs) using subprocess.Popen |
||
52 | then wait for all of them to complete. |
||
53 | Runs batches of multiprocessing.cpu_count() * 2 from cmds |
||
54 | returns a list of tuples containing each process' |
||
55 | returncode, stdout, stderr |
||
56 | """ |
||
57 | complete = [] |
||
58 | for cmds_batch in chunk(cmds, mp.cpu_count() * 2): |
||
59 | procs_batch = [Popen(cmd, **kwargs) for cmd in cmds_batch] |
||
60 | for proc in procs_batch: |
||
61 | stdout, stderr = proc.communicate() |
||
62 | complete.append((proc.returncode, stdout, stderr)) |
||
63 | return complete |
||
64 | |||
65 | |||
66 | _source_extensions = ''' |
||
67 | .h |
||
68 | .cc |
||
69 | .cpp |
||
70 | '''.split() |
||
71 | |||
72 | |||
73 | View Code Duplication | def get_sources(source_dir, exclude_globs=[]): |
|
0 ignored issues
–
show
|
|||
74 | sources = [] |
||
75 | for directory, subdirs, basenames in os.walk(source_dir): |
||
76 | for path in [os.path.join(directory, basename) |
||
77 | for basename in basenames]: |
||
78 | # filter out non-source files |
||
79 | if os.path.splitext(path)[1] not in _source_extensions: |
||
80 | continue |
||
81 | |||
82 | path = os.path.abspath(path) |
||
83 | |||
84 | # filter out files that match the globs in the globs file |
||
85 | if any([fnmatch(path, glob) for glob in exclude_globs]): |
||
86 | continue |
||
87 | |||
88 | sources.append(path) |
||
89 | return sources |
||
90 | |||
91 | |||
92 | View Code Duplication | def stdout_pathcolonline(completed_process, filenames): |
|
0 ignored issues
–
show
|
|||
93 | """ |
||
94 | given a completed process which may have reported some files as problematic |
||
95 | by printing the path name followed by ':' then a line number, examine |
||
96 | stdout and return the set of actually reported file names |
||
97 | """ |
||
98 | returncode, stdout, stderr = completed_process |
||
99 | bfilenames = set() |
||
100 | for filename in filenames: |
||
101 | bfilenames.add(filename.encode('utf-8') + b':') |
||
102 | problem_files = set() |
||
103 | for line in stdout.splitlines(): |
||
104 | for filename in bfilenames: |
||
105 | if line.startswith(filename): |
||
106 | problem_files.add(filename.decode('utf-8')) |
||
107 | bfilenames.remove(filename) |
||
108 | break |
||
109 | return problem_files, stdout |
||
110 | |||
111 |