1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
#!/usr/bin/env python3
# Copyright 2022 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: ISC
"""
Check that a Turtle file has valid syntax and strict formatting.
This is a strict tool that enforces machine formatting with serdi.
"""
import argparse
import difflib
import filecmp
import sys
import tempfile
import os
import subprocess
def _show_diff(from_lines, to_lines, from_path, to_path):
"Show a diff between two files, returning non-zero if they differ."
differences = False
for line in difflib.unified_diff(
from_lines,
to_lines,
fromfile=from_path,
tofile=to_path,
):
sys.stderr.write(line)
differences = True
return int(differences)
def _check_file_equals(patha, pathb):
"Check that two files are equal, returning non-zero if they differ."
for path in (patha, pathb):
if not os.access(path, os.F_OK):
sys.stderr.write(f"error: missing file {path}")
return 1
if filecmp.cmp(patha, pathb, shallow=False):
return 0
with open(patha, "r", encoding="utf-8") as in_a:
with open(pathb, "r", encoding="utf-8") as in_b:
return _show_diff(in_a.readlines(), in_b.readlines(), patha, pathb)
def run(serdi, filenames):
"Check that every file in filenames has valid formatted syntax."
status = 0
for filename in filenames:
rel_path = os.path.relpath(filename)
with tempfile.NamedTemporaryFile(mode="w", delete=False) as out:
out_name = out.name
command = [serdi, "-o", "turtle", rel_path]
subprocess.check_call(command, stdout=out)
if _check_file_equals(rel_path, out_name):
status = 1
os.remove(out_name)
return status
if __name__ == "__main__":
ap = argparse.ArgumentParser(
usage="%(prog)s [OPTION]... TURTLE_FILE...",
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
ap.add_argument("--serdi", default="serdi", help="path to serdi")
ap.add_argument("TURTLE_FILE", nargs="+", help="input file to check")
args = ap.parse_args(sys.argv[1:])
sys.exit(run(args.serdi, args.TURTLE_FILE))
|