Merged from trunk -r14274:14284
authorFabian Groffen <grobian@gentoo.org>
Mon, 21 Sep 2009 17:02:37 +0000 (17:02 -0000)
committerFabian Groffen <grobian@gentoo.org>
Mon, 21 Sep 2009 17:02:37 +0000 (17:02 -0000)
   | 14279   | Atom optimizations. Remove the metaclass and cache since it  |
   | zmedico | just slows it down. Thanks to Marat Radchenko                |
   |         | <marat@slonopotamus.org> for this patch.                     |

   | 14280   | Use a dict for Package.metadata, because it's faster. Thanks |
   | zmedico | to Marat Radchenko <marat@slonopotamus.org> for this patch   |
   |         | from bug #276813.                                            |

   | 14281   | Fix _expand_new_virtuals() to preserve USE deps in atoms for |
   | zmedico | new-style virtuals, and update the corresponding depgraph    |
   |         | code.                                                        |

   | 14282   | Avoid lots of redundant Atom constructor calls. Thanks to    |
   | zmedico | Marat Radchenko <marat@slonopotamus.org> for the initial     |
   |         | patch from bug #276813.                                      |

   | 14283   | Remove obsolete InvalidAtom handler in                       |
   | zmedico | _add_pkg_dep_string().                                       |

   | 14284   | Revert accidental changes                                    |
   | zmedico | _unicode_module_wrapper.__getattribute__ from previous       |
   |         | commit.                                                      |

svn path=/main/branches/prefix/; revision=14332

pym/_emerge/Blocker.py
pym/_emerge/FakeVartree.py
pym/_emerge/Package.py
pym/_emerge/actions.py
pym/_emerge/depgraph.py
pym/portage/__init__.py
pym/portage/dbapi/porttree.py
pym/portage/dep.py
pym/portage/sets/base.py

index ea93d6b8a43b813a625466a7248caebc64ad1600..fcebb8b37d53603faf7817ad47a87a8276ef27ce 100644 (file)
@@ -18,7 +18,7 @@ class Blocker(Task):
 
        def __init__(self, **kwargs):
                Task.__init__(self, **kwargs)
-               self.cp = portage.dep_getkey(self.atom)
+               self.cp = self.atom.cp
 
        def _get_hash_key(self):
                hash_key = getattr(self, "_hash_key", None)
index 25bed29056de91d2f1c1aedf3545df0526fd7c34..e895cc86bde378f4be9bc278586f084d23a40cdf 100644 (file)
@@ -76,8 +76,7 @@ class FakeVartree(portage.vartree):
                                portage.locks.unlockdir(vdb_lock)
                # Populate the old-style virtuals using the cached values.
                if not self.settings.treeVirtuals:
-                       self.settings.treeVirtuals = portage.util.map_dictlist_vals(
-                               portage.getCPFromCPV, self.get_all_provides())
+                       self.settings._populate_treeVirtuals(self)
 
                # Intialize variables needed for lazy cache pulls of the live ebuild
                # metadata.  This ensures that the vardb lock is released ASAP, without
index 6371f5d0512c8756dd7ee495bf355b85cd308fea..14570d1aea1423b5b15880928152d74382b53f3c 100644 (file)
@@ -5,7 +5,6 @@
 import re
 from itertools import chain
 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
@@ -152,33 +151,56 @@ _all_metadata_keys = set(x for x in portage.auxdbkeys \
        if not x.startswith("UNUSED_"))
 _all_metadata_keys.discard("CDEPEND")
 _all_metadata_keys.update(Package.metadata_keys)
+_all_metadata_keys = frozenset(_all_metadata_keys)
 
-_PackageMetadataWrapperBase = slot_dict_class(_all_metadata_keys)
-
-class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
+class _PackageMetadataWrapper(dict):
        """
        Detect metadata updates and synchronize Package attributes.
        """
 
        __slots__ = ("_pkg",)
-       _wrapped_keys = frozenset(
-               ["COUNTER", "INHERITED", "IUSE", "SLOT", "_mtime_"])
        _use_conditional_keys = frozenset(
                ['LICENSE', 'PROPERTIES', 'PROVIDE', 'RESTRICT',])
 
        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)
+               for k, v in self.iteritems():
+                       if k == 'INHERITED':
+                               if isinstance(v, basestring):
+                                       v = frozenset(v.split())
+                               self._pkg.inherited = v
+                       elif k == 'SLOT':
+                               self._pkg.slot = v
+                       elif k == 'IUSE':
+                               self._pkg.iuse = self._pkg._iuse(
+                                       v.split(), self._pkg.root_config.iuse_implicit)
+                       elif k == 'COUNTER':
+                               if isinstance(v, basestring):
+                                       try:
+                                               v = long(v.strip())
+                                       except ValueError:
+                                               v = 0
+                                               self['COUNTER'] = str(v)
+                               self._pkg.counter = v
+                       elif k == '_mtime_':
+                               if isinstance(v, basestring):
+                                       try:
+                                               v = long(v.strip())
+                                       except ValueError:
+                                               v = 0
+                               self._pkg.mtime = v
+                       elif k in self._use_conditional_keys:
+                               try:
+                                       use_reduce(paren_reduce(v), matchall=1)
+                               except portage.exception.InvalidDependString, e:
+                                       self._pkg._invalid_metadata(k + ".syntax", "%s: %s" % (k, e))
 
        def __getitem__(self, k):
