00001 import sys
00002 import urllib2
00003 import os
00004 import json
00005 import datetime
00006
00007 try:
00008 from MoinMoin.Page import Page
00009 except:
00010 sys.stderr.write("Cannot import Moin. For testing only")
00011
00012 from macroutils import wiki_url, get_repo_li, get_vcs_li, load_stack_release, \
00013 msg_doc_link, load_package_manifest, package_html_link, UtilException, \
00014 load_stack_manifest, sub_link, distro_names, \
00015 get_package_versions, CONTRIBUTE_TMPL
00016
00017 def get_nav(macro, stack_name, packages, distro=None):
00018 nav = '<script type="text/javascript" src="/js/roswiki.js"></script>'
00019 strong, em, text = macro.formatter.strong, macro.formatter.emphasis, macro.formatter.text
00020
00021 if not stack_name or stack_name == 'sandbox':
00022
00023 return nav
00024 elif [stack_name] == packages:
00025
00026 return nav
00027
00028
00029 distro_query = None
00030 if distro:
00031 distro_query = "distro=%s"%distro
00032
00033 page_name = macro.formatter.page.page_name
00034
00035
00036 if stack_name == page_name:
00037 top = strong(1)+text(stack_name)+strong(0)
00038 else:
00039 top = strong(1)+wiki_url(macro, stack_name, querystr=distro_query)+strong(0)
00040
00041
00042 packages = [s for s in packages if not s.startswith('test_')]
00043 packages.sort()
00044 parts = []
00045 for pkg in packages:
00046 if pkg == page_name:
00047 parts.append(text(pkg))
00048 else:
00049 parts.append(wiki_url(macro, pkg, querystr=distro_query))
00050
00051
00052 nav = nav + em(1) + top
00053 if parts:
00054 nav += text(': ')+parts[0]
00055 for part in parts[1:]:
00056 nav += text(' | ')+part
00057 nav += em(0)
00058 return nav
00059
00060 def is_stack_released(stack_name):
00061 stack_props = None
00062 for release_name in distro_names:
00063 if not stack_props:
00064 _, stack_props = load_stack_release(release_name, stack_name)
00065 return bool(stack_props)
00066
00067 def get_description(macro, data, type_):
00068
00069 authors = data.get('authors', 'unknown')
00070 try:
00071 if type(authors) != unicode:
00072 authors = unicode(authors, 'utf-8')
00073 except UnicodeDecodeError:
00074 authors = ''
00075 license = data.get('license', 'unknown')
00076
00077 description = data.get('description', '')
00078 try:
00079 if type(description) != unicode:
00080 description = unicode(description, 'utf-8')
00081 except UnicodeDecodeError:
00082 description = ''
00083
00084 f = macro.formatter
00085 p, div, li, ul = f.paragraph, f.div, f.listitem, f.bullet_list
00086 h, text, rawHTML = f.heading, f.text, f.rawHTML
00087
00088 if type_ == 'stack':
00089 title = 'Stack Summary'
00090 else:
00091 title = 'Package Summary'
00092 try:
00093 repo_li = get_repo_li(macro, data)
00094 vcs_li = get_vcs_li(macro, data)
00095
00096
00097
00098 desc = "<h1>"+text(title)+"</h1>"+\
00099 p(1,id="package-info")+rawHTML(description)+p(0)+\
00100 p(1,id="package-info")+ul(1)+\
00101 li(1)+text("Author: "+authors)+li(0)+\
00102 li(1)+text("License: "+license)+li(0)+\
00103 repo_li+\
00104 vcs_li+\
00105 ul(0)+p(0)
00106 except UnicodeDecodeError:
00107 desc = h(1, 2)+text(title)+h(0,2)+p(1)+text('Error retrieving '+title)+p(0)
00108 return desc
00109
00110 def li_if_exists(macro, page, sub_page):
00111 li = macro.formatter.listitem
00112 if Page(macro.request, '%s/%s'%(page, sub_page)).exists():
00113 return li(1)+sub_link(macro, page, sub_page)+li(0)
00114 else:
00115 return ''
00116
00117 def distro_html(distro, distros):
00118 active = [distro.encode("iso-8859-1")]
00119 inactive = [x.encode("iso-8859-1") for x in distros if not x == distro]
00120 sectionarg = '''{show:%s, hide:%s}''' %(active, inactive)
00121 html = '''<button id="%s" onClick="Version(%s);this.style.color='#e6e6e6';this.style.background='#3e4f6e';''' % (distro, sectionarg)
00122 for inactive_distro in inactive:
00123 html += '''document.getElementById('%s').style.background='#e6e6e6';document.getElementById('%s').style.color='#3e4f6e';''' % (inactive_distro, inactive_distro)
00124 html += '''return false"> %s </button>''' % (distro)
00125 return html
00126
00127 def generate_package_header(macro, package_name, opt_distro=None):
00128 if not package_name:
00129 return "ERROR in PackageHeader. Usage: [[PackageHeader(package_name opt_distro)]]"
00130 if ' ' in package_name:
00131
00132 splits = package_name.split(' ')
00133 if len(splits) > 2:
00134 return "ERROR in PackageHeader. Usage: [[PackageHeader(pkg_name opt_distro)]]"
00135 package_name, distro = splits
00136
00137 try:
00138 data = load_package_manifest(package_name, opt_distro)
00139 except UtilException, e:
00140 name = "name: %s, distro: %s" % (package_name, opt_distro)
00141 return CONTRIBUTE_TMPL%locals()
00142
00143 nav = []
00144
00145 package_type = data.get('package_type', 'package')
00146 is_metapackage = package_type in ['stack', 'metapackage']
00147
00148 if is_metapackage:
00149 nav.append(get_nav(macro, package_name, list(set(data.get('packages', []))), distro=opt_distro))
00150
00151 metapackages = data.get('metapackages', None)
00152
00153 if package_type == 'stack':
00154 stack_name = package_name
00155 else:
00156 stack_name = ''
00157
00158 if metapackages:
00159 for metapackage in metapackages:
00160 try:
00161 metapackage_data = load_package_manifest(metapackage, opt_distro)
00162 nav.append(get_nav(macro, metapackage, list(set(metapackage_data.get('packages', []))), distro=opt_distro))
00163 metapackage_type = metapackage_data.get('package_type', None)
00164 if metapackage_type == 'stack':
00165 stack_name = metapackage
00166 except UtilException, e:
00167 continue
00168
00169
00170 if stack_name:
00171 repo_name = stack_name
00172 elif data.has_key('repo_name'):
00173 repo_name = data['repo_name']
00174 elif data.has_key('vcs_url'):
00175 repo_name = os.path.splitext(os.path.basename(data['vcs_url']))[0]
00176 else:
00177 repo_name = os.path.splitext(os.path.basename(data['vcs_uri']))[0]
00178
00179
00180 status_string = "<b>Doc job status is unknown.</b>"
00181 if opt_distro:
00182 jenkins_url = 'http://jenkins.willowgarage.com:8080/job/%s' % \
00183 (data.get("doc_job", "doc-%s-%s" % (opt_distro, repo_name)))
00184 try:
00185 jenkins_stream = urllib2.urlopen('%s/lastBuild/api/json' % \
00186 (jenkins_url), timeout=1.0)
00187 status_json = json.load(jenkins_stream)
00188 result = status_json.get("result", "UNKNOWN")
00189 timestamp = datetime.datetime.fromtimestamp(int(status_json.get("timestamp", 0)) / 1000.0)
00190 time_str = timestamp.strftime("%B %d, %Y at %I:%M %p")
00191 if result == 'SUCCESS':
00192 status_string = '<i>Documentation generated on %s</i>' % (time_str)
00193 elif result is None:
00194 status_string = '<i>Documentation is currently being re-generated</i>'
00195 else:
00196 if result =='FAILURE' and data.has_key('timestamp'):
00197 last_timestamp = datetime.datetime.fromtimestamp(data['timestamp'])
00198 last_time_str = last_timestamp.strftime("%B %d, %Y at %I:%M %p")
00199 time_str = last_time_str
00200 status_string = '<i>Documentation generated on %s</i><span style="font-size:10px"> (Doc job status: %s <a href="%s/lastBuild/testReport">details</a>).</span>' % (time_str, result.lower(), jenkins_url)
00201 except Exception as e:
00202 status_string = "<b>Could not retreive doc job information, communication with jenkins failed %s, %s</b>" % (e, jenkins_url)
00203 pass
00204
00205 doc_status = '%s<br><br>' % status_string
00206 desc = get_description(macro, data, 'package')
00207 links = get_package_links(macro, package_name, data, opt_distro, repo_name=repo_name, metapackage=is_metapackage)
00208
00209 html = '<br><br>'.join([macro.formatter.rawHTML(item) for item in nav])
00210 if html:
00211 html = html + '<br><br>'
00212
00213 return doc_status + html + links + desc
00214
00215
00216 def get_package_links(macro, package_name, data, distro, repo_name=None, metapackage=False):
00217 f = macro.formatter
00218 p, url, div = f.paragraph, f.url, f.div
00219 em, strong, h, text = f.emphasis, f.strong, f.heading, f.text
00220 li, ul = f.listitem, f.bullet_list
00221
00222 review_status = data.get('review_status', 'unreviewed')
00223
00224 external_website = data.get('url', '') or ''
00225 if 'ros.org' in external_website or 'willowgarage.com' in external_website:
00226 external_website = u''
00227
00228 if 'external_documentation' in data:
00229 api_documentation = data['external_documentation']
00230 else:
00231 api_documentation = data['api_documentation']
00232
00233 msgs = data.get('msgs', [])
00234 srvs = data.get('srvs', [])
00235
00236
00237 msg_doc_title = "Msg/Srv API"
00238 if msgs and not srvs:
00239 msg_doc_title = "Msg API"
00240 elif srvs and not msgs:
00241 msg_doc_title = "Srv API"
00242
00243 if '3rdparty' in review_status:
00244 review_str = ''
00245 else:
00246 review_str = li(1)+sub_link(macro, package_name, 'Reviews') + text(' ('+review_status+')')+li(0)
00247 if external_website:
00248 external_website = li(1)+url(1, url=external_website)+text("%s website"%(package_name))+url(0)+li(0)
00249
00250
00251 troubleshoot = li_if_exists(macro, package_name, 'Troubleshooting')
00252 tutorials = li_if_exists(macro, package_name, 'Tutorials')
00253
00254 if repo_name:
00255 releases_link = li(1)+sub_link(macro, repo_name, 'Releases')+li(0)
00256 changelist_link = li(1)+sub_link(macro, repo_name, 'ChangeList', title='Change List')+li(0)
00257 roadmap_link = li_if_exists(macro, repo_name, 'Roadmap')
00258 else:
00259 releases_link = ''
00260 changelist_link = ''
00261 roadmap_link = ''
00262
00263
00264 if metapackage:
00265 code_api = ''
00266 elif 'ros.org/doc/api' in api_documentation:
00267 code_api = li(1)+strong(1)+url(1, url=package_html_link(package_name, distro))+text("Code API")+url(0)+strong(0)+li(0)
00268 else:
00269 code_api = li(1)+strong(1)+url(1, url=api_documentation)+text("Code API")+url(0)+strong(0)+li(0)
00270
00271 if not msgs and not srvs:
00272 msg_doc = text('')
00273 else:
00274 msg_doc = li(1)+strong(1)+msg_doc_link(package_name, msg_doc_title, distro)+strong(0)+li(0)
00275
00276 try:
00277 package_links = div(1, css_class="package-links")+\
00278 strong(1)+text("Package Links")+strong(0)+\
00279 ul(1)+\
00280 code_api+\
00281 msg_doc+\
00282 external_website+\
00283 tutorials+\
00284 troubleshoot+\
00285 li(1)+url(1, url='http://answers.ros.org/questions/scope:all/sort:activity-desc/tags:%s/page:1/'%(package_name))+text("FAQ")+url(0)+li(0)+\
00286 changelist_link+\
00287 roadmap_link+\
00288 releases_link+\
00289 review_str+\
00290 ul(0)
00291 except UnicodeDecodeError:
00292 package_links = div(1, css_class="package-links")
00293
00294 package_links += get_dependency_list(macro, data, css_prefix=distro, distro=distro)
00295 package_links+=div(0)
00296 return package_links
00297
00298 def get_stack_links(macro, stack_name, data, packages, is_unary, distro):
00299 f = macro.formatter
00300 p, div, h, text = f.paragraph, f.div, f.heading, f.text
00301 li, ul, strong = f.listitem, f.bullet_list, f.strong
00302
00303 is_released = is_stack_released(stack_name)
00304
00305
00306 if is_released:
00307 releases_link = li(1)+sub_link(macro, stack_name, 'Releases')+li(0)
00308 changelist_link = li(1)+sub_link(macro, stack_name, 'ChangeList', title='Change List')+li(0)
00309 else:
00310 releases_link = changelist_link = ''
00311 if not is_unary:
00312 troubleshooting_link = li_if_exists(macro, stack_name, 'Troubleshooting')
00313 review_status = data.get('review_status', 'unreviewed')
00314 review_link = li(1)+sub_link(macro, stack_name, 'Reviews') + text(' ('+review_status+')')+li(0)
00315 tutorials_link=li_if_exists(macro, stack_name, 'Tutorials')
00316 else:
00317 troubleshooting_link = review_link = tutorials_link = ''
00318
00319 roadmap_link = li_if_exists(macro, stack_name, 'Roadmap')
00320 try:
00321 links = div(1, css_class="package-links")+strong(1)+text('Stack Links')+strong(0)+\
00322 ul(1)+\
00323 tutorials_link+\
00324 troubleshooting_link+\
00325 releases_link+\
00326 changelist_link+\
00327 roadmap_link+\
00328 review_link+\
00329 ul(0)
00330 except UnicodeDecodeError:
00331 links = div(1, css_class="package-links")
00332
00333 links += get_dependency_list(macro, data, css_prefix='stack-%s'%distro, distro=distro) + div(0)
00334 return links
00335
00336 def get_dependency_list(macro, data, css_prefix='',distro=None):
00337 f = macro.formatter
00338 li, ul, strong, div = f.listitem, f.bullet_list, f.strong, f.div
00339
00340 depends = data.get('depends', [])
00341 depends_on = data.get('depends_on', [])
00342
00343 distro_query = None
00344 if distro:
00345 distro_query = "distro=%s"%distro
00346
00347 links = ''
00348 if depends:
00349 depends.sort()
00350 links += strong(1)+\
00351 '<a href="#" onClick="toggleExpandable(\'%sdependencies-list\');">Dependencies</a> (%s)'%(css_prefix, len(depends))+\
00352 strong(0)+'<br />'+\
00353 '<div id="%sdependencies-list" style="display:none">'%(css_prefix)+\
00354 ul(1)
00355 for d in depends:
00356 links += li(1)+wiki_url(macro,d,shorten=20,querystr=distro_query)+li(0)
00357 links += ul(0)+div(0)
00358 if depends_on:
00359 depends_on.sort()
00360 links += strong(1)+\
00361 '<a href="#" onClick="toggleExpandable(\'%sused-by-list\');">Used by</a> (%s)'%(css_prefix, len(depends_on))+\
00362 strong(0)+"<br />"+\
00363 '<div id="%sused-by-list" style="display:none">'%(css_prefix)+ul(1)
00364 for d in depends_on:
00365 links += li(1)+wiki_url(macro,d,shorten=20,querystr=distro_query)+li(0)
00366 links += ul(0)+div(0)
00367
00368 return links
00369