qubes-installer-qubes-os/anaconda/tests/lib/gladecheck.py
Marek Marczykowski-Górecki 6bc5671491
anaconda: update to 25.20.9-1
Apply:
  git diff --full-index --binary anaconda-23.19.10-1..anaconda-25.20.9-1

And resolve conflicts.

QubesOS/qubes-issues#2574
2017-02-14 02:36:20 +01:00

183 lines
6.9 KiB
Python

#
# 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/>.
"""
Common classes and functions for checking glade files.
Glade file tests should provide a python file containing a subclass of
GladeTest, below. When nose is run with GladePlugin, each GladeTest
implementation will be run against each glade file.
"""
# Print more helpful messages before raising ImportError
try:
from lxml import etree
except ImportError:
print("No module named lxml, you need to install the python3-lxml package")
raise
try:
from pocketlint.translatepo import translate_all
except ImportError:
print("Unable to load po translation module. You may need to install python3-polib")
raise
from abc import ABCMeta, abstractmethod
import os
import unittest
import copy
import nose
from filelist import testfilelist
import logging
log = logging.getLogger('nose.plugins.glade')
class GladeTest(unittest.TestCase, metaclass=ABCMeta):
"""A framework for checking glade files.
Subclasses must implement the checkGlade method, which will be run for
each glade file that is part of the test. The unittest assert* methods
are available. If checkGlade returns without raising an exception it
is considered to pass.
If the translatable property is True and --translate was provided on the
command line, checkGlade will also be called with translated versions of
each glade file.
"""
translatable = False
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Set by the plugin in prepareTestCase, since that's easier than
# trying to override how this object is created.
self.glade_trees = []
self.translated_trees = {}
@abstractmethod
def checkGlade(self, tree):
"""Check a parsed glade file.
:param etree.ElementTree tree: The parsed glade file
"""
pass
def test_glade_file(self):
"""Run checkGlade for each glade file."""
for tree in self.glade_trees:
with self.subTest(glade_file=tree.getroot().base):
self.checkGlade(tree)
if self.translatable:
for lang, trees in self.translated_trees.items():
for tree in trees:
with self.subTest(glade_file=tree.getroot().base, lang=lang):
self.checkGlade(tree)
class GladePlugin(nose.plugins.Plugin):
name = "glade"
enabled = True
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# These are filled during configure(), after we've decided what files
# to check and whether to translate them.
# Translations are a dict of {'lang': [list of trees]}
self.glade_trees = []
self.translated_trees = {}
def options(self, parser, env):
# Do not call the superclass options() to skip setting up the
# enable/disable options.
parser.add_option("--glade-file", action="append",
help="Glade file(s) to test. If none specified, all files will be tested")
parser.add_option("--notranslate", dest="translate", action="store_false", default=False,
help="Do not test translations of glade files")
parser.add_option("--translate", action="store_true",
help="Test glade files with translations")
parser.add_option("--podir", action="store", type=str,
default=os.environ.get('top_srcdir', '.') + "/po",
metavar="PODIR", help="Directory containing .po files")
def configure(self, options, conf):
super().configure(options, conf)
# If no glade files were specified, find all of them
if options.glade_file:
glade_files = options.glade_file
else:
glade_files = testfilelist(lambda x: x.endswith('.glade'))
# Parse all of the glade files
log.info("Parsing glade files...")
for glade_file in glade_files:
self.glade_trees.append(etree.parse(glade_file))
if options.translate:
log.info("Loading translations...")
podicts = translate_all(options.podir)
# Loop over each available language
for lang, langmap in podicts.items():
self.translated_trees[lang] = []
# For each language, loop over the parsed glade files
for tree in self.glade_trees:
# Make a copy of the tree to translate and save it to
# the list for this language
tree = copy.deepcopy(tree)
self.translated_trees[lang].append(tree)
# Save the language as an attribute of the root of the tree
tree.getroot().set("lang", lang)
# Look for all properties with translatable=yes and translate them
for translatable in tree.xpath('//property[@translatable="yes"]'):
try:
xlated_text = langmap.get(translatable.text, context=translatable.get('context'))[0]
# Add the untranslated text as an attribute to this node
translatable.set("original_text", translatable.text)
# Replace the actual text
translatable.text = xlated_text
except KeyError:
# No translation available for this string in this language
pass
def prepareTestCase(self, testcase):
# Add the glade files to the GladeTest object
testcase.test.glade_trees = self.glade_trees
testcase.test.translated_trees = self.translated_trees
def describeTest(self, testcase):
# Return the first line of the doc string on checkGlade instead
# of the string for test_glade_file. If there is no doc string,
# return the name of the class.
doc = testcase.test.checkGlade.__doc__
if doc:
return doc.strip().split("\n")[0].strip()
else:
return testcase.test.__class__.__name__
def wantClass(self, cls):
# Make sure we grab all the GladeTest subclasses, and only GladeTest
# subclasses, regardless of name.
return issubclass(cls, GladeTest) and cls != GladeTest