github.com/RedHatInsights/insights-content-service@v1.0.0/utils/json_check.py (about) 1 # Copyright © 2020 Pavel Tisnovsky 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 """ 16 Simple checker of all JSONs in the given directory (usually repository). 17 18 Usage: 19 ----- 20 json_check.py [-h] [-v] [-n] -d DIRECTORY 21 22 Optional arguments: 23 ------------------ 24 -h, --help show this help message and exit 25 -v, --verbose make it verbose 26 -n, --no-colors disable color output 27 -d DIRECTORY--directory DIRECTORY 28 directory with JSON files to check 29 """ 30 31 # Link to generated documentation for this script: 32 # ----------------------------------------------- 33 # <https://redhatinsights.github.io/insights-results-aggregator/json_check.html> 34 35 from pathlib import Path 36 from json import load 37 from sys import exit 38 from os import popen 39 from argparse import ArgumentParser 40 41 42 def read_control_code(operation): 43 """Try to execute tput to read control code for selected operation.""" 44 return popen("tput " + operation, "r").readline() 45 46 47 def check_jsons(verbose, directory): 48 """Check all JSON files found in current directory and all subdirectories.""" 49 # Reset counters with number of passes and number of failures. 50 passes = 0 51 failures = 0 52 53 # Find all files in current directory and subdirectories with `*.json` 54 # extension. Files are found recursivelly. 55 files = list(Path(directory).rglob("*.json")) 56 57 # Iterate over all files found by previous command. 58 for file in files: 59 try: 60 # If the file can be opened and loaded as JSON, everything is fine. 61 with file.open() as fin: 62 # Try to load and parse the content of JSON file. 63 obj = load(fin) 64 # At this point the JSON has been loaded and parsed correctly. 65 if verbose is not None: 66 print("{} is valid".format(file)) 67 68 passes += 1 69 except ValueError as e: 70 # There are several reasons and possibilities why the file can not 71 # be read as JSON, so we just print the error message taken from 72 # exception object. 73 print("{} is invalid".format(file)) 74 failures += 1 75 print(e) 76 77 # Just the counters needs to be returned because all other informations 78 # about problems have been displayed already. 79 return passes, failures 80 81 82 def display_report(passes, failures, nocolors): 83 """Display report about number of passes and failures.""" 84 # First of all, we need to setup colors to be displayed on terminal. Colors 85 # are displayed by using terminal escape control codes. When color output 86 # are not enabled on command line, we can simply use empty strings in 87 # output instead of real color escape codes. 88 red_background = green_background = magenta_background = no_color = "" 89 90 # If colors are enabled by command line parameter, use control sequence 91 # returned by `tput` command. 92 if not nocolors: 93 red_background = read_control_code("setab 1") 94 green_background = read_control_code("setab 2") 95 magenta_background = read_control_code("setab 5") 96 no_color = read_control_code("sgr0") 97 98 # There are four possible outcomes of JSON check: 99 # 1. no JSON files has been found 100 # 2. all files are ok 101 # 3. none of JSON files can be read and parsed 102 # 4. some files can be read and parsed, some can not 103 if failures == 0: 104 # If there are no failures, then check if any JSON file has been found at all. 105 if passes == 0: 106 print("{}[WARN]{}: no JSON files detected".format(magenta_background, no_color)) 107 else: 108 print("{}[OK]{}: all JSONs have proper format".format(green_background, no_color)) 109 else: 110 print("{}[FAIL]{}: invalid JSON(s) detected".format(red_background, no_color)) 111 112 # Print just number of passes and failures at the end, as this information 113 # can be processed on CI. 114 print("{} passes".format(passes)) 115 print("{} failures".format(failures)) 116 117 118 def main(): 119 """Entry point to this tool.""" 120 # First of all, we need to specify all command line flags that are 121 # recognized by this tool. 122 parser = ArgumentParser() 123 parser.add_argument("-v", "--verbose", dest="verbose", help="make it verbose", 124 action="store_true", default=None) 125 parser.add_argument("-n", "--no-colors", dest="nocolors", help="disable color output", 126 action="store_true", default=None) 127 parser.add_argument("-d", "--directory", dest="directory", 128 help="directory with JSON files to check", 129 action="store", default=".") 130 131 # Now it is time to parse flags, check the actual content of command line 132 # and fill in the object stored in variable named `args`. 133 args = parser.parse_args() 134 135 # Check all JSON files, display problems, and get counters with number of 136 # passes and failures. 137 passes, failures = check_jsons(args.verbose, args.directory) 138 139 # Display detailed report and summary as well. 140 display_report(passes, failures, args.nocolors) 141 142 # If any error is found, return with exit code check to non-zero value. 143 if failures > 0: 144 exit(1) 145 146 147 # If this script is started from command line, run the `main` function 148 # which represents entry point to the processing. 149 if __name__ == "__main__": 150 """Entry point to this tool.""" 151 main()