k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/hack/verify-flags-underscore.py (about)

     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  
    17  import argparse
    18  import os
    19  import re
    20  import sys
    21  
    22  parser = argparse.ArgumentParser()
    23  parser.add_argument("filenames", help="list of files to check, all files if unspecified", nargs='*')
    24  args = 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
    27  def 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  
    47  def 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.
    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  
    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  
   109  def 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  
   120  if __name__ == "__main__":
   121    sys.exit(main())