OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python2 | |
2 # Copyright 2017 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 from __future__ import absolute_import | |
7 from __future__ import division | |
8 from __future__ import print_function | |
9 | |
10 import argparse | |
11 import contextlib | |
12 import glob | |
13 import io | |
14 import json | |
15 import os | |
16 import sys | |
17 import urllib | |
18 import Image | |
19 | |
20 # This script downloads the default popular sites and large icons associated | |
21 # with it. If an icon is too large, it will get resized in the process. | |
sfiera
2017/02/16 18:54:16
This here would be a good use of a file-level """
fhorschig
2017/02/17 16:24:04
Okay.
| |
22 | |
23 DEFAULT_POPULAR_SITES = ("https://www.gstatic.com/chrome/ntp/" | |
24 "suggested_sites_DEFAULT_5.json") | |
25 LARGE_ICON_KEY = "large_icon_url" | |
26 SITE_TITLE_KEY = "title" | |
27 MAXIMAL_SIZE = 144 | |
28 SITE_ICON_DELETE = "icon[0-9].png" | |
29 SITE_ICON_FORMAT = "icon%d.png" | |
30 NTP_TILES_RESOURCE_PATH = os.path.join( | |
31 os.path.dirname(os.path.realpath(__file__)), "resources") | |
32 DEFAULT_POPULAR_SITES_PATH = os.path.join(NTP_TILES_RESOURCE_PATH, | |
33 "default_popular_sites.json") | |
34 | |
35 def download_popular_sites(url): | |
36 print("Downloading popular sites... (" + url + ")") | |
37 with contextlib.closing(urllib.urlopen(url=url)) as url_data: | |
38 data = json.load(url_data) | |
39 print("... done. (%d sites found)" % len(data)) | |
40 return data | |
41 | |
42 def write_to_json(data, out_path, pretty_print): | |
43 separators = (",", ":") | |
44 indent = None | |
45 sort = False | |
46 if pretty_print: | |
47 separators = (",", ": ") | |
48 indent = 4 | |
49 sort = True | |
50 with open(out_path, "w") as f: | |
51 json.dump(data, f, sort_keys=sort, indent=indent, separators=separators) | |
52 print("JSON was written to " + out_path) | |
53 | |
54 def delete_old_icons(): | |
55 print("Deleting old icons..") | |
56 for f in glob.glob(os.path.join(NTP_TILES_RESOURCE_PATH, SITE_ICON_DELETE)): | |
57 os.remove(os.path.join(f)) | |
58 print("... done.") | |
59 | |
60 def download_image_for_popular_site(site): | |
61 with contextlib.closing(urllib.urlopen(url=site[LARGE_ICON_KEY])) as url_data: | |
62 image_response_data = url_data.read() | |
63 return Image.open(io.BytesIO(image_response_data)) | |
sfiera
2017/02/16 18:54:16
I'm still concerned that you might be un-optimizin
fhorschig
2017/02/17 16:24:04
As discussed, I noew introduced the highest compre
| |
64 | |
65 def resize_if_too_large(image, max_size): | |
66 if image.size[0] > max_size: # Width is sufficient to compare squared icons. | |
67 print("... and resizing image from %s to %s ..." % | |
68 (image.size, (max_size, max_size))); | |
69 image.thumbnail((max_size, max_size), Image.ANTIALIAS) | |
70 | |
71 | |
72 def lacks_required_keys(site): | |
73 return not SITE_TITLE_KEY in site or not LARGE_ICON_KEY in site | |
74 | |
75 | |
76 def main(): | |
77 parser = argparse.ArgumentParser( | |
78 description="Downloads the latest popular sites and their icons. \n\n" | |
79 "It is possible to customize the default like this:\n" | |
80 " 1. python " + __file__ + " -o temp.json --skip_icons " | |
81 "--pretty_print\n" | |
82 " 2. Adjust the downloaded temp.json\n" | |
83 " 3. python " + __file__ + " -f temp.json -s 96\n\n" | |
84 "The result would be a minified version of your customized JSON " | |
85 "and all icons would be downloaded as you specified.\n The icons " | |
86 "had a max size of 96x96.", | |
87 formatter_class=argparse.RawTextHelpFormatter) | |
88 parser.add_argument("-s", "--size", metavar="size_in_px", type=int, | |
89 default=MAXIMAL_SIZE, | |
90 help="size to scale too large icons down to; defaults " | |
91 "to 144px") | |
92 parser.add_argument("-u", "--url", metavar="url", type=str, | |
sfiera
2017/02/16 18:54:16
If you have a long flag name, the metavar should d
fhorschig
2017/02/17 16:24:04
Yes but it's CAPS. But in this case it's maybe mor
| |
93 default=DEFAULT_POPULAR_SITES, | |
94 help="the endpoint to query for json of sites") | |
95 parser.add_argument("--skip_icons", action="store_true", | |
sfiera
2017/02/16 18:54:16
In Chromium, I think we typically use --skip-icons
fhorschig
2017/02/17 16:24:04
Done.
| |
96 help="do not download icons") | |
97 parser.add_argument("--skip_resizing", action="store_true", | |
98 help="do not resize any icons") | |
99 parser.add_argument("-f", "--in_file", metavar="path_to_json_file", | |
100 type=str, | |
sfiera
2017/02/16 18:54:16
See also argparse.FileType.
fhorschig
2017/02/17 16:24:04
There is little advantage using that as I would ne
| |
101 help="skip download and load icons for a local json") | |
102 parser.add_argument("-o", "--out_path", metavar="path_to_out_file", | |
103 type=str, default=DEFAULT_POPULAR_SITES_PATH, | |
104 help="skip download and load icons for a local json") | |
105 parser.add_argument("-p", "--pretty_print", action="store_true", | |
106 help="pretty_print instead of minifying the JSON") | |
107 args = parser.parse_args() | |
108 | |
109 if args.in_file: | |
110 with open(args.in_file) as f: | |
111 popular_sites = json.load(f) | |
112 else: | |
113 popular_sites = download_popular_sites(args.url) | |
114 write_to_json(popular_sites, args.out_path, args.pretty_print) | |
115 | |
116 if args.skip_icons: | |
117 return | |
118 | |
119 delete_old_icons() | |
120 for i, site in enumerate(popular_sites): | |
121 if lacks_required_keys(site): | |
122 print("Could not download large image for site: %r" % site) | |
123 continue | |
124 print("Downloading icon for '%r'..." % site[SITE_TITLE_KEY]) | |
125 image = download_image_for_popular_site(site) | |
126 if not args.skip_resizing: | |
127 resize_if_too_large(image, args.size) | |
128 image_name = SITE_ICON_FORMAT % i | |
129 image.save(os.path.join(NTP_TILES_RESOURCE_PATH, image_name), "PNG") | |
130 print("... done. (Stored as " + image_name + ")"); | |
131 | |
132 | |
133 if __name__ == "__main__": | |
134 main() | |
OLD | NEW |