Python Forum
Script to check the syntax of Python files
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Script to check the syntax of Python files
#1
The following code is a CLI script to check the syntax of python code. Here is the usage string
Output:
usage: check_syntax.py [-h] FILENAME [FILENAME ...] Check Python source file syntax by attempting compilation. positional arguments: FILENAME Files to compile options: -h, --help show this help message and exit
Further updates of this code will happen in this gist.
# check_syntax.py - script to check the syntax of Python files
# inspired by the standard library's 'py_compile' module.

import importlib.machinery
import sys
import traceback

__all__ = ["has_valid_syntax", "main", "CheckSyntaxError"]


class CheckSyntaxError(Exception):
    """Exception raised when an error occurs while attempting to
    compile the file.

    To raise this exception, use

        raise PyCompileError(exc_type,exc_value,file[,msg])

    where

        exc_type:   exception type to be used in error message
                    type name can be accesses as class variable
                    'exc_type_name'

        exc_value:  exception value to be used in error message
                    can be accesses as class variable 'exc_value'

        file:       name of file being compiled to be used in error message
                    can be accesses as class variable 'file'

        msg:        string message to be written as error message
                    If no value is given, a default exception message will be
                    given, consistent with 'standard' py_compile output.
                    message (or default) can be accesses as class variable
                    'msg'

    """

    def __init__(self, exc_type, exc_value, file, msg=""):
        exc_type_name = exc_type.__name__
        if exc_type is SyntaxError:
            tbtext = "".join(traceback.format_exception_only(exc_type, exc_value))
            errmsg = tbtext.replace('File "<string>"', 'File "%s"' % file)
        else:
            errmsg = "Sorry: %s: %s" % (exc_type_name, exc_value)

        Exception.__init__(self, msg or errmsg, exc_type_name, exc_value, file)

        self.exc_type_name = exc_type_name
        self.exc_value = exc_value
        self.file = file
        self.msg = msg or errmsg

    def __str__(self):
        return self.msg


def has_valid_syntax(file, dfile=None, doraise=False, optimize=-1, quiet=0):
    """Check the syntax of a Python source file.

    :param file: The source file name.
    :param dfile: Purported file name, i.e. the file name that shows up in
        error messages.  Defaults to the source file name.
    :param doraise: Flag indicating whether or not an exception should be
        raised when a compile error is found.  If an exception occurs and this
        flag is set to False, a string indicating the nature of the exception
        will be printed, and the function will return to the caller. If an
        exception occurs and this flag is set to True, a CheckSyntaxError
        exception will be raised.
    :param optimize: The optimization level for the compiler.  Valid values
        are -1, 0, 1 and 2.  A value of -1 means to use the optimization
        level of the current interpreter, as given by -O command line options.
    :param quiet: Return full output with False or 0, errors only with 1,
        and no output with 2.

    :return: None

    """
    loader = importlib.machinery.SourceFileLoader("<py_compile>", file)
    source_bytes = loader.get_data(file)
    try:
        compile(source_bytes, dfile or file, "exec", optimize=optimize)
    except Exception as err:
        py_exc = CheckSyntaxError(err.__class__, err, dfile or file)
        if quiet < 2:
            if doraise:
                raise py_exc
            else:
                sys.stderr.write(py_exc.msg + "\n")
        return False
    else:
        return True


def main():
    import argparse

    description = "Check Python source file syntax by attempting compilation."
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument(
        "filenames",
        nargs="+",
        help="Files to compile",
        metavar="FILENAME",
    )
    args = parser.parse_args()
    if args.filenames == ["-"]:
        filenames = [filename.rstrip("\n") for filename in sys.stdin.readlines()]
    else:
        filenames = args.filenames
    result = True
    kwargs = {"doraise": False, "quiet": 0}
    for filename in filenames:
        filename = filename.rstrip("\n")
        result = has_valid_syntax(filename, **kwargs) and result
    else:
        return parser.exit(0 if result else 1)


if __name__ == "__main__":
    main()
« We can solve any problem by introducing an extra level of indirection »
Reply
#2
The script doesn't show anything even though I added extra errors.

Python 3.11.2 on LMDE6 (Debian 12)

my script to test

#!/usr/bin/env python3

pint("hello world")
the output in my IDE

Output:
Traceback (most recent call last): File "/tmp/./tmp.py", line 3, in <module> pint("hello world") ^^^^ NameError: name 'pint' is not defined. Did you mean: 'print'?
Reply
#3
(Oct-19-2024, 01:16 PM)Axel_Erfurt Wrote: The script doesn't show anything even though I added extra errors.
pint('hello world') is not a syntax error! The script only detects syntax errors.
« We can solve any problem by introducing an extra level of indirection »
Reply
#4
(Oct-19-2024, 01:16 PM)Axel_Erfurt Wrote: pint("hello world")
how could the Python compiler know that was bad without running it? it is valid code ... for a context that has a pint() function. the compiler can only catch bad code, which i understand to be syntax errors. maybe some funny Unicode values can cause a compile failure. but you'd want to catch those, too.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Watch files and automatically run a script in Linux Gribouillis 4 5,654 Aug-14-2023, 11:57 AM
Last Post: Gribouillis
  script to check bash scripts Skaperen 3 3,354 Sep-19-2019, 10:26 PM
Last Post: Skaperen
Lightbulb Script broke with Python 3 / improve script for printing aspecteleven 4 5,343 Feb-22-2019, 12:23 PM
Last Post: buran
  script to filter python files Skaperen 3 75,331 Nov-03-2016, 02:41 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020