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