3
# this is part of langpack-o-matic
5
# (C) 2019 Canonical Ltd.
6
# Author: Łukasz 'sil2100' Zemczak <lukasz.zemczak@canonical.com>
8
# Print out a sanity-test report of the generated language-packs, comparing it
9
# with the previous langpack contents.
17
from collections import defaultdict
18
from optparse import OptionParser
21
_logger = logging.getLogger('langpack-sanity-report')
24
def scan_langpacks(packdir):
25
langpacks = defaultdict(dict)
26
for family in ('sources-base', 'sources-update'):
27
familydir = os.path.join(packdir, family)
28
for pack in os.listdir(familydir):
29
pack_path = os.path.join(familydir, pack)
30
if os.path.isdir(pack_path):
31
_logger.debug('Scanning {}...'.format(pack_path))
32
# Get the overall size of the langpack
33
cmd = ['du', '-s', pack_path]
35
du = subprocess.check_output(
36
cmd, universal_newlines=True)
37
except subprocess.CalledProcessError as e:
38
print('Could not call du properly')
40
size = int(du.split('\t')[0])
41
po_dir = os.path.join(pack_path, 'data')
42
# Get the list of pofiles for the given langpack
43
cmd = ['find', po_dir, '-name', '*.po', '-printf', '%P\n']
45
find = subprocess.check_output(
46
cmd, universal_newlines=True)
47
except subprocess.CalledProcessError as e:
48
print('Could not call find properly')
50
pofiles = find.split('\n')
51
langpacks[pack]['size'] = size
52
langpacks[pack]['pofiles'] = pofiles
56
def sanity_check(prev_packs, next_packs, threshold):
57
# Check if any languages have been dropped
58
print('\nChecking for dropped languages...')
59
next_set = set(next_packs.keys())
60
prev_set = set(prev_packs.keys())
61
missing_set = prev_set - next_set
63
print('The following language-packs have been dropped:')
64
for pack in missing_set:
66
print('\nRunning per-language-pack checks...')
67
for langpack, data in next_packs.items():
68
if langpack not in prev_packs:
69
# New language-pack, ignoring
71
# Check if there are any langpacks that shrunk in size drastically
72
next_size = data['size']
73
prev_size = prev_packs[langpack]['size']
74
size_diff = next_size - prev_size
75
if size_diff < (-threshold):
76
# The langpack got worringly smaller in comparison, report
77
print('{} shrunk in size above threshold (was {}, is {})'.format(
78
langpack, prev_size, next_size))
79
# Check if any po files have been dropped completely
80
next_pofiles = set(data['pofiles'])
81
prev_pofiles = set(prev_packs[langpack]['pofiles'])
82
dropped_set = prev_pofiles - next_pofiles
84
print('{} dropped the following .po files:\n {}'.format(
86
'\n '.join(dropped_set)))
90
parser = OptionParser(
91
usage='Usage: %prog [options] olddir newdir')
93
'-d', '--debug', dest='debug', action='store_true')
95
'-t', '--threshold', dest='threshold', type='int',
96
help='Maximum allowed decrease in a langpack\'s size before treating '
97
'it as something suspicious - in KiB (default: 64).',
99
opts, args = parser.parse_args()
101
print('Please provide paths to the old and new langpack directories.')
104
logging.basicConfig(level=logging.DEBUG)
105
# Perform the sanity check
108
print('Performing language-pack sanity checks, comparing between '
111
prev_packs = scan_langpacks(prev_dir)
112
next_packs = scan_langpacks(next_dir)
113
sanity_check(prev_packs, next_packs, opts.threshold)
116
if __name__ == '__main__':