1 # Copyright 1999-2009 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
7 from itertools import chain
9 from portage.dep import paren_reduce, use_reduce, \
10 paren_normalize, paren_enclose
11 from _emerge.Task import Task
13 if sys.hexversion >= 0x3000000:
19 __hash__ = Task.__hash__
20 __slots__ = ("built", "cpv", "depth",
21 "installed", "metadata", "onlydeps", "operation",
22 "root_config", "type_name",
23 "category", "counter", "cp", "cpv_split",
24 "inherited", "invalid", "iuse", "mtime",
25 "pf", "pv_split", "root", "slot", "slot_atom",) + \
29 "CHOST", "COUNTER", "DEPEND", "EAPI",
30 "INHERITED", "IUSE", "KEYWORDS",
31 "LICENSE", "PDEPEND", "PROVIDE", "RDEPEND",
32 "repository", "PROPERTIES", "RESTRICT", "SLOT", "USE", "_mtime_"]
34 def __init__(self, **kwargs):
35 Task.__init__(self, **kwargs)
36 self.root = self.root_config.root
37 self.metadata = _PackageMetadataWrapper(self, self.metadata)
39 self.metadata['CHOST'] = self.root_config.settings.get('CHOST', '')
40 self.cp = portage.cpv_getkey(self.cpv)
43 # Avoid an InvalidAtom exception when creating slot_atom.
44 # This package instance will be masked due to empty SLOT.
46 self.slot_atom = portage.dep.Atom("%s:%s" % (self.cp, slot))
47 self.category, self.pf = portage.catsplit(self.cpv)
48 self.cpv_split = portage.catpkgsplit(self.cpv)
49 self.pv_split = self.cpv_split[1:]
51 def _invalid_metadata(self, msg_type, msg):
52 if self.invalid is None:
54 msgs = self.invalid.get(msg_type)
57 self.invalid[msg_type] = msgs
60 class _use_class(object):
62 __slots__ = ("__weakref__", "enabled")
64 def __init__(self, use):
65 self.enabled = frozenset(use)
70 self._use = self._use_class(self.metadata['USE'].split())
75 __slots__ = ("__weakref__", "all", "enabled", "disabled",
76 "iuse_implicit", "tokens") + \
79 def __init__(self, tokens, iuse_implicit):
80 self.tokens = tuple(tokens)
81 self.iuse_implicit = iuse_implicit
90 disabled.append(x[1:])
93 self.enabled = frozenset(enabled)
94 self.disabled = frozenset(disabled)
95 self.all = frozenset(chain(enabled, disabled, other))
100 @returns: A regular expression that matches valid USE values which
101 may be specified in USE dependencies.
105 except AttributeError:
106 # Escape anything except ".*" which is supposed
107 # to pass through from _get_implicit_iuse()
108 regex = (re.escape(x) for x in \
109 chain(self.all, self.iuse_implicit))
110 regex = "^(%s)$" % "|".join(regex)
111 regex = re.compile(regex.replace("\\.\\*", ".*"))
115 def _get_hash_key(self):
116 hash_key = getattr(self, "_hash_key", None)
118 if self.operation is None:
119 self.operation = "merge"
120 if self.onlydeps or self.installed:
121 self.operation = "nomerge"
123 (self.type_name, self.root, self.cpv, self.operation)
124 return self._hash_key
126 def __lt__(self, other):
127 if other.cp != self.cp:
129 if portage.pkgcmp(self.pv_split, other.pv_split) < 0:
133 def __le__(self, other):
134 if other.cp != self.cp:
136 if portage.pkgcmp(self.pv_split, other.pv_split) <= 0:
140 def __gt__(self, other):
141 if other.cp != self.cp:
143 if portage.pkgcmp(self.pv_split, other.pv_split) > 0:
147 def __ge__(self, other):
148 if other.cp != self.cp:
150 if portage.pkgcmp(self.pv_split, other.pv_split) >= 0:
154 _all_metadata_keys = set(x for x in portage.auxdbkeys \
155 if not x.startswith("UNUSED_"))
156 _all_metadata_keys.update(Package.metadata_keys)
157 _all_metadata_keys = frozenset(_all_metadata_keys)
159 class _PackageMetadataWrapper(dict):
161 Detect metadata updates and synchronize Package attributes.
164 __slots__ = ("_pkg",)
165 _use_conditional_keys = frozenset(
166 ['LICENSE', 'PROPERTIES', 'PROVIDE', 'RESTRICT',])
168 def __init__(self, pkg, metadata):
171 # USE is lazy, but we want it to show up in self.keys().
173 self.update(metadata)
174 for k, v in self.items():
176 if isinstance(v, basestring):
177 v = frozenset(v.split())
178 self._pkg.inherited = v
182 self._pkg.iuse = self._pkg._iuse(
183 v.split(), self._pkg.root_config.iuse_implicit)
185 if isinstance(v, basestring):
190 self['COUNTER'] = str(v)
191 self._pkg.counter = v
193 if isinstance(v, basestring):
199 elif k in self._use_conditional_keys:
201 use_reduce(paren_reduce(v), matchall=1)
202 except portage.exception.InvalidDependString as e:
203 self._pkg._invalid_metadata(k + ".syntax", "%s: %s" % (k, e))
205 def __getitem__(self, k):
206 v = dict.__getitem__(self, k)
207 if k in self._use_conditional_keys:
208 if self._pkg.root_config.settings.local_config and '?' in v:
210 v = paren_enclose(paren_normalize(use_reduce(
211 paren_reduce(v), uselist=self._pkg.use.enabled)))
212 except portage.exception.InvalidDependString:
213 # This error should already have been registered via
214 # self._pkg._invalid_metadata().
219 elif k == 'USE' and not self._pkg.built:
221 # This is lazy because it's expensive.
222 pkgsettings = self._pkg.root_config.trees[
223 'porttree'].dbapi.doebuild_settings
224 pkgsettings.setcpv(self._pkg)
225 v = pkgsettings["PORTAGE_USE"]
231 def properties(self):
232 return self['PROPERTIES'].split()
236 return self['RESTRICT'].split()