| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Docbuilder for extension docs.""" | 6 """Docbuilder for extension docs.""" |
| 7 | 7 |
| 8 import os | 8 import os |
| 9 import os.path | 9 import os.path |
| 10 import shutil | 10 import shutil |
| 11 import sys | 11 import sys |
| 12 import time | 12 import time |
| 13 import urllib | 13 import urllib |
| 14 | 14 |
| 15 from subprocess import Popen, PIPE | 15 from subprocess import Popen, PIPE |
| 16 from optparse import OptionParser | 16 from optparse import OptionParser |
| 17 | 17 |
| 18 _script_path = os.path.realpath(__file__) | 18 _script_path = os.path.realpath(__file__) |
| 19 _build_dir = os.path.dirname(_script_path) | 19 _build_dir = os.path.dirname(_script_path) |
| 20 _base_dir = os.path.normpath(_build_dir + "/..") | 20 _base_dir = os.path.normpath(_build_dir + "/..") |
| 21 _static_dir = _base_dir + "/static" | 21 _static_dir = _base_dir + "/static" |
| 22 _js_dir = _base_dir + "/js" | 22 _js_dir = _base_dir + "/js" |
| 23 _template_dir = _base_dir + "/template" | 23 _template_dir = _base_dir + "/template" |
| 24 _samples_dir = _base_dir + "/examples" |
| 24 _extension_api_dir = os.path.normpath(_base_dir + "/../api") | 25 _extension_api_dir = os.path.normpath(_base_dir + "/../api") |
| 25 | 26 |
| 26 _extension_api_json = _extension_api_dir + "/extension_api.json" | 27 _extension_api_json = _extension_api_dir + "/extension_api.json" |
| 27 _api_template_html = _template_dir + "/api_template.html" | 28 _api_template_html = _template_dir + "/api_template.html" |
| 28 _page_shell_html = _template_dir + "/page_shell.html" | 29 _page_shell_html = _template_dir + "/page_shell.html" |
| 29 _generator_html = _build_dir + "/generator.html" | 30 _generator_html = _build_dir + "/generator.html" |
| 31 _samples_json = _base_dir + "/samples.json" |
| 30 | 32 |
| 31 _expected_output_preamble = "<!DOCTYPE html>" | 33 _expected_output_preamble = "<!DOCTYPE html>" |
| 32 _expected_output_postamble = "</body></html>" | 34 _expected_output_postamble = "</body></html>" |
| 33 | 35 |
| 34 # HACK! This is required because we can only depend on python 2.4 and | 36 # HACK! This is required because we can only depend on python 2.4 and |
| 35 # the calling environment may not be setup to set the PYTHONPATH | 37 # the calling environment may not be setup to set the PYTHONPATH |
| 36 sys.path.append(os.path.normpath(_base_dir + | 38 sys.path.append(os.path.normpath(_base_dir + |
| 37 "/../../../../third_party")) | 39 "/../../../../third_party")) |
| 38 import simplejson as json | 40 import simplejson as json |
| 41 from directory import Sample |
| 42 from directory import ApiManifest |
| 43 from directory import SamplesManifest |
| 39 | 44 |
| 40 def RenderPage(name, test_shell): | 45 def RenderPage(name, test_shell): |
| 41 """ | 46 """ |
| 42 Calls test_shell --layout-tests .../generator.html?<name> and writes the | 47 Calls test_shell --layout-tests .../generator.html?<name> and writes the |
| 43 result to .../docs/<name>.html | 48 result to .../docs/<name>.html |
| 44 """ | 49 """ |
| 45 if not name: | 50 if not name: |
| 46 raise Exception("RenderPage called with empty name") | 51 raise Exception("RenderPage called with empty name") |
| 47 | 52 |
| 48 generator_url = "file:" + urllib.pathname2url(_generator_html) + "?" + name | 53 generator_url = "file:" + urllib.pathname2url(_generator_html) + "?" + name |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 | 130 |
| 126 for loc in search_locations: | 131 for loc in search_locations: |
| 127 if os.path.isfile(loc): | 132 if os.path.isfile(loc): |
| 128 return loc | 133 return loc |
| 129 | 134 |
| 130 raise Exception ("Could not find test_shell executable\n" + | 135 raise Exception ("Could not find test_shell executable\n" + |
| 131 "**test_shell may need to be built**\n" + | 136 "**test_shell may need to be built**\n" + |
| 132 "Searched: \n" + "\n".join(search_locations) + "\n" + | 137 "Searched: \n" + "\n".join(search_locations) + "\n" + |
| 133 "To specify a path to test_shell use --test-shell-path") | 138 "To specify a path to test_shell use --test-shell-path") |
| 134 | 139 |
| 135 def GetAPIModuleNames(): | |
| 136 try: | |
| 137 contents = open(_extension_api_json, 'r').read() | |
| 138 except IOError, msg: | |
| 139 raise Exception("Failed to read the file that defines the extensions API. " | |
| 140 "The specific error was: %s." % msg) | |
| 141 | |
| 142 try: | |
| 143 extension_api = json.loads(contents, encoding="ASCII") | |
| 144 except ValueError, msg: | |
| 145 raise Exception("File %s has a syntax error: %s" % | |
| 146 (_extension_api_json, msg)) | |
| 147 # Exclude modules with a "nodoc" property. | |
| 148 return set(module['namespace'].encode() for module in extension_api | |
| 149 if "nodoc" not in module) | |
| 150 | |
| 151 def GetStaticFileNames(): | 140 def GetStaticFileNames(): |
| 152 static_files = os.listdir(_static_dir) | 141 static_files = os.listdir(_static_dir) |
| 153 return set(os.path.splitext(file_name)[0] | 142 return set(os.path.splitext(file_name)[0] |
| 154 for file_name in static_files | 143 for file_name in static_files |
| 155 if file_name.endswith(".html") and not file_name.startswith(".")) | 144 if file_name.endswith(".html") and not file_name.startswith(".")) |
| 156 | 145 |
| 157 def main(): | 146 def main(): |
| 158 # Prevent windows from using cygwin python. | 147 # Prevent windows from using cygwin python. |
| 159 if (sys.platform == "cygwin"): | 148 if (sys.platform == "cygwin"): |
| 160 raise Exception("Building docs not supported for cygwin python.\n" | 149 raise Exception("Building docs not supported for cygwin python.\n" |
| 161 "Please run the build.bat script.") | 150 "Please run the build.bat script.") |
| 162 | 151 |
| 163 parser = OptionParser() | 152 parser = OptionParser() |
| 164 parser.add_option("--test-shell-path", dest="test_shell_path") | 153 parser.add_option("--test-shell-path", dest="test_shell_path") |
| 154 parser.add_option("--page-name", dest="page_name") |
| 165 (options, args) = parser.parse_args() | 155 (options, args) = parser.parse_args() |
| 166 | 156 |
| 167 if (options.test_shell_path and os.path.isfile(options.test_shell_path)): | 157 if (options.test_shell_path and os.path.isfile(options.test_shell_path)): |
| 168 test_shell = options.test_shell_path | 158 test_shell = options.test_shell_path |
| 169 else: | 159 else: |
| 170 test_shell = FindTestShell() | 160 test_shell = FindTestShell() |
| 171 | 161 |
| 162 # Load the manifest of existing API Methods |
| 163 api_manifest = ApiManifest(_extension_api_json) |
| 164 |
| 172 # Read static file names | 165 # Read static file names |
| 173 static_names = GetStaticFileNames() | 166 static_names = GetStaticFileNames() |
| 174 | 167 |
| 175 # Read module names | 168 # Read module names |
| 176 module_names = GetAPIModuleNames() | 169 module_names = api_manifest.getModuleNames() |
| 177 | 170 |
| 178 # All pages to generate | 171 # All pages to generate |
| 179 page_names = static_names | module_names | 172 page_names = static_names | module_names |
| 180 | 173 |
| 174 # Allow the user to render a single page if they want |
| 175 if options.page_name: |
| 176 if options.page_name in page_names: |
| 177 page_names = [options.page_name] |
| 178 else: |
| 179 raise Exception("--page-name argument must be one of %s." % |
| 180 ', '.join(sorted(page_names))) |
| 181 |
| 182 # Render a manifest file containing metadata about all the extension samples |
| 183 samples_manifest = SamplesManifest(_samples_dir, _base_dir, api_manifest) |
| 184 samples_manifest.writeToFile(_samples_json) |
| 185 |
| 181 modified_files = [] | 186 modified_files = [] |
| 182 for page in page_names: | 187 for page in page_names: |
| 183 modified_file = RenderPage(page, test_shell) | 188 modified_file = RenderPage(page, test_shell) |
| 184 if (modified_file): | 189 if (modified_file): |
| 185 modified_files.append(modified_file) | 190 modified_files.append(modified_file) |
| 186 | 191 |
| 187 if (len(modified_files) == 0): | 192 if (len(modified_files) == 0): |
| 188 print "Output files match existing files. No changes made." | 193 print "Output files match existing files. No changes made." |
| 189 else: | 194 else: |
| 190 print ("ATTENTION: EXTENSION DOCS HAVE CHANGED\n" + | 195 print ("ATTENTION: EXTENSION DOCS HAVE CHANGED\n" + |
| 191 "The following files have been modified and should be checked\n" + | 196 "The following files have been modified and should be checked\n" + |
| 192 "into source control (ideally in the same changelist as the\n" + | 197 "into source control (ideally in the same changelist as the\n" + |
| 193 "underlying files that resulting in their changing).") | 198 "underlying files that resulting in their changing).") |
| 194 for f in modified_files: | 199 for f in modified_files: |
| 195 print f | 200 print f |
| 196 | 201 |
| 197 # Hack. Sleep here, otherwise windows doesn't properly close the debug.log | 202 # Hack. Sleep here, otherwise windows doesn't properly close the debug.log |
| 198 # and the os.remove will fail with a "Permission denied". | 203 # and the os.remove will fail with a "Permission denied". |
| 199 time.sleep(1) | 204 time.sleep(1) |
| 200 debug_log = os.path.normpath(_build_dir + "/" + "debug.log") | 205 debug_log = os.path.normpath(_build_dir + "/" + "debug.log") |
| 201 if (os.path.isfile(debug_log)): | 206 if (os.path.isfile(debug_log)): |
| 202 os.remove(debug_log) | 207 os.remove(debug_log) |
| 203 | 208 |
| 204 return os.EX_OK | 209 return os.EX_OK |
| 205 | 210 |
| 206 if __name__ == '__main__': | 211 if __name__ == '__main__': |
| 207 sys.exit(main()) | 212 sys.exit(main()) |
| OLD | NEW |