Commit 89dddba8 authored by Mark Canterbury's avatar Mark Canterbury
Browse files

Making XML linter happy

parent 5457003b
Loading
Loading
Loading
Loading
Loading
+10 −7
Original line number Original line Diff line number Diff line
@@ -62,8 +62,10 @@
                                        <common:Value>ServiceA</common:Value>
                                        <common:Value>ServiceA</common:Value>
                                    </common:DictionaryEntry>
                                    </common:DictionaryEntry>
                                </config:AssociatedLIServiceTypes>
                                </config:AssociatedLIServiceTypes>
                                <config:AssociatedLDRequestSubtypes/> <!-- In this example, no LD types are supported -->
                                <config:AssociatedLDRequestSubtypes/>
                                <config:AssociatedLPRequestSubtypes/> <!-- In this example, no LP types are supported -->
                                <!-- In this example, no LD types are supported -->
                                <config:AssociatedLPRequestSubtypes/>
                                <!-- In this example, no LP types are supported -->
                            </config:TargetingConfiguration>
                            </config:TargetingConfiguration>
                            <config:TargetingConfiguration>
                            <config:TargetingConfiguration>
                                <config:FormatName>PropietaryIdentifier</config:FormatName>
                                <config:FormatName>PropietaryIdentifier</config:FormatName>
@@ -81,8 +83,10 @@
                                        <common:Value>ServiceB</common:Value>
                                        <common:Value>ServiceB</common:Value>
                                    </common:DictionaryEntry>
                                    </common:DictionaryEntry>
                                </config:AssociatedLIServiceTypes>
                                </config:AssociatedLIServiceTypes>
                                <config:AssociatedLDRequestSubtypes/> <!-- In this example, no LD types are supported -->
                                <config:AssociatedLDRequestSubtypes/>
                                <config:AssociatedLPRequestSubtypes/> <!-- In this example, no LP types are supported -->
                                <!-- In this example, no LD types are supported -->
                                <config:AssociatedLPRequestSubtypes/>
                                <!-- In this example, no LP types are supported -->
                            </config:TargetingConfiguration>
                            </config:TargetingConfiguration>
                        </TargetingConfigurations>
                        </TargetingConfigurations>
                        <SupportedLIWorkflowEndpoints>
                        <SupportedLIWorkflowEndpoints>
@@ -96,8 +100,7 @@
                                <config:URL>https://ts103120.example.com/li/authorisation/new</config:URL>
                                <config:URL>https://ts103120.example.com/li/authorisation/new</config:URL>
                            </config:SupportedLIWorkflowEndpoint>
                            </config:SupportedLIWorkflowEndpoint>
                        </SupportedLIWorkflowEndpoints>
                        </SupportedLIWorkflowEndpoints>
                        <SupportedLPWorkflowEndpoints>
                        <SupportedLPWorkflowEndpoints/>
                        </SupportedLPWorkflowEndpoints>
                    </GETCSPCONFIGResponse>
                    </GETCSPCONFIGResponse>
                </ActionResponse>
                </ActionResponse>
            </ActionResponses>
            </ActionResponses>
+4 −2
Original line number Original line Diff line number Diff line
@@ -76,7 +76,8 @@
                                <config:FormatName>PropietaryIdentifier</config:FormatName>
                                <config:FormatName>PropietaryIdentifier</config:FormatName>
                                <config:FormatOwner>ACTOR02</config:FormatOwner>
                                <config:FormatOwner>ACTOR02</config:FormatOwner>
                                <config:Guidance>This targeting configuration defines that the service provider accepts lawful disclosure and lawful preservation requests for the propietary identifier format type described in the TargetFormatTypeDefinitions, associated with Service A for the "Subscriber Data" category only</config:Guidance>
                                <config:Guidance>This targeting configuration defines that the service provider accepts lawful disclosure and lawful preservation requests for the propietary identifier format type described in the TargetFormatTypeDefinitions, associated with Service A for the "Subscriber Data" category only</config:Guidance>
                                <config:AssociatedLIServiceTypes/> <!-- In this example, no LI types are supported -->
                                <config:AssociatedLIServiceTypes/>
                                <!-- In this example, no LI types are supported -->
                                <config:AssociatedLDRequestTypes>
                                <config:AssociatedLDRequestTypes>
                                    <common:DictionaryEntry>
                                    <common:DictionaryEntry>
                                        <common:Owner>ETSI</common:Owner>
                                        <common:Owner>ETSI</common:Owner>
