Beispiel #1
0
def parse_directives(
        directive_lines: Iterable[Tuple[int, int, str]]) -> AnalysisOptionSet:
    """
    Parse options from directives in comments.

    >>> parse_directives([(1, 0, "off")]).enabled
    False
    """
    result = AnalysisOptionSet()
    for lineno, _colno, directive in directive_lines:
        for part in directive.split():
            if part == "on":
                part = "enabled=1"
            if part == "off":
                part = "enabled="
            pair = part.split("=", 2)
            if len(pair) != 2:
                raise InvalidDirective(f'Malformed option: "{part}"', lineno)
            key, strvalue = pair
            if key not in AnalysisOptionSet.directive_fields:
                raise InvalidDirective(f'Unknown option: "{key}"', lineno)
            value = AnalysisOptionSet.parse_field(key, strvalue)
            if value is None:
                raise InvalidDirective(
                    f'"{strvalue}" is not a valid "{key}" value', lineno)
            if getattr(result, key) is not None:
                raise InvalidDirective(
                    f'Option "{key}" is set multiple times at the same scope',
                    lineno)
            result = result.overlay(AnalysisOptionSet(**{key: value}))
    return result
Beispiel #2
0
def check_fail(
    fn: Callable, optionset: AnalysisOptionSet = AnalysisOptionSet()
) -> ComparableLists:
    local_opts = AnalysisOptionSet(max_iterations=40, per_condition_timeout=5)
    options = local_opts.overlay(optionset)
    states = [m.state for m in run_checkables(analyze_function(fn, options))]
    return (states, [MessageType.POST_FAIL])
Beispiel #3
0
def check_post_err(
    fn: Callable, optionset: AnalysisOptionSet = AnalysisOptionSet()
) -> ComparableLists:
    local_opts = AnalysisOptionSet(max_iterations=20)
    options = local_opts.overlay(optionset)
    states = [m.state for m in run_checkables(analyze_function(fn, options))]
    return (states, [MessageType.POST_ERR])
Beispiel #4
0
def collect_options(thing: Any) -> AnalysisOptionSet:
    parent_opts = AnalysisOptionSet()
    is_package = thing.__name__ == getattr(thing, "__package__", None)
    if getattr(thing, "__module__", None):
        parent_opts = collect_options(sys.modules[thing.__module__])
    elif getattr(thing, "__package__", None):
        if is_package:
            parent_pkg, _, _ = thing.__package__.rpartition(".")
        else:
            parent_pkg = thing.__package__
        if parent_pkg:
            parent_opts = collect_options(sys.modules[parent_pkg])

    lines: Iterable[str]
    if is_package:
        try:
            lines = importlib.resources.read_text(thing,
                                                  "__init__.py").splitlines()
        except FileNotFoundError:
            lines = []
    else:
        _file, _start, lines = sourcelines(thing)
    directives = get_directives(lines)
    if inspect.ismodule(thing):
        # Only look at toplevel comments in modules
        # (we don't want to catch directives for functions inside it)
        # TODO: detect directives at other levels like classes etc and warn that they
        # will be ignored.
        directives = [(l, c, t) for (l, c, t) in directives if c == 0]
    my_opts = parse_directives(directives)
    return parent_opts.overlay(my_opts)
Beispiel #5
0
def check_unknown(
    fn: Callable, optionset: AnalysisOptionSet = AnalysisOptionSet()
) -> ComparableLists:
    local_opts = AnalysisOptionSet(max_iterations=40, per_condition_timeout=3)
    options = local_opts.overlay(optionset)
    messages = [(m.state, m.message, m.traceback)
                for m in run_checkables(analyze_function(fn, options))]
    return (messages, [(MessageType.CANNOT_CONFIRM, "Not confirmed.", "")])
Beispiel #6
0
def check_ok(
    fn: Callable, optionset: AnalysisOptionSet = AnalysisOptionSet()
) -> ComparableLists:
    local_opts = AnalysisOptionSet(per_condition_timeout=5)
    options = local_opts.overlay(optionset)
    messages = [
        message for message in run_checkables(analyze_function(fn, options))
        if message.state != MessageType.CONFIRMED
    ]
    return (messages, [])
Beispiel #7
0
def check_exec_err(
    fn: Callable, message_prefix="", optionset: AnalysisOptionSet = AnalysisOptionSet()
) -> ComparableLists:
    local_opts = AnalysisOptionSet(max_iterations=20, per_condition_timeout=5)
    options = local_opts.overlay(optionset)
    messages = run_checkables(analyze_function(fn, options))
    if all(m.message.startswith(message_prefix) for m in messages):
        return ([m.state for m in messages], [MessageType.EXEC_ERR])
    else:
        return (
            [(m.state, m.message) for m in messages],
            [(MessageType.EXEC_ERR, message_prefix)],
        )
Beispiel #8
0
def collect_options(thing: Any) -> AnalysisOptionSet:
    parent_opts = AnalysisOptionSet()
    if getattr(thing, "__module__", None):
        parent_opts = collect_options(sys.modules[thing.__module__])
    elif hasattr(thing, "__package__"):
        if thing.__package__ and thing.__package__ != thing.__name__:
            parent_opts = collect_options(sys.modules[thing.__package__])

    _file, start, lines = sourcelines(thing)
    directives = get_directives(lines)
    if inspect.ismodule(thing):
        # Only look at toplevel comments in modules
        # (we don't want to catch directives for functions inside it)
        # TODO: detect directives at other levels like classes etc and warn that they
        # will be ignored.
        directives = [(l, c, t) for (l, c, t) in directives if c == 0]
    my_opts = parse_directives(directives)
    return parent_opts.overlay(my_opts)
Beispiel #9
0
def check_states(
    fn: Callable, optionset: AnalysisOptionSet = AnalysisOptionSet()
) -> Set[MessageType]:
    local_opts = AnalysisOptionSet(max_iterations=40, per_condition_timeout=5)
    options = local_opts.overlay(optionset)
    return set([m.state for m in run_checkables(analyze_function(fn, options))])