def _check_base_parsers(base_parsers: List[base.BaseParser], attrdict: dict) -> None: """Check that the base parser list fulfills all requirements.""" if base.BaseParser.REPO_DISCOVERY in base_parsers: # the REPO_DISCOVERY parser requires both the STUDENTS parser and # the api argument to the command function, see # https://github.com/repobee/repobee/issues/716 for details if base.BaseParser.STUDENTS not in base_parsers: raise exceptions.PlugError( "REPO_DISCOVERY parser requires STUDENT parser") elif "api" not in inspect.signature(attrdict["command"]).parameters: raise exceptions.PlugError( "REPO_DISCOVERY parser requires command function to use api " "argument")
def _inner(func): if "repobee_plug_spec" not in dir(func): raise exceptions.PlugError("can't deprecate non-hook function", func=func) deprs = _Deprecations() deprs.deprecate_hook(func.__name__, dep) return func
def _check_for_cycle(self, paths: List[pathlib.Path]) -> None: """Check if there's a cycle in the inheritance.""" if self.path in paths: cycle = " -> ".join(map(str, paths + [self.path])) raise exceptions.PlugError( f"Cyclic inheritance detected in config: {cycle}" ) elif self.parent is not None: self.parent._check_for_cycle(paths + [self.path])
def _process_cli_plugin(bases, attrdict) -> dict: """Process a CLI plugin, generate its hook functions, and return a new attrdict with all attributes set correctly. """ attrdict_copy = dict(attrdict) # copy to avoid mutating original if cli.Command in bases and cli.CommandExtension in bases: raise exceptions.PlugError( "A plugin cannot be both a Command and a CommandExtension") if cli.Command in bases: settings = attrdict_copy.get("__settings__", cli.command_settings()) attrdict_copy["__settings__"] = settings _check_base_parsers(settings.base_parsers or [], attrdict_copy) elif cli.CommandExtension in bases: if "__settings__" not in attrdict_copy: raise exceptions.PlugError( "CommandExtension must have a '__settings__' attribute") handle_processed_args = _generate_handle_processed_args_func() attrdict_copy[handle_processed_args.__name__] = handle_processed_args attrdict_copy["attach_options"] = _attach_options configurable_argnames = list(_get_configurable_arguments(attrdict)) if configurable_argnames: def get_configurable_args(self) -> ConfigurableArguments: return ConfigurableArguments( config_section_name=self.__settings__.config_section_name or self.__plugin_name__, argnames=list( _get_configurable_arguments(self.__class__.__dict__)), ) attrdict_copy[get_configurable_args.__name__] = get_configurable_args return attrdict_copy
def _attach_options(self, config, parser): parser = (parser if not isinstance( self, cli.CommandExtension) else parser.add_argument_group( title=self.__plugin_name__, description=f"Arguments for the {self.__plugin_name__} plugin", )) config_name = self.__settings__.config_section_name or self.__plugin_name__ config_section = dict(config[config_name]) if config_name in config else {} opts = _extract_cli_options(self.__class__.__dict__) for (name, opt) in opts: configured_value = _get_configured_value(name, opt, config_section) if configured_value and not (hasattr(opt, "configurable") and opt.configurable): raise exceptions.PlugError( f"Plugin '{self.__plugin_name__}' does not allow " f"'{name}' to be configured") _add_option(name, opt, configured_value, parser) return parser
def _attach_options(self, config: repobee_plug.config.Config, parser): parser = (parser if not isinstance( self, cli.CommandExtension) else parser.add_argument_group( title=self.__plugin_name__, description=f"Arguments for the {self.__plugin_name__} plugin", )) section_name = (self.__settings__.config_section_name or self.__plugin_name__) opts = _extract_cli_options(self.__class__.__dict__) for (arg_name, opt) in opts: configured_value = config.get(section_name, arg_name) if configured_value and not getattr(opt, "configurable", None): raise exceptions.PlugError( f"Plugin '{self.__plugin_name__}' does not allow " f"'{arg_name}' to be configured") converted_value = (_convert_configured_value(opt, configured_value) if isinstance(opt, _Option) else None) _add_option(arg_name, opt, converted_value, parser) return parser
def path(self) -> pathlib.Path: if not self._path: raise exceptions.PlugError("path not set") return self._path