[master 2/5] Flatten the glade test directory.

dashea installerbot-noreply at redhat.com
Tue Jun 30 19:00:32 UTC 2015


From: David Shea <dshea at redhat.com>

Having a bunch of subdirectories with one file each seems kind of silly.
---
 tests/Makefile.am                                 |   2 +-
 tests/glade/accelerators/check_accelerators.py    | 257 ----------------------
 tests/glade/check_accelerators.py                 | 257 ++++++++++++++++++++++
 tests/glade/check_format_string.py                |  81 +++++++
 tests/glade/check_glade_validity.py               |  88 ++++++++
 tests/glade/check_icons.py                        |  75 +++++++
 tests/glade/check_invisible_char.py               |  82 +++++++
 tests/glade/check_markup.py                       | 138 ++++++++++++
 tests/glade/check_pw_visibility.py                |  93 ++++++++
 tests/glade/check_viewport.py                     |  79 +++++++
 tests/glade/format_string/check_format_string.py  |  81 -------
 tests/glade/icons/check_icons.py                  |  75 -------
 tests/glade/markup/check_markup.py                | 138 ------------
 tests/glade/pw_visibility/check_invisible_char.py |  82 -------
 tests/glade/pw_visibility/check_pw_visibility.py  |  93 --------
 tests/glade/run_glade_tests.sh                    |   6 +-
 tests/glade/validity/check_glade_validity.py      |  88 --------
 tests/glade/viewport/check_viewport.py            |  79 -------
 18 files changed, 897 insertions(+), 897 deletions(-)
 delete mode 100755 tests/glade/accelerators/check_accelerators.py
 create mode 100755 tests/glade/check_accelerators.py
 create mode 100755 tests/glade/check_format_string.py
 create mode 100755 tests/glade/check_glade_validity.py
 create mode 100755 tests/glade/check_icons.py
 create mode 100755 tests/glade/check_invisible_char.py
 create mode 100755 tests/glade/check_markup.py
 create mode 100755 tests/glade/check_pw_visibility.py
 create mode 100755 tests/glade/check_viewport.py
 delete mode 100755 tests/glade/format_string/check_format_string.py
 delete mode 100755 tests/glade/icons/check_icons.py
 delete mode 100755 tests/glade/markup/check_markup.py
 delete mode 100755 tests/glade/pw_visibility/check_invisible_char.py
 delete mode 100755 tests/glade/pw_visibility/check_pw_visibility.py
 delete mode 100755 tests/glade/validity/check_glade_validity.py
 delete mode 100755 tests/glade/viewport/check_viewport.py

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 26cfc6c..b742e6e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -34,7 +34,7 @@ AM_TESTS_ENVIRONMENT = top_srcdir="$(top_srcdir)" top_builddir="$(top_builddir)"
 TEST_EXTENSIONS = .sh
 
 # Test scripts need to be listed both here and in TESTS
