00001 from __future__ import with_statement
00002
00003 import os
00004 import sys
00005 import yaml
00006 import urllib2
00007 try:
00008 from MoinMoin.Page import Page
00009 except ImportError:
00010 print >> sys.stderr, "WARNING: Cannot load MoinMoin plugins, continuing load for testing only"
00011
00012 distro_names = ['boxturtle', 'cturtle', 'diamondback', 'electric', 'fuerte', 'groovy', 'unstable']
00013 distro_names_indexed = ['diamondback', 'electric', 'fuerte', 'groovy', 'unstable']
00014
00015
00016 doc_url = "http://ros.org/doc/"
00017
00018 doc_path = '/var/www/www.ros.org/html/doc/'
00019
00020 CONTRIBUTE_TMPL = """Cannot load information on <strong>%(name)s</strong>, which means that it is not yet in our index.
00021 Please see <a href="http://www.ros.org/wiki/Get%%20Involved#Indexing_Your_.2A-ros-pkg_Repository_for_Documentation_Generation">this page</a> for information on how to submit your repository to our index."""
00022
00023 class UtilException(Exception): pass
00024
00025 def ahref(url, text):
00026 """create HTML link to specified URL with link text"""
00027 return '<a href="%(url)s">%(text)s</a>'%locals()
00028
00029 def stack_manifest_file(stack, distro=None):
00030 """
00031 Generate filesystem path to stack.yaml for package
00032 """
00033 if distro:
00034 return os.path.join(doc_path, distro, 'api', stack, "stack.yaml")
00035 else:
00036 return os.path.join(doc_path, 'api', stack, "stack.yaml")
00037
00038 def repo_manifest_file(repo):
00039 """
00040 Generate filesystem path to stack.yaml for package
00041 """
00042 return os.path.join(doc_path, 'api', repo, "repo.yaml")
00043
00044 def package_manifest_file(package, distro=None):
00045 """
00046 Generate filesystem path to manifest.yaml for package
00047 """
00048 if distro:
00049 return os.path.join(doc_path, distro, 'api', package, "manifest.yaml")
00050 else:
00051 return os.path.join(doc_path, 'api', package, "manifest.yaml")
00052
00053 def get_package_versions(package):
00054 distros = []
00055 for d in distro_names_indexed:
00056 if os.path.exists(package_manifest_file(package, d)):
00057 distros.append(d)
00058 return distros
00059
00060 def package_html_link(package, distro=None):
00061 """
00062 Generate link to auto-generated package HTML documentation
00063 """
00064 if distro:
00065 return doc_url + distro + "/api/" + package + '/html/'
00066 else:
00067 return doc_url + "api/" + package + '/html/'
00068
00069 def msg_doc_link(package, link_title, distro=None):
00070 package_url = package_html_link(package, distro)
00071 return ahref('%(package_url)sindex-msg.html'%locals(), link_title)
00072
00073 def msg_link(package, msg):
00074 package_url = package_html_link(package)
00075 return ahref('%(package_url)smsg/%(msg)s.html'%locals(), msg)
00076
00077 def srv_link(package, srv):
00078 package_url = package_html_link(package)
00079 return ahref('%(package_url)ssrv/%(srv)s.html'%locals(), srv)
00080
00081 def sub_link(macro, page, sub, title=None):
00082 """
00083 Generate link to wiki subpage
00084 @param macro: macro instance
00085 @param page: current page name
00086 @param sub: sub page name
00087 @param title: (optional) link text
00088 """
00089 if title is None:
00090 title = sub
00091 return Page(macro.request, '%s/%s'%(page, sub)).link_to(macro.request, text=title)
00092
00093 def wiki_url(macro, page,shorten=None,querystr=None):
00094 """
00095 Create link to ROS wiki page
00096 """
00097 if not shorten or len(page) < shorten:
00098 page_text = page
00099 else:
00100 page_text = page[:shorten]+'...'
00101 return Page(macro.request, page).link_to(macro.request, text=page_text, querystr=querystr)
00102
00103 def get_repo_li(macro, props):
00104 """
00105 Get list item HTML for repository URL
00106 @param macro: Moin macro object
00107 @param props: package/stack manifest dictionary
00108 """
00109 if 'repository' in props and props['repository'] is not None:
00110 f = macro.formatter
00111 li = f.listitem
00112 return li(1)+f.text("Repository: ")+wiki_url(macro, props['repository'])+li(0)
00113 else:
00114 return ''
00115
00116 def get_vcs_li(macro, stack_data):
00117 if 'vcs' in stack_data and 'vcs_uri' in stack_data:
00118 type_ = stack_data['vcs']
00119 uri_display = uri = stack_data['vcs_uri']
00120
00121 if not uri:
00122 return ''
00123 if '//github.com/' in uri and uri.endswith('.git'):
00124 uri = uri[:-4]
00125 f = macro.formatter
00126 li = f.listitem
00127 return li(1)+f.text("Source: "+type_)+f.rawHTML(' <a href="%s">%s</a>'%(uri, uri_display))+li(0)
00128 else:
00129 return ''
00130
00131 def process_distro(stack_name, yaml_str):
00132 """
00133 @return: distro properties, stack properties. Stack properties
00134 is just for convenience as it is part of distro properties
00135 """
00136 distro = yaml.load(yaml_str)
00137 return distro, distro['stacks'][stack_name]
00138
00139 def load_stack_release(release_name, stack_name):
00140 """load in distro release info for stack"""
00141 if stack_name == 'ROS':
00142 stack_name = 'ros'
00143 try:
00144
00145 if release_name in ['boxturtle', 'cturtle', 'diamondback']:
00146 usock = open('/var/www/www.ros.org/html/distros/%s.rosdistro'%release_name)
00147 else:
00148 usock = urllib2.urlopen('https://code.ros.org/svn/release/trunk/distros/%s.rosdistro'%release_name)
00149 rosdistro_str = usock.read()
00150 usock.close()
00151 release, stack_props = process_distro(stack_name, rosdistro_str)
00152 except:
00153 release = stack_props = {}
00154 return release, stack_props
00155
00156 def _load_manifest_file(filename, name, type_='package'):
00157 """
00158 Load manifest.yaml properties into dictionary for package
00159 @param filename: file to load manifest data from
00160 @param name: printable name (for debugging)
00161 @return: manifest properties dictionary
00162 @raise UtilException: if unable to load. Text of error message is human-readable
00163 """
00164 if not os.path.exists(filename):
00165 raise UtilException('Newly proposed, mistyped, or obsolete %s. Could not find %s "'%(type_, type_) + name + '" in rosdoc')
00166
00167 try:
00168 with open(filename) as f:
00169 data = yaml.load(f)
00170 except:
00171 raise UtilException("Error loading manifest data")
00172
00173 if not data:
00174 raise UtilException("Unable to retrieve manifest data. Auto-generated documentation may need to regenerate")
00175 return data
00176
00177 def load_package_manifest(package_name, distro=None):
00178 """
00179 Load manifest.yaml properties into dictionary for package
00180 @param lang: optional language argument for localization, e.g. 'ja'
00181 @return: manifest properties dictionary
00182 @raise UtilException: if unable to load. Text of error message is human-readable
00183 """
00184 return _load_manifest_file(package_manifest_file(package_name, distro), package_name, "package")
00185
00186 def load_repo_manifest(repo_name):
00187 """
00188 Load repo.yaml properties into dictionary for package
00189 @param lang: optional language argument for localization, e.g. 'ja'
00190 @return: manifest properties dictionary
00191 @raise UtilException: if unable to load. Text of error message is human-readable
00192 """
00193 data = _load_manifest_file(repo_manifest_file(repo_name), repo_name, 'repository')
00194 if not data:
00195 raise UtilException("Unable to retrieve manifest data. Auto-generated documentation may need to regenerate")
00196 return data
00197
00198
00199 def load_stack_manifest(stack_name, distro=None):
00200 """
00201 Load stack.yaml properties into dictionary for package
00202 @param lang: optional language argument for localization, e.g. 'ja'
00203 @return: stack manifest properties dictionary
00204 @raise UtilException: if unable to load. Text of error message is human-readable
00205 """
00206 return _load_manifest_file(stack_manifest_file(stack_name, distro), stack_name, 'stack')