-               v = _PackageMetadataWrapperBase.__getitem__(self, k)
+               v = dict.__getitem__(self, k)
                if k in self._use_conditional_keys:
                        if self._pkg.root_config.settings.local_config and '?' in v:
                                try:
@@ -202,44 +224,6 @@ class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
 
                return v
 
-       def __setitem__(self, k, v):
-               _PackageMetadataWrapperBase.__setitem__(self, k, v)
-               if k in self._wrapped_keys:
-                       getattr(self, "_set_" + k.lower())(k, v)
-               elif k in self._use_conditional_keys:
-                       try:
-                               use_reduce(paren_reduce(v), matchall=1)
-                       except portage.exception.InvalidDependString, e:
-                               self._pkg._invalid_metadata(k + ".syntax", "%s: %s" % (k, e))
-
-       def _set_inherited(self, k, v):
-               if isinstance(v, basestring):
-                       v = frozenset(v.split())
-               self._pkg.inherited = v
-
-       def _set_iuse(self, k, v):
-               self._pkg.iuse = self._pkg._iuse(
-                       v.split(), self._pkg.root_config.iuse_implicit)
-
-       def _set_slot(self, k, v):
-               self._pkg.slot = v
-
-       def _set_counter(self, k, v):
-               if isinstance(v, basestring):
-                       try:
-                               v = long(v.strip())
-                       except ValueError:
-                               v = 0
-               self._pkg.counter = v
-
-       def _set__mtime_(self, k, v):
-               if isinstance(v, basestring):
-                       try:
-                               v = long(v.strip())
-                       except ValueError:
-                               v = 0
-               self._pkg.mtime = v
-
        @property
        def properties(self):
                return self['PROPERTIES'].split()
index 10d6577194d16e6240935ed802a2a8afd799d2bb..8dff6c5bb9cf0d4b7834be8093aaceb8f8ad30d8 100644 (file)
@@ -2677,8 +2677,7 @@ def display_news_notification(root_config, myopts):
        if not settings.treeVirtuals:
                # Populate these using our existing vartree, to avoid
                # having a temporary one instantiated.
