Example #1
0
def lint(module: Module) -> List:
    """
    @cc 5
    @desc lint the given module!
    @arg module: the module to lint
    @ret a list of issues found in this module
    """

    issues = []
    state = get_state()

    state.module_count += 1

    if module.doc and module.doc.no_lint:
        state.module_nolint_count += 1
        return []

    for rule in state.module_rules:
        if rule.check(module):
            issues.append(Issue(rule, module))

    for class_def in module.classes:
        issues.extend(class_lint(class_def))

    for function in module.functions:
        issues.extend(function_lint(function))

    return issues
Example #2
0
def class_lint(class_def: Class) -> List:
    """
    @cc 5
    @desc class specific lint
    @arg class_def: the Class object to lint
    @ret a list of issues found in this class
    """

    state = get_state()
    issues = []

    state.class_count += 1

    if class_def.doc and class_def.doc.no_lint:
        state.class_nolint_count += 1
        return []

    # check this class for rules
    for rule in state.class_rules:
        if rule.check(class_def):
            issues.append(Issue(rule, class_def))

    # check nested classes
    for sub_class in class_def.classes:
        issues.extend(class_lint(sub_class))

    # check functions within this class
    for function in class_def.functions:
        issues.extend(function_lint(function))

    return issues
Example #3
0
def parse_module(filename: str) -> Module:
    """
    @cc 5
    @desc parse a module into our archives' models
    @arg filename: the python file to parse
    @ret a parsed Module object of the given file
    """
    state = get_state()
    contents = ""
    if str(filename)[-2:] == "/-":
        contents, _, __ = decode_bytes(sys.stdin.buffer.read())
    elif not os.path.isfile(filename):
        raise Exception("file does not exist")
    else:
        with open(filename, encoding="utf-8",
                  errors="replace") as file_to_read:
            contents += file_to_read.read()
    try:
        ast = ast3.parse(contents)
    except:  # noqa
        out("error in parsing", color="red")
        if state.ignore_exceptions:
            sys.exit(0)
    module = Module(ast, filename)  # type: ignore
    return module
Example #4
0
def msg(data: Union[str, Dict, List]) -> None:
    """
    @cc 2
    @desc prints something to standard out in blue
    @arg data: either a string to print, or a list/dict to print nicely
    """
    state = get_state()
    if not state.quiet:
        if isinstance(data, (dict, list)):
            data = json.dumps(data, indent=2, sort_keys=True, default=str)
        click.secho(data, fg="blue")
Example #5
0
def debug(data: Union[str, Dict, List], force: bool = False) -> None:
    """
    @cc 2
    @desc only prints if verbose mode is on, formatting nicely if list/dict
    @arg data: either a string to print, or a list/dict to print nicely
    @arg force: force this debug to print, regardless of state/flags
    """
    state = get_state()
    if state.verbose or force:
        if isinstance(data, (dict, list)):
            data = json.dumps(data, indent=2, sort_keys=True, default=str)
        click.echo(click.style(data, fg="green"), err=True)
Example #6
0
def path_empty(src: Tuple[str], ctx: click.Context) -> None:
    """
    @cc 4
    @desc Exit if there is no src provided for formatting
    @arg src: a list of source files to lint
    @arg ctx: the context of the click cli application
    """
    state = get_state()
    if not src:
        if state.verbose or not state.quiet:
            err("no paths provided!")
        ctx.exit(2)
Example #7
0
def out(data: Union[str, Dict, List],
        force: bool = False,
        color: str = "green") -> None:
    """
    @cc 2
    @desc prints something to standard out
    @arg data: either a string to print, or a list/dict to print nicely
    @arg color: what color to print in
    @arg force: force this debug to print, regardless of state/flags
    """
    state = get_state()
    if not state.quiet or force:
        if isinstance(data, (dict, list)):
            data = json.dumps(data, indent=2, sort_keys=True, default=str)
        click.echo(click.style(data, fg=color))
Example #8
0
def function_lint(function: Function) -> List:
    """
    @cc 16
    @desc function specific lint
    @arg function: the Function object to lint
    @ret a list of issues found in this function
    """
    state = get_state()
    issues = []

    state.function_count += 1

    if function.doc and function.doc.no_lint:
        state.function_nolint_count += 1
        return []

    # check this function for rules
    for rule in state.function_rules:
        if rule.check(function):
            issues.append(Issue(rule, function))

    # check for missing args
    if MISSING_ARG.code not in state.disable_list:
        for arg_name in function.missing_args:
            issues.append(Issue(MISSING_ARG, function, dict(arg=arg_name)))

    # check for unexpected args
    if UNEXPECTED_ARG.code not in state.disable_list:
        for arg_name in function.unexpected_args:
            issues.append(Issue(UNEXPECTED_ARG, function, dict(arg=arg_name)))

    # check for untyped args
    if UNTYPED_ARG.code not in state.disable_list:
        for arg in [
                x for x in function.args
                if not x.typed and x.name not in DEFAULT_ARG_IGNORE
        ]:
            issues.append(Issue(UNTYPED_ARG, function, dict(arg=arg)))

    # check nested classes
    for sub_class in function.classes:
        issues.extend(class_lint(sub_class))

    # check all sub functions
    for sub_function in function.functions:
        issues.extend(function_lint(sub_function))

    return issues