$search
00001 #!/usr/bin/env python 00002 # Software License Agreement (BSD License) 00003 # 00004 # Copyright (c) 2008, Willow Garage, Inc. 00005 # All rights reserved. 00006 # 00007 # Redistribution and use in source and binary forms, with or without 00008 # modification, are permitted provided that the following conditions 00009 # are met: 00010 # 00011 # * Redistributions of source code must retain the above copyright 00012 # notice, this list of conditions and the following disclaimer. 00013 # * Redistributions in binary form must reproduce the above 00014 # copyright notice, this list of conditions and the following 00015 # disclaimer in the documentation and/or other materials provided 00016 # with the distribution. 00017 # * Neither the name of Willow Garage, Inc. nor the names of its 00018 # contributors may be used to endorse or promote products derived 00019 # from this software without specific prior written permission. 00020 # 00021 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 # POSSIBILITY OF SUCH DAMAGE. 00033 # 00034 # Revision $Id$ 00035 00036 from __future__ import with_statement 00037 00038 import cStringIO 00039 import time 00040 00041 import roslib.rospack 00042 00043 from rosdoc.rdcore import * 00044 00045 canonicalize = { 00046 'lgpl': 'LGPL', 00047 'unknown': 'Unknown', 00048 'BSD and GPL': 'BSD/GPL', 00049 'Commercial': 'Proprietary', 00050 'Closed': 'Commercial', 00051 'BSD.': 'BSD', 00052 'new BSD': 'BSD (new)', #for better alphabetizing 00053 'GPL v3': "GPLv3", 00054 'GNU GPL V3': 'GPLv3', 00055 'GPL 3.0': 'GPLv3', 00056 '?': 'Unknown', 00057 } 00058 00059 bsdstyle = ['bsd', 'bsd-style', 'new bsd', 'bsd (new)', 'zlib', 'zlib-style', 'mit', 'wxwindows', 'lgpl', 'free', 'python', 'python-style', 'bsl1.0', 'boost', 'apache', 'apache license, version 2.0', 'boost software license', 'public domain', 'apache license', 'BSD, Boost Software License (Poco)', 'BSD, Boost'] 00060 contaminated = ['gpl', 'creativecommons-by-nc-sa-2.0', 'commercial', 'proprietary'] 00061 # keep track of licenses we've reported as unknown 00062 _already_unknown = [] 00063 00064 contam_suffix = " (contaminated)" 00065 00066 ## all keys must be lower case 00067 license_urls = { 00068 'boost': 'http://www.boost.org/users/license.html', 00069 'bsl1.0': 'http://www.boost.org/LICENSE_1_0.txt', 00070 'boost software license': 'http://www.boost.org/users/license.html', 00071 'mit': 'http://www.opensource.org/licenses/mit-license.php', 00072 'new bsd': 'http://www.opensource.org/licenses/bsd-license.php', 00073 'bsd': 'http://www.opensource.org/licenses/bsd-license.php', 00074 'zlib': 'http://www.gzip.org/zlib/zlib_license.html', 00075 'lgpl': 'http://www.opensource.org/licenses/lgpl-2.1.php', 00076 'lgplv3': 'http://www.opensource.org/licenses/lgpl-3.0.html', 00077 'gpl': 'http://www.opensource.org/licenses/gpl-2.0.php', 00078 'gplv3': 'http://www.opensource.org/licenses/gpl-3.0.html', 00079 'nosa': 'http://www.opensource.org/licenses/nasa1.3.php', 00080 'creativecommons-by-nc-sa-2.0': 'http://creativecommons.org/licenses/by-nc-sa/2.0/', 00081 } 00082 00083 license_template = load_tmpl('license-index.html') 00084 00085 ################################################################################ 00086 # License logic 00087 00088 ## check to see if bsd package is contaminated by GPL 00089 ## @return str, [str]: license, blamelist 00090 def _check_contaminated(package, license, manifests): 00091 depslist = roslib.rospack.rospackexec(['deps', package]) 00092 blame = [] 00093 for dep in [d for d in depslist.split('\n') if d]: 00094 m = manifests[dep] 00095 dl = m.license or 'unknown' 00096 dl = dl.lower() 00097 if dl not in bsdstyle: #anything we don't whitelist is contaminated 00098 blame.append(dep) 00099 if 0: 00100 if dl in contaminated: 00101 blame.append(dep) 00102 elif not dl in bsdstyle: 00103 if not dl in _already_unknown: 00104 print "UNKNOWN", dl 00105 _already_unknown.append(dl) 00106 if blame: 00107 return license + contam_suffix, blame 00108 else: 00109 return license, blame 00110 00111 ## build up map of packages by license 00112 ## @return license_map, blame_list: {license: [packages]}, {package: package} 00113 def _generate_licenses_map(ctx): 00114 blamelist = {} 00115 licenses = {} 00116 licenses['unknown'] = [] 00117 00118 manifests = ctx.manifests 00119 00120 for package in ctx.doc_packages: 00121 00122 if not package in manifests: 00123 licenses['unknown'].append(package) 00124 continue 00125 00126 manifest = manifests[package] 00127 license = manifest.license or 'unknown' 00128 license = canonicalize.get(license, license) 00129 # reduce pesky 'licenses' that are just long copyright statements 00130 if 'Copyright' in license: 00131 license = 'unknown' 00132 license_url = manifest.license_url 00133 if license_url and not license in license_urls: 00134 license_urls[license.lower()] = license_url 00135 if license.lower() in bsdstyle: 00136 license, blame = _check_contaminated(package, license, manifests) 00137 if blame: 00138 blamelist[package] = blame 00139 if license in licenses: 00140 licenses[license].append(package) 00141 else: 00142 licenses[license] = [package] 00143 return licenses, blamelist 00144 00145 ################################################################################ 00146 # HTML Generation 00147 00148 ## @param packages [str]: list of packages to generate 'li' html links to 00149 def li_license_links(packages, blamelist, docdir): 00150 list = [] 00151 for p in packages: 00152 path = html_path(p, docdir) 00153 blame = blamelist.get(p, None) 00154 blamestr = ': (%s)'%(', '.join(blame)) if blame else '' 00155 list.append(' <li><a href="%s/index.html">%s</a>%s</li>'%(path, p, blamestr)) 00156 return '<ul>\n'+'\n'.join(list)+'</ul>\n' 00157 00158 00159 ## Generate index of packages by license 00160 def generate_license_index(ctx): 00161 docdir = ctx.docdir 00162 license_index = os.path.join(docdir, 'licenses.html') 00163 00164 licenses, blamelist = _generate_licenses_map(ctx) 00165 00166 buff = cStringIO.StringIO() 00167 keys = licenses.keys() 00168 keys.sort() 00169 00170 strs = ['<a href="#%s">%s</a> (%s)'%(k, k, len(licenses[k])) for k in keys if licenses[k]] 00171 contents = ', '.join(strs) 00172 00173 for license in keys: 00174 list = licenses[license] 00175 if not list: 00176 continue 00177 #license_urls breaks in our current way of overloading the 00178 #name to mark contaminated 00179 00180 real_license = license[:-len(contam_suffix)] if license.endswith(contam_suffix) else license 00181 real_license = real_license.lower() 00182 if real_license in license_urls: 00183 buff.write('<h3><a name="%s"></a><a href="%s">%s</a></h2>\n'%\ 00184 (license, license_urls[real_license], license)) 00185 else: 00186 buff.write('<h3><a name="%s"></a>%s</h2>\n'%(license, license)) 00187 list.sort() 00188 buff.write(li_license_links(list, blamelist, docdir)) 00189 00190 vars = {'$name': ctx.name, '$licenselist' : buff.getvalue(), 00191 '$date': time.strftime("%a, %d %b %Y %H:%M:%S"), '$toc': contents } 00192 with open(license_index, 'w') as f: 00193 f.write(instantiate_template(license_template, vars)) 00194 return [license_index]