-               settings.treeVirtuals = portage.util.map_dictlist_vals(
-                       portage.getCPFromCPV, trees["vartree"].get_all_provides())
+               settings._populate_treeVirtuals(trees["vartree"])
 
        for repo in portdb.getRepositories():
                unreadItems = checkUpdatedNewsItems(
index ad3e2d06e3116c55f35425f8fddc7740e51ce4b2..df54f2e0d4d50c434507df8612e2d585c9ab5966 100644 (file)
@@ -1148,26 +1148,16 @@ class depgraph(object):
                vardb = self._frozen_config.roots[dep_root].trees["vartree"].dbapi
 
                for atom in selected_atoms[pkg]:
-                       try:
-
-                               atom = portage.dep.Atom(atom)
-
-                               mypriority = dep_priority.copy()
-                               if not atom.blocker and vardb.match(atom):
-                                       mypriority.satisfied = True
 
-                               if not self._add_dep(Dependency(atom=atom,
-                                       blocker=atom.blocker, depth=depth, parent=pkg,
-                                       priority=mypriority, root=dep_root),
-                                       allow_unsatisfied=allow_unsatisfied):
-                                       return 0
+                       mypriority = dep_priority.copy()
+                       if not atom.blocker and vardb.match(atom):
+                               mypriority.satisfied = True
 
-                       except portage.exception.InvalidAtom, e:
-                               show_invalid_depstring_notice(
-                                       pkg, dep_string, str(e))
-                               del e
-                               if not pkg.installed:
-                                       return 0
+                       if not self._add_dep(Dependency(atom=atom,
+                               blocker=atom.blocker, depth=depth, parent=pkg,
+                               priority=mypriority, root=dep_root),
+                               allow_unsatisfied=allow_unsatisfied):
+                               return 0
 
                selected_atoms.pop(pkg)
 
@@ -1306,16 +1296,15 @@ class depgraph(object):
                atom_arg_map = self._dynamic_config._atom_arg_map
                root_config = self._frozen_config.roots[pkg.root]
                for atom in self._dynamic_config._set_atoms.iterAtomsForPackage(pkg):
-                       atom_cp = portage.dep_getkey(atom)
-                       if atom_cp != pkg.cp and \
-                               self._have_new_virt(pkg.root, atom_cp):
+                       if atom.cp != pkg.cp and \
+                               self._have_new_virt(pkg.root, atom.cp):
                                continue
                        visible_pkgs = \
                                self._dynamic_config._visible_pkgs[pkg.root].match_pkgs(atom)
                        visible_pkgs.reverse() # descending order
                        higher_slot = None
                        for visible_pkg in visible_pkgs:
-                               if visible_pkg.cp != atom_cp:
+                               if visible_pkg.cp != atom.cp:
                                        continue
                                if pkg >= visible_pkg:
                                        # This is descending order, and we're not
@@ -1606,9 +1595,8 @@ class depgraph(object):
                                self._spinner_update()
                                dep = Dependency(atom=atom, onlydeps=onlydeps,
                                        root=myroot, parent=arg)
-                               atom_cp = portage.dep_getkey(atom)
                                try:
-                                       pprovided = pprovideddict.get(portage.dep_getkey(atom))
+                                       pprovided = pprovideddict.get(atom.cp)
                                        if pprovided and portage.match_from_list(atom, pprovided):
                                                # A provided package has been specified on the command line.
                                                self._dynamic_config._pprovided_args.append((arg, atom))
@@ -1651,10 +1639,10 @@ class depgraph(object):
                                                        return 0, myfavorites
                                                self._dynamic_config._missing_args.append((arg, atom))
                                                continue
-                                       if atom_cp != pkg.cp:
+                                       if atom.cp != pkg.cp:
                                                # For old-style virtuals, we need to repeat the
                                                # package.provided check against the selected package.
-                                               expanded_atom = atom.replace(atom_cp, pkg.cp)
+                                               expanded_atom = atom.replace(atom.cp, pkg.cp)
                                                pprovided = pprovideddict.get(pkg.cp)
                                                if pprovided and \
                                                        portage.match_from_list(expanded_atom, pprovided):
@@ -1901,16 +1889,20 @@ class depgraph(object):
                        for node in atom_graph:
                                if isinstance(node, Atom):
                                        continue
-                               if node == parent.cpv:
+                               if node is parent:
                                        pkg = parent
                                else:
-                                       virt_atom = Atom('=' + node)
+                                       pkg, virt_atom = node
                                        if virt_atom not in chosen_atoms:
                                                continue
-                                       pkg, existing_node = self._select_package(
-                                               root, virt_atom)
-                                       if pkg is None:
-                                               raise AssertionError(node)
+                                       if not portage.match_from_list(virt_atom, [pkg]):
+                                               # Typically this means that the atom
+                                               # specifies USE deps that are unsatisfied
+                                               # by the selected package. The caller will
+                                               # record this as an unsatisfied dependency
+                                               # when necessary.
+                                               continue
+
                                selected_atoms[pkg] = [atom for atom in \
                                        atom_graph.child_nodes(node) if atom in chosen_atoms]
 
@@ -2392,7 +2384,7 @@ class depgraph(object):
 
                # Filter out any old-style virtual matches if they are
                # mixed with new-style virtual matches.
-               cp = portage.dep_getkey(atom)
+               cp = atom.cp
                if len(matched_packages) > 1 and \
                        "virtual" == portage.catsplit(cp)[0]:
                        for pkg in matched_packages:
@@ -2733,8 +2725,8 @@ class depgraph(object):
                                for provider_entry in virtuals[blocker.cp]:
                                        provider_cp = \
                                                portage.dep_getkey(provider_entry)
-                                       atoms.append(blocker.atom.replace(
-                                               blocker.cp, provider_cp))
+                                       atoms.append(Atom(blocker.atom.replace(
+                                               blocker.cp, provider_cp)))
                        else:
                                atoms = [blocker.atom]
 
@@ -4892,7 +4884,6 @@ class _dep_check_composite_db(portage.dbapi):
                        # any matching slots in the graph db.
                        slots = set()
                        slots.add(pkg.metadata["SLOT"])
-                       atom_cp = portage.dep_getkey(atom)
                        if pkg.cp.startswith("virtual/"):
                                # For new-style virtual lookahead that occurs inside
                                # dep_check(), examine all slots. This is needed
@@ -4913,7 +4904,7 @@ class _dep_check_composite_db(portage.dbapi):
                                ret.append(pkg.cpv)
                        slots.remove(pkg.metadata["SLOT"])
                        while slots:
-                               slot_atom = "%s:%s" % (atom_cp, slots.pop())
+                               slot_atom = Atom("%s:%s" % (atom.cp, slots.pop()))
                                pkg, existing = self._depgraph._select_package(
                                        self._root, slot_atom)
                                if not pkg:
@@ -5000,6 +4991,8 @@ class _dep_check_composite_db(portage.dbapi):
                metadata = self._cpv_pkg_map[cpv].metadata
                return [metadata.get(x, "") for x in wants]
 
+       def match_pkgs(self, atom):
+               return [self._cpv_pkg_map[cpv] for cpv in self.match(atom)]
 
 def ambiguous_package_name(arg, atoms, root_config, spinner, myopts):
 
index d6ca5aebd8646f1aa85428f56e4fa359aae72cc9..c9939c24ba273c654f28b303f6372027067d2daf 100644 (file)
@@ -3265,7 +3265,6 @@ class config(object):
                        # an incremental!
                        myincrementals.remove("USE")
 
-
                mydbs = self.configlist[:-1]
                mydbs.append(self.backupenv)
 
@@ -3512,12 +3511,21 @@ class config(object):
                if self.local_config and not self.treeVirtuals:
                        temp_vartree = vartree(myroot, None,
                                categories=self.categories, settings=self)
-                       # Reduce the provides into a list by CP.
-                       self.treeVirtuals = map_dictlist_vals(getCPFromCPV,temp_vartree.get_all_provides())
+                       self._populate_treeVirtuals(temp_vartree)
 
                self.virtuals = self.__getvirtuals_compile()
                return self.virtuals
 
+       def _populate_treeVirtuals(self, vartree):
+               """Reduce the provides into a list by CP."""
+               for provide, cpv_list in vartree.get_all_provides().iteritems():
+                       try:
+                               provide = dep.Atom(provide)
+                       except exception.InvalidAtom:
+                               continue
+                       self.treeVirtuals[provide.cp] = \
+                               [dep.Atom(cpv_getkey(cpv)) for cpv in cpv_list]
+
        def __getvirtuals_compile(self):
                """Stack installed and profile virtuals.  Preference for virtuals
                decreases from left to right.
@@ -6928,7 +6936,6 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                        # so do not check them again.
                        checkme = []
 
-
                if not emerge_skip_distfiles and \
                        need_distfiles and not fetch(
                        fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
@@ -7411,10 +7418,6 @@ def unmerge(cat, pkg, myroot, mysettings, mytrimworld=1, vartree=None,
                vartree.dbapi.linkmap._clear_cache()
                mylink.unlockdb()
 
-def getCPFromCPV(mycpv):
-       """Calls pkgsplit on a cpv and returns only the cp."""
-       return pkgsplit(mycpv)[0]
-
 def dep_virtual(mysplit, mysettings):
        "Does virtual dependency conversion"
        newsplit=[]
@@ -7441,10 +7444,6 @@ def dep_virtual(mysplit, mysettings):
                                newsplit.append(x)
        return newsplit
 
-# According to GLEP 37, RDEPEND is the only dependency type that is valid
-# for new-style virtuals. Repoman should enforce this.
-_virt_dep_keys = ("RDEPEND",)
-
 def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
        trees=None, use_mask=None, use_force=None, **kwargs):
        """Recursively expand new-style virtuals so as to collapse one or more
@@ -7461,15 +7460,14 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
        atom_graph = mytrees.get("atom_graph")
        parent = mytrees.get("parent")
        virt_parent = mytrees.get("virt_parent")
-       virt_eapi = mytrees.get("virt_eapi")
-       parent_cpv = None
+       graph_parent = None
        eapi = None
        if parent is not None:
                if virt_parent is not None:
-                       parent_cpv = virt_parent
-                       eapi = virt_eapi
+                       graph_parent = virt_parent
+                       eapi = virt_parent[0].metadata['EAPI']
                else:
-                       parent_cpv = parent.cpv
+                       graph_parent = parent
                        eapi = parent.metadata["EAPI"]
        repoman = not mysettings.local_config
        if kwargs["use_binaries"]:
@@ -7524,31 +7522,30 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                evaluated_atom += str(x.use.evaluate_conditionals(myuse))
                                x = portage.dep.Atom(evaluated_atom)
 
-               mykey = dep_getkey(x)
+               mykey = x.cp
                if not mykey.startswith("virtual/"):
                        newsplit.append(x)
-                       if parent_cpv is not None:
-                               atom_graph.add(x, parent_cpv)
+                       if atom_graph is not None:
+                               atom_graph.add(x, graph_parent)
                        continue
                mychoices = myvirtuals.get(mykey, [])
-               isblocker = x.startswith("!")
-               if isblocker:
+               if x.blocker:
                        # Virtual blockers are no longer expanded here since
                        # the un-expanded virtual atom is more useful for
                        # maintaining a cache of blocker atoms.
                        newsplit.append(x)
-                       if parent_cpv is not None:
-                               atom_graph.add(x, parent_cpv)
+                       if atom_graph is not None:
+                               atom_graph.add(x, graph_parent)
                        continue
 
-               if repoman:
+               if repoman or not hasattr(portdb, 'match_pkgs'):
                        if portdb.cp_list(x.cp):
                                newsplit.append(x)
                        else:
                                # TODO: Add PROVIDE check for repoman.
                                a = []
                                for y in mychoices:
-                                       a.append(portage.dep.Atom(x.replace(mykey, str(y.cp), 1)))
+                                       a.append(dep.Atom(x.replace(x.cp, y.cp, 1)))
                                if not a:
                                        newsplit.append(x)
                                elif len(a) == 1:
@@ -7557,15 +7554,17 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                        newsplit.append(['||'] + a)
                        continue
 
-               match_atom = x
                pkgs = []
-               matches = portdb.match(match_atom)
+               # Ignore USE deps here, since otherwise we might not
+               # get any matches. Choices with correct USE settings
+               # will be preferred in dep_zapdeps().
+               matches = portdb.match_pkgs(x.without_use)
                # Use descending order to prefer higher versions.
                matches.reverse()
-               for cpv in matches:
+               for pkg in matches:
                        # only use new-style matches
-                       if cpv.startswith("virtual/"):
-                               pkgs.append((cpv, catpkgsplit(cpv)[1:], portdb))
+                       if pkg.cp.startswith("virtual/"):
+                               pkgs.append(pkg)
                if not (pkgs or mychoices):
                        # This one couldn't be expanded as a new-style virtual.  Old-style
                        # virtuals have already been expanded by dep_virtual, so this one
@@ -7573,29 +7572,30 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                        # atom is not eliminated here since it may still represent a
                        # dependency that needs to be satisfied.
                        newsplit.append(x)
-                       if parent_cpv is not None:
-                               atom_graph.add(x, parent_cpv)
+                       if atom_graph is not None:
+                               atom_graph.add(x, graph_parent)
                        continue
 
                a = []
-               for y in pkgs:
-                       cpv, pv_split, db = y
-                       depstring = " ".join(db.aux_get(cpv, _virt_dep_keys))
+               for pkg in pkgs:
+                       virt_atom = '=' + pkg.cpv
+                       if x.use:
+                               virt_atom += str(x.use)
+                       virt_atom = dep.Atom(virt_atom)
+                       # According to GLEP 37, RDEPEND is the only dependency
+                       # type that is valid for new-style virtuals. Repoman
+                       # should enforce this.
+                       depstring = pkg.metadata['RDEPEND']
                        pkg_kwargs = kwargs.copy()
-                       if repoman:
-                               pass
-                       else:
-                               # for emerge
-                               use_split = db.aux_get(cpv, ["USE"])[0].split()
-                               pkg_kwargs["myuse"] = use_split
+                       pkg_kwargs["myuse"] = pkg.use.enabled
                        if edebug:
-                               print _("Virtual Parent:   "), y[0]
-                               print _("Virtual Depstring:"), depstring
+                               util.writemsg_level(_("Virtual Parent:      %s\n") \
+                                       % (pkg,), noiselevel=-1, level=logging.DEBUG)
+                               util.writemsg_level(_("Virtual Depstring:   %s\n") \
+                                       % (depstring,), noiselevel=-1, level=logging.DEBUG)
 
                        # Set EAPI used for validation in dep_check() recursion.
-                       new_eapi, = db.aux_get(cpv, ["EAPI"])
-                       mytrees["virt_eapi"] = new_eapi
-                       mytrees["virt_parent"] = cpv
+                       mytrees["virt_parent"] = (pkg, virt_atom)
 
                        try:
                                mycheck = dep_check(depstring, mydbapi, mysettings,
@@ -7604,49 +7604,45 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                # Restore previous EAPI after recursion.
                                if virt_parent is not None:
                                        mytrees["virt_parent"] = virt_parent
-                                       mytrees["virt_eapi"] = virt_eapi
                                else:
                                        del mytrees["virt_parent"]
-                                       del mytrees["virt_eapi"]
 
                        if not mycheck[0]:
                                raise portage.exception.ParseError(
                                        "%s: %s '%s'" % (y[0], mycheck[1], depstring))
 
                        # pull in the new-style virtual
-                       virt_atom = dep.Atom('=' + cpv)
                        mycheck[1].append(virt_atom)
                        a.append(mycheck[1])
-                       if parent_cpv is not None:
-                               atom_graph.add(virt_atom, parent_cpv)
+                       if atom_graph is not None:
+                               atom_graph.add(virt_atom, graph_parent)
                # Plain old-style virtuals.  New-style virtuals are preferred.
                if not pkgs:
                                for y in mychoices:
-                                       new_atom = portage.dep.Atom(
-                                               x.replace(mykey, dep_getkey(y), 1))
+                                       new_atom = dep.Atom(x.replace(x.cp, y.cp, 1))
                                        matches = portdb.match(new_atom)
                                        # portdb is an instance of depgraph._dep_check_composite_db, so
                                        # USE conditionals are already evaluated.
                                        if matches and mykey in \
                                                portdb.aux_get(matches[-1], ['PROVIDE'])[0].split():
                                                a.append(new_atom)
-                                               if parent_cpv is not None:
-                                                       atom_graph.add(new_atom, parent_cpv)
+                                               if atom_graph is not None:
+                                                       atom_graph.add(new_atom, graph_parent)
 
                if not a and mychoices:
                        # Check for a virtual package.provided match.
                        for y in mychoices:
-                               new_atom = portage.dep.Atom(x.replace(mykey, dep_getkey(y), 1))
+                               new_atom = dep.Atom(x.replace(x.cp, y.cp, 1))
                                if match_from_list(new_atom,
                                        pprovideddict.get(new_atom.cp, [])):
                                        a.append(new_atom)
-                                       if parent_cpv is not None:
-                                               atom_graph.add(new_atom, parent_cpv)
+                                       if atom_graph is not None:
+                                               atom_graph.add(new_atom, graph_parent)
 
                if not a:
                        newsplit.append(x)
-                       if parent_cpv is not None:
-                               atom_graph.add(x, parent_cpv)
+                       if atom_graph is not None:
+                               atom_graph.add(x, graph_parent)
                elif len(a) == 1:
                        newsplit.append(a[0])
                else:
@@ -7692,12 +7688,12 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
 
        if unreduced[0] != "||":
                unresolved = []
-               for dep, satisfied in izip(unreduced, reduced):
-                       if isinstance(dep, list):
-                               unresolved += dep_zapdeps(dep, satisfied, myroot,
+               for x, satisfied in izip(unreduced, reduced):
+                       if isinstance(x, list):
+                               unresolved += dep_zapdeps(x, satisfied, myroot,
                                        use_binaries=use_binaries, trees=trees)
                        elif not satisfied:
-                               unresolved.append(dep)
+                               unresolved.append(x)
                return unresolved
 
        # We're at a ( || atom ... ) type level and need to make a choice
@@ -7734,12 +7730,12 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
        # Sort the deps into installed, not installed but already 
        # in the graph and other, not installed and not in the graph
        # and other, with values of [[required_atom], availablility]
-       for dep, satisfied in izip(deps, satisfieds):
-               if isinstance(dep, list):
-                       atoms = dep_zapdeps(dep, satisfied, myroot,
+       for x, satisfied in izip(deps, satisfieds):
+               if isinstance(x, list):
+                       atoms = dep_zapdeps(x, satisfied, myroot,
                                use_binaries=use_binaries, trees=trees)
                else:
-                       atoms = [dep]
+                       atoms = [x]
                if not vardb:
                        # called by repoman
                        other.append((atoms, None, False))
@@ -7749,15 +7745,15 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                all_use_satisfied = True
                versions = {}
                for atom in atoms:
-                       if atom[:1] == "!":
+                       if atom.blocker:
                                continue
                        # Ignore USE dependencies here since we don't want USE
                        # settings to adversely affect || preference evaluation.
                        avail_pkg = mydbapi.match(atom.without_use)
                        if avail_pkg:
                                avail_pkg = avail_pkg[-1] # highest (ascending order)
-                               avail_slot = "%s:%s" % (dep_getkey(atom),
-                                       mydbapi.aux_get(avail_pkg, ["SLOT"])[0])
+                               avail_slot = dep.Atom("%s:%s" % (atom.cp,
+                                       mydbapi.aux_get(avail_pkg, ["SLOT"])[0]))
                        if not avail_pkg:
                                all_available = False
                                all_use_satisfied = False
@@ -7772,8 +7768,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                        avail_pkg_use = avail_pkg_use[-1]
                                        if avail_pkg_use != avail_pkg:
                                                avail_pkg = avail_pkg_use
-                                               avail_slot = "%s:%s" % (dep_getkey(atom),
-                                                       mydbapi.aux_get(avail_pkg, ["SLOT"])[0])
+                                               avail_slot = dep.Atom("%s:%s" % (atom.cp,
+                                                       mydbapi.aux_get(avail_pkg, ["SLOT"])[0]))
 
                        versions[avail_slot] = avail_pkg
 
@@ -7783,8 +7779,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                        # If any version of a package is already in the graph then we
                        # assume that it is preferred over other possible packages choices.
                        all_installed = True
-                       for atom in set([dep_getkey(atom) for atom in atoms \
-                               if atom[:1] != "!"]):
+                       for atom in set(dep.Atom(atom.cp) for atom in atoms \
+                               if not atom.blocker):
                                # New-style virtuals have zero cost to install.
                                if not vardb.match(atom) and not atom.startswith("virtual/"):
                                        all_installed = False
@@ -7832,13 +7828,13 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                                # installed package.
                                                cpv_slot_list = [parent]
                                                for atom in atoms:
-                                                       if "!" == atom[:1]:
+                                                       if atom.blocker:
                                                                continue
                                                        if vardb.match(atom):
                                                                # If the atom is satisfied by an installed
                                                                # version then it's not a circular dep.
                                                                continue
-                                                       if dep_getkey(atom) != parent.cp:
+                                                       if atom.cp != parent.cp:
                                                                continue
                                                        if match_from_list(atom, cpv_slot_list):
                                                                circular_atom = atom
@@ -7880,14 +7876,19 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
 
        assert(False) # This point should not be reachable
 
-
 def dep_expand(mydep, mydb=None, use_cache=1, settings=None):
+       '''
+       @rtype: Atom
+       '''
        if not len(mydep):
                return mydep
        if mydep[0]=="*":
                mydep=mydep[1:]
        orig_dep = mydep
-       mydep = dep_getcpv(orig_dep)
+       if isinstance(orig_dep, dep.Atom):
+               mydep = orig_dep.cpv
+       else:
+               mydep = dep_getcpv(orig_dep)
        myindex = orig_dep.index(mydep)
        prefix = orig_dep[:myindex]
        postfix = orig_dep[myindex+len(mydep):]
@@ -8004,7 +8005,7 @@ def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
                elif token[:1] == "!":
                        deplist[mypos] = False
                else:
-                       mykey = dep_getkey(deplist[mypos])
+                       mykey = deplist[mypos].cp
                        if mysettings and mykey in mysettings.pprovideddict and \
                                match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]):
                                deplist[mypos]=True
@@ -8034,8 +8035,23 @@ def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
                                        return None
        return deplist
 
+_cpv_key_re = re.compile('^' + dep._cpv + '$', re.VERBOSE)
 def cpv_getkey(mycpv):
-       return dep.dep_getkey('=' + mycpv)
+       """Calls pkgsplit on a cpv and returns only the cp."""
+       m = _cpv_key_re.match(mycpv)
+       if m is not None:
+               return m.group(2)
+       myslash = mycpv.split("/", 1)
+       mysplit=pkgsplit(myslash[-1])
+       if mysplit is None:
+               return None
+       mylen=len(myslash)
+       if mylen==2:
+               return myslash[0]+"/"+mysplit[0]
+       else:
+               return mysplit[0]
+
+getCPFromCPV = cpv_getkey
 
 def key_expand(mykey, mydb=None, use_cache=1, settings=None):
        mysplit=mykey.split("/")
@@ -8356,7 +8372,6 @@ def getmaskingstatus(mycpv, settings=None, portdb=None):
 
        return rValue
 
-
 auxdbkeys=[
   'DEPEND',    'RDEPEND',   'SLOT',      'SRC_URI',
        'RESTRICT',  'HOMEPAGE',  'LICENSE',   'DESCRIPTION',
@@ -8961,7 +8976,6 @@ def init_legacy_globals():
        root = settings["ROOT"]
        output._init(config_root=settings['PORTAGE_CONFIGROOT'])
 
-
        # ========================================================================
        # COMPATIBILITY
        # These attributes should not be used
index 10baa4b9c7f94667f3f61bb77e57a7f9b6b2c1ae..4cc07362ad48b89abebc2d66431d6e85dbc99e12 100644 (file)
@@ -949,7 +949,7 @@ class portdbapi(dbapi):
                        #this stuff only runs on first call of xmatch()
                        #create mydep, mykey from origdep
                        mydep = dep_expand(origdep, mydb=self, settings=self.mysettings)
-                       mykey = dep_getkey(mydep)
+                       mykey = mydep.cp
 
                if level == "list-visible":
                        #a list of all visible packages, not called directly (just by xmatch())
@@ -1133,7 +1133,6 @@ def close_portdbapi_caches():
        for i in portdbapi.portdbapi_instances:
                i.close_caches()
 
-
 class portagetree(object):
        def __init__(self, root="/", virtual=None, clone=None, settings=None):
                """
index b54c528fa0c540609e02ce3d709dda16c66c0a84..bd576b7686e4755d3f30bc8a7e617096c48052e3 100644 (file)
@@ -488,20 +488,6 @@ class _use_dep(object):
 
                return _use_dep(tokens)
 
-class _AtomCache(type):
-       """
-       Cache Atom instances from constructor calls and reuse
-       identical instances when available.
-       """
-       def __call__(cls, s):
-               if isinstance(s, Atom):
-                       return s
-               instance = cls._atoms.get(s)
-               if instance is None:
-                       instance = super(_AtomCache, cls).__call__(s)
-                       cls._atoms[s] = instance
-               return instance
-
 class Atom(object):
 
        """
@@ -509,9 +495,6 @@ class Atom(object):
        class emulates most of the str methods that are useful with atoms.
        """
 
-       __metaclass__ = _AtomCache
-       _atoms = weakref.WeakValueDictionary()
-
        __slots__ = ("__weakref__", "blocker", "cp", "cpv", "operator",
                "slot", "use", "without_use", "_str",)
 
@@ -528,12 +511,11 @@ class Atom(object):
                        self.overlap = self._overlap(forbid=forbid_overlap)
 
        def __init__(self, mypkg):
-               s = mypkg
+               s = mypkg = str(mypkg)
                obj_setattr = object.__setattr__
                obj_setattr(self, '_str', s)
 
-               blocker = "!" == s[:1]
-               if blocker:
+               if "!" == s[:1]:
                        blocker = self._blocker(forbid_overlap=("!" == s[1:2]))
                        if blocker.overlap.forbid:
                                s = s[2:]
@@ -546,31 +528,25 @@ class Atom(object):
                if m is None:
                        raise InvalidAtom(mypkg)
 
-               # Package name must not end in pattern
-               # which appears to be a valid version.
                if m.group('op') is not None:
-                       if m.group(_atom_re.groupindex['op'] + 4) is not None:
+                       base = _atom_re.groupindex['op']
+                       op = m.group(base + 1)
+                       cpv = m.group(base + 2)
+                       cp = m.group(base + 3)
+                       if m.group(base + 4) is not None:
                                raise InvalidAtom(mypkg)
                elif m.group('star') is not None:
-                       if m.group(_atom_re.groupindex['star'] + 3) is not None:
+                       base = _atom_re.groupindex['star']
+                       op = '=*'
+                       cpv = m.group(base + 1)
+                       cp = m.group(base + 2)
+                       if m.group(base + 3) is not None:
                                raise InvalidAtom(mypkg)
                elif m.group('simple') is not None:
-                       if m.group(_atom_re.groupindex['simple'] + 2) is not None:
-                               raise InvalidAtom(mypkg)
-               else:
-                       raise AssertionError(_("required group not found in atom: '%s'") % mypkg)
-
-               if m.group('op'):
-                       op = m.group(_atom_re.groupindex['op'] + 1)
-                       cpv = m.group(_atom_re.groupindex['op'] + 2)
-                       cp = m.group(_atom_re.groupindex['op'] + 3)
-               elif m.group('star'):
-                       op = '=*'
-                       cpv = m.group(_atom_re.groupindex['star'] + 1)
-                       cp = m.group(_atom_re.groupindex['star'] + 2)
-               elif m.group('simple'):
                        op = None
                        cpv = cp = m.group(_atom_re.groupindex['simple'] + 1)
+                       if m.group(_atom_re.groupindex['simple'] + 2) is not None:
+                               raise InvalidAtom(mypkg)
                else:
                        raise AssertionError(_("required group not found in atom: '%s'") % s)
                obj_setattr(self, "cp", cp)
@@ -578,13 +554,10 @@ class Atom(object):
                obj_setattr(self, "slot", m.group(_atom_re.groups - 1))
                obj_setattr(self, "operator", op)
 
-               use = dep_getusedeps(s)
-               if use:
-                       use = _use_dep(use)
-                       without_use = remove_slot(self)
-                       if self.slot is not None:
-                               without_use += ":" + self.slot
-                       without_use = Atom(without_use)
+               use_str = m.group(_atom_re.groups)
+               if use_str is not None:
+                       use = _use_dep(dep_getusedeps(s))
+                       without_use = Atom(m.group('without_use'))
                else:
                        use = None
                        without_use = self
@@ -830,9 +803,6 @@ def dep_getusedeps( depend ):
        @rtype: List
        @return: List of use flags ( or [] if no flags exist )
        """
-       use = getattr(depend, "use", None)
-       if use is not None and hasattr(use, "tokens"):
-               return use.tokens
        use_list = []
        open_bracket = depend.find('[')
        # -1 = failure (think c++ string::npos)
@@ -886,17 +856,16 @@ _pkg = r'[\w+][\w+-]*?'
 # 2.1.3 A slot name may contain any of the characters [A-Za-z0-9+_.-].
 # It must not begin with a hyphen or a dot.
 _slot = r':([\w+][\w+.-]*)'
-_optional_slot = '(?:' + _slot + ')?'
 
-_use = r'(\[.*\])?'
+_use = r'\[.*\]'
 _op = r'([=~]|[><]=?)'
 _cp = '(' + _cat + '/' + _pkg + '(-' + _version + ')?)'
 _cpv = '(' + _cp + '-' + _version + ')'
 
-_atom_re = re.compile('^(?:' +
+_atom_re = re.compile('^(?P<without_use>(?:' +
        '(?P<op>' + _op + _cpv + ')|' +
        '(?P<star>=' + _cpv + r'\*)|' +
-       '(?P<simple>' + _cp + '))' + _optional_slot + _use + '$', re.VERBOSE)
+       '(?P<simple>' + _cp + '))(?:' + _slot + ')?)(' + _use + ')?$', re.VERBOSE)
 
 def isvalidatom(atom, allow_blockers=False):
        """
@@ -1021,6 +990,8 @@ def match_to_list(mypkg, mylist):
        """
        matches = []
        for x in mylist:
+               if not isinstance(x, Atom):
+                       x = Atom(x)
                if match_from_list(x, [mypkg]):
                        if x not in matches:
                                matches.append(x)
@@ -1055,7 +1026,7 @@ def best_match_to_list(mypkg, mylist):
                        if maxvalue < 3:
                                maxvalue = 3
                                bestm = x
-               op_val = operator_values[get_operator(x)]
+               op_val = operator_values[x.operator]
                if op_val > maxvalue:
                        maxvalue = op_val
                        bestm  = x
@@ -1082,9 +1053,9 @@ def match_from_list(mydep, candidate_list):
        if not isinstance(mydep, Atom):
                mydep = Atom(mydep)
 
-       mycpv     = dep_getcpv(mydep)
+       mycpv     = mydep.cpv
        mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific
-       slot      = dep_getslot(mydep)
+       slot      = mydep.slot
 
        if not mycpv_cps:
                cat, pkg = catsplit(mycpv)
@@ -1097,7 +1068,7 @@ def match_from_list(mydep, candidate_list):
                                " (%s) (try adding an '=')") % (mydep))
 
        if ver and rev:
-               operator = get_operator(mydep)
+               operator = mydep.operator
                if not operator:
                        writemsg(_("!!! Invalid atom: %s\n") % mydep, noiselevel=-1)
                        return []
index 87a0d1db76affed2c2695dacb0b49159276cb168..adf05fbf87598f012d9e0072c86624d636ab13b1 100644 (file)
@@ -104,9 +104,8 @@ class PackageSet(object):
                        self._atommap.clear()
                        atoms = self._atoms
                for a in atoms:
-                       cp = dep_getkey(a)
-                       self._atommap.setdefault(cp, set())
-                       self._atommap[cp].add(a)
+                       self._atommap.setdefault(a.cp, set())
+                       self._atommap[a.cp].add(a)
        
        # Not sure if this one should really be in PackageSet
        def findAtomForPackage(self, pkg):