Package version up
[platform/upstream/libxkbcommon.git] / test / xkeyboard-config-test.py.in
index 752f027..c33e707 100755 (executable)
@@ -10,11 +10,11 @@ from pathlib import Path
 
 verbose = False
 
-DEFAULT_RULES_XML = '@XKB_CONFIG_ROOT@/rules/evdev.xml'
+DEFAULT_RULES_XML = "@XKB_CONFIG_ROOT@/rules/evdev.xml"
 
 # Meson needs to fill this in so we can call the tool in the buildir.
-EXTRA_PATH = '@MESON_BUILD_ROOT@'
-os.environ['PATH'] = ':'.join([EXTRA_PATH, os.getenv('PATH')])
+EXTRA_PATH = "@MESON_BUILD_ROOT@"
+os.environ["PATH"] = ":".join([EXTRA_PATH, os.getenv("PATH")])
 
 
 def escape(s):
@@ -30,6 +30,7 @@ def create_progress_bar(verbose):
     if not verbose and os.isatty(sys.stdout.fileno()):
         try:
             from tqdm import tqdm
+
             progress_bar = tqdm
         except ImportError:
             pass
@@ -56,13 +57,13 @@ class Invocation:
     def __str__(self):
         s = []
         rmlvo = [x or "" for x in self.rmlvo]
-        rmlvo = ', '.join([f'"{x}"' for x in rmlvo])
-        s.append(f'- rmlvo: [{rmlvo}]')
+        rmlvo = ", ".join([f'"{x}"' for x in rmlvo])
+        s.append(f"- rmlvo: [{rmlvo}]")
         s.append(f'  cmd: "{escape(self.command)}"')
-        s.append(f'  status: {self.exitstatus}')
+        s.append(f"  status: {self.exitstatus}")
         if self.error:
             s.append(f'  error: "{escape(self.error.strip())}"')
-        return '\n'.join(s)
+        return "\n".join(s)
 
     def run(self):
         raise NotImplementedError
@@ -71,37 +72,45 @@ class Invocation:
 class XkbCompInvocation(Invocation):
     def run(self):
         r, m, l, v, o = self.rmlvo
-        args = ['setxkbmap', '-print']
+        args = ["setxkbmap", "-print"]
         if r is not None:
-            args.append('-rules')
-            args.append('{}'.format(r))
+            args.append("-rules")
+            args.append("{}".format(r))
         if m is not None:
-            args.append('-model')
-            args.append('{}'.format(m))
+            args.append("-model")
+            args.append("{}".format(m))
         if l is not None:
-            args.append('-layout')
-            args.append('{}'.format(l))
+            args.append("-layout")
+            args.append("{}".format(l))
         if v is not None:
-            args.append('-variant')
-            args.append('{}'.format(v))
+            args.append("-variant")
+            args.append("{}".format(v))
         if o is not None:
-            args.append('-option')
-            args.append('{}'.format(o))
+            args.append("-option")
+            args.append("{}".format(o))
 
-        xkbcomp_args = ['xkbcomp', '-xkb', '-', '-']
+        xkbcomp_args = ["xkbcomp", "-xkb", "-", "-"]
 
         self.command = " ".join(args + ["|"] + xkbcomp_args)
 
-        setxkbmap = subprocess.Popen(args, stdout=subprocess.PIPE,
-                                     stderr=subprocess.PIPE, universal_newlines=True)
+        setxkbmap = subprocess.Popen(
+            args,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+            universal_newlines=True,
+        )
         stdout, stderr = setxkbmap.communicate()
         if "Cannot open display" in stderr:
             self.error = stderr
             self.exitstatus = 90
         else:
-            xkbcomp = subprocess.Popen(xkbcomp_args, stdin=subprocess.PIPE,
-                                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-                                       universal_newlines=True)
+            xkbcomp = subprocess.Popen(
+                xkbcomp_args,
+                stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE,
+                stderr=subprocess.PIPE,
+                universal_newlines=True,
+            )
             stdout, stderr = xkbcomp.communicate(stdout)
             if xkbcomp.returncode != 0:
                 self.error = "failed to compile keymap"
