source: lliurex-mate-welcome/trunk/fuentes/tools/app-index-debugger.py @ 3621

Last change on this file since 3621 was 3621, checked in by alviboi, 3 years ago

Upload ubuntu-mate-welcome package

  • Property svn:executable set to *
File size: 11.9 KB
Line 
1#!/usr/bin/env python3
2
3# Copyright 2016 Luke Horwell <lukehorwell37+code@gmail.com>
4#
5# Ubuntu MATE Welcome is free software: you can redistribute it and/or modify
6# it under the temms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Ubuntu MATE Welcome is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Ubuntu MATE Welcome. If not, see <http://www.gnu.org/licenses/>.
17#
18
19""" This utility helps diagnose and output useful information
20    about the application.json index used by Welcome.         """
21
22import os, sys, signal, inspect, json
23try:
24    from prettytable import PrettyTable
25except:
26    print("Requires python3-prettytable")
27    sys.exit(1)
28
29def load_index():
30    global index
31    global current_folder
32    current_folder = os.path.dirname( os.path.abspath(inspect.getfile(inspect.currentframe())) )
33    json_path = os.path.join(current_folder, '../data/js/applications.json' )
34
35    try:
36        with open(json_path) as data_file:
37            index = json.load(data_file)
38    except Exception as e:
39        print('Oops. JSON is invalid. The error is around here:')
40        print(e)
41        sys.exit()
42
43
44def list_all_apps():
45    global index
46    t = PrettyTable(["Category", 'Name', 'Main Package', 'Sub-Category', 'Open Source?', 'Arch', 'Releases', 'Works?'])
47    categories = list(index.keys())
48    categories.sort()
49
50    for category in categories:
51        category_items = list(index[category].keys())
52        category_items.sort()
53        for program_id in category_items:
54            data = [
55                    category,
56                    index[category][program_id]['name'],
57                    index[category][program_id]['main-package'],
58                    index[category][program_id]['subcategory'],
59                    str(index[category][program_id]['open-source']),
60                    index[category][program_id]['arch'],
61                    index[category][program_id]['releases'],
62                    str(index[category][program_id]['working']),
63                  ]
64            t.add_row(data)
65    print(t)
66    return
67
68
69def validate_apps():
70    global index
71    global current_folder
72    print('Scanning index for consistency...')
73    t = PrettyTable(["Category", 'Program ID', 'Severity', 'Variable', 'Fault'])
74    categories = list(index.keys())
75    categories.sort()
76    for category in categories:
77        category_items = list(index[category].keys())
78        category_items.sort()
79        for program_id in category_items:
80            app = index[category][program_id]
81            # Check for required variables.
82            for variable in ['name', 'img', 'main-package', 'description', 'subcategory', 'open-source', 'url-info', 'arch', 'releases', 'working']:
83                try:
84                    app[variable]
85                except:
86                    t.add_row([category, program_id, 'High', variable, 'Missing, is required.'])
87
88            # Check data types are consistent.
89            for variable in ['name', 'img', 'main-package', 'install-packages', 'remove-packages', 'subcategory', 'arch', 'releases']:
90                try:
91                    if not type(app[variable]) is str:
92                        t.add_row([category, program_id, 'High', variable, 'Must be a string.'])
93                except:
94                    pass
95
96            for variable in ['upgradable', 'boolean']:
97                try:
98                    if not type(app[variable]) is bool:
99                        t.add_row([category, program_id, 'High', variable, 'Must be a boolean.'])
100                except:
101                    pass
102
103            if not category == 'Unlisted':
104                for variable in ['description']:
105                    try:
106                        if not type(app[variable]) is list:
107                            t.add_row([category, program_id, 'High', variable, 'Must be a list.'])
108                    except:
109                        pass
110
111            if not category == 'Unlisted':
112                try:
113                    img = app['img']
114                except:
115                    img = 'null'
116
117                if not os.path.exists(os.path.join(current_folder, '../data/img/applications/', img + '.png' )):
118                    t.add_row([category, program_id, 'Optional', variable, 'Missing icon: "' + img + '.png"'])
119
120                if not os.path.exists(os.path.join(current_folder, '../data/img/applications/screenshots/', img + '-1.jpg' )):
121                    t.add_row([category, program_id, 'Optional', variable, 'No screenshot: "' + img + '-1.jpg"'])
122
123            try:
124                app['pre-install']
125                try:
126                    app['pre-install']['all']
127                except:
128                    t.add_row([category, program_id, 'High', variable, 'Missing explicit pre-install configuration for "all".'])
129            except:
130                t.add_row([category, program_id, 'High', variable, 'Missing pre-install configuration.'])
131
132            # Check that there is a valid arch specified for applications.
133            arch_check = app['arch'].split(',')
134            arch_OK = False
135            for arch in arch_check:
136                if arch == 'i386':
137                    pass
138                elif arch == 'amd64':
139                    pass
140                elif arch == 'armhf':
141                    pass
142                elif arch == 'powerpc':
143                    pass
144                else:
145                    t.add_row([category, program_id, 'High', variable, 'Invalid architecture: ' + arch])
146
147    print('\nIndex Validation Results\n')
148    print(t)
149    return
150
151
152def list_broken():
153    global index
154    t = PrettyTable(["Category", 'Program ID', 'Notes'])
155    categories = list(index.keys())
156    categories.sort()
157    for category in categories:
158        category_items = list(index[category].keys())
159        category_items.sort()
160        for program_id in category_items:
161            if not index[category][program_id]['working']:
162              try:
163                  # If the developer left any notes here.
164                  notes = index[category][program_id]['notes']
165              except:
166                  notes = ''
167              t.add_row([category, program_id,  notes])
168
169    print('\nBroken Applications\n')
170    print(t)
171    return
172
173
174def list_missing_arch(arch):
175    global index
176    t = PrettyTable(["Category", 'Program ID', 'Releases'])
177    categories = list(index.keys())
178    categories.sort()
179    for category in categories:
180        category_items = list(index[category].keys())
181        category_items.sort()
182        for program_id in category_items:
183            archs = index[category][program_id]['arch'].split(',')
184            if not any(arch in archs for word in archs):
185                t.add_row([category, program_id,  archs])
186
187    print('\nApplications missing for architecture: ' + arch + '\n')
188    print(t)
189    return
190
191
192def list_missing_codename(codename):
193    global index
194    t = PrettyTable(["Category", 'Program ID', 'Releases'])
195    categories = list(index.keys())
196    categories.sort()
197    for category in categories:
198        category_items = list(index[category].keys())
199        category_items.sort()
200        for program_id in category_items:
201            releases = index[category][program_id]['releases'].split(',')
202            if not any(codename in releases for word in releases):
203                t.add_row([category, program_id,  releases])
204
205    print('\nApplications missing for release: ' + codename + '\n')
206    print(t)
207    return
208
209
210def list_special_preinstall():
211    global index
212    t = PrettyTable(["Category", 'Program ID', 'Release', 'Methods'])
213    categories = list(index.keys())
214    categories.sort()
215    for category in categories:
216        category_items = list(index[category].keys())
217        category_items.sort()
218        for program_id in category_items:
219            try:
220                releases = list(index[category][program_id]['pre-install'].keys())
221            except:
222                continue
223            for release in releases:
224                if release == 'all':
225                    continue
226                else:
227                    methods = index[category][program_id]['pre-install'][release]['method']
228                    t.add_row([category, program_id, release, methods])
229
230    print('\nApplications with separate pre-configurations per release:')
231    print(t)
232    return
233
234
235def list_app_sources():
236    global index
237    t_ppa = PrettyTable(["Category", 'Program ID', 'Method', 'PPA'])
238    t_src = PrettyTable(["Category", 'Program ID', 'Method', 'Source File'])
239    t_utu = PrettyTable(["Category", 'Program ID'])
240    categories = list(index.keys())
241    categories.sort()
242    for category in categories:
243        category_items = list(index[category].keys())
244        category_items.sort()
245        for program_id in category_items:
246            try:
247                releases = list(index[category][program_id]['pre-install'].keys())
248            except:
249                continue
250            for release in releases:
251                methods = index[category][program_id]['pre-install'][release]['method'].split(',')
252                for method in methods:
253                    if method == 'ppa':
254                        ppa = index[category][program_id]['pre-install'][release]['enable-ppa']
255                        t_ppa.add_row([category, program_id, method, ppa])
256                    if method == 'manual':
257                        source_file = index[category][program_id]['pre-install'][release]['source-file'] + '.list'
258                        t_src.add_row([category, program_id, method, source_file])
259                    if method == 'skip':
260                        t_utu.add_row([category, program_id])
261
262    print('\nApplications that use the Ubuntu archives:')
263    print(t_utu)
264    print('\nApplications that use PPAs:')
265    print(t_ppa)
266    print('\nApplications that use external sources:')
267    print(t_src)
268    return
269
270
271def process_args():
272    args_ok = False
273    for arg in sys.argv:
274        if arg == '--help':
275            help()
276        if arg == '--validate':
277            args_ok = True
278            validate_apps()
279        if arg == '--list-index':
280            args_ok = True
281            list_all_apps()
282        if arg == '--list-broken':
283            args_ok = True
284            list_broken()
285        if arg.startswith('--list-missing-codename'):
286            codename = str(arg.split('--list-missing-codename=')[1])
287            args_ok = True
288            list_missing_codename(codename)
289        if arg.startswith('--list-missing-arch'):
290            arch = str(arg.split('--list-missing-arch=')[1])
291            args_ok = True
292            list_missing_arch(arch)
293        if arg == '--list-special':
294            args_ok = True
295            list_special_preinstall()
296        if arg == '--list-sources':
297            args_ok = True
298            list_app_sources()
299    if not args_ok:
300        print('Invalid arguments.')
301        help()
302
303
304def help():
305    print('Usage:')
306    print(' --validate                        Check index for consistent data types and required values.')
307    print(' --list-index                      List applications in the index.')
308    print(' --list-broken                     List applications that are not working.')
309    print(' --list-missing-codename=<RELEASE> List applications not present in a release.')
310    print(' --list-missing-arch=<ARCH>        List applications not present for an architecture.')
311    print(' --list-special                    List applications that pre-install differently on releases.')
312    print(' --list-sources                    List each application\'s source (eg. PPA, Ubuntu Archives)')
313    sys.exit()
314
315
316if __name__ == "__main__":
317    signal.signal(signal.SIGINT, signal.SIG_DFL)
318    if not sys.argv:
319        help()
320
321    load_index()
322    process_args()
Note: See TracBrowser for help on using the repository browser.