Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: cms/bin/generate_static_pages.py

Issue 5242593268989952: Issue 2340 - Don`t generate pages if less than 30% have been translated (Closed)
Patch Set: Don`t link to pages that don`t exist Created May 6, 2015, 3:19 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | cms/converters.py » ('j') | cms/sources.py » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # coding: utf-8 1 # coding: utf-8
2 2
3 # This file is part of the Adblock Plus web scripts, 3 # This file is part of the Adblock Plus web scripts,
4 # Copyright (C) 2006-2015 Eyeo GmbH 4 # Copyright (C) 2006-2015 Eyeo GmbH
5 # 5 #
6 # Adblock Plus is free software: you can redistribute it and/or modify 6 # Adblock Plus is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License version 3 as 7 # it under the terms of the GNU General Public License version 3 as
8 # published by the Free Software Foundation. 8 # published by the Free Software Foundation.
9 # 9 #
10 # Adblock Plus is distributed in the hope that it will be useful, 10 # Adblock Plus is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details. 13 # GNU General Public License for more details.
14 # 14 #
15 # You should have received a copy of the GNU General Public License 15 # You should have received a copy of the GNU General Public License
16 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 16 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
17 17
18 import sys 18 import sys
19 import os 19 import os
20 import re 20 import re
21 import errno 21 import errno
22 import codecs 22 import codecs
23 import ConfigParser
24 import functools
23 import logging 25 import logging
24 26
25 from cms.utils import process_page 27 from cms.utils import get_page_params, process_page
26 from cms.sources import MercurialSource 28 from cms.sources import MercurialSource
27 29
30 MIN_TRANSLATED = 0.3
31
28 def memoize(func): 32 def memoize(func):
29 memoized = {} 33 memoized = {}
30 def wrapper(*args): 34 def wrapper(*args):
31 try: 35 try:
32 return memoized[args] 36 return memoized[args]
33 except KeyError: 37 except KeyError:
34 return memoized.setdefault(args, func(*args)) 38 return memoized.setdefault(args, func(*args))
39 wrapper.original = func
Sebastian Noack 2015/05/06 16:15:30 I'm not sure if I like that hack. Note that it wou
Wladimir Palant 2015/05/06 17:21:59 True, I don't like passing in a dictionary either
Sebastian Noack 2015/05/06 19:12:15 Well, allowing to pass in a dict-like object, also
Wladimir Palant 2015/05/06 19:20:35 Thank you. Indeed, I do feel that the current appr
35 return wrapper 40 return wrapper
36 41
37 def generate_pages(repo, output_dir): 42 def generate_pages(repo, output_dir):
38 known_files = set() 43 known_files = set()
39 44
40 def write_file(path_parts, contents, binary=False): 45 def write_file(path_parts, contents, binary=False):
41 encoding = None if binary else "utf-8" 46 encoding = None if binary else "utf-8"
42 outfile = os.path.join(output_dir, *path_parts) 47 outfile = os.path.join(output_dir, *path_parts)
43 if outfile in known_files: 48 if outfile in known_files:
44 logging.warning("File %s has multiple sources", outfile) 49 logging.warning("File %s has multiple sources", outfile)
(...skipping 21 matching lines...) Expand all
66 source.read_config = memoize(source.read_config) 71 source.read_config = memoize(source.read_config)
67 source.read_template = memoize(source.read_template) 72 source.read_template = memoize(source.read_template)
68 source.read_locale = memoize(source.read_locale) 73 source.read_locale = memoize(source.read_locale)
69 source.read_include = memoize(source.read_include) 74 source.read_include = memoize(source.read_include)
70 75
71 config = source.read_config() 76 config = source.read_config()
72 defaultlocale = config.get("general", "defaultlocale") 77 defaultlocale = config.get("general", "defaultlocale")
73 locales = list(source.list_locales()) 78 locales = list(source.list_locales())
74 if defaultlocale not in locales: 79 if defaultlocale not in locales:
75 locales.append(defaultlocale) 80 locales.append(defaultlocale)
81
82 # First pass: compile the list of pages with given translation level
83 pagelist = set()
76 for page, format in source.list_pages(): 84 for page, format in source.list_pages():
77 for locale in locales: 85 for locale in locales:
78 if locale == defaultlocale or source.has_locale(locale, page): 86 if locale == defaultlocale:
79 pagedata = process_page(source, locale, page, format) 87 pagelist.add((locale, page))
88 elif source.has_locale(locale, page):
89 params = get_page_params(source, locale, page, format)
90 if params["translation_ratio"] >= MIN_TRANSLATED:
91 pagelist.add((locale, page))
80 92
81 # Make sure links to static files are versioned 93 # Override existance check to avoid linking to pages we don't generate
82 pagedata = re.sub(r'(<script\s[^<>]*\bsrc="/[^"<>]+)', r"\1?%s" % sour ce.version, pagedata) 94 def has_locale(orig_function, locale, page):
83 pagedata = re.sub(r'(<link\s[^<>]*\bhref="/[^"<>]+)', r"\1?%s" % sourc e.version, pagedata) 95 try:
84 pagedata = re.sub(r'(<img\s[^<>]*\bsrc="/[^"<>]+)', r"\1?%s" % source. version, pagedata) 96 page = config.get("locale_overrides", page)
97 except ConfigParser.Error:
98 pass
99 if (defaultlocale, page) in pagelist:
100 return locale != defaultlocale and (locale, page) in pagelist
101 else:
Sebastian Noack 2015/05/06 16:15:30 Nit: Redundant else statement. (Yes, I know you li
Wladimir Palant 2015/05/06 17:21:59 Done and made the logic here slightly more obvious
102 return orig_function(locale, page)
103 source.has_locale = functools.partial(has_locale, source.has_locale)
Sebastian Noack 2015/05/06 16:15:30 It took me a while to understand what you are doin
Wladimir Palant 2015/05/06 17:21:59 I thought you were a fan of clever solutions :)
104 source.resolve_link = memoize(source.resolve_link.original)
85 105
86 write_file([locale] + page.split("/"), pagedata) 106 # Second pass: actually generate pages this time
107 for locale, page in pagelist:
108 pagedata = process_page(source, locale, page)
109
110 # Make sure links to static files are versioned
111 pagedata = re.sub(r'(<script\s[^<>]*\bsrc="/[^"<>]+)', r"\1?%s" % source.v ersion, pagedata)
112 pagedata = re.sub(r'(<link\s[^<>]*\bhref="/[^"<>]+)', r"\1?%s" % source.ve rsion, pagedata)
113 pagedata = re.sub(r'(<img\s[^<>]*\bsrc="/[^"<>]+)', r"\1?%s" % source.vers ion, pagedata)
114
115 write_file([locale] + page.split("/"), pagedata)
87 116
88 for filename in source.list_localizable_files(): 117 for filename in source.list_localizable_files():
89 for locale in locales: 118 for locale in locales:
90 if source.has_localizable_file(locale, filename): 119 if source.has_localizable_file(locale, filename):
91 filedata = source.read_localizable_file(locale, filename) 120 filedata = source.read_localizable_file(locale, filename)
92 write_file([locale] + filename.split("/"), filedata, binary=True) 121 write_file([locale] + filename.split("/"), filedata, binary=True)
93 122
94 for filename in source.list_static(): 123 for filename in source.list_static():
95 write_file(filename.split("/"), source.read_static(filename), binary=True) 124 write_file(filename.split("/"), source.read_static(filename), binary=True)
96 125
97 def remove_unknown(dir): 126 def remove_unknown(dir):
98 files = os.listdir(dir) 127 files = os.listdir(dir)
99 for filename in files: 128 for filename in files:
100 path = os.path.join(dir, filename) 129 path = os.path.join(dir, filename)
101 if os.path.isfile(path) and path not in known_files: 130 if os.path.isfile(path) and path not in known_files:
102 os.remove(path) 131 os.remove(path)
103 elif os.path.isdir(path): 132 elif os.path.isdir(path):
104 remove_unknown(path) 133 remove_unknown(path)
105 if not os.listdir(path): 134 if not os.listdir(path):
106 os.rmdir(path) 135 os.rmdir(path)
107 remove_unknown(output_dir) 136 remove_unknown(output_dir)
108 137
109 if __name__ == "__main__": 138 if __name__ == "__main__":
110 if len(sys.argv) < 3: 139 if len(sys.argv) < 3:
111 print >>sys.stderr, "Usage: %s source_repository output_dir" % sys.argv[0] 140 print >>sys.stderr, "Usage: %s source_repository output_dir" % sys.argv[0]
112 sys.exit(1) 141 sys.exit(1)
113 142
114 repo, output_dir = sys.argv[1:3] 143 repo, output_dir = sys.argv[1:3]
115 generate_pages(repo, output_dir) 144 generate_pages(repo, output_dir)
OLDNEW
« no previous file with comments | « no previous file | cms/converters.py » ('j') | cms/sources.py » ('J')

Powered by Google App Engine
This is Rietveld