* Make Package.metadata['USE'] access trigger USE calculation for unbuilt
authorZac Medico <zmedico@gentoo.org>
Thu, 25 Jun 2009 00:33:47 +0000 (00:33 -0000)
committerZac Medico <zmedico@gentoo.org>
Thu, 25 Jun 2009 00:33:47 +0000 (00:33 -0000)
  ebuilds.
* Make Package.metadata['LICENSE'] access trigger USE conditional evaluation.
* Make Package.metadata['PROVIDE'] access trigger USE conditional evaluation.
* Initialize Package.metadata['CHOST'] in the Package constructor for
  unbuilt ebuilds.

svn path=/main/trunk/; revision=13686

pym/_emerge/Package.py
pym/_emerge/Scheduler.py
pym/_emerge/depgraph.py

index 4a40bf950b715479ce369c654bcf4bf454b34cc9..502bb7c84b56e1f3231b604e6c331d135adb375d 100644 (file)
@@ -10,7 +10,8 @@ except ImportError:
        import portage
 
 from portage.cache.mappings import slot_dict_class
-
+from portage.dep import paren_reduce, use_reduce, \
+       paren_normalize, paren_enclose
 from _emerge.Task import Task
 
 class Package(Task):
@@ -21,7 +22,8 @@ class Package(Task):
                "root_config", "type_name",
                "category", "counter", "cp", "cpv_split",
                "inherited", "iuse", "mtime",
-               "pf", "pv_split", "root", "slot", "slot_atom", "use")
+               "pf", "pv_split", "root", "slot", "slot_atom",) + \
+       ("_use",)
 
        metadata_keys = [
                "CHOST", "COUNTER", "DEPEND", "EAPI",
@@ -33,6 +35,8 @@ class Package(Task):
                Task.__init__(self, **kwargs)
                self.root = self.root_config.root
                self.metadata = _PackageMetadataWrapper(self, self.metadata)
+               if not self.built:
+                       self.metadata['CHOST'] = self.root_config.settings.get('CHOST', '')
                self.cp = portage.cpv_getkey(self.cpv)
                slot = self.slot
                if not slot:
@@ -44,13 +48,19 @@ class Package(Task):
                self.cpv_split = portage.catpkgsplit(self.cpv)
                self.pv_split = self.cpv_split[1:]
 
-       class _use(object):
+       class _use_class(object):
 
                __slots__ = ("__weakref__", "enabled")
 
                def __init__(self, use):
                        self.enabled = frozenset(use)
 
+       @property
+       def use(self):
+               if self._use is None:
+                       self._use = self._use_class(self.metadata['USE'].split())
+               return self._use
+
        class _iuse(object):
 
                __slots__ = ("__weakref__", "all", "enabled", "disabled", "iuse_implicit", "regex", "tokens")
@@ -141,13 +151,38 @@ class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
 
        __slots__ = ("_pkg",)
        _wrapped_keys = frozenset(
-               ["COUNTER", "INHERITED", "IUSE", "SLOT", "USE", "_mtime_"])
+               ["COUNTER", "INHERITED", "IUSE", "SLOT", "_mtime_"])
 
        def __init__(self, pkg, metadata):
                _PackageMetadataWrapperBase.__init__(self)
                self._pkg = pkg
+               """LICENSE with USE conditionals evaluated."""
+
+               if not pkg.built:
+                       # USE is lazy, but we want it to show up in self.keys().
+                       self['USE'] = ''
+
                self.update(metadata)
 
+       def __getitem__(self, k):
+               v = _PackageMetadataWrapperBase.__getitem__(self, k)
+               if k in ('PROVIDE', 'LICENSE',):
+                       if '?' in v:
+                               v = paren_enclose(paren_normalize(use_reduce(
+                                       paren_reduce(v), uselist=self._pkg.use.enabled)))
+                               self[k] = v
+
+               elif k == 'USE' and not self._pkg.built:
+                       if not v:
+                               # This is lazy because it's expensive.
+                               pkgsettings = self._pkg.root_config.trees[
+                                       'porttree'].dbapi.doebuild_settings
+                               pkgsettings.setcpv(self._pkg)
+                               v = pkgsettings["PORTAGE_USE"]
+                               self['USE'] = v
+
+               return v
+
        def __setitem__(self, k, v):
                _PackageMetadataWrapperBase.__setitem__(self, k, v)
                if k in self._wrapped_keys:
@@ -165,9 +200,6 @@ class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
        def _set_slot(self, k, v):
                self._pkg.slot = v
 
-       def _set_use(self, k, v):
-               self._pkg.use = self._pkg._use(v.split())
-
        def _set_counter(self, k, v):
                if isinstance(v, basestring):
                        try:
index f70cdd31202fa39dec58a671b66773dd47532677..d3a31c4c698e9dd35aa65fabf4e5763b5773163a 100644 (file)
@@ -1625,12 +1625,6 @@ class Scheduler(PollScheduler):
                db_keys = list(self.trees[root_config.root][
                        tree_type].dbapi._aux_cache_keys)
                metadata = izip(db_keys, db.aux_get(cpv, db_keys))