@@ -111,7 +112,8 @@
                                <config:FormatName>InternationalE164</config:FormatName>
                                <config:FormatName>InternationalE164</config:FormatName>
                                <config:FormatOwner>ETSI</config:FormatOwner>
                                <config:FormatOwner>ETSI</config:FormatOwner>
                                <config:Guidance>This targeting configuration defines that the service provider accepts lawful disclosure and lawful preservation requests for a telephone number (as ETSI standard format E164 number) associated with Service A and Service B for the "Traffic Data" and "Content Data" categories</config:Guidance>
                                <config:Guidance>This targeting configuration defines that the service provider accepts lawful disclosure and lawful preservation requests for a telephone number (as ETSI standard format E164 number) associated with Service A and Service B for the "Traffic Data" and "Content Data" categories</config:Guidance>
                                <config:AssociatedLIServiceTypes/> <!-- In this example, no LI types are supported -->
                                <config:AssociatedLIServiceTypes/>
                                <!-- In this example, no LI types are supported -->
                                <config:AssociatedLDRequestTypes>
                                <config:AssociatedLDRequestTypes>
                                    <common:DictionaryEntry>
                                    <common:DictionaryEntry>
                                        <common:Owner>ETSI</common:Owner>
                                        <common:Owner>ETSI</common:Owner>
+798 −44

File changed.

Preview size limit exceeded, changes collapsed.

+73 −31
Original line number Original line Diff line number Diff line
@@ -5,47 +5,80 @@ import subprocess
import colorama
import colorama
from colorama import Fore, Style
from colorama import Fore, Style


import argparse

colorama.init()
colorama.init()


ignore_paths = [Path(x) for x in ["testing/deps"]]
ignore_paths = [Path(x) for x in ["testing/deps"]]


# TODO - get rid of these exceptions when we can
ignore_files = [str(Path("104000/schema/TS_104_000.xsd")),
                str(Path("103221-2/TS_103_221_02_Configuration.xsd")),
                str(Path("103707/TS_103_707.xsd"))]



def print_colorized_diff_line(line: str):
def print_colorized_diff_line(line: str):
    if line.startswith("-"):
    if line.startswith("-"):
        print(f"{Fore.RED}{line}{Style.RESET_ALL}")
        return f"{Fore.RED}{line}{Style.RESET_ALL}"
    elif line.startswith("+"):
    elif line.startswith("+"):
        print(f"{Fore.GREEN}{line}{Style.RESET_ALL}")
        return f"{Fore.GREEN}{line}{Style.RESET_ALL}"
    else:
    else:
        print(line)
        return line



def lint(file: Path):
def run_linter(file: Path) -> str:
    completed = subprocess.run(
    completed = subprocess.run(
        ["xmllint", "--format", str(file)], capture_output=True, text=True, encoding="utf8"
        # TODO - get the spacing from the editorconfig, rather than hardcoding it
        ["xmllint", "--format", str(file)], capture_output=True, text=True, encoding="utf8", env={"XMLLINT_INDENT": "    "}
    )
    )

    if completed.returncode != 0:
    if completed.returncode != 0:
        print(f"{str(f)}: FAIL")
        raise RuntimeError(f"xmllint failed with error code {completed.returncode}")
        print(f"      xmlint error code {completed.returncode}")
        lines = completed.stderr.splitlines()
        for line in lines:
            print(f"      {line}")
        return len(lines)

    linted_xml = completed.stdout
    linted_xml = completed.stdout
    return linted_xml

