_emerge.resolver.package_tracker module

class _emerge.resolver.package_tracker.PackageConflict(root, pkgs, atom, description)

Bases: _emerge.resolver.package_tracker._PackageConflict

Class to track the reason for a conflict and the conflicting packages.

_asdict()

Return a new dict which maps field names to their values.

_field_defaults = {}
_fields = ('root', 'pkgs', 'atom', 'description')
classmethod _make(iterable)

Make a new _PackageConflict object from a sequence or iterable

_replace(**kwds)

Return a new _PackageConflict object replacing specified fields with new values

atom

Alias for field number 2

count(value, /)

Return number of occurrences of value.

description

Alias for field number 3

index(value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

pkgs

Alias for field number 1

root

Alias for field number 0

class _emerge.resolver.package_tracker.PackageTracker(soname_deps=False)

Bases: object

Behavior

This section is intended to give you a good conceptual overview of the PackageTracker class and its general behavior – how you can expect it to behave and how in turn expects to be used successfully by the programmer.

This class is used to model the behavior of a real Gentoo or other system using Portage for package management, along with the installed and to-be-installed packages. The installed packages are ones that are already on the system and recorded in /var/db/pkg, while the to-be-installed packages are a group of packages that Portage is considering installing on the system, based on the information in Portage’s dependency graph. Multiple roots are supported, so that situations can be modeled where ROOT is set to a non-default value (non-/).

You can use the add_pkg() method to add a to-be-merged package to the PackageTracker, and add_installed_pkg() to add an already-installed package to the package tracker. Typical use of the package tracker involves the depgraph.py code populating the package tracker with calls to add_installed_pkg() to add all installed packages on the system, and then it is initialized and ready for use. At that point, depgraph.py can use add_pkg() to add to-be-installed packages to the system.

It’s worth mentioning that PackageTracker uses Package objects as arguments, and stores these objects internally. There are parts of the code that ensure that a Package instance is added to the PackageTracker only once.

Note that when a to-be-merged package is added to the package tracker via add_pkg(), it will “cover up” (replace) any installed package that shares the same root-catpkg-slot or root-catpkg-version, meaning that calling the all_pkgs() or match() method will not return the installed package in the list. And the code does support the scenario where add_installed_pkg(pkg2) is called after a call to add_pkg(pkg1) – in this case, if pkg1 would ‘cover up’ pkg2, this will be identified and handled correctly.

But the package tracker is designed to have an important behavior in this regard – because PackageTracker has a remove() method, these replaced/covered-up packages are not permanently removed – so if you remove() a to-be-installed package that was “replacing” an installed package, the installed package will “reappear”. This removal functionality is used by the slot conflict code in depgraph.py to modify the list of to-be-installed packages as it addresses slot conflicts.

One of the main purposes of the PackageTracker is to detect conflicts between packages. Conflicts are detected on to-be-installed packages only.

A slot conflict is a situation where a to-be-installed package is added to the package tracker via add_pkg(), and there is already a to-be-installed package added that has the same root, catpkg and slot. These cannot co-exist.

A cpv conflict is a situation where a to-be-installed package is added to the package tracker via add_pkg(), and there is already a to-be-installed package added that has the same root, catpkg, and version+revision. These cannot co-exist.

The package tracker does not prevent slot and cpv conflicts from occurring. Instead, it allows them to be recorded and the conflicts() and slot_conflicts() method will cause the package tracker to look at its internal data structures and generate PackageConflict() objects for each conflict it finds.

The match() method is used extensively by depgraph.py to find packages that match a particular dependency atom. The code now also supports soname dependencies.

Future Functionality

The package tracker may be extended in the future to track additional useful information:

  • Packages that block one another. This information is not currently injected into the package tracker.

  • Sub-slot conflicts. It is possible to identify situations where a to-be-installed package is in a new sub-slot. In this case, the depgraph can be queried for parents of this dependency, and these parents can be scheduled to be rebuilt.

Variables
  • _cp_pkg_map – The collection of to-be-installed (not yet merged) packages. We care about conflicts in these packages.

  • _cp_vdb_pkg_map – The collection of already-installed packages.

  • _multi_pkgs – A list of keys in self._cp_pkg_map that have potential slot and cpv conflicts.

  • _replacing – The mechanism by which PackageTracker records to-be-installed packages that ‘cover up’ already-installed packages. self._replacing[cp_key] = [ new_pkg_that_replaced_cp_key... ].

  • _replaced_byself.replaced_by[cp_key] == [ replaced_pkg_1, replaced_pkg_2 ]

_add_provides(pkg)
add_installed_pkg(installed)

Add an installed package during vdb load. These packages are not returned by matched_pull as long as add_pkg hasn’t been called with them. They are only returned by match_final.

add_pkg(pkg)

Add a new package to the tracker. Records conflicts as necessary.

all_pkgs(root)

Iterates over all packages for the given root present in the tracker, including the installed packages.

conflicts()

Iterates over the currently existing conflicts.

contains(pkg, installed=True)

Checks if the package is in the tracker. If ‘installed’ is True, returns True for non-replaced installed packages.

discard_pkg(pkg)

Removes the package from the tracker. Does not raise KeyError if it is not present.

match(root, atom, installed=True)

Iterates over the packages matching ‘atom’. If ‘installed’ is True, installed non-replaced packages may also be returned.

remove_pkg(pkg)

Removes the package from the tracker. Raises KeyError if it isn’t present.

slot_conflicts()

Iterates over present slot conflicts. This is only intended for consumers that haven’t been updated to deal with other kinds of conflicts. This function should be removed once all consumers are updated.

class _emerge.resolver.package_tracker.PackageTrackerDbapiWrapper(root, package_tracker)

Bases: object

A wrapper class that provides parts of the legacy dbapi interface. Remove it once all consumers have died.

cp_list(cp)
cpv_inject(pkg)
match(atom, use_cache=None)
match_pkgs(atom)
class _emerge.resolver.package_tracker._PackageConflict(root, pkgs, atom, description)

Bases: tuple

_asdict()

Return a new dict which maps field names to their values.

_field_defaults = {}
_fields = ('root', 'pkgs', 'atom', 'description')
classmethod _make(iterable)

Make a new _PackageConflict object from a sequence or iterable

_replace(**kwds)

Return a new _PackageConflict object replacing specified fields with new values

atom

Alias for field number 2

count(value, /)

Return number of occurrences of value.

description

Alias for field number 3

index(value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

pkgs

Alias for field number 1

root

Alias for field number 0