save-suggestions.py 4.2 KB
Newer Older
1
#!/usr/bin/env python3
2
3

# This script generates a temporary copy of all translations including suggestions.
4
5
# We have created a local git clone before running this script.
# It takes the default branch to work on.
6
7
8
#
# Usage:
#
9
#   /var/lib/weblate/scripts/save-suggestions.py repopath
10

11
import argparse
12
13
import logging
import logging.config
14
import os
15
import pathlib
16
17
18
import subprocess
import sys

19
20
21
sys.path.insert(0, "/usr/local/share/weblate")
os.environ["DJANGO_SETTINGS_MODULE"] = "weblate.settings"
os.environ["DJANGO_IS_MANAGEMENT_COMMAND"] = "1"
22
23
24
25

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

26
from weblate.trans import models
27
28


29
logging.config.fileConfig('/var/lib/weblate/config/saveSuggestions.conf')
30
31
32

logger = logging.getLogger('saveSuggestions')

33
34
logger.info("Start a new run.")

intrigeri's avatar
Lint.    
intrigeri committed
35

36
37
def log_subprocess_output(cmd, **kwargs):
    """Add subprocess output to logger."""
intrigeri's avatar
Lint.    
intrigeri committed
38
    logger.info("Running command '%s':", " ".join(cmd))
39
    popen = subprocess.Popen(cmd, universal_newlines=True,
intrigeri's avatar
Lint.    
intrigeri committed
40
41
42
                             stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT,
                             **kwargs)
groente's avatar
groente committed
43
44
45
    for stdout_line in iter(popen.stdout.readline, ""):
        logger.debug(stdout_line.strip())
    popen.stdout.close()
groente's avatar
groente committed
46
47
48
    returncode = popen.wait()
    if returncode:
        raise subprocess.CalledProcessError(returncode, cmd)
groente's avatar
groente committed
49

intrigeri's avatar
Lint.    
intrigeri committed
50

51
52
53
54
55
56
57
58
59
60
61
62
def update_unit(translation, unit, target):
    # weblate/trans/models/translation.py: update_units
    src = unit.get_source_plurals()[0]
    add = False

    pounit, add = translation.store.find_unit(unit.context, src)

    # Bail out if we have not found anything
    if pounit is None or pounit.is_obsolete():
        logger.warning('message %s disappeared!', unit)

    pounit.set_target(target)     # update po file with first suggestion
63
    pounit.mark_fuzzy(False)           # mark change as non fuzzy
64
65


66
def commandline():
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-v", "--verbose",
        action='store_true',
        help="verbose logging.")
    parser.add_argument(
        "repopath",
        type=pathlib.Path,
        help="path to the repository.")
    args = parser.parse_args()
    prog = parser.prog

    if args.verbose:
        for handler in logging.getLogger().handlers:
            if isinstance(handler, logging.StreamHandler):
                handler.level = logging.DEBUG

    repopath = args.repopath

86
    try:
87
88
89
90
        log_subprocess_output(["git", "clean", "-fd"], cwd=str(repopath))
        log_subprocess_output(["git", "fetch"], cwd=str(repopath))
        log_subprocess_output(["git", "reset", 'FETCH_HEAD', "--hard"],
                                 cwd=str(repopath))
91
    except:
92
        logger.exception("Got an exception")
93
94
        raise

95
96
    logger.info("Start search for suggestions.")

97
    subprojects = models.Component.objects.all()
98

99
    for i, subproject in enumerate(subprojects):
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
        try:
            for translation in subproject.translation_set.all():
                changed = False
                for unit in translation.unit_set.all():
                    if unit.suggestions:
                        # Get newest most voted suggestion
                        date_sorted = sorted(unit.suggestions, key=lambda i: i.timestamp, reverse=True)
                        s = sorted(date_sorted, key=lambda i: i.get_num_votes(), reverse=True)[0]
                        logger.debug("found suggestion for %s", unit)
                        update_unit(translation, unit, s.target)
                        changed = True
                    elif unit.pending:
                        # Save uncommitted changes
                        logger.debug("uncommitted changes found for %s", unit)
                        update_unit(translation, unit, unit.target)
                        changed = True

                # save with suggestions
                if changed:
119
                    with (repopath/translation.filename).open("wb") as f:
120
121
122
123
                        translation.store.store.serialize(f)
        except:
            logger.exception("Got an exception for %s(%i)", subproject.name, i)
            raise
124
    logger.info("Successfully updated %s.", repopath)
125
126
127

if __name__ == "__main__":
    commandline()