...
1#!/usr/bin/env python3
2
3# Copyright 2015 The Kubernetes Authors.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# 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, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import argparse
18import os
19import re
20import sys
21
22parser = argparse.ArgumentParser()
23parser.add_argument("filenames", help="list of files to check, all files if unspecified", nargs='*')
24args = parser.parse_args()
25
26# Cargo culted from http://stackoverflow.com/questions/898669/how-can-i-detect-if-a-file-is-binary-non-text-in-python
27def is_binary(pathname):
28 """Return true if the given filename is binary.
29 @raise EnvironmentError: if the file does not exist or cannot be accessed.
30 @attention: found @ http://bytes.com/topic/python/answers/21222-determine-file-type-binary-text on 6/08/2010
31 @author: Trent Mick <TrentM@ActiveState.com>
32 @author: Jorge Orpinel <jorge@orpinel.com>"""
33 try:
34 with open(pathname, 'r') as f:
35 CHUNKSIZE = 1024
36 while True:
37 chunk = f.read(CHUNKSIZE)
38 if '\0' in chunk: # found null byte
39 return True
40 if len(chunk) < CHUNKSIZE:
41 break # done
42 except:
43 return True
44
45 return False
46
47def get_all_files(rootdir):
48 all_files = []
49 for root, dirs, files in os.walk(rootdir):
50 # don't visit certain dirs
51 if 'vendor' in dirs:
52 dirs.remove('vendor')
53 if 'staging' in dirs:
54 dirs.remove('staging')
55 if '_output' in dirs:
56 dirs.remove('_output')
57 if 'third_party' in dirs:
58 dirs.remove('third_party')
59 if '.git' in dirs:
60 dirs.remove('.git')
61
62 for name in files:
63 pathname = os.path.join(root, name)
64 if not is_binary(pathname):
65 all_files.append(pathname)
66 return all_files
67
68# Collects all the flags used in golang files and verifies the flags do
69# not contain underscore. If any flag needs to be excluded from this check,
70# need to add that flag in hack/verify-flags/excluded-flags.txt.
71def check_underscore_in_flags(rootdir, files):
72 # preload the 'known' flags which don't follow the - standard
73 pathname = os.path.join(rootdir, "hack/verify-flags/excluded-flags.txt")
74 f = open(pathname, 'r')
75 excluded_flags = set(f.read().splitlines())
76 f.close()
77
78 regexs = [ re.compile('Var[P]?\([^,]*, "([^"]*)"'),
79 re.compile('.String[P]?\("([^"]*)",[^,]+,[^)]+\)'),
80 re.compile('.Int[P]?\("([^"]*)",[^,]+,[^)]+\)'),
81 re.compile('.Bool[P]?\("([^"]*)",[^,]+,[^)]+\)'),
82 re.compile('.Duration[P]?\("([^"]*)",[^,]+,[^)]+\)'),
83 re.compile('.StringSlice[P]?\("([^"]*)",[^,]+,[^)]+\)') ]
84
85 new_excluded_flags = set()
86 # walk all the files looking for any flags being declared
87 for pathname in files:
88 if not pathname.endswith(".go"):
89 continue
90 f = open(pathname, 'r')
91 data = f.read()
92 f.close()
93 matches = []
94 for regex in regexs:
95 matches = matches + regex.findall(data)
96 for flag in matches:
97 if any(x in flag for x in excluded_flags):
98 continue
99 if "_" in flag:
100 new_excluded_flags.add(flag)
101 if len(new_excluded_flags) != 0:
102 print("Found a flag declared with an _ but which is not explicitly listed as a valid flag name in hack/verify-flags/excluded-flags.txt")
103 print("Are you certain this flag should not have been declared with an - instead?")
104 l = list(new_excluded_flags)
105 l.sort()
106 print(("%s" % "\n".join(l)))
107 sys.exit(1)
108
109def main():
110 rootdir = os.path.dirname(__file__) + "/../"
111 rootdir = os.path.abspath(rootdir)
112
113 if len(args.filenames) > 0:
114 files = args.filenames
115 else:
116 files = get_all_files(rootdir)
117
118 check_underscore_in_flags(rootdir, files)
119
120if __name__ == "__main__":
121 sys.exit(main())
View as plain text