@@ -112,27 +121,33 @@ class XkbCompInvocation(Invocation):
 
 
 class XkbcommonInvocation(Invocation):
+    UNRECOGNIZED_KEYSYM_ERROR = "XKB-107"
+
     def run(self):
         r, m, l, v, o = self.rmlvo
         args = [
-            'xkbcli-compile-keymap',  # this is run in the builddir
-            '--verbose',
-            '--rules', r,
-            '--model', m,
-            '--layout', l,
+            "xkbcli-compile-keymap",  # this is run in the builddir
+            "--verbose",
+            "--rules",
+            r,
+            "--model",
+            m,
+            "--layout",
+            l,
         ]
         if v is not None:
-            args += ['--variant', v]
+            args += ["--variant", v]
         if o is not None:
-            args += ['--options', o]
+            args += ["--options", o]
 
         self.command = " ".join(args)
         try:
-            output = subprocess.check_output(args, stderr=subprocess.STDOUT,
-                                             universal_newlines=True)
-            if "unrecognized keysym" in output:
-                for line in output.split('\n'):
-                    if "unrecognized keysym" in line:
+            output = subprocess.check_output(
+                args, stderr=subprocess.STDOUT, universal_newlines=True
+            )
+            if self.UNRECOGNIZED_KEYSYM_ERROR in output:
+                for line in output.split("\n"):
+                    if self.UNRECOGNIZED_KEYSYM_ERROR in line:
                         self.error = line
                 self.exitstatus = 99  # tool doesn't generate this one
             else:
@@ -145,11 +160,11 @@ class XkbcommonInvocation(Invocation):
 
 def xkbcommontool(rmlvo):
     try:
-        r = rmlvo.get('r', 'evdev')
-        m = rmlvo.get('m', 'pc105')
-        l = rmlvo.get('l', 'us')
-        v = rmlvo.get('v', None)
-        o = rmlvo.get('o', None)
+        r = rmlvo.get("r", "evdev")
+        m = rmlvo.get("m", "pc105")
+        l = rmlvo.get("l", "us")
+        v = rmlvo.get("v", None)
+        o = rmlvo.get("o", None)
         tool = XkbcommonInvocation(r, m, l, v, o)
         tool.run()
         return tool
@@ -159,11 +174,11 @@ def xkbcommontool(rmlvo):
 
 def xkbcomp(rmlvo):
     try:
-        r = rmlvo.get('r', 'evdev')
-        m = rmlvo.get('m', 'pc105')
-        l = rmlvo.get('l', 'us')
-        v = rmlvo.get('v', None)
-        o = rmlvo.get('o', None)
+        r = rmlvo.get("r", "evdev")
+        m = rmlvo.get("m", "pc105")
+        l = rmlvo.get("l", "us")
+        v = rmlvo.get("v", None)
+        o = rmlvo.get("o", None)
         tool = XkbCompInvocation(r, m, l, v, o)
         tool.run()
         return tool
@@ -173,25 +188,22 @@ def xkbcomp(rmlvo):
 
 def parse(path):
     root = ET.fromstring(open(path).read())
-    layouts = root.findall('layoutList/layout')
+    layouts = root.findall("layoutList/layout")
 
-    options = [
-        e.text
-        for e in root.findall('optionList/group/option/configItem/name')
-    ]
+    options = [e.text for e in root.findall("optionList/group/option/configItem/name")]
 
     combos = []
     for l in layouts:
-        layout = l.find('configItem/name').text
-        combos.append({'l': layout})
+        layout = l.find("configItem/name").text
+        combos.append({"l": layout})
 
-        variants = l.findall('variantList/variant')
+        variants = l.findall("variantList/variant")
         for v in variants:
-            variant = v.find('configItem/name').text
+            variant = v.find("configItem/name").text
 
-            combos.append({'l': layout, 'v': variant})
+            combos.append({"l": layout, "v": variant})
             for option in options:
-                combos.append({'l': layout, 'v': variant, 'o': option})
+                combos.append({"l": layout, "v": variant, "o": option})
 
     return combos
 
