[PATCH rtems-tools 2/2] misc: Add rtems-style command

Gedare Bloom gedare at rtems.org
Wed Aug 25 20:22:56 UTC 2021


On Mon, Aug 16, 2021 at 4:14 PM Ida Delphine <idadelm at gmail.com> wrote:
>
> Signed-off-by: Ida Delphine <idadelm at gmail.com>
>
> This command helps to check for style issues or reformat code given a file
> or directory. There are 4 flags:
> * -c, --check : Checks for style issues
> * -r, --reformat : Reformats the code
> * -p, --path : Path to file or dir to be checked or reformatted
> * -i, --ignore : Files to be ignored when checking or reformatting
> * -v, --verbose : Produces a more detailed output.
> ---
>  misc/rtems-style    |  16 +++++
>  misc/tools/style.py | 144 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 160 insertions(+)
>  create mode 100644 misc/rtems-style
>  create mode 100644 misc/tools/style.py
>
> diff --git a/misc/rtems-style b/misc/rtems-style
> new file mode 100644
> index 0000000..5a3e0e8
> --- /dev/null
> +++ b/misc/rtems-style
> @@ -0,0 +1,16 @@
> +#! /usr/bin/env python
> +

See https://docs.rtems.org/branches/master/eng/coding-file-hdr.html#python-file-template

I think this tool should be maybe rtems-c-style? It only focuses on C
and C Header files.

Maybe, later, we need to include rtems-asm-style and rtems-py-style?
Just some thoughts.

> +from __future__ import print_function
> +
> +import sys, os
> +
> +base = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
> +rtems = os.path.join(base, 'share', 'rtems')
> +sys.path = sys.path[0:1] + [rtems, base] + sys.path[1:]
> +
> +try:
> +    import misc.tools.style
> +    misc.tools.style.run()
> +except ImportError:
> +    print("Incorrect RTEMS Tools installation", file = sys.stderr)
> +    sys.exit(1)
> \ No newline at end of file
> diff --git a/misc/tools/style.py b/misc/tools/style.py
> new file mode 100644
> index 0000000..a101146
> --- /dev/null
> +++ b/misc/tools/style.py
> @@ -0,0 +1,144 @@
> +import argparse
> +import os
> +import sys
> +import re
> +
> +from rtemstoolkit import execute
> +from rtemstoolkit import git
> +
> +
> +def get_command():
> +    from rtemstoolkit import check
> +
> +    for version in ['', '8', '9', '10', '11']:
> +        if check.check_exe(None, 'clang-format' + version):
> +            command = 'clang-format' + version
> +            return command
> +    print("Clang-format not found in your system")
> +    sys.exit(1)
> +
> +
> +def arguments():
> +    parser = argparse.ArgumentParser(description="Tool for code formatting and style checking \
> +        for RTEMS")
> +    parser.add_argument("-c", "--check", dest="check", help="Check for style differences and \
> +        report the number of issues if found", action="store_true")
> +    parser.add_argument("-r", "--reformat", dest="reformat", help="Reformat the file/directory \
> +        with any style differences found", action="store_true")
> +    parser.add_argument("-p", "--path", dest="path", help="The path to be checked for style issues \
> +        or reformatted")
> +    parser.add_argument("--ignore", dest="ignore", help="Ignore files to be checked or reformatted")
> +    parser.add_argument("-v", "--verbose", dest="verbose", help="A more detailed outline of the \
> +        style issues", action='store_true')
> +    return [parser.parse_args(), parser.print_usage()]
> +
> +
> +

Check the style of your Python code. Make sure it conforms
https://docs.rtems.org/branches/master/eng/python-devel.html

I think we only want two blank lines between function bodies.

> +def get_diff(path, ignore_file=None):
> +    diff = ""
> +    ex = execute.capture_execution()
> +
> +
> +    def clang_to_git_diff(clang_output, path):

Why is this indented to here? I think this changes the visibility of
it to make it a nested function. Is this necessary/desired here?

