use format strings
[web/firmware-selector-openwrt-org.git] / misc / collect.py
1 #!/usr/bin/env python3
2
3 from pathlib import Path
4 import argparse
5 import json
6 import sys
7 import os
8
9 parser = argparse.ArgumentParser()
10 parser.add_argument('input_path', nargs='+',
11 help='Input folder that is traversed for OpenWrt JSON device files.')
12 parser.add_argument('--download-url', action='store', default='',
13 help='Link to get the image from. May contain {target}, {version} and {commit}')
14 parser.add_argument('--formatted', action='store_true',
15 help='Output formatted JSON data.')
16 parser.add_argument('--change-prefix',
17 help='Change the openwrt- file name prefix.')
18
19 args = parser.parse_args()
20
21 SUPPORTED_METADATA_VERSION = 1
22
23 def change_prefix(images, old_prefix, new_prefix):
24 for image in images:
25 if image['name'].startswith(old_prefix):
26 image['name'] = new_prefix + image['name'][len(old_prefix):]
27
28 # OpenWrt JSON device files
29 paths = []
30
31 # json output data
32 output = {}
33
34 for path in args.input_path:
35 if os.path.isdir(path):
36 for file in Path(path).rglob('*.json'):
37 paths.append(file)
38 else:
39 if not path.endswith('.json'):
40 sys.stderr.write(f'Folder does not exists: {path}\n')
41 exit(1)
42 paths.append(path)
43
44 def get_title_name(title):
45 if 'title' in title:
46 return title['title']
47 else:
48 return "{} {} {}".format(title.get('vendor', ''), title['model'], title.get('variant', '')).strip()
49
50 def add_profile(id, target, profile):
51 images = []
52 for image in profile['images']:
53 images.append({'name': image['name'], 'type': image['type']})
54
55 if target is None:
56 target = profile['target']
57
58 if args.change_prefix:
59 change_prefix(images, 'openwrt-', args.change_prefix)
60
61 for title in profile['titles']:
62 name = get_title_name(title)
63
64 if len(name) == 0:
65 sys.stderr.write(f'Empty title. Skip title in {path}\n')
66 continue
67
68 output['models'][name] = {'id': id, 'target': target, 'images': images}
69
70 for path in paths:
71 with open(path, "r") as file:
72 obj = json.load(file)
73
74 if obj['metadata_version'] != SUPPORTED_METADATA_VERSION:
75 sys.stderr.write(f'{path} has unsupported metadata version: {obj["metadata_version"]} => skip\n')
76 continue
77
78 code = obj.get('version_code', obj.get('version_commit'))
79
80 if not 'version_code' in output:
81 output = {
82 'version_code': code,
83 'download_url': args.download_url,
84 'models' : {}
85 }
86
87 # only support a version_number with images of a single version_commit
88 if output['version_code'] != code:
89 sys.stderr.write('mixed revisions for a release ({output["version_code"]} and {code}) => abort\n')
90 exit(1)
91
92 try:
93 if 'profiles' in obj:
94 for id in obj['profiles']:
95 add_profile(id, obj.get('target'), obj['profiles'][id])
96 else:
97 add_profile(obj['id'], obj['target'], obj)
98 except json.decoder.JSONDecodeError as e:
99 sys.stderr.write(f'Skip {path}\n {e}\n')
100 except KeyError as e:
101 sys.stderr.write(f'Abort on {path}\n Missing key {e}\n')
102 exit(1)
103
104 if args.formatted:
105 json.dump(output, sys.stdout, indent=" ", sort_keys=True)
106 else:
107 json.dump(output, sys.stdout, sort_keys=True)