Source code for git_lint.option_handler

# Copyright (C) 2015 Elf M. Sternberg
# Author: Elf M. Sternberg

from functools import reduce
from collections import namedtuple
import getopt

try:  # noqa: F401
    from typing import Dict, List, Text, Any, Optional, Union, Callable, Tuple  # noqa: F401
except:  # noqa: F401
    pass  # noqa: F401


Option = namedtuple('Option', ['short', 'long', 'takes', 'help', 'conflicts'])  # type: str, str, str, str, List[str]
Arguments = namedtuple('Arguments', ['arguments', 'filenames', 'excluded'])  # type: Dict[str, str], List[str], List[str]

# This was a lot shorter and smarter in Hy...

# A lot of what you see here is separated from git_lint itself, since this will not be
# relevant to the operation of pre-commit.

#   ___                              _   _    _
#  / __|___ _ __  _ __  __ _ _ _  __| | | |  (_)_ _  ___
# | (__/ _ \ '  \| '  \/ _` | ' \/ _` | | |__| | ' \/ -_)
#  \___\___/_|_|_|_|_|_\__,_|_||_\__,_| |____|_|_||_\___|
#


[docs]def cleanup_options(options, commandline): # type: (List[Option], List[str]) -> Arguments """Takes a table of options and the commandline, and returns a dictionary of those options that appear on the commandline along with any extra arguments. :param List(Tuple (string, string, boolean, string, List(string))) options, The table of options: One-letter option, long option, takes arguments, Help text, list of (long) options superseded by this one. : param List(strings) commandline The arguments as received by the start-up process : returns List(strings), List(strings), List(strings) The longopt dictionary of arguments and associated values (if any) The list of filenames left after argument processing The longopt list of arguments that were excluded by argument precedence """ def make_option_streamliner(options): # type: (List[Option]) -> Callable[[Dict[str, str], Option], Dict[str, str]] """Takes a list of option tuples, and returns a function that takes the output of getopt and reduces it to the longopt key and associated values as a dictionary. """ fullset = {} # type: Dict[str, str] for option in options: if option.long: fullset['--' + option.long] = option.long if option.short: fullset['-' + option.short] = option.long def streamliner(acc, it): # type: (Dict[str, str], Option) -> Dict[str, str] acc[fullset[it[0]]] = it[1] return acc return streamliner def remove_conflicted_options(options, request): # type: (List[Option], Dict[str, str]) -> Tuple[List[str], List[str]] """Takes our list of option tuples, and a cleaned copy of what was requested from getopt, and returns a copy of the request without any options that are marked as superseded, along with the list of superseded options """ def get_excluded_keys(memo, option): return memo + option.conflicts keys = request.keys() marked = [option for option in options if option.long in keys] exclude = reduce(get_excluded_keys, marked, []) excluded = [key for key in keys if key in exclude] cleaned = {key: request[key] for key in keys if key not in excluded} return (cleaned, excluded) def shortoptstogo(i): return i.short + ((i.takes and ':') or '') def longoptstogo(i): return i.long + ((i.takes and '=') or '') optstringsshort = ''.join([shortoptstogo(opt) for opt in options if opt.short]) optstringslong = [longoptstogo(opt) for opt in options] (chosen_options, filenames) = getopt.getopt(commandline[1:], optstringsshort, optstringslong) # Turns what getopt returns into something more human-readable streamline_options = make_option_streamliner(options) # Remove any options that are superseded by others. (ret, excluded) = remove_conflicted_options( options, reduce(streamline_options, chosen_options, {})) return Arguments(ret, filenames, excluded)