@@ -232,9 +244,9 @@ def run(combos, tool, njobs, keymap_output_dir):
                     keymap_file = fname
                     if keymap_file_fd:
                         keymap_file_fd.close()
-                    keymap_file_fd = open(keymap_file, 'a')
+                    keymap_file_fd = open(keymap_file, "a")
 
-                rmlvo = ', '.join([x or '' for x in invocation.rmlvo])
+                rmlvo = ", ".join([x or "" for x in invocation.rmlvo])
                 print(f"// {rmlvo}", file=keymap_file_fd)
                 print(invocation.keymap, file=keymap_file_fd)
                 keymap_file_fd.flush()
@@ -247,32 +259,56 @@ def main(args):
     global verbose
 
     tools = {
-        'libxkbcommon': xkbcommontool,
-        'xkbcomp': xkbcomp,
+        "libxkbcommon": xkbcommontool,
+        "xkbcomp": xkbcomp,
     }
 
     parser = argparse.ArgumentParser(
-        description='Tool to test all layout/variant/option combinations.'
+        description="""
+                    This tool compiles a keymap for each layout, variant and
+                    options combination in the given rules XML file. The output
+                    of this tool is YAML, use your favorite YAML parser to
+                    extract error messages. Errors are printed to stderr.
+                    """
+    )
+    parser.add_argument(
+        "path",
+        metavar="/path/to/evdev.xml",
+        nargs="?",
+        type=str,
+        default=DEFAULT_RULES_XML,
+        help="Path to xkeyboard-config's evdev.xml",
+    )
+    parser.add_argument(
+        "--tool",
+        choices=tools.keys(),
+        type=str,
+        default="libxkbcommon",
+        help="parsing tool to use",
+    )
+    parser.add_argument(
+        "--jobs",
+        "-j",
+        type=int,
+        default=os.cpu_count() * 4,
+        help="number of processes to use",
+    )
+    parser.add_argument("--verbose", "-v", default=False, action="store_true")
+    parser.add_argument(
+        "--keymap-output-dir",
+        default=None,
+        type=str,
+        help="Directory to print compiled keymaps to",
+    )
+    parser.add_argument(
+        "--layout", default=None, type=str, help="Only test the given layout"
+    )
+    parser.add_argument(
+        "--variant", default=None, type=str, help="Only test the given variant"
+    )
+    parser.add_argument(
+        "--option", default=None, type=str, help="Only test the given option"
     )
-    parser.add_argument('path', metavar='/path/to/evdev.xml',
-                        nargs='?', type=str,
-                        default=DEFAULT_RULES_XML,
-                        help='Path to xkeyboard-config\'s evdev.xml')
-    parser.add_argument('--tool', choices=tools.keys(),
-                        type=str, default='libxkbcommon',
-                        help='parsing tool to use')
-    parser.add_argument('--jobs', '-j', type=int,
-                        default=os.cpu_count() * 4,
-                        help='number of processes to use')
-    parser.add_argument('--verbose', '-v', default=False, action="store_true")
-    parser.add_argument('--keymap-output-dir', default=None, type=str,
-                        help='Directory to print compiled keymaps to')
-    parser.add_argument('--layout', default=None, type=str,
-                        help='Only test the given layout')
-    parser.add_argument('--variant', default=None, type=str,
-                        help='Only test the given variant')
-    parser.add_argument('--option', default=None, type=str,
-                        help='Only test the given option')
 
     args = parser.parse_args()
 
@@ -283,19 +319,21 @@ def main(args):
     tool = tools[args.tool]
 
     if any([args.layout, args.variant, args.option]):
-        combos = [{
-            'l': args.layout,
-            'v': args.variant,
-            'o': args.option,
-        }]
+        combos = [
+            {
+                "l": args.layout,
+                "v": args.variant,
+                "o": args.option,
+            }
+        ]
     else:
         combos = parse(args.path)
     failed = run(combos, tool, args.jobs, keymapdir)
     sys.exit(failed)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     try:
         main(sys.argv)
     except KeyboardInterrupt:
-        print('# Exiting after Ctrl+C')
+        print("# Exiting after Ctrl+C")