verify-flags-underscore.py 4.5 KB

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