From 0910e159ba18bf284671012e67c916eeea573cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Csord=C3=A1s?= Date: Wed, 27 Feb 2019 16:51:43 +0100 Subject: [PATCH] Refactoring sub-command directory structure --- Makefile | 14 ++-- .../cmd}/__init__.py | 0 .../{ => codechecker_analyzer}/cmd/analyze.py | 0 .../cmd/analyzer_version.py | 0 .../cmd/analyzers.py | 0 .../{ => codechecker_analyzer}/cmd/check.py | 17 +---- .../cmd/checkers.py | 0 .../{ => codechecker_analyzer}/cmd/log.py | 0 .../{ => codechecker_analyzer}/cmd/parse.py | 0 analyzer/tools/build-logger/README.md | 1 - bin/CodeChecker.py | 35 ++++++++-- {tools => libcodechecker/cmd}/__init__.py | 0 .../{libhandlers => cmd}/version.py | 8 +-- libcodechecker/libhandlers/__init__.py | 64 ------------------- scripts/build/create_commands.py | 23 ++++--- .../codechecker_client/cmd}/__init__.py | 0 .../{ => codechecker_client}/cmd/cmd.py | 0 .../{ => codechecker_client}/cmd/store.py | 0 web/codechecker_web/cmd/__init__.py | 5 ++ web/{ => codechecker_web}/cmd/web_version.py | 0 web/server/codechecker_server/cmd/__init__.py | 5 ++ .../{ => codechecker_server}/cmd/server.py | 0 web/tests/Makefile | 14 ++-- 23 files changed, 75 insertions(+), 111 deletions(-) rename analyzer/{tools => codechecker_analyzer/cmd}/__init__.py (100%) rename analyzer/{ => codechecker_analyzer}/cmd/analyze.py (100%) rename analyzer/{ => codechecker_analyzer}/cmd/analyzer_version.py (100%) rename analyzer/{ => codechecker_analyzer}/cmd/analyzers.py (100%) rename analyzer/{ => codechecker_analyzer}/cmd/check.py (98%) rename analyzer/{ => codechecker_analyzer}/cmd/checkers.py (100%) rename analyzer/{ => codechecker_analyzer}/cmd/log.py (100%) rename analyzer/{ => codechecker_analyzer}/cmd/parse.py (100%) rename {tools => libcodechecker/cmd}/__init__.py (100%) rename libcodechecker/{libhandlers => cmd}/version.py (91%) delete mode 100644 libcodechecker/libhandlers/__init__.py rename {tools/plist_to_html => web/client/codechecker_client/cmd}/__init__.py (100%) rename web/client/{ => codechecker_client}/cmd/cmd.py (100%) rename web/client/{ => codechecker_client}/cmd/store.py (100%) create mode 100644 web/codechecker_web/cmd/__init__.py rename web/{ => codechecker_web}/cmd/web_version.py (100%) create mode 100644 web/server/codechecker_server/cmd/__init__.py rename web/server/{ => codechecker_server}/cmd/server.py (100%) diff --git a/Makefile b/Makefile index 2953e57546..ca2d7cc78f 100644 --- a/Makefile +++ b/Makefile @@ -69,13 +69,9 @@ package: clean_package build_dir gen-docs thrift userguide build_plist_to_html b mkdir -p $(CC_BUILD_LIBCC_DIR) && \ mkdir -p $(CC_BUILD_LIB_DIR)/codechecker && \ cp -r $(ROOT)/libcodechecker/* $(CC_BUILD_LIBCC_DIR) && \ - cp -r $(CC_ANALYZER)/cmd/* $(CC_BUILD_LIBCC_DIR)/libhandlers && \ cp -r $(CC_ANALYZER)/codechecker_analyzer $(CC_BUILD_LIB_DIR) && \ cp -r $(CC_WEB)/codechecker_web $(CC_BUILD_LIB_DIR) && \ - cp -r $(CC_WEB)/cmd/* $(CC_BUILD_LIBCC_DIR)/libhandlers && \ - cp -r $(CC_SERVER)/cmd/* $(CC_BUILD_LIBCC_DIR)/libhandlers && \ cp -r $(CC_SERVER)/codechecker_server $(CC_BUILD_LIB_DIR) && \ - cp -r $(CC_CLIENT)/cmd/* $(CC_BUILD_LIBCC_DIR)/libhandlers && \ cp -r $(CC_CLIENT)/codechecker_client $(CC_BUILD_LIB_DIR) # Copy sub-commands. @@ -93,11 +89,11 @@ package: clean_package build_dir gen-docs thrift userguide build_plist_to_html b ./scripts/build/extend_version_file.py -r $(ROOT) -b $(BUILD_DIR) && \ mkdir -p $(CC_BUILD_DIR)/cc_bin && \ ./scripts/build/create_commands.py -b $(BUILD_DIR) \ - $(ROOT)/bin \ - $(CC_WEB)/bin \ - $(CC_SERVER)/bin \ - $(CC_CLIENT)/bin \ - $(CC_ANALYZER)/bin + $(ROOT)/bin:libcodechecker/cmd \ + $(CC_WEB)/bin:codechecker_web/cmd \ + $(CC_SERVER)/bin:codechecker_server/cmd \ + $(CC_CLIENT)/bin:codechecker_client/cmd \ + $(CC_ANALYZER)/bin:codechecker_analyzer/cmd # Copy web client files. mkdir -p $(CC_BUILD_WEB_DIR) && \ diff --git a/analyzer/tools/__init__.py b/analyzer/codechecker_analyzer/cmd/__init__.py similarity index 100% rename from analyzer/tools/__init__.py rename to analyzer/codechecker_analyzer/cmd/__init__.py diff --git a/analyzer/cmd/analyze.py b/analyzer/codechecker_analyzer/cmd/analyze.py similarity index 100% rename from analyzer/cmd/analyze.py rename to analyzer/codechecker_analyzer/cmd/analyze.py diff --git a/analyzer/cmd/analyzer_version.py b/analyzer/codechecker_analyzer/cmd/analyzer_version.py similarity index 100% rename from analyzer/cmd/analyzer_version.py rename to analyzer/codechecker_analyzer/cmd/analyzer_version.py diff --git a/analyzer/cmd/analyzers.py b/analyzer/codechecker_analyzer/cmd/analyzers.py similarity index 100% rename from analyzer/cmd/analyzers.py rename to analyzer/codechecker_analyzer/cmd/analyzers.py diff --git a/analyzer/cmd/check.py b/analyzer/codechecker_analyzer/cmd/check.py similarity index 98% rename from analyzer/cmd/check.py rename to analyzer/codechecker_analyzer/cmd/check.py index bb0e84d6ad..596dd9d328 100644 --- a/analyzer/cmd/check.py +++ b/analyzer/codechecker_analyzer/cmd/check.py @@ -21,7 +21,6 @@ from codechecker_analyzer.analyzers import analyzer_types from libcodechecker import logger -from libcodechecker import libhandlers from libcodechecker.util import RawDescriptionDefaultHelpFormatter LOG = logger.get_logger('system') @@ -484,16 +483,6 @@ def main(args): logger.setup_logger(args.verbose if 'verbose' in args else None) - def __load_module(name): - """Loads the given subcommand's definition from the libs.""" - try: - module = libhandlers.load_module(name) - except ImportError: - LOG.error("Couldn't import subcommand '%s'", name) - raise - - return module - def __update_if_key_exists(source, target, key): """Append the source Namespace's element with 'key' to target with the same key, but only if it exists.""" @@ -532,7 +521,7 @@ def __update_if_key_exists(source, target, key): __update_if_key_exists(args, log_args, 'quiet') __update_if_key_exists(args, log_args, 'verbose') - log_module = __load_module('log') + import codechecker_analyzer.cmd.log as log_module LOG.debug("Calling LOG with args:") LOG.debug(log_args) @@ -579,7 +568,7 @@ def __update_if_key_exists(source, target, key): setattr(analyze_args, 'clean', True) __update_if_key_exists(args, analyze_args, 'verbose') - analyze_module = __load_module('analyze') + import codechecker_analyzer.cmd.analyze as analyze_module LOG.debug("Calling ANALYZE with args:") LOG.debug(analyze_args) @@ -594,7 +583,7 @@ def __update_if_key_exists(source, target, key): __update_if_key_exists(args, parse_args, 'verbose') __update_if_key_exists(args, parse_args, 'skipfile') - parse_module = __load_module('parse') + import codechecker_analyzer.cmd.parse as parse_module LOG.debug("Calling PARSE with args:") LOG.debug(parse_args) diff --git a/analyzer/cmd/checkers.py b/analyzer/codechecker_analyzer/cmd/checkers.py similarity index 100% rename from analyzer/cmd/checkers.py rename to analyzer/codechecker_analyzer/cmd/checkers.py diff --git a/analyzer/cmd/log.py b/analyzer/codechecker_analyzer/cmd/log.py similarity index 100% rename from analyzer/cmd/log.py rename to analyzer/codechecker_analyzer/cmd/log.py diff --git a/analyzer/cmd/parse.py b/analyzer/codechecker_analyzer/cmd/parse.py similarity index 100% rename from analyzer/cmd/parse.py rename to analyzer/codechecker_analyzer/cmd/parse.py diff --git a/analyzer/tools/build-logger/README.md b/analyzer/tools/build-logger/README.md index 0af5000e6b..46bd27a3d6 100644 --- a/analyzer/tools/build-logger/README.md +++ b/analyzer/tools/build-logger/README.md @@ -7,7 +7,6 @@ This tool can capture the build process and generate a To build the project execute ~~~~~~~ -cd analyzer/tools/build-logger make -f Makefile.manual ~~~~~~~ diff --git a/bin/CodeChecker.py b/bin/CodeChecker.py index 7df1cf4ef0..2eb7ffb546 100755 --- a/bin/CodeChecker.py +++ b/bin/CodeChecker.py @@ -12,12 +12,39 @@ from __future__ import absolute_import import argparse +import imp import json import os import signal import sys -from libcodechecker import libhandlers + +def add_subcommand(subparsers, sub_cmd, cmd_module_path): + """ + Load the subcommand module and then add the subcommand to the available + subcommands in the given subparsers collection. + + subparsers has to be the return value of the add_parsers() method on an + argparse.ArgumentParser. + """ + m_path, m_name = os.path.split(cmd_module_path) + module_name = os.path.splitext(m_name)[0] + + cc_bin = os.path.dirname(os.path.realpath(__file__)) + full_module_path = os.path.join(cc_bin, '..', 'lib', 'python2.7', m_path) + + # Load the module named as the argument. + cmd_file, cmd_path, cmd_descr = imp.find_module(module_name, + [full_module_path]) + command_module = imp.load_module(module_name, + cmd_file, cmd_path, cmd_descr) + + # Now that the module is loaded, construct an ArgumentParser for it. + sc_parser = subparsers.add_parser( + sub_cmd, **command_module.get_argparser_ctor_args()) + + # Run the method which adds the arguments to the subcommand's handler. + command_module.add_arguments_to_parser(sc_parser) def main(subcommands=None): @@ -76,12 +103,12 @@ def signal_handler(sig, frame): if first_command in subcommands: # Consider only the given command as an available one. - subcommands = [first_command] + subcommands = {first_command: subcommands[first_command]} for subcommand in subcommands: - try: - libhandlers.add_subcommand(subparsers, str(subcommand)) + add_subcommand(subparsers, subcommand, + subcommands[subcommand]) except (IOError, ImportError): print("Couldn't import module for subcommand '" + subcommand + "'... ignoring.") diff --git a/tools/__init__.py b/libcodechecker/cmd/__init__.py similarity index 100% rename from tools/__init__.py rename to libcodechecker/cmd/__init__.py diff --git a/libcodechecker/libhandlers/version.py b/libcodechecker/cmd/version.py similarity index 91% rename from libcodechecker/libhandlers/version.py rename to libcodechecker/cmd/version.py index ade0e32f19..8c643360f9 100644 --- a/libcodechecker/libhandlers/version.py +++ b/libcodechecker/cmd/version.py @@ -63,7 +63,7 @@ def main(args): has_analyzer_version = False try: - from libcodechecker.libhandlers import analyzer_version + from codechecker_analyzer.cmd import analyzer_version has_analyzer_version = True # Print analyzer version information. @@ -73,13 +73,13 @@ def main(args): pass try: - from libcodechecker.libhandlers import webserver_version + from codechecker_web.cmd import web_version if has_analyzer_version: print() # Print a new line to separate version information. # Print web server version information. - print("CodeChecker web server version:") - webserver_version.print_version(output_format) + print("CodeChecker web version:") + web_version.print_version(output_format) except Exception: pass diff --git a/libcodechecker/libhandlers/__init__.py b/libcodechecker/libhandlers/__init__.py deleted file mode 100644 index ef362c97d0..0000000000 --- a/libcodechecker/libhandlers/__init__.py +++ /dev/null @@ -1,64 +0,0 @@ -# ------------------------------------------------------------------------- -# The CodeChecker Infrastructure -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# ------------------------------------------------------------------------- -""" -The libcodechecker.libhandlers package contains the individual subcommands that -can be used in CodeChecker. Each module in itself defines its subcommand's -argument list, help text, and the invocation. - -This file contains basic methods to handle dynamic subcommand loading. -""" -from __future__ import print_function -from __future__ import division -from __future__ import absolute_import - -import imp - - -def load_module(name): - """ - Load the subcommand module with the given name from the package. - This method returns the Python module object. - """ - # Even though command verbs and nouns are joined by a - # hyphen, the Python files contain underscores. - name = name.replace('-', '_') - - # Load the 'libcodechecker' module and acquire its path. - cc_file, cc_path, cc_descr = imp.find_module("libcodechecker") - libcc_path = imp.load_module("libcodechecker", - cc_file, cc_path, cc_descr).__path__ - - # Load the 'libcodechecker.libhandlers' module and acquire its path. - handler_file, handler_path, handler_descr = \ - imp.find_module("libhandlers", libcc_path) - libhandlers_path = imp.load_module("libhandlers", - handler_file, - handler_path, - handler_descr).__path__ - - # Load the module named as the argument. - command_file, command_path, command_descr = \ - imp.find_module(name, libhandlers_path) - return imp.load_module(name, command_file, command_path, command_descr) - - -def add_subcommand(subparsers, subcommand): - """ - Load the subcommand module and then add the subcommand to the available - subcommands in the given subparsers collection. - - subparsers has to be the return value of the add_parsers() method on an - argparse.ArgumentParser. - """ - - command_module = load_module(subcommand) - - # Now that the module is loaded, construct an ArgumentParser for it. - sc_parser = subparsers.add_parser( - subcommand, **command_module.get_argparser_ctor_args()) - - # Run the method which adds the arguments to the subcommand's handler. - command_module.add_arguments_to_parser(sc_parser) diff --git a/scripts/build/create_commands.py b/scripts/build/create_commands.py index d594f6a19f..34a99d3960 100755 --- a/scripts/build/create_commands.py +++ b/scripts/build/create_commands.py @@ -18,7 +18,7 @@ LOG.addHandler(log_handler) -def copy_entry_points(input_dirs, build_dir): +def copy_entry_points(input_data, build_dir): """ Copy CodeChecker entry point sub-commands. """ @@ -26,8 +26,11 @@ def copy_entry_points(input_dirs, build_dir): package_bin = os.path.join(package_root, 'bin') target_cc = os.path.join(package_root, 'cc_bin') - available_commands = [] - for input_dir in input_dirs: + available_commands = {} + for i in input_data: + module_name = i.split(':')[1] + input_dir = i.split(':')[0] + for input_file in glob.glob(os.path.join(input_dir, '*')): file_name = os.path.basename(input_file) if not file_name.endswith(".py"): @@ -36,7 +39,10 @@ def copy_entry_points(input_dirs, build_dir): # entry points. if file_name.startswith("codechecker-"): command_name = file_name.replace("codechecker-", "") - available_commands.append(command_name) + + file_name = command_name.replace('-', '_') + module_path = module_name + '/' + file_name + '.py' + available_commands[command_name] = module_path skip_content = "# DO_NOT_INSTALL_TO_PATH" with open(input_file, 'r') as file: @@ -57,11 +63,9 @@ def copy_entry_points(input_dirs, build_dir): # .py files are Python code that must run in a valid env. shutil.copy2(input_file, target_cc) - available_commands.sort() - commands_json = os.path.join(target_cc, 'commands.json') with open(commands_json, 'w') as commands: - json.dump(available_commands, commands, sort_keys=True) + json.dump(available_commands, commands, sort_keys=True, indent=2) if __name__ == "__main__": @@ -76,7 +80,10 @@ def copy_entry_points(input_dirs, build_dir): nargs='+', metavar='folder', help="List of directories which contains CodeChecker " - "sub-commands") + "sub-commands. The format of sub-commands is: " + ":, where " + " is the module where the " + "sub-command can be found.") parser.add_argument('-b', '--build-dir', required=True, diff --git a/tools/plist_to_html/__init__.py b/web/client/codechecker_client/cmd/__init__.py similarity index 100% rename from tools/plist_to_html/__init__.py rename to web/client/codechecker_client/cmd/__init__.py diff --git a/web/client/cmd/cmd.py b/web/client/codechecker_client/cmd/cmd.py similarity index 100% rename from web/client/cmd/cmd.py rename to web/client/codechecker_client/cmd/cmd.py diff --git a/web/client/cmd/store.py b/web/client/codechecker_client/cmd/store.py similarity index 100% rename from web/client/cmd/store.py rename to web/client/codechecker_client/cmd/store.py diff --git a/web/codechecker_web/cmd/__init__.py b/web/codechecker_web/cmd/__init__.py new file mode 100644 index 0000000000..9f68a237a0 --- /dev/null +++ b/web/codechecker_web/cmd/__init__.py @@ -0,0 +1,5 @@ +# ------------------------------------------------------------------------- +# The CodeChecker Infrastructure +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# ------------------------------------------------------------------------- diff --git a/web/cmd/web_version.py b/web/codechecker_web/cmd/web_version.py similarity index 100% rename from web/cmd/web_version.py rename to web/codechecker_web/cmd/web_version.py diff --git a/web/server/codechecker_server/cmd/__init__.py b/web/server/codechecker_server/cmd/__init__.py new file mode 100644 index 0000000000..9f68a237a0 --- /dev/null +++ b/web/server/codechecker_server/cmd/__init__.py @@ -0,0 +1,5 @@ +# ------------------------------------------------------------------------- +# The CodeChecker Infrastructure +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# ------------------------------------------------------------------------- diff --git a/web/server/cmd/server.py b/web/server/codechecker_server/cmd/server.py similarity index 100% rename from web/server/cmd/server.py rename to web/server/codechecker_server/cmd/server.py diff --git a/web/tests/Makefile b/web/tests/Makefile index 579882777f..5c0cc6330c 100644 --- a/web/tests/Makefile +++ b/web/tests/Makefile @@ -26,19 +26,19 @@ test_novenv: pycodestyle pylint test_unit_novenv test_functional_novenv PYCODESTYLE_TEST_CMD = pycodestyle \ --exclude=server/codechecker_server/migrations \ - bin cmd codechecker_web tests \ - client/bin client/codechecker_client client/cmd \ - server/bin server/codechecker_server server/cmd server/tests \ + bin codechecker_web tests \ + client/bin client/codechecker_client \ + server/bin server/codechecker_server server/tests \ tests pycodestyle: venv_dev $(ACTIVATE_DEV_VENV) && $(PYCODESTYLE_TEST_CMD) -PYLINT_TEST_CMD = pylint bin/codechecker-web-version cmd/web_version.py \ +PYLINT_TEST_CMD = pylint bin/codechecker-web-version \ codechecker_web \ - client/cmd/cmd.py client/cmd/store.py client/codechecker_client \ - server/bin/codechecker-server server/cmd/server.py \ - server/codechecker_server server/tests/unit \ + client/bin/codechecker-cmd client/bin/codechecker-store \ + client/codechecker_client \ + server/bin/codechecker-server server/codechecker_server server/tests/unit \ --rcfile=$(ROOT)/.pylintrc \ --disable=all \ --enable=logging-format-interpolation,old-style-class