Blame translation-canary/translation_canary/translated/__init__.py

Packit Service af52df
# Framework for testing translations
Packit Service af52df
#
Packit Service af52df
# Copyright (C) 2015  Red Hat, Inc.
Packit Service af52df
#
Packit Service af52df
# This copyrighted material is made available to anyone wishing to use,
Packit Service af52df
# modify, copy, or redistribute it subject to the terms and conditions of
Packit Service af52df
# the GNU Lesser General Public License v.2, or (at your option) any later
Packit Service af52df
# version. This program is distributed in the hope that it will be useful,
Packit Service af52df
# but WITHOUT ANY WARRANTY expressed or implied, including the implied
Packit Service af52df
# warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
Packit Service af52df
# the GNU Lesser General Public License for more details.  You should have
Packit Service af52df
# received a copy of the GNU Lesser General Public License along with this
Packit Service af52df
# program; if not, write to the Free Software Foundation, Inc., 51 Franklin
Packit Service af52df
# Street, Fifth Floor, Boston, MA 02110-1301, USA.  Any Red Hat trademarks
Packit Service af52df
# that are incorporated in the source code or documentation are not subject
Packit Service af52df
# to the GNU Lesser General Public License and may only be used or
Packit Service af52df
# replicated with the express permission of Red Hat, Inc.
Packit Service af52df
#
Packit Service af52df
# Red Hat Author(s): David Shea <dshea@redhat.com>
Packit Service af52df
Packit Service af52df
"""
Packit Service af52df
Framework for running tests against translations.
Packit Service af52df
Packit Service af52df
Tests are loaded from modules in this directory. A test is any callable object
Packit Service af52df
within the module with a name that starts with 'test_'.
Packit Service af52df
Packit Service af52df
Each test is called with the name of .po file to test as an argument. A test
Packit Service af52df
passes if it returns without raising an exception.
Packit Service af52df
"""
Packit Service af52df
Packit Service af52df
import os, warnings
Packit Service af52df
Packit Service af52df
_tests = []
Packit Service af52df
Packit Service af52df
# Gather tests from this directory
Packit Service af52df
import pkgutil
Packit Service af52df
for finder, mod_name, _ispkg in pkgutil.iter_modules(__path__):
Packit Service af52df
    # Skip __main__
Packit Service af52df
    if mod_name == "__main__":
Packit Service af52df
        continue
Packit Service af52df
Packit Service af52df
    # Load the module
Packit Service af52df
    module = finder.find_module(mod_name).load_module(mod_name)
Packit Service af52df
Packit Service af52df
    # Look for attributes that start with 'test_' and add them to the test list
Packit Service af52df
    for attrname, attr in module.__dict__.items():
Packit Service af52df
        if attrname.startswith('test_') and callable(attr):
Packit Service af52df
            _tests.append(attr)
Packit Service af52df
Packit Service af52df
def _remove_lingua(linguas, language):
Packit Service af52df
    # Read in the LINGUAS file
Packit Service af52df
    with open(linguas, "rt") as f:
Packit Service af52df
        lingua_lines = f.readlines()
Packit Service af52df
Packit Service af52df
    output_lines = []
Packit Service af52df
    for line in lingua_lines:
Packit Service af52df
        # Leave comments alone
Packit Service af52df
        if line.startswith('#'):
Packit Service af52df
            output_lines.append(line)
Packit Service af52df
            continue
Packit Service af52df
Packit Service af52df
        # Split the line into a list of languages, remove the one we don't
Packit Service af52df
        # want, and put it back together
Packit Service af52df
        lingua_list = line.split()
Packit Service af52df
        lingua_list.remove(language)
Packit Service af52df
        output_lines.append(" ".join(lingua_list))
Packit Service af52df
Packit Service af52df
    # Write LINGUAS back out
Packit Service af52df
    with open(linguas, "wt") as f:
Packit Service af52df
        f.writelines(output_lines)
Packit Service af52df
Packit Service af52df
def testFile(pofile, prefix=None, releaseMode=False, modifyLinguas=True):
Packit Service af52df
    """Run all registered tests against the given .mo file.
Packit Service af52df
Packit Service af52df
       If run in release mode, this function will always return true, and if
Packit Service af52df
       the mofile does not pass the tests the langauge will be removed.
Packit Service af52df
Packit Service af52df
       :param str mofile: The .mo file name to check
Packit Service af52df
       :param str prefix: An optional directory prefix to strip from error messages
Packit Service af52df
       :param bool releaseMode: whether to run in release mode
Packit Service af52df
       :param bool modifyLinguas: whether to remove translations from LINGUAS in release mode
Packit Service af52df
       :return: whether the checks succeeded or not
Packit Service af52df
       :rtype: bool
Packit Service af52df
    """
