forked from NVIDIA/DALI
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lint.py
164 lines (143 loc) · 5.98 KB
/
lint.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/env python
# Copyright (c) 2020-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import glob
import itertools
import re
import argparse
import sys
import subprocess
# Linter script, that calls cpplint.py, specifically for DALI repo.
# This will be called in `make lint` cmake target
# Q: How to configure git hook for pre-push linter check?
# A: Create a file `.git/hooks/pre-push`:
#
# #!/bin/sh
# DALI_ROOT_DIR=$(git rev-parse --show-toplevel)
# python $DALI_ROOT_DIR/tools/lint.py $DALI_ROOT_DIR --nproc=10
# ret=$?
# if [ $ret -ne 0 ]; then
# exit 1
# fi
# exit 0
# Specifies, which files are to be excluded
# These filters are regexes, not typical unix-like path specification
negative_filters = [
".*operators/reader/nvdecoder/nvcuvid.h",
".*operators/reader/nvdecoder/cuviddec.h",
".*operators/reader/loader/video/nvdecode/*",
".*operators/sequence/optical_flow/optical_flow_impl/nvOpticalFlowCuda.h",
".*operators/sequence/optical_flow/optical_flow_impl/nvOpticalFlowCommon.h",
".*python/dummy.cu"
]
def negative_filtering(patterns: list, file_list):
"""
Patterns shall be a list of regex patterns
"""
if len(patterns) == 0:
return file_list
prog = re.compile(patterns.pop())
it = (i for i in file_list if not prog.search(i))
return negative_filtering(patterns, it)
def gather_files(path: str, patterns: list, antipatterns: list):
"""
Gather files, based on `path`, that match `patterns` unix-like specification
and do not match `antipatterns` regexes
"""
curr_path = os.getcwd()
os.chdir(path)
positive_iterators = [glob.iglob(os.path.join('**', pattern), recursive=True) for pattern in
patterns]
linted_files = itertools.chain(*positive_iterators)
linted_files = (os.path.join(path, file) for file in linted_files)
linted_files = negative_filtering(antipatterns.copy(), linted_files)
ret = list(linted_files)
os.chdir(curr_path)
return ret
def gen_cmd(dali_root_dir, file_list, process_includes=False):
"""
Command for calling cpplint.py
"""
if not file_list:
return ["true"]
cmd = ["python",
os.path.join(dali_root_dir, "third_party", "cpplint.py"),
"--quiet",
"--linelength=100",
"--headers=h,cuh",
"--root=" + os.path.join(dali_root_dir, "include" if process_includes else "")]
cmd.extend(file_list)
return cmd
def lint(dali_root_dir, file_list, process_includes, n_subproc):
"""
n_subprocesses: how many subprocesses to use for linter processing
Returns: 0 if lint passed, 1 otherwise
"""
if len(file_list) == 0:
return 0
cmds = []
diff = int(len(file_list) / n_subproc)
for process_idx in range(n_subproc - 1):
cmds.append(gen_cmd(dali_root_dir=dali_root_dir,
file_list=file_list[process_idx * diff: (process_idx + 1) * diff],
process_includes=process_includes))
cmds.append(gen_cmd(dali_root_dir=dali_root_dir,
file_list=file_list[(n_subproc - 1) * diff:],
process_includes=process_includes))
subprocesses = [subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for cmd in
cmds]
success = True
for subproc in subprocesses:
stdout, stderr = subproc.communicate()
success *= not bool(subproc.poll())
if len(stderr) > 0:
print(stderr.decode("utf-8"))
return 0 if success else 1
def main(dali_root_dir, n_subproc=1, file_list=None):
cc_files = gather_files(
os.path.join(dali_root_dir, "dali"),
["*.cc", "*.h", "*.cu", "*.cuh"] if file_list is None else file_list,
negative_filters)
inc_files = gather_files(
os.path.join(dali_root_dir, "include"),
["*.h", "*.cuh", "*.inc", "*.inl"] if file_list is None else file_list,
negative_filters)
tf_plugin_files = gather_files(
os.path.join(dali_root_dir, "dali_tf_plugin"),
["*.cc", "*.h", "*.cu", "*.cuh"] if file_list is None else file_list,
negative_filters)
cc_code = lint(dali_root_dir=dali_root_dir, file_list=cc_files, process_includes=False,
n_subproc=n_subproc)
inc_code = lint(dali_root_dir=dali_root_dir, file_list=inc_files, process_includes=True,
n_subproc=n_subproc)
tf_plugin_code = lint(dali_root_dir=dali_root_dir, file_list=tf_plugin_files,
process_includes=False, n_subproc=n_subproc)
if cc_code != 0 or inc_code != 0 or tf_plugin_code != 0:
sys.exit(1)
sys.exit(0)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="Run linter check for DALI files. Gather all code-files "
"(h, cuh, cc, cu, inc, inl, py) and perform linter check on them.")
parser.add_argument('dali_root_path', type=str,
help='Root path of DALI repository '
'(pointed directory should contain `.git` folder)')
parser.add_argument('--nproc', type=int, default=1,
help='Number of processes to spawn for linter verification')
parser.add_argument('--file-list', nargs='*',
help='List of files. This overrides the default scenario')
args = parser.parse_args()
assert args.nproc > 0
main(str(args.dali_root_path), args.nproc, file_list=args.file_list)