-dist_check_SCRIPTS = $(srcdir)/glade/*/*.py \
+dist_check_SCRIPTS = $(srcdir)/glade/*.py \
 		     glade/run_glade_tests.sh \
 		     $(srcdir)/lib/*.py \
 		     $(srcdir)/lib/*.sh \
diff --git a/tests/glade/accelerators/check_accelerators.py b/tests/glade/accelerators/check_accelerators.py
deleted file mode 100755
index ab87ec1..0000000
--- a/tests/glade/accelerators/check_accelerators.py
+++ /dev/null
@@ -1,257 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2013  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: David Shea <dshea at redhat.com>
-
-# Ignore any interruptible calls
-# pylint: disable=interruptible-system-call
-
-import sys
-import argparse
-import re
-import os.path
-import copy
-import locale
-
-# Import translation methods if needed
-if ('-t' in sys.argv) or ('--translate' in sys.argv):
-    try:
-        from translatepo import translate_all
-    except ImportError:
-        print("Unable to load po translation module")
-        sys.exit(99)
-
-try:
-    from lxml import etree
-except ImportError:
-    print("You need to install the python-lxml package to use check_accelerators.py")
-    sys.exit(1)
-
-accel_re = re.compile(r'_(?P<accel>.)')
-success = True
-
-def is_exception(node, conflicting_node, language=None):
-    # Check for a comment of the form
-    # <!-- check_accelerators: <conflicting-node-id> -->
-    # The node passed in is the label property of the widget rather than the
-    # <object> node itself, so we actually want the id attribute of the parent node.
-    for comment in node.xpath("./preceding-sibling::comment()[contains(., 'check_accelerators:')]"):
-        if comment.text.split(":")[1].strip() == conflicting_node.getparent().attrib['id']:
-            return True
-
-    return False
-
-def add_check_accel(glade_filename, accels, label, po_map):
-    """Check whether an accelerator conflicts with existing accelerators.
-       and add it to the current accelerator context.
-    """
-    global success
-
-    if po_map:
-        try:
-            label_texts = po_map.get(label.text, label.get("context"))
-        except KeyError:
-            return
-
-        # If there is more than one translation (i.e., a plural string), check
-        # that the accelerator is the same for all translations
-        if len(label_texts) > 1:
-            match = accel_re.search(label_texts[0])
-            if match:
-                accel0 = match.group('accel').lower()
-            else:
-                accel0 = None
-
-            for label_text in label_texts[1:]:
-                match = accel_re.search(label_text)
-                if match:
-                    accel = match.group('accel').lower()
-                else:
-                    accel = None
-
-                if accel != accel0:
-                    print("Mismatched accelerator in translations for %s in language %s" % \
-                            (label.text, po_map.metadata['Language']))
-                    success = False
-
-        label.text = label_texts[0]
-        lang_str = " for language %s" % po_map.metadata['Language']
-    else:
-        lang_str = ""
-
-    match = accel_re.search(label.text)
-    if match:
-        accel = match.group('accel').lower()
-        if accel in accels:
-            # Check for an exception comment
-            if is_exception(label, accels[accel]):
-                return
-
-            print(("Accelerator collision for key %s in %s%s\n    line %d: %s\n    line %d: %s" %\
-                    (accel, os.path.normpath(glade_filename), lang_str,
-                        accels[accel].sourceline, accels[accel].text,
-                        label.sourceline, label.text)).encode("utf-8"))
-            success = False
-        else:
-            accels[accel] = label
-    else:
-        print(("No accelerator defined for %s in %s%s: line %d" %\
-                (label.text, os.path.normpath(glade_filename), lang_str,
-                    label.sourceline)).encode("utf-8"))
-        success = False
-
-def combine_accels(glade_filename, list_a, list_b, po_map):
-    if not list_a:
-        return list_b
-    if not list_b:
-        return list_a
-
-    newlist = []
-    for accels_a in list_a:
-        for accels_b in list_b:
-            new_accels = copy.copy(accels_a)
-            for accel in accels_b.keys():
-                add_check_accel(glade_filename, new_accels, accels_b[accel], po_map)
-            newlist.append(new_accels)
-    return newlist
-
-# GtkNotebook widgets define several child widgets, not all of which are active
-# at the same time. To further complicate things, an object can have more than
-# one GtkNotebook child, and a GtkNotebook can have GtkNotebook children.
-#
-# To handle this, GtkNotebook objects are processed separately.
-# process_object returns a list of possible accelerator dictionaries, and each of
-# these is compared against the list of accelerators returned for the object's
-# other GtkNotebook children.
-
-def process_object(glade_filename, interface_object, po_map):
-    """Process keyboard shortcuts for a given glade object.
-
-       The return value from this function is a list of accelerator
-       dictionaries, with each consiting of accelerator shortcut characters
-       as keys and the corresponding <object> Element objects as values. Each
-       dictionary represents a set of accelerators that could be active at any
-       given time.
-    """
-    # Start with an empty context for things that are always active
-    accels = [{}]
-
-    # Add everything that isn't a child of a GtkNotebook
-    for label in interface_object.xpath(".//property[@name='label' and ../property[@name='use_underline']/text() = 'True' and not(ancestor::object[@class='GtkNotebook'])]"):
-        add_check_accel(glade_filename, accels[0], label, po_map)
-
-    # For each GtkNotebook tab that is not a child of another notebook,
-    # add the tab to the top-level context
-    for notebook_label in interface_object.xpath(".//object[@class='GtkNotebook' and not(ancestor::object[@class='GtkNotebook'])]/child[@type='tab']//property[@name='label' and ../property[@name='use_underline']/text() = 'True']"):
-        add_check_accel(glade_filename, accels[0], notebook_label, po_map)
-
-    # Now process each non-tab object in each Gtknotebook that is not a child
-    # of another notebook. For each Gtk notebook, each non-tab child represents
-    # a separate potentially-active context. Since each list returned by
-    # process_object for a GtkNotebook child is independent of each other
-    # GtkNotebook child, we can just combine all of them into a single list.
-    # For example, say there's a notebook with two panes. The first pane
-    # contains another notebook with two panes. Let's call the main pane
-    # A, and the panes in the child GtkNotebook A_1 and A_2. A contains an
-    # accelerator for 'a', A_1 contains accelerators for 'b' and 'c', and A_2
-    # contains accelerators for 'b' and 'c'. The list returned would look like:
-    #   [{'a': label1, 'b': label2, 'c': label3},
-    #    {'a': label1, 'b': label4, 'c': label5}]
-    # Then when we process the other pane in the outermost Notebook (let's call
-    # it B), we find acclerators for 'a' and 'b':
-    #   [{'a': label6, 'b': label7}].
-    # None of these dictionaries are active at the same time. Because
-    # process_object on A combined the accelerators that are in the top-level
-    # of A with each of the accelerators in the Notebook children of A, we can
-    # treat A as if it were actually two panes at the same-level of B and just
-    # create a list of three dictionaries for the whole notebook.
-    #
-    # A deepcopy of each object is taken so that the object can be treated as a
-    # separate XML document so that the ancestor axis stuff works.
-
-    for notebook in interface_object.xpath(".//object[@class='GtkNotebook' and not(ancestor::object[@class='GtkNotebook'])]"):
-        # Create the list of dictionaries for the notebook
-        notebook_list = []
-        for child in notebook.xpath("./child[not(@type='tab')]"):
-            notebook_list.extend(process_object(glade_filename, copy.deepcopy(child), po_map))
-
-        # Now combine this with our list of accelerators
-        accels = combine_accels(glade_filename, accels, notebook_list, po_map)
-
-    return accels
-
-def check_glade(glade_filename, po_map=None):
-    with open(glade_filename) as glade_file:
-        # Parse the XML
-        glade_tree = etree.parse(glade_file)
-
-        # Treat each top-level object as a separate context
-        for interface_object in glade_tree.xpath("/interface/object"):
-            process_object(glade_filename, interface_object, po_map)
-
-def main(argv=None):
-    if argv is None:
-        argv = sys.argv
-
-    parser = argparse.ArgumentParser("Check for duplicated accelerators")
-    parser.add_argument("-t", "--translate", action='store_true',
-            help="Check translated strings")
-    parser.add_argument("-p", "--podir", action='store', type=str,
-            metavar='PODIR', help='Directory containing po files', default='./po')
-    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
-            help='The glade file to check')
-    args = parser.parse_args(args=argv)
-
-    # First check the untranslated strings in each file
-    for glade_file in args.glade_files:
-        check_glade(glade_file)
-
-    # Now loop over all of the translations
-    if args.translate:
-        import langtable
-
-        podicts = translate_all(args.podir)
-
-        for (lang, po_map) in ((key, podicts[key]) for key in podicts.keys()):
-            # Set the locale so that we can use lower() on accelerator keys.
-            # If the language is of the form xx_XX, use that as the
-            # locale name. Otherwise use the first locale that
-            # langtable returns for the language. If that doesn't work,
-            # just use C and hope for the best.
-            if '_' in lang:
-                locale.setlocale(locale.LC_ALL, lang)
-            else:
-                locale_list = langtable.list_locales(languageId=lang)
-                if locale_list:
-                    try:
-                        locale.setlocale(locale.LC_ALL, locale_list[0])
-                    except locale.Error:
-                        print("No such locale %s, using C" % locale_list[0])
-                        locale.setlocale(locale.LC_ALL, 'C')
-                else:
-                    locale.setlocale(locale.LC_ALL, 'C')
-
-            for glade_file in args.glade_files:
-                check_glade(glade_file, po_map)
-
-if __name__ == "__main__":
-    main(sys.argv[1:])
-
-    if success:
-        sys.exit(0)
-    else:
-        sys.exit(1)
diff --git a/tests/glade/check_accelerators.py b/tests/glade/check_accelerators.py
new file mode 100755
index 0000000..ab87ec1
--- /dev/null
+++ b/tests/glade/check_accelerators.py
@@ -0,0 +1,257 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2013  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Shea <dshea at redhat.com>
+
+# Ignore any interruptible calls
+# pylint: disable=interruptible-system-call
+
+import sys
+import argparse
+import re
+import os.path
+import copy
+import locale
+
+# Import translation methods if needed
+if ('-t' in sys.argv) or ('--translate' in sys.argv):
+    try:
+        from translatepo import translate_all
+    except ImportError:
+        print("Unable to load po translation module")
+        sys.exit(99)
+
+try:
+    from lxml import etree
+except ImportError:
+    print("You need to install the python-lxml package to use check_accelerators.py")
+    sys.exit(1)
+
+accel_re = re.compile(r'_(?P<accel>.)')
+success = True
+
+def is_exception(node, conflicting_node, language=None):
+    # Check for a comment of the form
+    # <!-- check_accelerators: <conflicting-node-id> -->
+    # The node passed in is the label property of the widget rather than the
+    # <object> node itself, so we actually want the id attribute of the parent node.
+    for comment in node.xpath("./preceding-sibling::comment()[contains(., 'check_accelerators:')]"):
+        if comment.text.split(":")[1].strip() == conflicting_node.getparent().attrib['id']:
+            return True
+
+    return False
+
+def add_check_accel(glade_filename, accels, label, po_map):
+    """Check whether an accelerator conflicts with existing accelerators.
+       and add it to the current accelerator context.
+    """
+    global success
+
+    if po_map:
+        try:
+            label_texts = po_map.get(label.text, label.get("context"))
+        except KeyError:
+            return
+
+        # If there is more than one translation (i.e., a plural string), check
+        # that the accelerator is the same for all translations
+        if len(label_texts) > 1:
+            match = accel_re.search(label_texts[0])
+            if match:
+                accel0 = match.group('accel').lower()
+            else:
+                accel0 = None
+
+            for label_text in label_texts[1:]:
+                match = accel_re.search(label_text)
+                if match:
+                    accel = match.group('accel').lower()
+                else:
+                    accel = None
+
+                if accel != accel0:
+                    print("Mismatched accelerator in translations for %s in language %s" % \
+                            (label.text, po_map.metadata['Language']))
+                    success = False
+
+        label.text = label_texts[0]
+        lang_str = " for language %s" % po_map.metadata['Language']
+    else:
+        lang_str = ""
+
+    match = accel_re.search(label.text)
+    if match:
+        accel = match.group('accel').lower()
+        if accel in accels:
+            # Check for an exception comment
+            if is_exception(label, accels[accel]):
+                return
+
+            print(("Accelerator collision for key %s in %s%s\n    line %d: %s\n    line %d: %s" %\
+                    (accel, os.path.normpath(glade_filename), lang_str,
+                        accels[accel].sourceline, accels[accel].text,
+                        label.sourceline, label.text)).encode("utf-8"))
+            success = False
+        else:
+            accels[accel] = label
+    else:
+        print(("No accelerator defined for %s in %s%s: line %d" %\
+                (label.text, os.path.normpath(glade_filename), lang_str,
+                    label.sourceline)).encode("utf-8"))
+        success = False
+
+def combine_accels(glade_filename, list_a, list_b, po_map):
+    if not list_a:
+        return list_b
+    if not list_b:
+        return list_a
+
+    newlist = []
+    for accels_a in list_a:
+        for accels_b in list_b:
+            new_accels = copy.copy(accels_a)
+            for accel in accels_b.keys():
+                add_check_accel(glade_filename, new_accels, accels_b[accel], po_map)
+            newlist.append(new_accels)
+    return newlist
+
+# GtkNotebook widgets define several child widgets, not all of which are active
+# at the same time. To further complicate things, an object can have more than
+# one GtkNotebook child, and a GtkNotebook can have GtkNotebook children.
+#
+# To handle this, GtkNotebook objects are processed separately.
+# process_object returns a list of possible accelerator dictionaries, and each of
+# these is compared against the list of accelerators returned for the object's
+# other GtkNotebook children.
+
+def process_object(glade_filename, interface_object, po_map):
+    """Process keyboard shortcuts for a given glade object.
+
+       The return value from this function is a list of accelerator
+       dictionaries, with each consiting of accelerator shortcut characters
+       as keys and the corresponding <object> Element objects as values. Each
+       dictionary represents a set of accelerators that could be active at any
+       given time.
+    """
+    # Start with an empty context for things that are always active
+    accels = [{}]
+
+    # Add everything that isn't a child of a GtkNotebook
+    for label in interface_object.xpath(".//property[@name='label' and ../property[@name='use_underline']/text() = 'True' and not(ancestor::object[@class='GtkNotebook'])]"):
+        add_check_accel(glade_filename, accels[0], label, po_map)
+
+    # For each GtkNotebook tab that is not a child of another notebook,
+    # add the tab to the top-level context
+    for notebook_label in interface_object.xpath(".//object[@class='GtkNotebook' and not(ancestor::object[@class='GtkNotebook'])]/child[@type='tab']//property[@name='label' and ../property[@name='use_underline']/text() = 'True']"):
+        add_check_accel(glade_filename, accels[0], notebook_label, po_map)
+
+    # Now process each non-tab object in each Gtknotebook that is not a child
+    # of another notebook. For each Gtk notebook, each non-tab child represents
+    # a separate potentially-active context. Since each list returned by
+    # process_object for a GtkNotebook child is independent of each other
+    # GtkNotebook child, we can just combine all of them into a single list.
+    # For example, say there's a notebook with two panes. The first pane
+    # contains another notebook with two panes. Let's call the main pane
+    # A, and the panes in the child GtkNotebook A_1 and A_2. A contains an
+    # accelerator for 'a', A_1 contains accelerators for 'b' and 'c', and A_2
+    # contains accelerators for 'b' and 'c'. The list returned would look like:
+    #   [{'a': label1, 'b': label2, 'c': label3},
+    #    {'a': label1, 'b': label4, 'c': label5}]
+    # Then when we process the other pane in the outermost Notebook (let's call
+    # it B), we find acclerators for 'a' and 'b':
+    #   [{'a': label6, 'b': label7}].
+    # None of these dictionaries are active at the same time. Because
+    # process_object on A combined the accelerators that are in the top-level
+    # of A with each of the accelerators in the Notebook children of A, we can
+    # treat A as if it were actually two panes at the same-level of B and just
+    # create a list of three dictionaries for the whole notebook.
+    #
+    # A deepcopy of each object is taken so that the object can be treated as a
+    # separate XML document so that the ancestor axis stuff works.
+
+    for notebook in interface_object.xpath(".//object[@class='GtkNotebook' and not(ancestor::object[@class='GtkNotebook'])]"):
+        # Create the list of dictionaries for the notebook
+        notebook_list = []
+        for child in notebook.xpath("./child[not(@type='tab')]"):
+            notebook_list.extend(process_object(glade_filename, copy.deepcopy(child), po_map))
+
+        # Now combine this with our list of accelerators
+        accels = combine_accels(glade_filename, accels, notebook_list, po_map)
+
+    return accels
+
+def check_glade(glade_filename, po_map=None):
+    with open(glade_filename) as glade_file:
+        # Parse the XML
+        glade_tree = etree.parse(glade_file)
+
+        # Treat each top-level object as a separate context
+        for interface_object in glade_tree.xpath("/interface/object"):
+            process_object(glade_filename, interface_object, po_map)
+
+def main(argv=None):
+    if argv is None:
+        argv = sys.argv
+
+    parser = argparse.ArgumentParser("Check for duplicated accelerators")
+    parser.add_argument("-t", "--translate", action='store_true',
+            help="Check translated strings")
+    parser.add_argument("-p", "--podir", action='store', type=str,
+            metavar='PODIR', help='Directory containing po files', default='./po')
+    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
+            help='The glade file to check')
+    args = parser.parse_args(args=argv)
+
+    # First check the untranslated strings in each file
+    for glade_file in args.glade_files:
+        check_glade(glade_file)
+
+    # Now loop over all of the translations
+    if args.translate:
+        import langtable
+
+        podicts = translate_all(args.podir)
+
+        for (lang, po_map) in ((key, podicts[key]) for key in podicts.keys()):
+            # Set the locale so that we can use lower() on accelerator keys.
+            # If the language is of the form xx_XX, use that as the
+            # locale name. Otherwise use the first locale that
+            # langtable returns for the language. If that doesn't work,
+            # just use C and hope for the best.
+            if '_' in lang:
+                locale.setlocale(locale.LC_ALL, lang)
+            else:
+                locale_list = langtable.list_locales(languageId=lang)
+                if locale_list:
+                    try:
+                        locale.setlocale(locale.LC_ALL, locale_list[0])
+                    except locale.Error:
+                        print("No such locale %s, using C" % locale_list[0])
+                        locale.setlocale(locale.LC_ALL, 'C')
+                else:
+                    locale.setlocale(locale.LC_ALL, 'C')
+
+            for glade_file in args.glade_files:
+                check_glade(glade_file, po_map)
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
+
+    if success:
+        sys.exit(0)
+    else:
+        sys.exit(1)
diff --git a/tests/glade/check_format_string.py b/tests/glade/check_format_string.py
new file mode 100755
index 0000000..b730a94
--- /dev/null
+++ b/tests/glade/check_format_string.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2014  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Shea <dshea at redhat.com>
+#
+
+"""
+Python script to ensure that translatable format strings are not present
+in Glade files.
+
+Since format substitution is language-dependent, gettext is unable to check
+the validity of format string translations for strings within glade. Instead,
+the format string constant, the translation substitution, and the format
+substitution should all happen outside of glade. Untranslated placeholder
+strings are allowable within glade.
+"""
+
+# Ignore any interruptible calls
+# pylint: disable=interruptible-system-call
+
+import sys
+import argparse
+import re
+
+try:
+    from lxml import etree
+except ImportError:
+    print("You need to install the python-lxml package to use check_format_string.py")
+    sys.exit(1)
+
+def check_glade_file(glade_file_path):
+    global success
+
+    with open(glade_file_path) as glade_file:
+        # Parse the XML
+        glade_tree = etree.parse(glade_file)
+
+        # Check any property with translatable="yes"
+        for translatable in glade_tree.xpath(".//*[@translatable='yes']"):
+            # Look for % followed by an open parenthesis (indicating %(name)
+            # style substitution), one of the python format conversion flags
+            # (#0- +hlL), or one of the python conversion types 
+            # (diouxXeEfFgGcrs)
+            if re.search(r'%[-(#0 +hlLdiouxXeEfFgGcrs]', translatable.text):
+                print("Translatable format string found in glade at %s:%d" % \
+                        (glade_file_path, translatable.sourceline))
+                success = False
+
+if __name__ == "__main__":
+    success = True
+    parser = argparse.ArgumentParser("Check that password entries have visibility set to False")
+
+    # Ignore translation arguments
+    parser.add_argument("-t", "--translate", action='store_true',
+            help=argparse.SUPPRESS)
+    parser.add_argument("-p", "--podir", action='store', type=str,
+            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
+
+    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
+            help='The glade file to check')
+    args = parser.parse_args(args=sys.argv[1:])
+
+    success = True
+    for file_path in args.glade_files:
+        check_glade_file(file_path)
+
+    sys.exit(0 if success else 1)
diff --git a/tests/glade/check_glade_validity.py b/tests/glade/check_glade_validity.py
new file mode 100755
index 0000000..1101472
--- /dev/null
+++ b/tests/glade/check_glade_validity.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2014  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Shea <dshea at redhat.com>
+
+import sys
+import argparse
+
+from collections import Counter
+
+try:
+    from lxml import etree
+except ImportError:
+    print("You need to install the python-lxml package to run the glade checks")
+    sys.exit(99)
+
+success = True
+
+def main(argv):
+    global success
+
+    for glade_file in argv:
+        # Parse the glade file to ensure it's well-formed
+        try:
+            glade_tree = etree.parse(glade_file)
+        except etree.XMLSyntaxError:
+            print("%s is not a valid XML file" % glade_file)
+            success = False
+            continue
+
+        # Check for duplicate IDs
+        # Build a Counter from a list of all ids, extracts the ones with count > 1
+        # Fun fact: glade uses <col id="<number>"> in GtkListStore data, so ids
+        # aren't actually unique and getting an object with a particular ID
+        # isn't as simple as document.getElementById. Only check the IDs on objects.
+        for glade_id in [c for c in Counter(glade_tree.xpath(".//object/@id")).most_common() \
+                if c[1] > 1]:
+            print("%s: ID %s appears %d times" % (glade_file, glade_id[0], glade_id[1]))
+            success = False
+
+        # Check for ID references
+        # mnemonic_widget properties and action-widget elements need to refer to
+        # valid object ids.
+        for mnemonic_widget in glade_tree.xpath(".//property[@name='mnemonic_widget']"):
+            if not glade_tree.xpath(".//object[@id='%s']" % mnemonic_widget.text):
+                print("mnemonic_widget reference to invalid ID %s at line %d of %s" % \
+                        (mnemonic_widget.text, mnemonic_widget.sourceline, glade_file))
+                success = False
+
+        for action_widget in glade_tree.xpath(".//action-widget"):
+            if not glade_tree.xpath(".//object[@id='%s']" % action_widget.text):
+                print("action-widget reference to invalid ID %s at line %d of %s" % \
+                        (action_widget.text, action_widget.sourceline, glade_file))
+                success = False
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser("Check glade file validity")
+
+    # Ignore translation arguments
+    parser.add_argument("-t", "--translate", action='store_true',
+            help=argparse.SUPPRESS)
+    parser.add_argument("-p", "--podir", action='store', type=str,
+            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
+
+    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
+            help='The glade file to check')
+    args = parser.parse_args(args=sys.argv[1:])
+
+    main(args.glade_files)
+
+    if success:
+        sys.exit(0)
+    else:
+        sys.exit(1)
diff --git a/tests/glade/check_icons.py b/tests/glade/check_icons.py
new file mode 100755
index 0000000..bfeac6d
--- /dev/null
+++ b/tests/glade/check_icons.py
@@ -0,0 +1,75 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2014  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Shea <dshea at redhat.com>
+#
+"""
+Check that all icons referenced from glade files are valid in the gnome icon theme.
+"""
+
+# Ignore any interruptible calls
+# pylint: disable=interruptible-system-call
+
+import argparse
+import sys
+
+try:
+    from lxml import etree
+except ImportError:
+    print("You need to install the python-lxml package to use check_pw_visibility.py")
+    sys.exit(1)
+
+from iconcheck import icon_exists
+
+def check_glade_file(glade_file_path):
+    glade_success = True
+    with open(glade_file_path) as glade_file:
+        # Parse the XML
+        glade_tree = etree.parse(glade_file)
+
+        # Stock image names are deprecated
+        for element in glade_tree.xpath("//property[@name='stock' or @name='stock_id']"):
+            glade_success = False
+            print("Deprecated stock icon found at %s:%d" % (glade_file_path, element.sourceline))
+
+        # Check whether named icons exist
+        for element in glade_tree.xpath("//property[@name='icon_name']"):
+            if not icon_exists(element.text):
+                glade_success = False
+                print("Invalid icon name %s found at %s:%d" % (element.text, glade_file_path, element.sourceline))
+
+    return glade_success
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser("Check that password entries have visibility set to False")
+
+    # Ignore translation arguments
+    parser.add_argument("-t", "--translate", action='store_true',
+            help=argparse.SUPPRESS)
+    parser.add_argument("-p", "--podir", action='store', type=str,
+            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
+
+    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
+            help='The glade file to check')
+    args = parser.parse_args(args=sys.argv[1:])
+
+    success = True
+    for file_path in args.glade_files:
+        if not check_glade_file(file_path):
+            success = False
+
+    sys.exit(0 if success else 1)
diff --git a/tests/glade/check_invisible_char.py b/tests/glade/check_invisible_char.py
new file mode 100755
index 0000000..72d8486
--- /dev/null
+++ b/tests/glade/check_invisible_char.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python2
+#
+# Copyright (C) 2015  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Shea <dshea at redhat.com>
+#
+
+"""
+Check that the invisible_char in glade files is actually a char.
+
+The invisible char is often non-ASCII and sometimes that gets clobbered.
+"""
+
+# Ignore any interruptible calls
+# pylint: disable=interruptible-system-call
+
+import argparse
+import sys
+
+try:
+    from lxml import etree
+except ImportError:
+    print("You need to install the python-lxml package to use check_pw_visibility.py")
+    sys.exit(1)
+
+def check_glade_file(glade_file_path):
+    succ = True
+
+    with open(glade_file_path, "r") as glade_file:
+        tree = etree.parse(glade_file)
+        # Only look for entries with an invisible_char property
+        for entry in tree.xpath("//object[@class='GtkEntry' and ./property[@name='invisible_char']]"):
+            # Check the contents of the invisible_char property
+            invis = entry.xpath("./property[@name='invisible_char']")[0]
+            if len(invis.text) != 1:
+                print("invisible_char at %s:%s not a character" % (glade_file_path, invis.sourceline))
+                succ = False
+
+            # If the char is '?' that's probably also bad
+            if invis.text == '?':
+                print("invisible_char at %s:%s is not what you want" % (glade_file_path, invis.sourceline))
+
+            # Check that invisible_char even does anything: visibility should be False
+            if not entry.xpath("./property[@name='visibility' and ./text() = 'False']"):
+                print("Pointless invisible_char found at %s:%s" % (glade_file_path, invis.sourceline))
+                succ = False
+
+    return succ
+
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser("Check that invisible character properties are set correctly")
+
+    # Ignore translation arguments
+    parser.add_argument("-t", "--translate", action='store_true',
+            help=argparse.SUPPRESS)
+    parser.add_argument("-p", "--podir", action='store', type=str,
+            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
+
+    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
+            help='The glade file to check')
+    args = parser.parse_args(args=sys.argv[1:])
+
+    success = True
+    for file_path in args.glade_files:
+        if not check_glade_file(file_path):
+            success = False
+
+    sys.exit(0 if success else 1)
diff --git a/tests/glade/check_markup.py b/tests/glade/check_markup.py
new file mode 100755
index 0000000..ba639da
--- /dev/null
+++ b/tests/glade/check_markup.py
@@ -0,0 +1,138 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2014  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Shea <dshea at redhat.com>
+#
+
+"""
+Python script to check that properties in glade using Pango markup contain
+valid markup.
+"""
+
+# Ignore any interruptible calls
+# pylint: disable=interruptible-system-call
+
+import sys
+import argparse
+
+# Import translation methods if needed
+if ('-t' in sys.argv) or ('--translate' in sys.argv):
+    try:
+        from translatepo import translate_all
+    except ImportError:
+        print("Unable to load po translation module")
+        sys.exit(99)
+
+from pangocheck import markup_nodes, markup_match, markup_necessary
+
+try:
+    from lxml import etree
+except ImportError:
+    print("You need to install the python-lxml package to use check_markup.py")
+    sys.exit(99)
+
+class PangoElementException(Exception):
+    def __init__(self, element):
+        Exception.__init__(self)
+        self.element = element
+
+    def __str__(self):
+        return "Invalid element %s" % self.element
+
+def _validate_pango_markup(root):
+    """Validate parsed pango markup.
+
+       :param etree.ElementTree root: The pango markup parsed as an XML ElementTree
+       :raises PangoElementException: If the pango markup contains unknown elements
+    """
+    if root.tag not in markup_nodes:
+        raise PangoElementException(root.tag)
+
+    for child in root:
+        _validate_pango_markup(child)
+
+def check_glade_file(glade_file_path, po_map=None):
+    glade_success = True
+    with open(glade_file_path) as glade_file:
+        # Parse the XML
+        glade_tree = etree.parse(glade_file)
+
+        # Search for label properties on objects that have use_markup set to True
+        for label in glade_tree.xpath(".//property[@name='label' and ../property[@name='use_markup']/text() = 'True']"):
+            if po_map:
+                try:
+                    label_texts = po_map.get(label.text, label.get("context"))
+                except KeyError:
+                    continue
+                lang_str = " for language %s" % po_map.metadata['Language']
+            else:
+                label_texts = (label.text,)
+                lang_str = ""
+
+            # Wrap the label text in <markup> tags and parse the tree
+            for label_text in label_texts:
+                try:
+                    # pylint: disable=unescaped-markup
+                    pango_tree = etree.fromstring("<markup>%s</markup>" % label_text)
+                    _validate_pango_markup(pango_tree)
+
+                    # Check if the markup is necessary
+                    if not markup_necessary(pango_tree):
+                        print("Markup could be expressed as attributes at %s%s:%d" % \
+                                (glade_file_path, lang_str, label.sourceline))
+                        glade_success = False
+                except etree.XMLSyntaxError:
+                    print("Unable to parse pango markup at %s%s:%d" % \
+                            (glade_file_path, lang_str, label.sourceline))
+                    glade_success = False
+                except PangoElementException as px:
+                    print("Invalid pango element %s at %s%s:%d" % \
+                            (px.element, glade_file_path, lang_str, label.sourceline))
+                    glade_success = False
+                else:
+                    if po_map:
+                        # Check that translated markup has the same elements and attributes
+                        if not markup_match(label.text, label_text):
+                            print("Translated markup does not contain the same elements and attributes at %s%s:%d" % \
+                                    (glade_file_path, lang_str, label.sourceline))
+                            glade_success = False
+    return glade_success
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser("Check Pango markup validity")
+    parser.add_argument("-t", "--translate", action='store_true',
+            help="Check translated strings")
+    parser.add_argument("-p", "--podir", action='store', type=str,
+            metavar='PODIR', help='Directory containing po files', default='./po')
+    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
+            help='The glade file to check')
+    args = parser.parse_args(args=sys.argv[1:])
+
+    success = True
+    for file_path in args.glade_files:
+        if not check_glade_file(file_path):
+            success = False
+
+    # Now loop over all of the translations
+    if args.translate:
+        podicts = translate_all(args.podir)
+        for po_dict in podicts.values():
+            for file_path in args.glade_files:
+                if not check_glade_file(file_path, po_dict):
+                    success = False
+
+    sys.exit(0 if success else 1)
diff --git a/tests/glade/check_pw_visibility.py b/tests/glade/check_pw_visibility.py
new file mode 100755
index 0000000..f48f875
--- /dev/null
+++ b/tests/glade/check_pw_visibility.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2013  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Vratislav Podzimek <vpodzime at redhat.com>
+#
+
+"""
+Simple python script checking that password GtkEntries in the given .glade files
+have the visibility set to False.
+
+"""
+
+# Ignore any interruptible calls
+# pylint: disable=interruptible-system-call
+
+import argparse
+import sys
+
+try:
+    from lxml import etree
+except ImportError:
+    print("You need to install the python-lxml package to use check_pw_visibility.py")
+    sys.exit(1)
+
+PW_ID_INDICATORS = ("pw", "password", "passwd", "passphrase")
+
+def check_glade_file(glade_file_path):
+    def check_entry(entry, fpath):
+        succ = True
+
+        entry_id = entry.attrib.get("id", "UNKNOWN ID")
+        visibility_props = entry.xpath("./property[@name='visibility']")
+
+        # no entry should have visibility specified multiple times
+        if len(visibility_props) > 1:
+            print("Visibility specified multiple times for the entry %s (%s)" % (entry_id, fpath))
+            succ = False
+
+        # password entry should have visibility set to False
+        if any(ind in entry_id.lower() for ind in PW_ID_INDICATORS):
+            if not visibility_props:
+                print("Visibility not specified for the password entry %s (%s)" % (entry_id, fpath))
+                succ = False
+            elif visibility_props[0].text.strip() != "False":
+                print("Visibility not set properly for the password entry %s (%s)" % (entry_id, fpath))
+                succ = False
+        # only password entries should have the visibility set to False
+        elif visibility_props and visibility_props[0].text.strip() == "False":
+            print("Non-password entry %s (%s) has the visibility set to False (bad id?)" % (entry_id, fpath))
+            succ = False
+
+        return succ
+
+    succ = True
+    with open(glade_file_path, "r") as glade_file:
+        tree = etree.parse(glade_file)
+        for entry in tree.xpath("//object[@class='GtkEntry']"):
+            succ = succ and check_entry(entry, glade_file_path)
+
+        return succ
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser("Check that password entries have visibility set to False")
+
+    # Ignore translation arguments
+    parser.add_argument("-t", "--translate", action='store_true',
+            help=argparse.SUPPRESS)
+    parser.add_argument("-p", "--podir", action='store', type=str,
+            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
+
+    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
+            help='The glade file to check')
+    args = parser.parse_args(args=sys.argv[1:])
+
+    success = True
+    for file_path in args.glade_files:
+        success = success and check_glade_file(file_path)
+
+    sys.exit(0 if success else 1)
diff --git a/tests/glade/check_viewport.py b/tests/glade/check_viewport.py
new file mode 100755
index 0000000..bd9d771
--- /dev/null
+++ b/tests/glade/check_viewport.py
@@ -0,0 +1,79 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2014  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Shea <dshea at redhat.com>
+#
+
+"""
+Check that widgets that implement GtkScrollable are not placed within a
+GtkViewport. If a widget knows how to scroll itself we probably don't want
+to add an extra layer.
+"""
+
+# Ignore any interruptible calls
+# pylint: disable=interruptible-system-call
+
+import argparse
+import sys
+
+try:
+    from lxml import etree
+except ImportError:
+    print("You need to install the python-lxml package to use check_pw_visibility.py")
+    sys.exit(1)
+
+# I guess we could look at the introspected classes and see if they implement the Scrollable
+# interface but that sounds like kind of a pain
+SCROLLABLES = ["GtkIconView", "GtkLayout", "GtkTextView", "GtkToolPalette",
+               "GtkTreeView", "GtkViewport"]
+
+def check_glade_file(glade_file_path):
+    glade_success = True
+    with open(glade_file_path) as glade_file:
+        # Parse the XML
+        glade_tree = etree.parse(glade_file)
+
+        # Look for something like:
+        # <object class="GtkViewport">
+        #   <child>
+        #      <object class="GtkTreeView">
+        for scrollable in SCROLLABLES:
+            for element in glade_tree.xpath(".//object[@class='GtkViewport']/child/object[@class='%s']" % scrollable):
+                glade_success = False
+                print("%s contained in GtkViewport at %s:%d" % (scrollable, glade_file_path,
+                                                                element.sourceline))
+    return glade_success
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser("Check that password entries have visibility set to False")
+
+    # Ignore translation arguments
+    parser.add_argument("-t", "--translate", action='store_true',
+            help=argparse.SUPPRESS)
+    parser.add_argument("-p", "--podir", action='store', type=str,
+            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
+
+    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
+            help='The glade file to check')
+    args = parser.parse_args(args=sys.argv[1:])
+
+    success = True
+    for file_path in args.glade_files:
+        if not check_glade_file(file_path):
+            success = False
+
+    sys.exit(0 if success else 1)
diff --git a/tests/glade/format_string/check_format_string.py b/tests/glade/format_string/check_format_string.py
deleted file mode 100755
index b730a94..0000000
--- a/tests/glade/format_string/check_format_string.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2014  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: David Shea <dshea at redhat.com>
-#
-
-"""
-Python script to ensure that translatable format strings are not present
-in Glade files.
-
-Since format substitution is language-dependent, gettext is unable to check
-the validity of format string translations for strings within glade. Instead,
-the format string constant, the translation substitution, and the format
-substitution should all happen outside of glade. Untranslated placeholder
-strings are allowable within glade.
-"""
-
-# Ignore any interruptible calls
-# pylint: disable=interruptible-system-call
-
-import sys
-import argparse
-import re
-
-try:
-    from lxml import etree
-except ImportError:
-    print("You need to install the python-lxml package to use check_format_string.py")
-    sys.exit(1)
-
-def check_glade_file(glade_file_path):
-    global success
-
-    with open(glade_file_path) as glade_file:
-        # Parse the XML
-        glade_tree = etree.parse(glade_file)
-
-        # Check any property with translatable="yes"
-        for translatable in glade_tree.xpath(".//*[@translatable='yes']"):
-            # Look for % followed by an open parenthesis (indicating %(name)
-            # style substitution), one of the python format conversion flags
-            # (#0- +hlL), or one of the python conversion types 
-            # (diouxXeEfFgGcrs)
-            if re.search(r'%[-(#0 +hlLdiouxXeEfFgGcrs]', translatable.text):
-                print("Translatable format string found in glade at %s:%d" % \
-                        (glade_file_path, translatable.sourceline))
-                success = False
-
-if __name__ == "__main__":
-    success = True
-    parser = argparse.ArgumentParser("Check that password entries have visibility set to False")
-
-    # Ignore translation arguments
-    parser.add_argument("-t", "--translate", action='store_true',
-            help=argparse.SUPPRESS)
-    parser.add_argument("-p", "--podir", action='store', type=str,
-            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
-
-    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
-            help='The glade file to check')
-    args = parser.parse_args(args=sys.argv[1:])
-
-    success = True
-    for file_path in args.glade_files:
-        check_glade_file(file_path)
-
-    sys.exit(0 if success else 1)
diff --git a/tests/glade/icons/check_icons.py b/tests/glade/icons/check_icons.py
deleted file mode 100755
index bfeac6d..0000000
--- a/tests/glade/icons/check_icons.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2014  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: David Shea <dshea at redhat.com>
-#
-"""
-Check that all icons referenced from glade files are valid in the gnome icon theme.
-"""
-
-# Ignore any interruptible calls
-# pylint: disable=interruptible-system-call
-
-import argparse
-import sys
-
-try:
-    from lxml import etree
-except ImportError:
-    print("You need to install the python-lxml package to use check_pw_visibility.py")
-    sys.exit(1)
-
-from iconcheck import icon_exists
-
-def check_glade_file(glade_file_path):
-    glade_success = True
-    with open(glade_file_path) as glade_file:
-        # Parse the XML
-        glade_tree = etree.parse(glade_file)
-
-        # Stock image names are deprecated
-        for element in glade_tree.xpath("//property[@name='stock' or @name='stock_id']"):
-            glade_success = False
-            print("Deprecated stock icon found at %s:%d" % (glade_file_path, element.sourceline))
-
-        # Check whether named icons exist
-        for element in glade_tree.xpath("//property[@name='icon_name']"):
-            if not icon_exists(element.text):
-                glade_success = False
-                print("Invalid icon name %s found at %s:%d" % (element.text, glade_file_path, element.sourceline))
-
-    return glade_success
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser("Check that password entries have visibility set to False")
-
-    # Ignore translation arguments
-    parser.add_argument("-t", "--translate", action='store_true',
-            help=argparse.SUPPRESS)
-    parser.add_argument("-p", "--podir", action='store', type=str,
-            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
-
-    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
-            help='The glade file to check')
-    args = parser.parse_args(args=sys.argv[1:])
-
-    success = True
-    for file_path in args.glade_files:
-        if not check_glade_file(file_path):
-            success = False
-
-    sys.exit(0 if success else 1)
diff --git a/tests/glade/markup/check_markup.py b/tests/glade/markup/check_markup.py
deleted file mode 100755
index ba639da..0000000
--- a/tests/glade/markup/check_markup.py
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2014  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: David Shea <dshea at redhat.com>
-#
-
-"""
-Python script to check that properties in glade using Pango markup contain
-valid markup.
-"""
-
-# Ignore any interruptible calls
-# pylint: disable=interruptible-system-call
-
-import sys
-import argparse
-
-# Import translation methods if needed
-if ('-t' in sys.argv) or ('--translate' in sys.argv):
-    try:
-        from translatepo import translate_all
-    except ImportError:
-        print("Unable to load po translation module")
-        sys.exit(99)
-
-from pangocheck import markup_nodes, markup_match, markup_necessary
-
-try:
-    from lxml import etree
-except ImportError:
-    print("You need to install the python-lxml package to use check_markup.py")
-    sys.exit(99)
-
-class PangoElementException(Exception):
-    def __init__(self, element):
-        Exception.__init__(self)
-        self.element = element
-
-    def __str__(self):
-        return "Invalid element %s" % self.element
-
-def _validate_pango_markup(root):
-    """Validate parsed pango markup.
-
-       :param etree.ElementTree root: The pango markup parsed as an XML ElementTree
-       :raises PangoElementException: If the pango markup contains unknown elements
-    """
-    if root.tag not in markup_nodes:
-        raise PangoElementException(root.tag)
-
-    for child in root:
-        _validate_pango_markup(child)
-
-def check_glade_file(glade_file_path, po_map=None):
-    glade_success = True
-    with open(glade_file_path) as glade_file:
-        # Parse the XML
-        glade_tree = etree.parse(glade_file)
-
-        # Search for label properties on objects that have use_markup set to True
-        for label in glade_tree.xpath(".//property[@name='label' and ../property[@name='use_markup']/text() = 'True']"):
-            if po_map:
-                try:
-                    label_texts = po_map.get(label.text, label.get("context"))
-                except KeyError:
-                    continue
-                lang_str = " for language %s" % po_map.metadata['Language']
-            else:
-                label_texts = (label.text,)
-                lang_str = ""
-
-            # Wrap the label text in <markup> tags and parse the tree
-            for label_text in label_texts:
-                try:
-                    # pylint: disable=unescaped-markup
-                    pango_tree = etree.fromstring("<markup>%s</markup>" % label_text)
-                    _validate_pango_markup(pango_tree)
-
-                    # Check if the markup is necessary
-                    if not markup_necessary(pango_tree):
-                        print("Markup could be expressed as attributes at %s%s:%d" % \
-                                (glade_file_path, lang_str, label.sourceline))
-                        glade_success = False
-                except etree.XMLSyntaxError:
-                    print("Unable to parse pango markup at %s%s:%d" % \
-                            (glade_file_path, lang_str, label.sourceline))
-                    glade_success = False
-                except PangoElementException as px:
-                    print("Invalid pango element %s at %s%s:%d" % \
-                            (px.element, glade_file_path, lang_str, label.sourceline))
-                    glade_success = False
-                else:
-                    if po_map:
-                        # Check that translated markup has the same elements and attributes
-                        if not markup_match(label.text, label_text):
-                            print("Translated markup does not contain the same elements and attributes at %s%s:%d" % \
-                                    (glade_file_path, lang_str, label.sourceline))
-                            glade_success = False
-    return glade_success
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser("Check Pango markup validity")
-    parser.add_argument("-t", "--translate", action='store_true',
-            help="Check translated strings")
-    parser.add_argument("-p", "--podir", action='store', type=str,
-            metavar='PODIR', help='Directory containing po files', default='./po')
-    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
-            help='The glade file to check')
-    args = parser.parse_args(args=sys.argv[1:])
-
-    success = True
-    for file_path in args.glade_files:
-        if not check_glade_file(file_path):
-            success = False
-
-    # Now loop over all of the translations
-    if args.translate:
-        podicts = translate_all(args.podir)
-        for po_dict in podicts.values():
-            for file_path in args.glade_files:
-                if not check_glade_file(file_path, po_dict):
-                    success = False
-
-    sys.exit(0 if success else 1)
diff --git a/tests/glade/pw_visibility/check_invisible_char.py b/tests/glade/pw_visibility/check_invisible_char.py
deleted file mode 100755
index 72d8486..0000000
--- a/tests/glade/pw_visibility/check_invisible_char.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/python2
-#
-# Copyright (C) 2015  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: David Shea <dshea at redhat.com>
-#
-
-"""
-Check that the invisible_char in glade files is actually a char.
-
-The invisible char is often non-ASCII and sometimes that gets clobbered.
-"""
-
-# Ignore any interruptible calls
-# pylint: disable=interruptible-system-call
-
-import argparse
-import sys
-
-try:
-    from lxml import etree
-except ImportError:
-    print("You need to install the python-lxml package to use check_pw_visibility.py")
-    sys.exit(1)
-
-def check_glade_file(glade_file_path):
-    succ = True
-
-    with open(glade_file_path, "r") as glade_file:
-        tree = etree.parse(glade_file)
-        # Only look for entries with an invisible_char property
-        for entry in tree.xpath("//object[@class='GtkEntry' and ./property[@name='invisible_char']]"):
-            # Check the contents of the invisible_char property
-            invis = entry.xpath("./property[@name='invisible_char']")[0]
-            if len(invis.text) != 1:
-                print("invisible_char at %s:%s not a character" % (glade_file_path, invis.sourceline))
-                succ = False
-
-            # If the char is '?' that's probably also bad
-            if invis.text == '?':
-                print("invisible_char at %s:%s is not what you want" % (glade_file_path, invis.sourceline))
-
-            # Check that invisible_char even does anything: visibility should be False
-            if not entry.xpath("./property[@name='visibility' and ./text() = 'False']"):
-                print("Pointless invisible_char found at %s:%s" % (glade_file_path, invis.sourceline))
-                succ = False
-
-    return succ
-
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser("Check that invisible character properties are set correctly")
-
-    # Ignore translation arguments
-    parser.add_argument("-t", "--translate", action='store_true',
-            help=argparse.SUPPRESS)
-    parser.add_argument("-p", "--podir", action='store', type=str,
-            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
-
-    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
-            help='The glade file to check')
-    args = parser.parse_args(args=sys.argv[1:])
-
-    success = True
-    for file_path in args.glade_files:
-        if not check_glade_file(file_path):
-            success = False
-
-    sys.exit(0 if success else 1)
diff --git a/tests/glade/pw_visibility/check_pw_visibility.py b/tests/glade/pw_visibility/check_pw_visibility.py
deleted file mode 100755
index f48f875..0000000
--- a/tests/glade/pw_visibility/check_pw_visibility.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2013  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: Vratislav Podzimek <vpodzime at redhat.com>
-#
-
-"""
-Simple python script checking that password GtkEntries in the given .glade files
-have the visibility set to False.
-
-"""
-
-# Ignore any interruptible calls
-# pylint: disable=interruptible-system-call
-
-import argparse
-import sys
-
-try:
-    from lxml import etree
-except ImportError:
-    print("You need to install the python-lxml package to use check_pw_visibility.py")
-    sys.exit(1)
-
-PW_ID_INDICATORS = ("pw", "password", "passwd", "passphrase")
-
-def check_glade_file(glade_file_path):
-    def check_entry(entry, fpath):
-        succ = True
-
-        entry_id = entry.attrib.get("id", "UNKNOWN ID")
-        visibility_props = entry.xpath("./property[@name='visibility']")
-
-        # no entry should have visibility specified multiple times
-        if len(visibility_props) > 1:
-            print("Visibility specified multiple times for the entry %s (%s)" % (entry_id, fpath))
-            succ = False
-
-        # password entry should have visibility set to False
-        if any(ind in entry_id.lower() for ind in PW_ID_INDICATORS):
-            if not visibility_props:
-                print("Visibility not specified for the password entry %s (%s)" % (entry_id, fpath))
-                succ = False
-            elif visibility_props[0].text.strip() != "False":
-                print("Visibility not set properly for the password entry %s (%s)" % (entry_id, fpath))
-                succ = False
-        # only password entries should have the visibility set to False
-        elif visibility_props and visibility_props[0].text.strip() == "False":
-            print("Non-password entry %s (%s) has the visibility set to False (bad id?)" % (entry_id, fpath))
-            succ = False
-
-        return succ
-
-    succ = True
-    with open(glade_file_path, "r") as glade_file:
-        tree = etree.parse(glade_file)
-        for entry in tree.xpath("//object[@class='GtkEntry']"):
-            succ = succ and check_entry(entry, glade_file_path)
-
-        return succ
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser("Check that password entries have visibility set to False")
-
-    # Ignore translation arguments
-    parser.add_argument("-t", "--translate", action='store_true',
-            help=argparse.SUPPRESS)
-    parser.add_argument("-p", "--podir", action='store', type=str,
-            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
-
-    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
-            help='The glade file to check')
-    args = parser.parse_args(args=sys.argv[1:])
-
-    success = True
-    for file_path in args.glade_files:
-        success = success and check_glade_file(file_path)
-
-    sys.exit(0 if success else 1)
diff --git a/tests/glade/run_glade_tests.sh b/tests/glade/run_glade_tests.sh
index 9ff3a2f..0a4f9f9 100755
--- a/tests/glade/run_glade_tests.sh
+++ b/tests/glade/run_glade_tests.sh
@@ -6,13 +6,13 @@ if ! type parallel 2>&1 > /dev/null; then
 fi
 
 if ! rpm -q gnome-icon-theme &> /dev/null; then
-    # used in icons/check_icons.py;tests/lib/iconcheck.py
+    # used in check_icons.py;tests/lib/iconcheck.py
     echo "gnome-icon-theme must be installed"
     exit 99
 fi
 
 if ! rpm -q gnome-icon-theme-symbolic &> /dev/null; then
-    # used in icons/check_icons.py;tests/lib/iconcheck.py
+    # used in check_icons.py;tests/lib/iconcheck.py
     echo "gnome-icon-theme-symbolic must be installed"
     exit 99
 fi
@@ -38,7 +38,7 @@ if [ "$translate_set" -eq 1 -a "$podir_set" -eq 0 ]; then
 fi
 
 status=0
-for check in ${srcdir}/*/check_*.py ; do
+for check in ${srcdir}/check_*.py ; do
     findtestfiles -name '*.glade' | parallel --no-notice --gnu -j0 "${check}" "$@" {}
     if [ "$?" -ne 0 ]; then
         status=1
