Example #1
0
def test__cli__formatters__violation():
    """ NB Position is 1 + start_pos """
    c = PositionedChunk('foobarbar', 10, 20, 'context')
    r = RuleGhost('A', 'DESC')
    v = RuleViolation(c, r, [])
    f = format_violation(v)
    assert escape_ansi(f) == "L:  20 | P:  11 | A | DESC"
Example #2
0
def test__cli__formatters__violation():
    """Test formatting violations.

    NB Position is 1 + start_pos.
    """
    s = RawSegment("foobarbar", FilePositionMarker(0, 20, 11, 100))
    r = RuleGhost("A", "DESC")
    v = SQLLintError(segment=s, rule=r)
    f = format_violation(v)
    assert escape_ansi(f) == "L:  20 | P:  11 |    A | DESC"
Example #3
0
def _print_out_violations_and_timing(
    bench: bool,
    code_only: bool,
    total_time: float,
    verbose: int,
    parsed_strings: List[ParsedString],
) -> int:
    """Used by human formatting during the parse."""
    violations_count = 0
    timing = TimingSummary()

    for parsed_string in parsed_strings:
        timing.add(parsed_string.time_dict)

        if parsed_string.tree:
            click.echo(parsed_string.tree.stringify(code_only=code_only))
        else:
            # TODO: Make this prettier
            click.echo("...Failed to Parse...")  # pragma: no cover

        violations_count += len(parsed_string.violations)
        if parsed_string.violations:
            click.echo("==== parsing violations ====")  # pragma: no cover
        for v in parsed_string.violations:
            click.echo(format_violation(v))  # pragma: no cover
        if parsed_string.violations and parsed_string.config.get(
                "dialect") == "ansi":
            click.echo(format_dialect_warning())  # pragma: no cover

        if verbose >= 2:
            click.echo("==== timings ====")
            click.echo(cli_table(parsed_string.time_dict.items()))

    if verbose >= 2 or bench:
        click.echo("==== overall timings ====")
        click.echo(cli_table([("Clock time", total_time)]))
        timing_summary = timing.summary()
        for step in timing_summary:
            click.echo(f"=== {step} ===")
            click.echo(cli_table(timing_summary[step].items()))

    return violations_count
def test__cli__formatters__violation():
    """Test formatting violations.

    NB Position is 1 + start_pos.
    """
    s = RawSegment(
        "foobarbar",
        PositionMarker(
            slice(10, 19),
            slice(10, 19),
            TemplatedFile.from_string("      \n\n  foobarbar"),
        ),
    )
    r = RuleGhost("A", "DESC")
    v = SQLLintError(segment=s, rule=r)
    f = format_violation(v)
    # Position is 3, 3 becase foobarbar is on the third
    # line (i.e. it has two newlines preceding it) and
    # it's at the third position in that line (i.e. there
    # are two characters between it and the preceeding
    # newline).
    assert escape_ansi(f) == "L:   3 | P:   3 |    A | DESC"
Example #5
0
def parse(path,
          code_only,
          format,
          profiler,
          bench,
          nofail,
          logger=None,
          **kwargs):
    """Parse SQL files and just spit out the result.

    PATH is the path to a sql file or directory to lint. This can be either a
    file ('path/to/file.sql'), a path ('directory/of/sql/files'), a single ('-')
    character to indicate reading from *stdin* or a dot/blank ('.'/' ') which will
    be interpreted like passing the current working directory as a path argument.
    """
    # Initialise the benchmarker
    bencher = BenchIt()  # starts the timer
    c = get_config(**kwargs)
    # We don't want anything else to be logged if we want json or yaml output
    non_human_output = format in ("json", "yaml")
    lnt, formatter = get_linter_and_formatter(c, silent=non_human_output)
    verbose = c.get("verbose")
    recurse = c.get("recurse")

    formatter.dispatch_config(lnt)

    # Set up logging.
    set_logging_level(verbosity=verbose,
                      logger=logger,
                      stderr_output=non_human_output)

    # TODO: do this better
    nv = 0
    if profiler:
        # Set up the profiler if required
        try:
            import cProfile
        except ImportError:
            click.echo("The cProfiler is not available on your platform.")
            sys.exit(1)
        pr = cProfile.Profile()
        pr.enable()

    bencher("Parse setup")
    try:
        # handle stdin if specified via lone '-'
        if "-" == path:
            # put the parser result in a list to iterate later
            result = [
                lnt.parse_string(sys.stdin.read(),
                                 "stdin",
                                 recurse=recurse,
                                 config=lnt.config),
            ]
        else:
            # A single path must be specified for this command
            # TODO: Remove verbose
            result = lnt.parse_path(path, recurse=recurse)

        # iterative print for human readout
        if format == "human":
            for parsed_string in result:
                if parsed_string.tree:
                    click.echo(
                        parsed_string.tree.stringify(code_only=code_only))
                else:
                    # TODO: Make this prettier
                    click.echo("...Failed to Parse...")
                nv += len(parsed_string.violations)
                if parsed_string.violations:
                    click.echo("==== parsing violations ====")
                for v in parsed_string.violations:
                    click.echo(format_violation(v))
                if (parsed_string.violations
                        and parsed_string.config.get("dialect") == "ansi"):
                    click.echo(format_dialect_warning())
                if verbose >= 2:
                    click.echo("==== timings ====")
                    click.echo(cli_table(parsed_string.time_dict.items()))
                bencher("Output details for file")
        else:
            # collect result and print as single payload
            # will need to zip in the file paths
            filepaths = ["stdin"] if "-" == path else lnt.paths_from_path(path)
            result = [
                dict(
                    filepath=filepath,
                    segments=parsed.as_record(code_only=code_only,
                                              show_raw=True)
                    if parsed else None,
                ) for filepath, (parsed, _, _, _, _) in zip(filepaths, result)
            ]

            if format == "yaml":
                # For yaml dumping always dump double quoted strings if they contain tabs or newlines.
                yaml.add_representer(str, quoted_presenter)

                click.echo(yaml.dump(result))
            elif format == "json":
                click.echo(json.dumps(result))
    except IOError:
        click.echo(
            colorize(
                "The path {0!r} could not be accessed. Check it exists.".
                format(path),
                "red",
            ))
        sys.exit(1)

    if profiler:
        pr.disable()
        profiler_buffer = StringIO()
        ps = pstats.Stats(pr, stream=profiler_buffer).sort_stats("cumulative")
        ps.print_stats()
        click.echo("==== profiler stats ====")
        # Only print the first 50 lines of it
        click.echo("\n".join(profiler_buffer.getvalue().split("\n")[:50]))

    if bench:
        click.echo("\n\n==== bencher stats ====")
        bencher.display()

    if nv > 0 and not nofail:
        sys.exit(66)
    else:
        sys.exit(0)
