def __init__(self, args, reporter=None, exit=True): # pylint: disable=redefined-builtin self._rcfile = None self._plugins = [] self.verbose = None try: preprocess_options( args, { # option: (callback, takearg) "init-hook": (cb_init_hook, True), "rcfile": (self.cb_set_rcfile, True), "load-plugins": (self.cb_add_plugins, True), "verbose": (self.cb_verbose_mode, False), }, ) except ArgumentPreprocessingError as ex: print(ex, file=sys.stderr) sys.exit(32) self.linter = linter = self.LinterClass( ( ( "rcfile", { "action": "callback", "callback": Run._return_one, "group": "Commands", "type": "string", "metavar": "<file>", "help": "Specify a configuration file to load.", }, ), ( "init-hook", { "action": "callback", "callback": Run._return_one, "type": "string", "metavar": "<code>", "level": 1, "help": "Python code to execute, usually for sys.path " "manipulation such as pygtk.require().", }, ), ( "help-msg", { "action": "callback", "type": "string", "metavar": "<msg-id>", "callback": self.cb_help_message, "group": "Commands", "help": "Display a help message for the given message id and " "exit. The value may be a comma separated list of message ids.", }, ), ( "list-msgs", { "action": "callback", "metavar": "<msg-id>", "callback": self.cb_list_messages, "group": "Commands", "level": 1, "help": "Generate pylint's messages.", }, ), ( "list-msgs-enabled", { "action": "callback", "metavar": "<msg-id>", "callback": self.cb_list_messages_enabled, "group": "Commands", "level": 1, "help": "Display a list of what messages are enabled " "and disabled with the given configuration.", }, ), ( "list-groups", { "action": "callback", "metavar": "<msg-id>", "callback": self.cb_list_groups, "group": "Commands", "level": 1, "help": "List pylint's message groups.", }, ), ( "list-conf-levels", { "action": "callback", "callback": cb_list_confidence_levels, "group": "Commands", "level": 1, "help": "Generate pylint's confidence levels.", }, ), ( "list-extensions", { "action": "callback", "callback": cb_list_extensions, "group": "Commands", "level": 1, "help": "List available extensions.", }, ), ( "full-documentation", { "action": "callback", "metavar": "<msg-id>", "callback": self.cb_full_documentation, "group": "Commands", "level": 1, "help": "Generate pylint's full documentation.", }, ), ( "generate-rcfile", { "action": "callback", "callback": self.cb_generate_config, "group": "Commands", "help": "Generate a sample configuration file according to " "the current configuration. You can put other options " "before this one to get them in the generated " "configuration.", }, ), ( "generate-man", { "action": "callback", "callback": self.cb_generate_manpage, "group": "Commands", "help": "Generate pylint's man page.", "hide": True, }, ), ( "errors-only", { "action": "callback", "callback": self.cb_error_mode, "short": "E", "help": "In error mode, checkers without error messages are " "disabled and for others, only the ERROR messages are " "displayed, and no reports are done by default.", }, ), ( "py3k", { "action": "callback", "callback": self.cb_python3_porting_mode, "help": "In Python 3 porting mode, all checkers will be " "disabled and only messages emitted by the porting " "checker will be displayed.", }, ), ( "verbose", { "action": "callback", "callback": self.cb_verbose_mode, "short": "v", "help": "In verbose mode, extra non-checker-related info " "will be displayed.", }, ), ), option_groups=self.option_groups, pylintrc=self._rcfile, ) # register standard checkers linter.load_default_plugins() # load command line plugins linter.load_plugin_modules(self._plugins) # add some help section linter.add_help_section("Environment variables", config.ENV_HELP, level=1) # pylint: disable=bad-continuation linter.add_help_section( "Output", "Using the default text output, the message format is : \n" " \n" " MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE \n" " \n" "There are 5 kind of message types : \n" " * (C) convention, for programming standard violation \n" " * (R) refactor, for bad code smell \n" " * (W) warning, for python specific problems \n" " * (E) error, for probable bugs in the code \n" " * (F) fatal, if an error occurred which prevented pylint from doing further\n" "processing.\n", level=1, ) linter.add_help_section( "Output status code", "Pylint should leave with following status code: \n" " * 0 if everything went fine \n" " * 1 if a fatal message was issued \n" " * 2 if an error message was issued \n" " * 4 if a warning message was issued \n" " * 8 if a refactor message was issued \n" " * 16 if a convention message was issued \n" " * 32 on usage error \n" " \n" "status 1 to 16 will be bit-ORed so you can know which different categories has\n" "been issued by analysing pylint output status code\n", level=1, ) # read configuration linter.disable("I") linter.enable("c-extension-no-member") linter.read_config_file(verbose=self.verbose) config_parser = linter.cfgfile_parser # run init hook, if present, before loading plugins if config_parser.has_option("MASTER", "init-hook"): cb_init_hook( "init-hook", utils._unquote(config_parser.get("MASTER", "init-hook"))) # is there some additional plugins in the file configuration, in if config_parser.has_option("MASTER", "load-plugins"): plugins = utils._splitstrip( config_parser.get("MASTER", "load-plugins")) linter.load_plugin_modules(plugins) # now we can load file config and command line, plugins (which can # provide options) have been registered linter.load_config_file() if reporter: # if a custom reporter is provided as argument, it may be overridden # by file parameters, so re-set it here, but before command line # parsing so it's still overrideable by command line option linter.set_reporter(reporter) try: args = linter.load_command_line_configuration(args) except SystemExit as exc: if exc.code == 2: # bad options exc.code = 32 raise if not args: print(linter.help()) sys.exit(32) if linter.config.jobs < 0: print( "Jobs number (%d) should be greater than or equal to 0" % linter.config.jobs, file=sys.stderr, ) sys.exit(32) if linter.config.jobs > 1 or linter.config.jobs == 0: if multiprocessing is None: print( "Multiprocessing library is missing, " "fallback to single process", file=sys.stderr, ) linter.set_option("jobs", 1) elif linter.config.jobs == 0: linter.config.jobs = _cpu_count() # We have loaded configuration from config file and command line. Now, we can # load plugin specific configuration. linter.load_plugin_configuration() linter.check(args) score_value = linter.generate_reports() if exit: if linter.config.exit_zero: sys.exit(0) else: if score_value and score_value > linter.config.fail_under: sys.exit(0) sys.exit(self.linter.msg_status)
def _config_initialization( linter: "PyLinter", args_list: List[str], reporter: Union[reporters.BaseReporter, reporters.MultiReporter, None] = None, config_file: Union[None, str, Path] = None, verbose_mode: bool = False, ) -> List[str]: """Parse all available options, read config files and command line arguments and set options accordingly. """ config_file = Path(config_file) if config_file else None # Set the current module to the configuration file # to allow raising messages on the configuration file. linter.set_current_module(str(config_file) if config_file else None) # Read the configuration file config_file_parser = config._ConfigurationFileParser(verbose_mode, linter) try: config_data, config_args = config_file_parser.parse_config_file( file_path=config_file ) except OSError as ex: print(ex, file=sys.stderr) sys.exit(32) # Run init hook, if present, before loading plugins if "init-hook" in config_data: exec(utils._unquote(config_data["init-hook"])) # pylint: disable=exec-used # Load plugins if specified in the config file if "load-plugins" in config_data: linter.load_plugin_modules(utils._splitstrip(config_data["load-plugins"])) # pylint: disable-next=fixme # TODO: Remove everything until set_reporter once the optparse # implementation is no longer needed # Load optparse command line arguments try: # The parser is stored on linter.cfgfile_parser with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) linter.read_config_file(config_file=config_file, verbose=verbose_mode) except OSError as ex: print(ex, file=sys.stderr) sys.exit(32) # Now we can load file config, plugins (which can # provide options) have been registered with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) linter.load_config_file() # pylint: disable-next=fixme # TODO: Optparse: This has been disabled pre-maturely because it interferes with # argparse option parsing for 'disable' and 'enable'. # try: # with warnings.catch_warnings(): # warnings.filterwarnings("ignore", category=DeprecationWarning) # linter.load_command_line_configuration(args_list) # except SystemExit as exc: # if exc.code == 2: # bad options # exc.code = 32 # raise # First we parse any options from a configuration file linter._parse_configuration_file(config_args) # Then, if a custom reporter is provided as argument, it may be overridden # by file parameters, so we re-set it here. We do this before command line # parsing, so it's still overridable by command line options if reporter: linter.set_reporter(reporter) # Now we parse any options from the command line, so they can override # the configuration file parsed_args_list = linter._parse_command_line_configuration(args_list) # We have loaded configuration from config file and command line. Now, we can # load plugin specific configuration. linter.load_plugin_configuration() # parsed_args_list should now only be a list of files/directories to lint. # All other options have been removed from the list. if not parsed_args_list: print(linter.help()) sys.exit(32) # Now that plugins are loaded, get list of all fail_on messages, and enable them linter.enable_fail_on_messages() linter._parse_error_mode() return parsed_args_list
def _config_initialization( linter: "PyLinter", args_list: List[str], reporter: Union[reporters.BaseReporter, reporters.MultiReporter, None] = None, config_file: Union[None, str, Path] = None, verbose_mode: Optional[bool] = None, ) -> List[str]: """Parse all available options, read config files and command line arguments and set options accordingly. """ # Read the config file. The parser is stored on linter.cfgfile_parser try: linter.read_config_file(config_file=config_file, verbose=verbose_mode) except OSError as ex: print(ex, file=sys.stderr) sys.exit(32) config_parser = linter.cfgfile_parser # Run init hook, if present, before loading plugins if config_parser.has_option("MASTER", "init-hook"): exec( # pylint: disable=exec-used utils._unquote(config_parser.get("MASTER", "init-hook"))) # Load plugins if specified in the config file if config_parser.has_option("MASTER", "load-plugins"): plugins = utils._splitstrip(config_parser.get("MASTER", "load-plugins")) linter.load_plugin_modules(plugins) # Now we can load file config, plugins (which can # provide options) have been registered linter.load_config_file() if reporter: # If a custom reporter is provided as argument, it may be overridden # by file parameters, so re-set it here, but before command line # parsing, so it's still overridable by command line option linter.set_reporter(reporter) # Load command line arguments try: args_list = linter.load_command_line_configuration(args_list) except SystemExit as exc: if exc.code == 2: # bad options exc.code = 32 raise # args_list should now only be a list of files/directories to lint. All options have # been removed from the list if not args_list: print(linter.help()) sys.exit(32) # We have loaded configuration from config file and command line. Now, we can # load plugin specific configuration. linter.load_plugin_configuration() # Now that plugins are loaded, get list of all fail_on messages, and enable them linter.enable_fail_on_messages() return args_list
def _config_initialization( linter: PyLinter, args_list: list[str], reporter: reporters.BaseReporter | reporters.MultiReporter | None = None, config_file: None | str | Path = None, verbose_mode: bool = False, ) -> list[str]: """Parse all available options, read config files and command line arguments and set options accordingly. """ config_file = Path(config_file) if config_file else None # Set the current module to the configuration file # to allow raising messages on the configuration file. linter.set_current_module(str(config_file) if config_file else "") # Read the configuration file config_file_parser = _ConfigurationFileParser(verbose_mode, linter) try: config_data, config_args = config_file_parser.parse_config_file( file_path=config_file) except OSError as ex: print(ex, file=sys.stderr) sys.exit(32) # Run init hook, if present, before loading plugins if "init-hook" in config_data: exec(utils._unquote(config_data["init-hook"])) # pylint: disable=exec-used # Load plugins if specified in the config file if "load-plugins" in config_data: linter.load_plugin_modules( utils._splitstrip(config_data["load-plugins"])) unrecognized_options_message = None # First we parse any options from a configuration file try: linter._parse_configuration_file(config_args) except _UnrecognizedOptionError as exc: unrecognized_options_message = ", ".join(exc.options) # Then, if a custom reporter is provided as argument, it may be overridden # by file parameters, so we re-set it here. We do this before command line # parsing, so it's still overridable by command line options if reporter: linter.set_reporter(reporter) # Set the current module to the command line # to allow raising messages on it linter.set_current_module("Command line") # Now we parse any options from the command line, so they can override # the configuration file parsed_args_list = linter._parse_command_line_configuration(args_list) # Check if there are any options that we do not recognize unrecognized_options: list[str] = [] for opt in parsed_args_list: if opt.startswith("--"): unrecognized_options.append(opt[2:]) elif opt.startswith("-"): unrecognized_options.append(opt[1:]) if unrecognized_options: msg = ", ".join(unrecognized_options) linter._arg_parser.error(f"Unrecognized option found: {msg}") # Now that config file and command line options have been loaded # with all disables, it is safe to emit messages if unrecognized_options_message is not None: linter.set_current_module(str(config_file) if config_file else "") linter.add_message("unrecognized-option", args=unrecognized_options_message, line=0) linter._emit_stashed_messages() # Set the current module to configuration as we don't know where # the --load-plugins key is coming from linter.set_current_module("Command line or configuration file") # We have loaded configuration from config file and command line. Now, we can # load plugin specific configuration. linter.load_plugin_configuration() # Now that plugins are loaded, get list of all fail_on messages, and enable them linter.enable_fail_on_messages() linter._parse_error_mode() # Link the base Namespace object on the current directory linter._directory_namespaces[Path(".").resolve()] = (linter.config, {}) # parsed_args_list should now only be a list of files/directories to lint. # All other options have been removed from the list. return parsed_args_list
def __init__( self, args, reporter=None, exit=True, do_exit=UNUSED_PARAM_SENTINEL, ): # pylint: disable=redefined-builtin self._rcfile = None self._output = None self._version_asked = False self._plugins = [] self.verbose = None try: preprocess_options( args, { # option: (callback, takearg) "version": (self.version_asked, False), "init-hook": (cb_init_hook, True), "rcfile": (self.cb_set_rcfile, True), "load-plugins": (self.cb_add_plugins, True), "enable-all-extensions": (self.cb_enable_all_extensions, False), "verbose": (self.cb_verbose_mode, False), "output": (self.cb_set_output, True), }, ) except ArgumentPreprocessingError as ex: print(ex, file=sys.stderr) sys.exit(32) self.linter = linter = self.LinterClass( ( ( "rcfile", { "action": "callback", "callback": Run._return_one, "group": "Commands", "type": "string", "metavar": "<file>", "help": "Specify a configuration file to load.", }, ), ( "output", { "action": "callback", "callback": Run._return_one, "group": "Commands", "type": "string", "metavar": "<file>", "help": "Specify an output file.", }, ), ( "init-hook", { "action": "callback", "callback": Run._return_one, "type": "string", "metavar": "<code>", "level": 1, "help": "Python code to execute, usually for sys.path " "manipulation such as pygtk.require().", }, ), ( "help-msg", { "action": "callback", "type": "string", "metavar": "<msg-id>", "callback": self.cb_help_message, "group": "Commands", "help": "Display a help message for the given message id and " "exit. The value may be a comma separated list of message ids.", }, ), ( "list-msgs", { "action": "callback", "metavar": "<msg-id>", "callback": self.cb_list_messages, "group": "Commands", "level": 1, "help": "Display a list of all pylint's messages divided by whether " "they are emittable with the given interpreter.", }, ), ( "list-msgs-enabled", { "action": "callback", "metavar": "<msg-id>", "callback": self.cb_list_messages_enabled, "group": "Commands", "level": 1, "help": "Display a list of what messages are enabled, " "disabled and non-emittable with the given configuration.", }, ), ( "list-groups", { "action": "callback", "metavar": "<msg-id>", "callback": self.cb_list_groups, "group": "Commands", "level": 1, "help": "List pylint's message groups.", }, ), ( "list-conf-levels", { "action": "callback", "callback": cb_list_confidence_levels, "group": "Commands", "level": 1, "help": "Generate pylint's confidence levels.", }, ), ( "list-extensions", { "action": "callback", "callback": cb_list_extensions, "group": "Commands", "level": 1, "help": "List available extensions.", }, ), ( "full-documentation", { "action": "callback", "metavar": "<msg-id>", "callback": self.cb_full_documentation, "group": "Commands", "level": 1, "help": "Generate pylint's full documentation.", }, ), ( "generate-rcfile", { "action": "callback", "callback": self.cb_generate_config, "group": "Commands", "help": "Generate a sample configuration file according to " "the current configuration. You can put other options " "before this one to get them in the generated " "configuration.", }, ), ( "generate-man", { "action": "callback", "callback": self.cb_generate_manpage, "group": "Commands", "help": "Generate pylint's man page.", "hide": True, }, ), ( "errors-only", { "action": "callback", "callback": self.cb_error_mode, "short": "E", "help": "In error mode, checkers without error messages are " "disabled and for others, only the ERROR messages are " "displayed, and no reports are done by default.", }, ), ( "verbose", { "action": "callback", "callback": self.cb_verbose_mode, "short": "v", "help": "In verbose mode, extra non-checker-related info " "will be displayed.", }, ), ( "enable-all-extensions", { "action": "callback", "callback": self.cb_enable_all_extensions, "help": "Load and enable all available extensions. " "Use --list-extensions to see a list all available extensions.", }, ), ), option_groups=self.option_groups, pylintrc=self._rcfile, ) # register standard checkers if self._version_asked: print(full_version) sys.exit(0) linter.load_default_plugins() # load command line plugins linter.load_plugin_modules(self._plugins) # add some help section linter.add_help_section( "Environment variables", f""" The following environment variables are used: * PYLINTHOME Path to the directory where persistent data for the run will be stored. If not found, it defaults to '{DEFAULT_PYLINT_HOME}' or '{OLD_DEFAULT_PYLINT_HOME}' (in the current working directory). * PYLINTRC Path to the configuration file. See the documentation for the method used to search for configuration file. """, level=1, ) linter.add_help_section( "Output", "Using the default text output, the message format is : \n" " \n" " MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE \n" " \n" "There are 5 kind of message types : \n" " * (C) convention, for programming standard violation \n" " * (R) refactor, for bad code smell \n" " * (W) warning, for python specific problems \n" " * (E) error, for probable bugs in the code \n" " * (F) fatal, if an error occurred which prevented pylint from doing further\n" "processing.\n", level=1, ) linter.add_help_section( "Output status code", "Pylint should leave with following status code: \n" " * 0 if everything went fine \n" " * 1 if a fatal message was issued \n" " * 2 if an error message was issued \n" " * 4 if a warning message was issued \n" " * 8 if a refactor message was issued \n" " * 16 if a convention message was issued \n" " * 32 on usage error \n" " \n" "status 1 to 16 will be bit-ORed so you can know which different categories has\n" "been issued by analysing pylint output status code\n", level=1, ) # read configuration linter.disable("I") linter.enable("c-extension-no-member") try: linter.read_config_file(verbose=self.verbose) except OSError as ex: print(ex, file=sys.stderr) sys.exit(32) config_parser = linter.cfgfile_parser # run init hook, if present, before loading plugins if config_parser.has_option("MASTER", "init-hook"): cb_init_hook( "init-hook", utils._unquote(config_parser.get("MASTER", "init-hook"))) # is there some additional plugins in the file configuration, in if config_parser.has_option("MASTER", "load-plugins"): plugins = utils._splitstrip( config_parser.get("MASTER", "load-plugins")) linter.load_plugin_modules(plugins) # now we can load file config and command line, plugins (which can # provide options) have been registered linter.load_config_file() if reporter: # if a custom reporter is provided as argument, it may be overridden # by file parameters, so re-set it here, but before command line # parsing so it's still overrideable by command line option linter.set_reporter(reporter) try: args = linter.load_command_line_configuration(args) except SystemExit as exc: if exc.code == 2: # bad options exc.code = 32 raise if not args: print(linter.help()) sys.exit(32) if linter.config.jobs < 0: print( f"Jobs number ({linter.config.jobs}) should be greater than or equal to 0", file=sys.stderr, ) sys.exit(32) if linter.config.jobs > 1 or linter.config.jobs == 0: if multiprocessing is None: print( "Multiprocessing library is missing, fallback to single process", file=sys.stderr, ) linter.set_option("jobs", 1) elif linter.config.jobs == 0: linter.config.jobs = _cpu_count() # We have loaded configuration from config file and command line. Now, we can # load plugin specific configuration. linter.load_plugin_configuration() # Now that plugins are loaded, get list of all fail_on messages, and enable them linter.enable_fail_on_messages() if self._output: try: with open(self._output, "w", encoding="utf-8") as output: linter.reporter.out = output linter.check(args) score_value = linter.generate_reports() except OSError as ex: print(ex, file=sys.stderr) sys.exit(32) else: linter.check(args) score_value = linter.generate_reports() if do_exit is not UNUSED_PARAM_SENTINEL: warnings.warn( "do_exit is deprecated and it is going to be removed in a future version.", DeprecationWarning, ) exit = do_exit if exit: if linter.config.exit_zero: sys.exit(0) elif linter.any_fail_on_issues(): # We need to make sure we return a failing exit code in this case. # So we use self.linter.msg_status if that is non-zero, otherwise we just return 1. sys.exit(self.linter.msg_status or 1) elif score_value is not None: if score_value >= linter.config.fail_under: sys.exit(0) else: # We need to make sure we return a failing exit code in this case. # So we use self.linter.msg_status if that is non-zero, otherwise we just return 1. sys.exit(self.linter.msg_status or 1) else: sys.exit(self.linter.msg_status)