Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / tools / telemetry / build / update_docs.py
blob2b11da50009f664077048712222cf6d6c58c77d7
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 import logging
5 import optparse
6 import os
7 import pkgutil
8 import pydoc
9 import re
10 import sys
12 import telemetry
13 from telemetry.core import util
15 telemetry_dir = util.GetTelemetryDir()
16 docs_dir = os.path.join(telemetry_dir, 'docs')
18 def RemoveAllDocs():
19 for dirname, _, filenames in os.walk(docs_dir):
20 for filename in filenames:
21 os.remove(os.path.join(dirname, filename))
23 def GenerateHTMLForModule(module):
24 html = pydoc.html.page(pydoc.describe(module),
25 pydoc.html.document(module, module.__name__))
27 # pydoc writes out html with links in a variety of funky ways. We need
28 # to fix them up.
29 assert not telemetry_dir.endswith(os.sep)
30 links = re.findall('(<a href="(.+?)">(.+?)</a>)', html)
31 for link_match in links:
32 link, href, link_text = link_match
33 if not href.startswith('file:'):
34 continue
36 new_href = href.replace('file:', '')
37 new_href = new_href.replace(telemetry_dir, os.pardir)
38 new_href = new_href.replace(os.sep, '/')
40 new_link_text = link_text.replace(telemetry_dir + os.sep, '')
42 new_link = '<a href="%s">%s</a>' % (new_href, new_link_text)
43 html = html.replace(link, new_link)
45 # pydoc writes out html with absolute path file links. This is not suitable
46 # for checked in documentation. So, fix up the HTML after it is generated.
47 #html = re.sub('href="file:%s' % telemetry_dir, 'href="..', html)
48 #html = re.sub(telemetry_dir + os.sep, '', html)
49 return html
51 def WriteHTMLForModule(module):
52 page = GenerateHTMLForModule(module)
53 path = os.path.join(docs_dir, '%s.html' % module.__name__)
54 with open(path, 'w') as f:
55 sys.stderr.write('Wrote %s\n' % os.path.relpath(path))
56 f.write(page)
58 def GetAllModulesToDocument(module):
59 modules = [module]
60 for _, modname, _ in pkgutil.walk_packages(
61 module.__path__, module.__name__ + '.'):
62 if modname.endswith('_unittest'):
63 logging.debug("skipping %s due to being a unittest", modname)
64 continue
66 module = __import__(modname, fromlist=[""])
67 name, _ = os.path.splitext(module.__file__)
68 if not os.path.exists(name + '.py'):
69 logging.info("skipping %s due to being an orphan .pyc", module.__file__)
70 continue
72 modules.append(module)
73 return modules
75 class AlreadyDocumentedModule(object):
76 def __init__(self, filename):
77 self.filename = filename
79 @property
80 def name(self):
81 basename = os.path.basename(self.filename)
82 return os.path.splitext(basename)[0]
84 @property
85 def contents(self):
86 with open(self.filename, 'r') as f:
87 return f.read()
89 def GetAlreadyDocumentedModules():
90 modules = []
91 for dirname, _, filenames in os.walk(docs_dir):
92 for filename in filenames:
93 path = os.path.join(dirname, filename)
94 modules.append(AlreadyDocumentedModule(path))
95 return modules
98 def IsUpdateDocsNeeded():
99 already_documented_modules = GetAlreadyDocumentedModules()
100 already_documented_modules_by_name = dict(
101 (module.name, module) for module in already_documented_modules)
102 current_modules = GetAllModulesToDocument(telemetry)
104 # Quick check: if the names of modules has changed, we definitely need
105 # an update.
106 already_documented_module_names = set(
107 m.name for m in already_documented_modules)
109 current_module_names = set([m.__name__ for m in current_modules])
111 if current_module_names != already_documented_module_names:
112 return True
114 # Generate the new docs and compare aganist the old. If changed, then a
115 # an update is needed.
116 for current_module in current_modules:
117 already_documented_module = already_documented_modules_by_name[
118 current_module.__name__]
119 current_html = GenerateHTMLForModule(current_module)
120 if current_html != already_documented_module.contents:
121 return True
123 return False
125 def Main(args):
126 parser = optparse.OptionParser()
127 parser.add_option(
128 '-v', '--verbose', action='count', dest='verbosity',
129 help='Increase verbosity level (repeat as needed)')
130 options, args = parser.parse_args(args)
131 if options.verbosity >= 2:
132 logging.getLogger().setLevel(logging.DEBUG)
133 elif options.verbosity:
134 logging.getLogger().setLevel(logging.INFO)
135 else:
136 logging.getLogger().setLevel(logging.WARNING)
138 assert os.path.isdir(docs_dir)
140 RemoveAllDocs()
142 old_cwd = os.getcwd()
143 try:
144 os.chdir(telemetry_dir)
145 for module in GetAllModulesToDocument(telemetry):
146 WriteHTMLForModule(module)
147 finally:
148 os.chdir(old_cwd)