aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/portage/dbapi/__init__.py')
-rw-r--r--lib/portage/dbapi/__init__.py113
1 files changed, 59 insertions, 54 deletions
diff --git a/lib/portage/dbapi/__init__.py b/lib/portage/dbapi/__init__.py
index 717ab95d5..9105227c7 100644
--- a/lib/portage/dbapi/__init__.py
+++ b/lib/portage/dbapi/__init__.py
@@ -1,10 +1,14 @@
-# Copyright 1998-2020 Gentoo Authors
+# Copyright 1998-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
__all__ = ["dbapi"]
import functools
+import logging
import re
+import sys
+from typing import Any, Dict, List, Optional, Tuple
+from collections.abc import Sequence
import portage
@@ -22,14 +26,18 @@ from portage.const import MERGING_IDENTIFIER
from portage import os
from portage import auxdbkeys
from portage.eapi import _get_eapi_attrs
-from portage.exception import InvalidData
+from portage.exception import (
+ CorruptionKeyError,
+ InvalidBinaryPackageFormat,
+ InvalidData,
+)
from portage.localization import _
from _emerge.Package import Package
class dbapi:
_category_re = re.compile(r"^\w[-.+\w]*$", re.UNICODE)
- _categories = None
+ _categories: Optional[tuple[str, ...]] = None
_use_mutable = False
_known_keys = frozenset(auxdbkeys)
_pkg_str_aux_keys = ("EAPI", "KEYWORDS", "SLOT", "repository")
@@ -38,7 +46,7 @@ class dbapi:
pass
@property
- def categories(self):
+ def categories(self) -> tuple[str, ...]:
"""
Use self.cp_all() to generate a category list. Mutable instances
can delete the self._categories attribute in cases when the cached
@@ -46,17 +54,17 @@ class dbapi:
"""
if self._categories is not None:
return self._categories
- self._categories = tuple(sorted(set(catsplit(x)[0] for x in self.cp_all())))
+ self._categories = tuple(sorted({catsplit(x)[0] for x in self.cp_all()}))
return self._categories
def close_caches(self):
pass
- def cp_list(self, cp, use_cache=1):
+ def cp_list(self, cp: str, use_cache: int = 1) -> Any:
raise NotImplementedError(self)
@staticmethod
- def _cmp_cpv(cpv1, cpv2):
+ def _cmp_cpv(cpv1, cpv2) -> int:
result = vercmp(cpv1.version, cpv2.version)
if result == 0 and cpv1.build_time is not None and cpv2.build_time is not None:
result = (cpv1.build_time > cpv2.build_time) - (
@@ -65,7 +73,7 @@ class dbapi:
return result
@staticmethod
- def _cpv_sort_ascending(cpv_list):
+ def _cpv_sort_ascending(cpv_list: Sequence[Any]) -> None:
"""
Use this to sort self.cp_list() results in ascending
order. It sorts in place and returns None.
@@ -76,7 +84,7 @@ class dbapi:
# dict to map strings back to their original values.
cpv_list.sort(key=cmp_sort_key(dbapi._cmp_cpv))
- def cpv_all(self):
+ def cpv_all(self) -> list[str]:
"""Return all CPVs in the db
Args:
None
@@ -93,16 +101,18 @@ class dbapi:
cpv_list.extend(self.cp_list(cp))
return cpv_list
- def cp_all(self, sort=False):
+ def cp_all(self, sort: bool = False) -> list[str]:
"""Implement this in a child class
Args
sort - return sorted results
Returns:
A list of strings 1 per CP in the datastore
"""
- return NotImplementedError
+ raise NotImplementedError
- def aux_get(self, mycpv, mylist, myrepo=None):
+ def aux_get(
+ self, mycpv: str, mylist: str, myrepo: Optional[str] = None
+ ) -> list[str]:
"""Return the metadata keys in mylist for mycpv
Args:
mycpv - "sys-apps/foo-1.0"
@@ -114,7 +124,7 @@ class dbapi:
"""
raise NotImplementedError
- def aux_update(self, cpv, metadata_updates):
+ def aux_update(self, cpv: str, metadata_updates: dict[str, Any]) -> None:
"""
Args:
cpv - "sys-apps/foo-1.0"
@@ -124,7 +134,7 @@ class dbapi:
"""
raise NotImplementedError
- def match(self, origdep, use_cache=1):
+ def match(self, origdep: str, use_cache: int = 1):
"""Given a dependency, try to find packages that match
Args:
origdep - Depend atom
@@ -138,7 +148,7 @@ class dbapi:
self._iter_match(mydep, self.cp_list(mydep.cp, use_cache=use_cache))
)
- def _iter_match(self, atom, cpv_iter):
+ def _iter_match(self, atom: str, cpv_iter):
cpv_iter = iter(match_from_list(atom, cpv_iter))
if atom.repo:
cpv_iter = self._iter_match_repo(atom, cpv_iter)
@@ -150,7 +160,7 @@ class dbapi:
def _pkg_str(self, cpv, repo):
"""
- This is used to contruct _pkg_str instances on-demand during
+ This is used to construct _pkg_str instances on-demand during
matching. If cpv is a _pkg_str instance with slot attribute,
then simply return it. Otherwise, fetch metadata and construct
a _pkg_str instance. This may raise KeyError or InvalidData.
@@ -219,17 +229,9 @@ class dbapi:
yield cpv
- def _repoman_iuse_implicit_cnstr(self, pkg, metadata):
- """
- In repoman's version of _iuse_implicit_cnstr, account for modifications
- of the self.settings reference between calls.
- """
- eapi_attrs = _get_eapi_attrs(metadata["EAPI"])
- if eapi_attrs.iuse_effective:
- iuse_implicit_match = lambda flag: self.settings._iuse_effective_match(flag)
- else:
- iuse_implicit_match = lambda flag: self.settings._iuse_implicit_match(flag)
- return iuse_implicit_match
+ @staticmethod
+ def _iuse_implicit_built(iuse_implicit_match, use, flag):
+ return iuse_implicit_match(flag) or flag in use
def _iuse_implicit_cnstr(self, pkg, metadata):
"""
@@ -265,25 +267,25 @@ class dbapi:
# This behavior is only used for EAPIs that support IUSE_EFFECTIVE,
# since built USE settings for earlier EAPIs may contain a large
# number of irrelevant flags.
- prof_iuse = iuse_implicit_match
- enabled = frozenset(metadata["USE"].split()).__contains__
- iuse_implicit_match = lambda flag: prof_iuse(flag) or enabled(flag)
+ iuse_implicit_match = functools.partial(
+ self._iuse_implicit_built,
+ iuse_implicit_match,
+ frozenset(metadata["USE"].split()),
+ )
return iuse_implicit_match
def _match_use(self, atom, pkg, metadata, ignore_profile=False):
iuse_implicit_match = self._iuse_implicit_cnstr(pkg, metadata)
- usealiases = self.settings._use_manager.getUseAliases(pkg)
iuse = Package._iuse(
None,
metadata["IUSE"].split(),
iuse_implicit_match,
- usealiases,
metadata["EAPI"],
)
for x in atom.unevaluated_atom.use.required:
- if iuse.get_real_flag(x) is None:
+ if iuse.get_flag(x) is None:
return False
if atom.use is None:
@@ -297,18 +299,16 @@ class dbapi:
# with implicit IUSE, in order to avoid potential
# inconsistencies in USE dep matching (see bug #453400).
use = frozenset(
- x for x in metadata["USE"].split() if iuse.get_real_flag(x) is not None
+ x for x in metadata["USE"].split() if iuse.get_flag(x) is not None
)
missing_enabled = frozenset(
- x for x in atom.use.missing_enabled if iuse.get_real_flag(x) is None
+ x for x in atom.use.missing_enabled if iuse.get_flag(x) is None
)
missing_disabled = frozenset(
- x for x in atom.use.missing_disabled if iuse.get_real_flag(x) is None
- )
- enabled = frozenset((iuse.get_real_flag(x) or x) for x in atom.use.enabled)
- disabled = frozenset(
- (iuse.get_real_flag(x) or x) for x in atom.use.disabled
+ x for x in atom.use.missing_disabled if iuse.get_flag(x) is None
)
+ enabled = frozenset((iuse.get_flag(x) or x) for x in atom.use.enabled)
+ disabled = frozenset((iuse.get_flag(x) or x) for x in atom.use.disabled)
if enabled:
if any(x in enabled for x in missing_disabled):
@@ -333,7 +333,7 @@ class dbapi:
pkg, stable=self.settings._parent_stable
)
if any(
- x in usemask and iuse.get_real_flag(x) is not None
+ x in usemask and iuse.get_flag(x) is not None
for x in atom.use.enabled
):
return False
@@ -342,9 +342,7 @@ class dbapi:
pkg, stable=self.settings._parent_stable
)
if any(
- x in useforce
- and x not in usemask
- and iuse.get_real_flag(x) is not None
+ x in useforce and x not in usemask and iuse.get_flag(x) is not None
for x in atom.use.disabled
):
return False
@@ -352,15 +350,13 @@ class dbapi:
# Check unsatisfied use-default deps
if atom.use.enabled:
missing_disabled = frozenset(
- x
- for x in atom.use.missing_disabled
- if iuse.get_real_flag(x) is None
+ x for x in atom.use.missing_disabled if iuse.get_flag(x) is None
)
if any(x in atom.use.enabled for x in missing_disabled):
return False
if atom.use.disabled:
missing_enabled = frozenset(
- x for x in atom.use.missing_enabled if iuse.get_real_flag(x) is None
+ x for x in atom.use.missing_enabled if iuse.get_flag(x) is None
)
if any(x in atom.use.disabled for x in missing_enabled):
return False
@@ -371,11 +367,11 @@ class dbapi:
if "/" + MERGING_IDENTIFIER in mypath:
if os.path.exists(mypath):
writemsg(
- colorize("BAD", _("INCOMPLETE MERGE:")) + " %s\n" % mypath,
+ colorize("BAD", _("INCOMPLETE MERGE:")) + f" {mypath}\n",
noiselevel=-1,
)
else:
- writemsg("!!! Invalid db entry: %s\n" % mypath, noiselevel=-1)
+ writemsg(f"!!! Invalid db entry: {mypath}\n", noiselevel=-1)
def update_ents(self, updates, onProgress=None, onUpdate=None):
"""
@@ -412,7 +408,7 @@ class dbapi:
pkg = _pkg_str(cpv, metadata=metadata, settings=self.settings)
except InvalidData:
continue
- metadata = dict((k, metadata[k]) for k in update_keys)
+ metadata = {k: metadata[k] for k in update_keys}
if repo_dict is None:
updates_list = updates
else:
@@ -431,7 +427,12 @@ class dbapi:
updates_list, metadata, parent=pkg
)
if metadata_updates:
- aux_update(cpv, metadata_updates)
+ try:
+ aux_update(cpv, metadata_updates)
+ except (InvalidBinaryPackageFormat, CorruptionKeyError) as e:
+ logging.warning(
+ f"{e.__class__.__name__}: {e}", exc_info=sys.exc_info()
+ )
if onUpdate:
onUpdate(maxval, i + 1)
if onProgress:
@@ -474,7 +475,11 @@ class dbapi:
and mycpv.sub_slot
and mycpv.sub_slot not in (mycpv.slot, newslot)
):
- newslot = "%s/%s" % (newslot, mycpv.sub_slot)
+ newslot = f"{newslot}/{mycpv.sub_slot}"
mydata = {"SLOT": newslot + "\n"}
- self.aux_update(mycpv, mydata)
+ try:
+ self.aux_update(mycpv, mydata)
+ except CorruptionKeyError as e:
+ logging.warning(f"{e.__class__.__name__}: {e}", exc_info=sys.exc_info())
+ continue
return moves