def get_linting_errors(file: Path) -> str | None:
    linted_xml = run_linter(file)
    orig_xml = file.read_text(encoding="utf8")
    orig_xml = file.read_text(encoding="utf8")
    diff = list(unified_diff(orig_xml.splitlines(), linted_xml.splitlines()))
    diff = list(unified_diff(orig_xml.splitlines(), linted_xml.splitlines()))
    if len(diff) == 0:
    if len(diff) == 0:
        print(f"{str(f)}")
        return None
        return 0
    else:
        return "\n".join([print_colorized_diff_line(d) for d in diff])

def prettify_file(file: Path):
    linted_xml = run_linter(file)
    linting_errors = get_linting_errors(file)
    if linting_errors:
        file.write_text(linted_xml, encoding="utf8")
        return True
    else:
    else:
        print(f"{str(f)}: {len(diff)} linting errors")
        print("Linter returned no errors - nothing to do!")
        for d in diff:
        return False
            print("".join(d))
        return len(diff)




if __name__ == "__main__":
if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    
    parser.add_argument("-i", "--input", help="Specific file to lint (use - for stdin). If omitted, lint all XML files in the repo.")
    parser.add_argument("-p", "--prettify", action="store_true", help="Rewrite the file to no longer offend the linter")
    args = parser.parse_args()

    if args.prettify:
        if args.input is None:
            print("Prettify required an input file to be specified (-i | --input)")
            exit(-1)
        else:
            path = Path(args.input)
            if not path.exists():
                print(f"Could not find file {args.input}")
            if prettify_file(path):
                exit(1)
            else:
                exit(0)

    files = []
    if args.input:
        files.append(Path(args.input))
    else:
        root = Path("./")
        root = Path("./")
        files = list(root.rglob("*.xml")) + list(root.rglob("*.xsd"))
        files = list(root.rglob("*.xml")) + list(root.rglob("*.xsd"))


@@ -55,22 +88,31 @@ if __name__ == "__main__":
    print("")
    print("")
    print(f"Linting XML / XSD files...")
    print(f"Linting XML / XSD files...")


    error_files = {}

    for f in files:
    for f in files:
        if len(list(set(f.parents) & set(ignore_paths))) > 0:
        if (len(list(set(f.parents) & set(ignore_paths))) > 0) or\
           (str(f) in ignore_files):
            print(f"(Ignoring {f})")
            print(f"(Ignoring {f})")
            continue
            continue
        new_errors = lint(f)
        new_errors = get_linting_errors(f)
        errors += new_errors
        if new_errors:
        files_with_errors += 1 if new_errors > 0 else 0
            files_with_errors += 1
            print(f"{str(f)}")
            error_files[str(f)] = new_errors
        else:
            print(f"{str(f)}")



    for k,v in error_files.items():
        print("───────────────────────────────────────────────────────────────────")
        print (f"{k}")
        print (v)
    print("───────────────────────────────────────────────────────────────────")
    print("───────────────────────────────────────────────────────────────────")
    print(
        f"Files: {len(files)} ({files_with_errors} with errors)  Total errors: {errors}"
    )
    if files_with_errors == 0:
    if files_with_errors == 0:
        print("✅ OK")
        print("✅ OK")
    else:
    else:
        print("Fail")
        print(f"{files_with_errors} out of {len(files)} files had linting errors")
    print("───────────────────────────────────────────────────────────────────")
    print("───────────────────────────────────────────────────────────────────")


    if files_with_errors > 0:
    if files_with_errors > 0:
+1 −1

File changed.

Contains only whitespace changes.

+1 −1

File changed.

Contains only whitespace changes.

+2 −2

File changed.

Contains only whitespace changes.

+7 −7

File changed.

Contains only whitespace changes.

+12 −12

File changed.

Contains only whitespace changes.

+40 −40

File changed.

Contains only whitespace changes.

Loading