3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # Script to evaluate LPE test output and update reference files.
7 # Copyright (C) 2023-2024 Authors
10 # PBS <pbs3141@gmail.com>
11 # Martin Owens <doctormo@gmail.com>
13 # Released under GNU GPL v2+, read the file 'COPYING' for more information.
15 import os
, re
, sys
, argparse
17 description
= '''Evaluate LPE test output and update reference files.
20 1. Download the "complete raw" job log from one of the test pipelines and place it in the same directory as this script, named joblog.txt. Alternatively, collect the output from running the test suite.
21 2. Run the script and examine the output.
22 3. If there are no regressions, say yes when it offers to update the testfiles/lpe_tests/* files.
25 The output consists of the old paths 'a.txt', new paths 'b.txt', and visual comparison 'path-comparison.svg'.
26 For each LPE test failure,
27 - The old path is written on a single line to 'a.txt'.
28 - The new path is written on a single line to 'b.txt'.
29 - A group is written to 'path-comparison.svg' containing the old path in yellow and the new path in cyan,
30 with additive blend mode. Non-matching areas therefore appear in either yellow or cyan.'''
36 txt
= input("[y/n]: ").lower()
37 if txt
in ('y', 'yes'): return True
38 if txt
in ('n', 'no'): return False
39 sys
.stdout
.write("\nPlease specify yes or no.\n")
41 def update_reference_files(path
, a
, b
, svg
, id):
43 m
= re
.search("testfiles", svg
)
45 sys
.stderr
.write(f
"Warning: Ignoring file '{svg}'\n")
48 # Open and cache the contents of the file
49 name
= os
.path
.join(path
, svg
[m
.start():])
50 if name
not in open_testfiles
:
51 with
open(name
, "r") as tmpf
:
52 open_testfiles
[name
] = tmpf
.read()
54 contents
= open_testfiles
[name
]
55 m
= re
.search(fr
'\bid *= *"{id}"', contents
)
57 sys
.stderr
.write(f
"Warning: Ignoring id {id}\n")
61 contents
.rfind("<path", 0, m
.start()),
62 contents
.rfind("<ellipse", 0, m
.start())
65 sys
.stderr
.write(f
"Warning: Couldn't find start of path for {id}\n")
68 m
= re
.compile(r
'\bd *= *"').search(contents
, i
)
70 sys
.stderr
.write(f
"Warning: Couldn't find d attribute for {id}\n")
74 j
= contents
.find('"', i
)
76 sys
.stderr
.write(f
"Warning: Couldn't find end of d attribute for {id}\n")
79 contents
= contents
[:i
] + b
+ contents
[j
:]
80 open_testfiles
[name
] = contents
82 def found(cmpf
, af
, bf
, inkscape
, count
, a
, b
, svg
, id):
84 <path style="fill:#ffff00;stroke:none" d="{a}" id="good{count}" />
85 <path style="fill:#00ffff;stroke:none;mix-blend-mode:lighten" d="{b}" id="bad{count}" />
90 update_reference_files(inkscape
, a
, b
, svg
, id)
93 parser
= argparse
.ArgumentParser(prog
='lpetest-parse.py', description
=description
, formatter_class
=argparse
.RawTextHelpFormatter
)
94 parser
.add_argument('--log', default
='joblog.txt', metavar
='FILE', help='Input file containing test log')
95 parser
.add_argument('--cmp', default
='path-comparison.svg', metavar
='FILE', help='Output file for visualisation of path differences')
96 parser
.add_argument('--a', default
='a.txt', metavar
='FILE', help='Output file for original paths')
97 parser
.add_argument('--b', default
='b.txt', metavar
='FILE', help='Output file for new paths')
98 parser
.add_argument('--inkscape', default
='..', metavar
='DIR', help='Inkscape project root directory')
99 args
= parser
.parse_args()
101 if not os
.path
.isdir(os
.path
.join(args
.inkscape
, '.git')):
102 sys
.stderr
.write(f
"Project not found in '{args.inkscape}'\n\n")
103 sys
.stderr
.write("Please run this from the Inkscape project root directory, or pass it as --inkscape\n")
106 if not os
.path
.isfile(args
.log
):
107 sys
.stderr
.write(f
"Test log not found in '{args.log}'\n\n")
108 sys
.stderr
.write("Please run the suite or download log file from a CI pipeline first\n")
111 with
open(args
.log
, "r") as logf
:
114 with
open(args
.cmp, "w") as cmpf
, open(args
.a
, "w") as af
, open(args
.b
, "w") as bf
:
115 cmpf
.write("<svg>\n")
119 for tag
, value
in re
.findall(r
"\s*\d+:\s+(?P<name>svg|id|a|b):\s*\d+:\s+(?P<value>.+)", log
):
123 found(cmpf
, af
, bf
, args
.inkscape
, count
, **data
)
125 cmpf
.write("</svg>\n")
127 if len(open_testfiles
) > 0:
128 print("Overwrite these files?")
129 for name
in open_testfiles
.keys():
133 for name
, contents
in open_testfiles
.items():
134 with
open(name
, "w") as out
:
137 if __name__
== "__main__":