Package portage :: Package package :: Package ebuild :: Package _config :: Module LicenseManager
[hide private]

Source Code for Module portage.package.ebuild._config.LicenseManager

  1  # Copyright 201-2012 Gentoo Foundation 
  2  # Distributed under the terms of the GNU General Public License v2 
  3   
  4  __all__ = ( 
  5          'LicenseManager', 
  6  ) 
  7   
  8  from portage import os 
  9  from portage.dep import ExtendedAtomDict, use_reduce 
 10  from portage.exception import InvalidDependString 
 11  from portage.localization import _ 
 12  from portage.util import grabdict, grabdict_package, writemsg 
 13  from portage.versions import cpv_getkey, _pkg_str 
 14   
 15  from portage.package.ebuild._config.helper import ordered_by_atom_specificity 
 16   
 17   
18 -class LicenseManager(object):
19
20 - def __init__(self, license_group_locations, abs_user_config, user_config=True):
21 22 self._accept_license_str = None 23 self._accept_license = None 24 self._license_groups = {} 25 self._plicensedict = ExtendedAtomDict(dict) 26 self._undef_lic_groups = set() 27 28 if user_config: 29 license_group_locations = list(license_group_locations) + [abs_user_config] 30 31 self._read_license_groups(license_group_locations) 32 33 if user_config: 34 self._read_user_config(abs_user_config)
35
36 - def _read_user_config(self, abs_user_config):
37 licdict = grabdict_package(os.path.join( 38 abs_user_config, "package.license"), recursive=1, allow_wildcard=True, allow_repo=True, verify_eapi=False) 39 for k, v in licdict.items(): 40 self._plicensedict.setdefault(k.cp, {})[k] = \ 41 self.expandLicenseTokens(v)
42
43 - def _read_license_groups(self, locations):
44 for loc in locations: 45 for k, v in grabdict( 46 os.path.join(loc, "license_groups")).items(): 47 self._license_groups.setdefault(k, []).extend(v) 48 49 for k, v in self._license_groups.items(): 50 self._license_groups[k] = frozenset(v)
51
52 - def extract_global_changes(self, old=""):
53 ret = old 54 atom_license_map = self._plicensedict.get("*/*") 55 if atom_license_map is not None: 56 v = atom_license_map.pop("*/*", None) 57 if v is not None: 58 ret = " ".join(v) 59 if old: 60 ret = old + " " + ret 61 if not atom_license_map: 62 #No tokens left in atom_license_map, remove it. 63 del self._plicensedict["*/*"] 64 return ret
65
66 - def expandLicenseTokens(self, tokens):
67 """ Take a token from ACCEPT_LICENSE or package.license and expand it 68 if it's a group token (indicated by @) or just return it if it's not a 69 group. If a group is negated then negate all group elements.""" 70 expanded_tokens = [] 71 for x in tokens: 72 expanded_tokens.extend(self._expandLicenseToken(x, None)) 73 return expanded_tokens
74
75 - def _expandLicenseToken(self, token, traversed_groups):
76 negate = False 77 rValue = [] 78 if token.startswith("-"): 79 negate = True 80 license_name = token[1:] 81 else: 82 license_name = token 83 if not license_name.startswith("@"): 84 rValue.append(token) 85 return rValue 86 group_name = license_name[1:] 87 if traversed_groups is None: 88 traversed_groups = set() 89 license_group = self._license_groups.get(group_name) 90 if group_name in traversed_groups: 91 writemsg(_("Circular license group reference" 92 " detected in '%s'\n") % group_name, noiselevel=-1) 93 rValue.append("@"+group_name) 94 elif license_group: 95 traversed_groups.add(group_name) 96 for l in license_group: 97 if l.startswith("-"): 98 writemsg(_("Skipping invalid element %s" 99 " in license group '%s'\n") % (l, group_name), 100 noiselevel=-1) 101 else: 102 rValue.extend(self._expandLicenseToken(l, traversed_groups)) 103 else: 104 if self._license_groups and \ 105 group_name not in self._undef_lic_groups: 106 self._undef_lic_groups.add(group_name) 107 writemsg(_("Undefined license group '%s'\n") % group_name, 108 noiselevel=-1) 109 rValue.append("@"+group_name) 110 if negate: 111 rValue = ["-" + token for token in rValue] 112 return rValue
113
114 - def _getPkgAcceptLicense(self, cpv, slot, repo):
115 """ 116 Get an ACCEPT_LICENSE list, accounting for package.license. 117 """ 118 accept_license = self._accept_license 119 cp = cpv_getkey(cpv) 120 cpdict = self._plicensedict.get(cp) 121 if cpdict: 122 if not hasattr(cpv, slot): 123 cpv = _pkg_str(cpv, slot=slot, repo=repo) 124 plicence_list = ordered_by_atom_specificity(cpdict, cpv) 125 if plicence_list: 126 accept_license = list(self._accept_license) 127 for x in plicence_list: 128 accept_license.extend(x) 129 return accept_license
130
131 - def get_prunned_accept_license(self, cpv, use, lic, slot, repo):
132 """ 133 Generate a pruned version of ACCEPT_LICENSE, by intersection with 134 LICENSE. This is required since otherwise ACCEPT_LICENSE might be 135 too big (bigger than ARG_MAX), causing execve() calls to fail with 136 E2BIG errors as in bug #262647. 137 """ 138 try: 139 licenses = set(use_reduce(lic, uselist=use, flat=True)) 140 except InvalidDependString: 141 licenses = set() 142 licenses.discard('||') 143 144 accept_license = self._getPkgAcceptLicense(cpv, slot, repo) 145 146 if accept_license: 147 acceptable_licenses = set() 148 for x in accept_license: 149 if x == '*': 150 acceptable_licenses.update(licenses) 151 elif x == '-*': 152 acceptable_licenses.clear() 153 elif x[:1] == '-': 154 acceptable_licenses.discard(x[1:]) 155 elif x in licenses: 156 acceptable_licenses.add(x) 157 158 licenses = acceptable_licenses 159 return ' '.join(sorted(licenses))
160
161 - def getMissingLicenses(self, cpv, use, lic, slot, repo):
162 """ 163 Take a LICENSE string and return a list of any licenses that the user 164 may need to accept for the given package. The returned list will not 165 contain any licenses that have already been accepted. This method 166 can throw an InvalidDependString exception. 167 168 @param cpv: The package name (for package.license support) 169 @type cpv: String 170 @param use: "USE" from the cpv's metadata 171 @type use: String 172 @param lic: "LICENSE" from the cpv's metadata 173 @type lic: String 174 @param slot: "SLOT" from the cpv's metadata 175 @type slot: String 176 @rtype: List 177 @return: A list of licenses that have not been accepted. 178 """ 179 180 licenses = set(use_reduce(lic, matchall=1, flat=True)) 181 licenses.discard('||') 182 183 acceptable_licenses = set() 184 for x in self._getPkgAcceptLicense(cpv, slot, repo): 185 if x == '*': 186 acceptable_licenses.update(licenses) 187 elif x == '-*': 188 acceptable_licenses.clear() 189 elif x[:1] == '-': 190 acceptable_licenses.discard(x[1:]) 191 else: 192 acceptable_licenses.add(x) 193 194 license_str = lic 195 if "?" in license_str: 196 use = use.split() 197 else: 198 use = [] 199 200 license_struct = use_reduce(license_str, uselist=use, opconvert=True) 201 return self._getMaskedLicenses(license_struct, acceptable_licenses)
202
203 - def _getMaskedLicenses(self, license_struct, acceptable_licenses):
204 if not license_struct: 205 return [] 206 if license_struct[0] == "||": 207 ret = [] 208 for element in license_struct[1:]: 209 if isinstance(element, list): 210 if element: 211 tmp = self._getMaskedLicenses(element, acceptable_licenses) 212 if not tmp: 213 return [] 214 ret.extend(tmp) 215 else: 216 if element in acceptable_licenses: 217 return [] 218 ret.append(element) 219 # Return all masked licenses, since we don't know which combination 220 # (if any) the user will decide to unmask. 221 return ret 222 223 ret = [] 224 for element in license_struct: 225 if isinstance(element, list): 226 if element: 227 ret.extend(self._getMaskedLicenses(element, 228 acceptable_licenses)) 229 else: 230 if element not in acceptable_licenses: 231 ret.append(element) 232 return ret
233
234 - def set_accept_license_str(self, accept_license_str):
235 if accept_license_str != self._accept_license_str: 236 self._accept_license_str = accept_license_str 237 self._accept_license = tuple(self.expandLicenseTokens(accept_license_str.split()))
238