diff --git a/tests/glade/validity/check_glade_validity.py b/tests/glade/validity/check_glade_validity.py
deleted file mode 100755
index 1101472..0000000
--- a/tests/glade/validity/check_glade_validity.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2014  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: David Shea <dshea at redhat.com>
-
-import sys
-import argparse
-
-from collections import Counter
-
-try:
-    from lxml import etree
-except ImportError:
-    print("You need to install the python-lxml package to run the glade checks")
-    sys.exit(99)
-
-success = True
-
-def main(argv):
-    global success
-
-    for glade_file in argv:
-        # Parse the glade file to ensure it's well-formed
-        try:
-            glade_tree = etree.parse(glade_file)
-        except etree.XMLSyntaxError:
-            print("%s is not a valid XML file" % glade_file)
-            success = False
-            continue
-
-        # Check for duplicate IDs
-        # Build a Counter from a list of all ids, extracts the ones with count > 1
-        # Fun fact: glade uses <col id="<number>"> in GtkListStore data, so ids
-        # aren't actually unique and getting an object with a particular ID
-        # isn't as simple as document.getElementById. Only check the IDs on objects.
-        for glade_id in [c for c in Counter(glade_tree.xpath(".//object/@id")).most_common() \
-                if c[1] > 1]:
-            print("%s: ID %s appears %d times" % (glade_file, glade_id[0], glade_id[1]))
-            success = False
-
-        # Check for ID references
-        # mnemonic_widget properties and action-widget elements need to refer to
-        # valid object ids.
-        for mnemonic_widget in glade_tree.xpath(".//property[@name='mnemonic_widget']"):
-            if not glade_tree.xpath(".//object[@id='%s']" % mnemonic_widget.text):
-                print("mnemonic_widget reference to invalid ID %s at line %d of %s" % \
-                        (mnemonic_widget.text, mnemonic_widget.sourceline, glade_file))
-                success = False
-
-        for action_widget in glade_tree.xpath(".//action-widget"):
-            if not glade_tree.xpath(".//object[@id='%s']" % action_widget.text):
-                print("action-widget reference to invalid ID %s at line %d of %s" % \
-                        (action_widget.text, action_widget.sourceline, glade_file))
-                success = False
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser("Check glade file validity")
-
-    # Ignore translation arguments
-    parser.add_argument("-t", "--translate", action='store_true',
-            help=argparse.SUPPRESS)
-    parser.add_argument("-p", "--podir", action='store', type=str,
-            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
-
-    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
-            help='The glade file to check')
-    args = parser.parse_args(args=sys.argv[1:])
-
-    main(args.glade_files)
-
-    if success:
-        sys.exit(0)
-    else:
-        sys.exit(1)
diff --git a/tests/glade/viewport/check_viewport.py b/tests/glade/viewport/check_viewport.py
deleted file mode 100755
index bd9d771..0000000
--- a/tests/glade/viewport/check_viewport.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2014  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: David Shea <dshea at redhat.com>
-#
-
-"""
-Check that widgets that implement GtkScrollable are not placed within a
-GtkViewport. If a widget knows how to scroll itself we probably don't want
-to add an extra layer.
-"""
-
-# Ignore any interruptible calls
-# pylint: disable=interruptible-system-call
-
-import argparse
-import sys
-
-try:
-    from lxml import etree
-except ImportError:
-    print("You need to install the python-lxml package to use check_pw_visibility.py")
-    sys.exit(1)
-
-# I guess we could look at the introspected classes and see if they implement the Scrollable
-# interface but that sounds like kind of a pain
-SCROLLABLES = ["GtkIconView", "GtkLayout", "GtkTextView", "GtkToolPalette",
-               "GtkTreeView", "GtkViewport"]
-
-def check_glade_file(glade_file_path):
-    glade_success = True
-    with open(glade_file_path) as glade_file:
-        # Parse the XML
-        glade_tree = etree.parse(glade_file)
-
-        # Look for something like:
-        # <object class="GtkViewport">
-        #   <child>
-        #      <object class="GtkTreeView">
-        for scrollable in SCROLLABLES:
-            for element in glade_tree.xpath(".//object[@class='GtkViewport']/child/object[@class='%s']" % scrollable):
-                glade_success = False
-                print("%s contained in GtkViewport at %s:%d" % (scrollable, glade_file_path,
-                                                                element.sourceline))
-    return glade_success
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser("Check that password entries have visibility set to False")
-
-    # Ignore translation arguments
-    parser.add_argument("-t", "--translate", action='store_true',
-            help=argparse.SUPPRESS)
-    parser.add_argument("-p", "--podir", action='store', type=str,
-            metavar='PODIR', help=argparse.SUPPRESS, default='./po')
-
-    parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
-            help='The glade file to check')
-    args = parser.parse_args(args=sys.argv[1:])
-
-    success = True
-    for file_path in args.glade_files:
-        if not check_glade_file(file_path):
-            success = False
-
-    sys.exit(0 if success else 1)


-- 
To view this commit on github, visit https://github.com/rhinstaller/anaconda/commit/34437dea25eaab492145e7de9b52873f1b9ab58a


More information about the anaconda-patches mailing list