def check_config_integrity(config_file: Union[str, pathlib.Path]) -> None: """Raise an exception if the configuration file contains syntactical errors, or if the defaults are misconfigured. Note that plugin options are not checked. Args: config_file: path to the config file. """ config_file = pathlib.Path(config_file) if not config_file.is_file(): raise exception.FileError( "no config file found, expected location: " + str(config_file) ) try: defaults = _read_defaults(config_file) except configparser.ParsingError as exc: errors = ", ".join( f"(line {line_nr}: {line})" for line_nr, line in exc.errors ) raise exception.FileError( msg=( f"config file at {config_file} contains syntax errors: " f"{errors}" ) ) check_defaults(defaults, config_file)
def _extract_groups(args: argparse.Namespace) -> List[plug.StudentTeam]: """Extract groups from args namespace.` Args: args: A namespace object. Returns: a list of student usernames, or None of neither `students` or `students_file` is in the namespace. """ if "students" in args and args.students: students = [plug.StudentTeam(members=[s]) for s in args.students] elif "students_file" in args and args.students_file: students_file = pathlib.Path(args.students_file).resolve() if not students_file.is_file(): raise exception.FileError( "'{!s}' is not a file".format(students_file)) if not students_file.stat().st_size: raise exception.FileError("'{!s}' is empty".format(students_file)) students = [ plug.StudentTeam(members=[s for s in group.strip().split()]) for group in students_file.read_text( encoding=sys.getdefaultencoding()).split(os.linesep) if group # skip blank lines ] else: students = [] return students
def _extract_groups(args: argparse.Namespace) -> List[plug.StudentTeam]: """Extract groups from args namespace.` Args: args: A namespace object. Returns: a list of student usernames, or None of neither `students` or `students_file` is in the namespace. """ if "students" in args and args.students: students = [plug.StudentTeam(members=[s]) for s in args.students] elif "students_file" in args and args.students_file: students_file = pathlib.Path(args.students_file).resolve() if not students_file.is_file(): raise exception.FileError(f"'{students_file}' is not a file") if not students_file.stat().st_size: raise exception.FileError(f"'{students_file}' is empty") students = list( plug.manager.hook.parse_students_file(students_file=students_file)) else: students = [] return students
def setup_logging(terminal_level: int = logging.WARNING) -> None: """Setup logging by creating the required log directory and setting up the logger. Args: terminal_level: The logging level to use for printing to stderr. """ logfile = constants.LOG_DIR / f"{_repobee._external_package_name}.log" _ensure_size_less(logfile, max_size=constants.MAX_LOGFILE_SIZE) try: os.makedirs(str(constants.LOG_DIR), exist_ok=True) except Exception as exc: raise exception.FileError( f"can't create log directory at {constants.LOG_DIR}") from exc daiquiri.setup( level=logging.DEBUG, outputs=( daiquiri.output.Stream( sys.stderr, formatter=daiquiri.formatter.ColorFormatter( fmt="%(color)s[%(levelname)s] %(message)s%(color_stop)s"), level=terminal_level, ), daiquiri.output.File( filename=str(logfile), formatter=daiquiri.formatter.ColorFormatter( fmt="%(asctime)s [PID %(process)d] [%(levelname)s] " "%(name)s -> %(message)s"), level=logging.DEBUG, ), ), ) _filter_tokens()
def _read_config(config_file: pathlib.Path) -> configparser.ConfigParser: config_parser = configparser.ConfigParser() try: config_parser.read(str(config_file)) except configparser.MissingSectionHeaderError: pass # handled by the next check if constants.CORE_SECTION_HDR not in config_parser: raise exception.FileError( "config file at '{!s}' does not contain the required " "[repobee] header".format(config_file)) return config_parser
def _read_config(config_file: pathlib.Path) -> configparser.ConfigParser: config_parser = configparser.ConfigParser() try: config_parser.read(str(config_file)) except configparser.MissingSectionHeaderError: pass # handled by the next check if plug.Config.CORE_SECTION_NAME not in config_parser: raise exception.FileError( f"config file at '{str(config_file)}' does not contain the " f"required [repobee] header") return config_parser
def _check_defaults(defaults: Mapping[str, str], config_file: Union[str, pathlib.Path]): """Raise an exception if defaults contain keys that are not configurable arguments. Args: defaults: A dictionary of defaults. config_file: Path to the config file. """ configured = defaults.keys() if (configured - constants.CONFIGURABLE_ARGS): # there are surpluss arguments raise exception.FileError( f"config file at {config_file} contains invalid default keys: " f"{', '.join(configured - constants.CONFIGURABLE_ARGS)}")