Packit Service af52df
    success = True
Packit Service af52df
    for test in _tests:
Packit Service af52df
        # Don't print the tmpdir path in error messages
Packit Service af52df
        if prefix is not None and pofile.startswith(prefix):
Packit Service af52df
            poerror = pofile[len(prefix):]
Packit Service af52df
        else:
Packit Service af52df
            poerror = pofile
Packit Service af52df
Packit Service af52df
        try:
Packit Service af52df
            with warnings.catch_warnings(record=True) as w:
Packit Service af52df
                test(pofile)
Packit Service af52df
Packit Service af52df
                # Print any warnings collected
Packit Service af52df
                for warn in w:
Packit Service af52df
                    print("%s warned on %s: %s" % (test.__name__, poerror, warn.message))
Packit Service af52df
        except Exception as e: # pylint: disable=broad-except
Packit Service af52df
            print("%s failed on %s: %s" % (test.__name__, poerror, str(e)))
Packit Service af52df
            if releaseMode:
Packit Service af52df
                # Remove the po file and the .mo file built from it
Packit Service af52df
                print("Removing %s" % pofile)
Packit Service af52df
                os.remove(pofile)
Packit Service af52df
Packit Service af52df
                # Check for both .mo and .gmo
Packit Service af52df
                mofile = os.path.splitext(pofile)[0] + '.mo'
Packit Service af52df
                if os.path.exists(mofile):
Packit Service af52df
                    print("Removing %s" % mofile)
Packit Service af52df
                    os.remove(mofile)
Packit Service af52df
Packit Service af52df
                gmofile = os.path.splitext(pofile)[0] + '.gmo'
Packit Service af52df
                if os.path.exists(gmofile):
Packit Service af52df
                    print("Removing %s" % gmofile)
Packit Service af52df
                    os.remove(gmofile)
Packit Service af52df
Packit Service af52df
                if modifyLinguas:
Packit Service af52df
                    # If there is a LINGUAS file in the po directory, remove the
Packit Service af52df
                    # language from it
Packit Service af52df
                    linguas = os.path.join(os.path.dirname(mofile), 'LINGUAS')
Packit Service af52df
                    if os.path.exists(linguas):
Packit Service af52df
                        language = os.path.splitext(os.path.basename(pofile))[0]
Packit Service af52df
                        print("Removing %s from LINGUAS" % language)
Packit Service af52df
                        _remove_lingua(linguas, language)
Packit Service af52df
Packit Service af52df
                # No need to run the rest of the tests since we just killed the file
Packit Service af52df
                break
Packit Service af52df
            else:
Packit Service af52df
                success = False
Packit Service af52df
Packit Service af52df
    return success
Packit Service af52df
Packit Service af52df
def testSourceTree(srcdir, releaseMode=False, modifyLinguas=True):
Packit Service af52df
    """Runs all registered tests against all .po files in the given directory.
Packit Service af52df
Packit Service af52df
       If run in release mode, this function will always return True and the
Packit Service af52df
       languages that do not pass the tests will be removed.
Packit Service af52df
Packit Service af52df
       :param str srcdir: The path to the source directory to check
Packit Service af52df
       :param bool releaseMode: whether to run in release mode
Packit Service af52df
       :param bool modifyLinguas: whether to remove translations from LINGUAS in release mode
Packit Service af52df
       :return: whether the checks succeeded or not
Packit Service af52df
       :rtype: bool
Packit Service af52df
    """
Packit Service af52df
    success = True
Packit Service af52df
    srcdir = os.path.normpath(srcdir)
Packit Service af52df
Packit Service af52df
    for dirpath, _dirnames, paths in os.walk(srcdir):
Packit Service af52df
        for pofile in (os.path.join(dirpath, path) for path in paths if path.endswith('.po')):
Packit Service af52df
            if not testFile(pofile, prefix=srcdir + "/", releaseMode=releaseMode, modifyLinguas=modifyLinguas):
Packit Service af52df
                success = False
Packit Service af52df
Packit Service af52df
    return success