-               pkg = Package(cpv=cpv, metadata=metadata,
+               return Package(built=(type_name != 'ebuild'),
+                       cpv=cpv, metadata=metadata,
                        root_config=root_config, installed=installed)
-               if type_name == "ebuild":
-                       settings = self.pkgsettings[root_config.root]
-                       settings.setcpv(pkg)
-                       pkg.metadata["USE"] = settings["PORTAGE_USE"]
-                       pkg.metadata['CHOST'] = settings.get('CHOST', '')
-
-               return pkg
index b773a27594d9fa77efa473df092d60c298fd730a..af352fd5d9f514835107ce3f96c1e69eda19d69d 100644 (file)
@@ -1147,9 +1147,6 @@ class depgraph(object):
                                metadata = izip(db_keys, portdb.aux_get(mykey, db_keys))
                                pkg = Package(type_name="ebuild", root_config=root_config,
                                        cpv=mykey, metadata=metadata, onlydeps=onlydeps)
-                               pkgsettings.setcpv(pkg)
-                               pkg.metadata["USE"] = pkgsettings["PORTAGE_USE"]
-                               pkg.metadata['CHOST'] = pkgsettings.get('CHOST', '')
                                self._pkg_cache[pkg] = pkg
                                args.append(PackageArg(arg=x, package=pkg,
                                        root_config=root_config))
@@ -1893,10 +1890,8 @@ class depgraph(object):
                                                continue
                                        reinstall_for_flags = None
                                        cache_key = (pkg_type, root, cpv, pkg_status)
-                                       calculated_use = True
                                        pkg = self._pkg_cache.get(cache_key)
                                        if pkg is None:
-                                               calculated_use = False
                                                try:
                                                        metadata = izip(db_keys, db.aux_get(cpv, db_keys))
                                                except KeyError:
@@ -1908,14 +1903,6 @@ class depgraph(object):
                                                metadata = pkg.metadata
                                                if not built:
                                                        metadata['CHOST'] = pkgsettings.get('CHOST', '')
-                                               if not built and ("?" in metadata["LICENSE"] or \
-                                                       "?" in metadata["PROVIDE"]):
-                                                       # This is avoided whenever possible because
-                                                       # it's expensive. It only needs to be done here
-                                                       # if it has an effect on visibility.
-                                                       pkgsettings.setcpv(pkg)
-                                                       metadata["USE"] = pkgsettings["PORTAGE_USE"]
-                                                       calculated_use = True
                                                self._pkg_cache[pkg] = pkg
 
                                        if not installed or (built and matched_packages):
@@ -1967,11 +1954,9 @@ class depgraph(object):
                                                                                if not visible(pkgsettings, pkg_eb):
                                                                                        continue
 
-                                       if not pkg.built and not calculated_use:
-                                               # This is avoided whenever possible because
-                                               # it's expensive.
-                                               pkgsettings.setcpv(pkg)
-                                               pkg.metadata["USE"] = pkgsettings["PORTAGE_USE"]
+                                       # Calculation of USE for unbuilt ebuilds is relatively
+                                       # expensive, so it is only performed lazily, after the
+                                       # above visibility checks are complete.
 
                                        if pkg.cp != atom.cp:
                                                # A cpv can be returned from dbapi.match() as an
@@ -1984,8 +1969,6 @@ class depgraph(object):
                                        myarg = None
                                        if root == self.target_root:
                                                try:
-                                                       # Ebuild USE must have been calculated prior
-                                                       # to this point, in case atoms have USE deps.
                                                        myarg = self._iter_atoms_for_pkg(pkg).next()
                                                except StopIteration:
                                                        pass
@@ -2235,13 +2218,9 @@ class depgraph(object):
                                metadata = izip(db_keys, db.aux_get(cpv, db_keys))
                        except KeyError:
                                raise portage.exception.PackageNotFound(cpv)
-                       pkg = Package(cpv=cpv, metadata=metadata,
+                       pkg = Package(built=(type_name != "ebuild"), cpv=cpv,
+                               metadata=metadata,
                                root_config=root_config, installed=installed)
-                       if type_name == "ebuild":
-                               settings = self.pkgsettings[root_config.root]
-                               settings.setcpv(pkg)
-                               pkg.metadata["USE"] = settings["PORTAGE_USE"]
-                               pkg.metadata['CHOST'] = settings.get('CHOST', '')
                        self._pkg_cache[pkg] = pkg
                return pkg
 
@@ -4381,11 +4360,6 @@ class depgraph(object):
                                installed=installed, metadata=metadata,
                                operation=action, root_config=root_config,
                                type_name=pkg_type)
-                       if pkg_type == "ebuild":
-                               pkgsettings = self.pkgsettings[myroot]
-                               pkgsettings.setcpv(pkg)
-                               pkg.metadata["USE"] = pkgsettings["PORTAGE_USE"]
-                               pkg.metadata['CHOST'] = pkgsettings.get('CHOST', '')
                        self._pkg_cache[pkg] = pkg
 
                        root_config = self.roots[pkg.root]
@@ -4827,10 +4801,7 @@ def get_mask_info(root_config, cpv, pkgsettings,
                        db.aux_get(cpv, db_keys)))
        except KeyError:
                metadata = None
-       if metadata and not built:
-               pkgsettings.setcpv(cpv, mydb=metadata)
-               metadata["USE"] = pkgsettings["PORTAGE_USE"]
-               metadata['CHOST'] = pkgsettings.get('CHOST', '')
+
        if metadata is None:
                mreasons = ["corruption"]
        else: