$search
00001 # Software License Agreement (BSD License) 00002 # 00003 # Copyright (c) 2009, Willow Garage, Inc. 00004 # All rights reserved. 00005 # 00006 # Redistribution and use in source and binary forms, with or without 00007 # modification, are permitted provided that the following conditions 00008 # are met: 00009 # 00010 # * Redistributions of source code must retain the above copyright 00011 # notice, this list of conditions and the following disclaimer. 00012 # * Redistributions in binary form must reproduce the above 00013 # copyright notice, this list of conditions and the following 00014 # disclaimer in the documentation and/or other materials provided 00015 # with the distribution. 00016 # * Neither the name of Willow Garage, Inc. nor the names of its 00017 # contributors may be used to endorse or promote products derived 00018 # from this software without specific prior written permission. 00019 # 00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00031 # POSSIBILITY OF SUCH DAMAGE. 00032 # 00033 # Revision $Id$ 00034 # $Author$ 00035 from __future__ import with_statement 00036 00037 import cStringIO 00038 import os 00039 import sys 00040 import time 00041 import shutil 00042 00043 import roslib.msgs 00044 import roslib.scriptutil 00045 import roslib.srvs 00046 import roslib.stacks 00047 00048 from roslib.msgs import msg_file 00049 from roslib.srvs import srv_file 00050 00051 from rosdoc.rdcore import * 00052 import rosmsg 00053 00054 msg_template = load_tmpl('msg.template') 00055 msg_index_template = load_tmpl('msg-index.template') 00056 00057 def _href(link, text): 00058 return '<a href="%(link)s">%(text)s</a>'%locals() 00059 00060 def type_link(type_, base_package): 00061 base_type = roslib.msgs.base_msg_type(type_) 00062 base_type = roslib.msgs.resolve_type(base_type, base_package) 00063 if base_type in roslib.msgs.BUILTIN_TYPES: 00064 return type_ 00065 package, base_type = roslib.names.package_resource_name(base_type) 00066 # always chain upwards to msg dir 00067 if not package or package == base_package: 00068 return _href("../msg/%s.html"%base_type, type_) 00069 else: 00070 return _href("../../../%(package)s/html/msg/%(base_type)s.html"%locals(), type_) 00071 00072 def index_type_link(pref, type_, base_package): 00073 if type_ in roslib.msgs.BUILTIN_TYPES: 00074 return type_ 00075 base_type_ = roslib.msgs.base_msg_type(type_) 00076 package, base_type_ = roslib.names.package_resource_name(base_type_) 00077 if not package or package == base_package: 00078 return _href("%s/%s.html"%(pref, base_type_), type_) 00079 else: 00080 return _href("../../%(package)s/html/%(pref)s/%(base_type_)s.html"%locals(), type_) 00081 00082 def _generate_raw_text(raw_fn, msg): 00083 raw_text = raw_fn(msg, raw=True) 00084 s = '' 00085 for line in raw_text.split('\n'): 00086 line = line.replace(' ', ' ') 00087 parts = line.split('#') 00088 if len(parts) > 1: 00089 s = s + parts[0]+'<font color="blue">#%s</font><br/>'%('#'.join(parts[1:])) 00090 else: 00091 s = s + "%s<br/>"%parts[0] 00092 return s 00093 00094 def _generate_msg_text_from_spec(package, spec, buff=None, indent=0): 00095 if buff is None: 00096 buff = cStringIO.StringIO() 00097 for c in spec.constants: 00098 buff.write("%s%s %s=%s<br />"%(" "*indent, c.type, c.name, c.val_text)) 00099 for type_, name in zip(spec.types, spec.names): 00100 buff.write("%s%s %s<br />"%(" "*indent, type_link(type_, package), name)) 00101 base_type = roslib.msgs.base_msg_type(type_) 00102 base_type = roslib.msgs.resolve_type(base_type, package) 00103 if not base_type in roslib.msgs.BUILTIN_TYPES: 00104 subspec = roslib.msgs.get_registered(base_type) 00105 _generate_msg_text_from_spec(package, subspec, buff, indent + 4) 00106 return buff.getvalue() 00107 00108 def _generate_msg_text(package, type_): 00109 #print "generate", package, type_ 00110 name, spec = roslib.msgs.load_from_file(msg_file(package, type_)) 00111 return _generate_msg_text_from_spec(package, spec) 00112 00113 def _generate_srv_text(package, type_): 00114 name, spec = roslib.srvs.load_from_file(srv_file(package, type_)) 00115 return _generate_msg_text_from_spec(package, spec.request) + \ 00116 '<hr />'+\ 00117 _generate_msg_text_from_spec(package, spec.response) 00118 00119 def generate_srv_doc(srv): 00120 package, base_type = roslib.names.package_resource_name(srv) 00121 d = { 'name': srv, 'ext': 'srv', 'type': 'Service', 00122 'package': package, 'base_type' : base_type, 00123 'date': str(time.strftime('%a, %d %b %Y %H:%M:%S'))} 00124 d['fancy_text'] = _generate_srv_text(package, base_type) 00125 d['raw_text'] = _generate_raw_text(rosmsg.get_srv_text, srv) 00126 raw_text = _generate_raw_text(rosmsg.get_srv_text, srv) 00127 return msg_template%d 00128 00129 def generate_msg_doc(msg): 00130 package, base_type = roslib.names.package_resource_name(msg) 00131 d = { 'name': msg, 'ext': 'msg', 'type': 'Message', 00132 'package': package, 'base_type' : base_type, 00133 'date': str(time.strftime('%a, %d %b %Y %H:%M:%S'))} 00134 d['fancy_text'] = _generate_msg_text(package, base_type) 00135 d['raw_text'] = _generate_raw_text(rosmsg.get_msg_text, msg) 00136 return msg_template%d 00137 00138 def generate_msg_index(package, file_d, msgs, srvs, wiki_url): 00139 d = {'package': package, 'msg_list' : '', 'srv_list': '', 00140 'package_url': wiki_url, 00141 'date': str(time.strftime('%a, %d %b %Y %H:%M:%S'))} 00142 if msgs: 00143 d['msg_list'] = """<h2>Message types</h2> 00144 <div class="msg-list"> 00145 <ul> 00146 %s 00147 </ul> 00148 </div>"""%'\n'.join([" <li>%s</li>"%index_type_link('msg', m, package) for m in msgs]) 00149 00150 if srvs: 00151 d['srv_list'] = """<h2>Service types</h2> 00152 <div class="srv-list"> 00153 <ul> 00154 %s 00155 </ul> 00156 </div>"""%'\n'.join([" <li>%s</li>"%index_type_link('srv', s, package) for s in srvs]) 00157 00158 file_p = os.path.join(file_d, 'index-msg.html') 00159 text = msg_index_template % d 00160 with open(file_p, 'w') as f: 00161 #print "writing", file_p 00162 f.write(text) 00163 00164 00165 ## generate manifest.yaml files for MoinMoin PackageHeader macro 00166 def generate_msg_docs(ctx): 00167 try: 00168 import yaml 00169 except ImportError: 00170 print >> sys.stderr, "Cannot import yaml, will not generate MoinMoin PackageHeader files" 00171 return 00172 00173 docdir = ctx.docdir 00174 manifests = ctx.manifests 00175 packages = ctx.packages 00176 for p in packages.iterkeys(): 00177 if not ctx.should_document(p): 00178 continue 00179 00180 # roslib.msgs work, load specs into memory 00181 roslib.msgs.reinit() 00182 roslib.msgs.load_package_dependencies(p, load_recursive=True) 00183 roslib.msgs.load_package(p) 00184 00185 # create the directory for the autogen files 00186 file_d = os.path.join(docdir, p, 'html') 00187 if not os.path.exists(file_d): 00188 os.makedirs(file_d) 00189 00190 # get a list of what we are documenting 00191 msgs = roslib.msgs.list_msg_types(p, False) 00192 srvs = roslib.srvs.list_srv_types(p, False) 00193 00194 # generate the top-level index 00195 wiki_url = '<li>%s</li>\n'%_href(ctx.manifests[p].url, 'Wiki page for %s'%p) 00196 generate_msg_index(p, file_d, msgs, srvs, wiki_url) 00197 00198 # create dir for msg documentation 00199 if msgs: 00200 msg_d = os.path.join(file_d, 'msg') 00201 if not os.path.exists(msg_d): 00202 os.makedirs(msg_d) 00203 00204 # document the messages 00205 for m in msgs: 00206 try: 00207 text = generate_msg_doc('%s/%s'%(p,m)) 00208 file_p = os.path.join(msg_d, '%s.html'%m) 00209 with open(file_p, 'w') as f: 00210 #print "writing", file_p 00211 f.write(text) 00212 except Exception, e: 00213 print >> sys.stderr, "FAILED to generate for %s/%s: %s"%(p, m, str(e)) 00214 00215 # create dir for srv documentation 00216 if srvs: 00217 srv_d = os.path.join(file_d,'srv') 00218 if not os.path.exists(srv_d): 00219 os.makedirs(srv_d) 00220 00221 # document the services 00222 for s in srvs: 00223 try: 00224 text = generate_srv_doc('%s/%s'%(p,s)) 00225 file_p = os.path.join(srv_d, '%s.html'%s) 00226 with open(file_p, 'w') as f: 00227 #print "writing", file_p 00228 f.write(text) 00229 except Exception, e: 00230 print >> sys.stderr, "FAILED to generate for %s/%s: %s"%(p, s, str(e)) 00231 00232 # we don't return an explicit list of artifacts as we generate into same tree 00233 return [] 00234 00235 00236 00237 00238 00239 00240 00241 00242 00243