A Python lint tool
main()
The Py7 script invokes main()(Listing 2) automatically unless you do not include source code files as CLI parameters (if there are no parameters, Py7 exits with an error). It reports the Py7 tool version information and then checks for additional CLI parameters. If a help parameter (-h or --help) is present, then usage() is called, with a normal exit.
Listing 2
main()
01 def main():
02 print("")
03 version()
04 print("")
05
06 if len(sys.argv) == 2 and sys.argv[1] in ('-h', '--help'):
07 usage()
08 sys.exit(0)
09
10 if len(sys.argv) < 2:
11 print(":: ")
12 print(":: Error: No Python files given to check!")
13 print(":: ")
14 usage()
15 sys.exit(1)
16
17 check_modules() # check for and install required modules
18
19 print("::")
20 print(":: Beginning Py7 Lint")
21 print("::")
22 print(" ")
23 for i in range(1, len(sys.argv)):
24 print("\n::--- ... ---::\n")
25 run_lint_tests(sys.argv[i])
26 print(" ")
27 print("::")
28 print(":: Completed Py7 Lint")
29 print("::")
30 input("\nPress any key to continue...\n")
31 sys.exit(0)
The main() function then checks that the various modules are installed in the Python environment by calling check_modules() (line 17) each time Py7 is run.
Then in lines 19-31, main() runs the various lint tools against the Python source code files given as CLI parameters. After checking and verifying the modules are available, main then iterates over the CLI parameters, which are each Python source code file selected for linting. Each file is then passed to run_lint_tets to lint the code.
check_modules()
The check_modules() function (Listing 3) uses a list of the modules, PY_MOD_LIST, which is defined as a global attribute; check_modules() uses a for loop to iterate over PY_MOD_LIST. The find_spec function in the importlib module checks to see if the module exists.
Listing 3
check_modules
01 def main():
02 print("")
03 version()
04 print("")
05
06 if len(sys.argv) == 2 and sys.argv[1] in ('-h', '--help'):
07 usage()
08 sys.exit(0)
09
10 if len(sys.argv) < 2:
11 print(":: ")
12 print(":: Error: No Python files given to check!")
13 print(":: ")
14 usage()
15 sys.exit(1)
16
17 check_modules() # check for and install required modules
18
19 print("::")
20 print(":: Beginning Py7 Lint")
21 print("::")
22 print(" ")
23 for i in range(1, len(sys.argv)):
24 print("\n::--- ... ---::\n")
25 run_lint_tests(sys.argv[i])
26 print(" ")
27 print("::")
28 print(":: Completed Py7 Lint")
29 print("::")
30 input("\nPress any key to continue...\n")
31 sys.exit(0)01 def check_modules():
02 print("#")
03 print("# Python Linter Tool Script ", __release__)
04 print("# ")
05 print("# Checking for required Python modules...")
06 print("#")
07 for package in PY_MOD_LIST:
08 print(" ")
09 has_mod = importlib.util.find_spec(package)
10 if has_mod:
11 print(f' #:>The {package} module exists.')
12 else:
13 print(f' #:>The {package} module absent.')
14 tmp_argv = sys.argv
15 sys.argv = ["pip", "install"] + [ package ]
16 try:
17 run_module("pip", run_name="__main__")
18 except SystemExit as exception:
19 print("exit code: ", exception.code)
20 if exception.code != 0 :
21 print(":: ")
22 print(f':: Error: The {package} module NOT installed; end tests!')
23 print(":: ")
24 sys.exit(2)
25 sys.argv = tmp_argv
26 print(" #:> ")
27 print(f' #:>The {package} module installed.')
28 print(" #:> ")
29 print("")
30 input("\nPress any key to continue...\n")
31 print("")
If a module is not found when using check_modules, the module is then installed using run_module() in the runpy module within a try statement. First, the system CLI arguments are stored, and then the module to be installed is set as an argument.
The run_module function then invokes the pip module with the __main__ function. The original Py7 tool simply executed pip as a sub-process, but that caused problems in later versions of Python.
The return code from the pip module __main__ function is checked with the exception object of the try statement. If the return code is anything except zero, then the Py7 tool reports an error and exits, because Py7 cannot run without all the tools installed.
run_lint_tests()
After the lint tools are verified as installed, main() runs each test on each Python source file. Using a for loop, each file listed as a CLI parameter is passed in a call to run_lint_tests() (Listing 4) on the Python source code file.
Listing 4
run_lint_tests()
01 def main():
02 print("")
03 version()
04 print("")
05
06 if len(sys.argv) == 2 and sys.argv[1] in ('-h', '--help'):
07 usage()
08 sys.exit(0)
09
10 if len(sys.argv) < 2:
11 print(":: ")
12 print(":: Error: No Python files given to check!")
13 print(":: ")
14 usage()
15 sys.exit(1)
16
17 check_modules() # check for and install required modules
18
19 print("::")
20 print(":: Beginning Py7 Lint")
21 print("::")
22 print(" ")
23 for i in range(1, len(sys.argv)):
24 print("\n::--- ... ---::\n")
25 run_lint_tests(sys.argv[i])
26 print(" ")
27 print("::")
28 print(":: Completed Py7 Lint")
29 print("::")
30 input("\nPress any key to continue...\n")
31 sys.exit(0)01 def check_modules():
02 print("#")
03 print("# Python Linter Tool Script ", __release__)
04 print("# ")
05 print("# Checking for required Python modules...")
06 print("#")
07 for package in PY_MOD_LIST:
08 print(" ")
09 has_mod = importlib.util.find_spec(package)
10 if has_mod:
11 print(f' #:>The {package} module exists.')
12 else:
13 print(f' #:>The {package} module absent.')
14 tmp_argv = sys.argv
15 sys.argv = ["pip", "install"] + [ package ]
16 try:
17 run_module("pip", run_name="__main__")
18 except SystemExit as exception:
19 print("exit code: ", exception.code)
20 if exception.code != 0 :
21 print(":: ")
22 print(f':: Error: The {package} module NOT installed; end tests!')
23 print(":: ")
24 sys.exit(2)
25 sys.argv = tmp_argv
26 print(" #:> ")
27 print(f' #:>The {package} module installed.')
28 print(" #:> ")
29 print("")
30 input("\nPress any key to continue...\n")
31 print("")01 def run_lint_tests(file): #25-LOC
02 for py_mod in PY_MOD_LIST:
03 has_file = os.path.isfile(file)
04 if not has_file:
05 print(":: ")
06 print(f':: Error: File {file} not found; end tests!')
07 print(":: ")
08 return
09 if py_mod == "mccabe":
10 cmd = py_mod + '--min ' + MCCABE_MIN + ' ' + file
11 else:
12 cmd = py_mod + ' ' + file
13 print(" ::>")
14 print(f' ::> {py_mod} on file: {file}')
15 print(" ::>")
16 result = run(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True,
17 shell=True, check=False)
18 if len(result.stdout) == 0:
19 print(" ::> ")
20 print(" ::> [\nNo problems detected.", "\n ::> ]")
21 print(" ::> ")
22 else:
23 print(" ::> ")
24 print(" ::> [\n", result.stdout, "\n ::> ]")
25 print(" ::> ")
The run_lint_tests() function uses a for loop to iterate over PY_MOD_LIST and invokes each test on the Python source file, capturing the output that is reported to the user. If the Python source file does not exist, the function returns. For the McCabe lint check, the McCabe complexity's artificial CLI parameter is created using the Python script attribute MCCABE_MIN, which sets the minimum McCabe complexity threshold for an error in the check.
« Previous 1 2 3 4 Next »
Buy this article as PDF
(incl. VAT)