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

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