> +        import os
> +        import tempfile
> +
> +        fd, tmp_path = tempfile.mkstemp()
> +        try:
> +            with os.fdopen(fd, 'w') as tmp:

I think this is trying to open fd again?  Seems wrong, since the fd
file descriptor is already open? I'm not sure.

> +
> +                tmp.write(clang_output)
> +                repo = git.repo(".")

I wonder if we need to provide an argument to the location of the git
repo instead of assume the script runs from within it?

> +            return repo.diff(['--no-index', path, tmp_path])
> +
> +        finally:
> +            os.remove(tmp_path)

Is this all the cleanup needed? what about closing the open fd?

> +
> +    if os.path.isfile(path) == True:
> +        cmd = get_command() + " --style=file " + path
> +        output_clang = ex.command(command=cmd, shell=True)
> +        output_clang = output_clang[2]
> +        diff = clang_to_git_diff(output_clang, path)
> +    else:
> +        onlyfiles = [f for f in os.listdir(path)]
> +        for file in onlyfiles:
> +            file = os.path.join(path, file)
> +
> +            if ignore_file is not None and file == ignore_file:

is there only one ignore_file? Shouldn't there be a set of them? I'm
not sure how this works.

> +                continue
> +
> +            if file.endswith('.c') or file.endswith('.h'):
> +                cmd = get_command() + " --style=file " + file
> +                output_clang = ex.command(command=cmd, shell=True)
> +                output_clang = output_clang[2]
> +                diff += clang_to_git_diff(output_clang, os.path.join(path, file))
> +    return diff
> +
> +
> +def color_text(string, col, style=1):
> +    return f"\033[{style};{col};{col}m{string}\033[0;0m"
> +

I think we need to make sure colored text works well cross-platform.
It might be safer to avoid color in here.

> +
> +def handle_errors(path, output, verbose=False,):
extra comma here?

> +    if len(output) < 1:
> +        print("Everything is clean - No style issues")
> +    else:
> +        print(color_text("Checking for style differences...", 34, style=3))
> +
> +        out = output.split('\n')
> +        files = []
> +        num_diff = 0
> +        for line in out:
> +
> +            if line.startswith("---"):
> +                file = str(re.sub('^---\s[ab]', '', line))
> +                files.append(file)
> +
> +            elif line.startswith('+'):
> +                num_diff += 1
> +                if verbose == True:
> +                    print(color_text(line, 34))
> +                    continue
> +            if verbose == True:
> +                print(line)
> +
> +        print(color_text("\nFiles affected:", 33))
> +
> +        for file in files:
> +            print(file)
> +
> +        message = "\nStyleWarning: You have about a total of " + str(num_diff) + \
> +                " style issue(s) in the " + str(len(files)) + " file(s) listed above"
> +        print(color_text(message, 31))
> +
> +
> +def reformat(path, output):
> +    if len(output) > 0:
> +        onlyfiles = [f for f in os.listdir(path)]
> +        for file in onlyfiles:
> +            if file.endswith('.c') or file.endswith('.h'):
> +                cmd = get_command() + " -i -style=file " + os.path.join(path, file)
> +                ex = execute.capture_execution()
> +                ex.command(command=cmd, shell=True)
> +    else:
> +        print("Everything is clean. No style issues")
> +        return 0
> +
> +
> +def run(args = sys.argv):
> +    args = arguments()
> +    if os.path.exists(args[0].path) == False:
> +        print("Please enter a correct path!!")

It can be helpful to show what was the incorrect path input to help
someone know what they did wrong.

> +        sys.exit(1)
Why exiting instead of returning?

> +    output = get_diff(args[0].path)
> +    if args[0].check == True:
> +        handle_errors(args[0].path, output, verbose=args[0].verbose)
> +    elif args[0].reformat == True:
> +        reformat(args[0].path, output)
> +    else:
> +        args[1]
?

> +        sys.exit(1)
> +
> +
> +if __name__ == "__main__":
> +    run()
> --
> 2.25.1
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel


More information about the devel mailing list