Example #6
0
def parse(
    path,
    code_only,
    include_meta,
    format,
    profiler,
    bench,
    nofail,
    logger=None,
    **kwargs,
):
    """Parse SQL files and just spit out the result.

    PATH is the path to a sql file or directory to lint. This can be either a
    file ('path/to/file.sql'), a path ('directory/of/sql/files'), a single ('-')
    character to indicate reading from *stdin* or a dot/blank ('.'/' ') which will
    be interpreted like passing the current working directory as a path argument.
    """
    c = get_config(**kwargs)
    # We don't want anything else to be logged if we want json or yaml output
    non_human_output = format in ("json", "yaml")
    lnt, formatter = get_linter_and_formatter(c, silent=non_human_output)
    verbose = c.get("verbose")
    recurse = c.get("recurse")

    formatter.dispatch_config(lnt)

    # Set up logging.
    set_logging_level(verbosity=verbose, logger=logger, stderr_output=non_human_output)

    # TODO: do this better
    nv = 0
    if profiler:
        # Set up the profiler if required
        try:
            import cProfile
        except ImportError:  # pragma: no cover
            click.echo("The cProfiler is not available on your platform.")
            sys.exit(1)
        pr = cProfile.Profile()
        pr.enable()

    try:
        t0 = time.monotonic()
        # handle stdin if specified via lone '-'
        if "-" == path:
            # put the parser result in a list to iterate later
            result = [
                lnt.parse_string(
                    sys.stdin.read(), "stdin", recurse=recurse, config=lnt.config
                ),
            ]
        else:
            # A single path must be specified for this command
            result = lnt.parse_path(path, recurse=recurse)
        total_time = time.monotonic() - t0

        # iterative print for human readout
        if format == "human":
            timing = TimingSummary()
            for parsed_string in result:
                timing.add(parsed_string.time_dict)
                if parsed_string.tree:
                    click.echo(parsed_string.tree.stringify(code_only=code_only))
                else:
                    # TODO: Make this prettier
                    click.echo("...Failed to Parse...")  # pragma: no cover
                nv += len(parsed_string.violations)
                if parsed_string.violations:
                    click.echo("==== parsing violations ====")  # pragma: no cover
                for v in parsed_string.violations:
                    click.echo(format_violation(v))  # pragma: no cover
                if (
                    parsed_string.violations
                    and parsed_string.config.get("dialect") == "ansi"
                ):
                    click.echo(format_dialect_warning())  # pragma: no cover
                if verbose >= 2:
                    click.echo("==== timings ====")
                    click.echo(cli_table(parsed_string.time_dict.items()))
            if verbose >= 2 or bench:
                click.echo("==== overall timings ====")
                click.echo(cli_table([("Clock time", total_time)]))
                timing_summary = timing.summary()
                for step in timing_summary:
                    click.echo(f"=== {step} ===")
                    click.echo(cli_table(timing_summary[step].items()))
        else:
            result = [
                dict(
                    filepath=linted_result.fname,
                    segments=linted_result.tree.as_record(
                        code_only=code_only, show_raw=True, include_meta=include_meta
                    )
                    if linted_result.tree
                    else None,
                )
                for linted_result in result
            ]

            if format == "yaml":
                # For yaml dumping always dump double quoted strings if they contain tabs or newlines.
                yaml.add_representer(str, quoted_presenter)

                click.echo(yaml.dump(result))
            elif format == "json":
                click.echo(json.dumps(result))
    except OSError:  # pragma: no cover
        click.echo(
            colorize(
                f"The path {path!r} could not be accessed. Check it exists.",
                "red",
            ),
            err=True,
        )
        sys.exit(1)

    if profiler:
        pr.disable()
        profiler_buffer = StringIO()
        ps = pstats.Stats(pr, stream=profiler_buffer).sort_stats("cumulative")
        ps.print_stats()
        click.echo("==== profiler stats ====")
        # Only print the first 50 lines of it
        click.echo("\n".join(profiler_buffer.getvalue().split("\n")[:50]))

    if nv > 0 and not nofail:
        sys.exit(66)  # pragma: no cover
    else:
        sys.exit(0)