aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pym/gentoolkit/enalyze/lib.py')
-rw-r--r--pym/gentoolkit/enalyze/lib.py685
1 files changed, 347 insertions, 338 deletions
diff --git a/pym/gentoolkit/enalyze/lib.py b/pym/gentoolkit/enalyze/lib.py
index 50c7d11..6d7cb4e 100644
--- a/pym/gentoolkit/enalyze/lib.py
+++ b/pym/gentoolkit/enalyze/lib.py
@@ -10,349 +10,358 @@
from gentoolkit import errors
from gentoolkit.keyword import reduce_keywords
-from gentoolkit.flag import (reduce_flags, get_flags, get_all_cpv_use,
- filter_flags, get_installed_use, defaulted_flags)
-#from gentoolkit.package import Package
+from gentoolkit.flag import (
+ reduce_flags,
+ get_flags,
+ get_all_cpv_use,
+ filter_flags,
+ get_installed_use,
+ defaulted_flags,
+)
+
+# from gentoolkit.package import Package
import portage
class FlagAnalyzer:
- """Specialty functions for analysing an installed package's
- USE flags. Can be used for single or mulitple use without
- needing to be reset unless the system USE flags are changed.
-
- @type system: list or set
- @param system: the default system USE flags.
- @type _get_flags: function
- @param _get_flags: Normally defaulted, can be overriden for testing
- @type _get_used: function
- @param _get_used: Normally defaulted, can be overriden for testing
- """
- def __init__(self,
- system,
- filter_defaults=False,
- target="USE",
- _get_flags=get_flags,
- _get_used=get_installed_use
- ):
- self.get_flags = _get_flags
- self.get_used = _get_used
- self.filter_defaults = filter_defaults
- self.target = target
- self.reset(system)
-
- def reset(self, system):
- """Resets the internal system USE flags and use_expand variables
- to the new setting. The use_expand variable is handled internally.
-
- @type system: list or set
- @param system: the default system USE flags.
- """
- self.system = set(system)
- self.use_expand = portage.settings['USE_EXPAND'].lower().split()
-
- def analyse_cpv(self, cpv):
- """Gets all relavent USE flag info for a cpv and breaks them down
- into 3 sets, plus (package.use enabled), minus ( package.use disabled),
- unset.
-
- @param cpv: string. 'cat/pkg-ver'
- @rtype tuple of sets
- @return (plus, minus, unset) sets of USE flags
- """
- installed = set(self.get_used(cpv, self.target))
- _iuse = self.get_flags(cpv)
- iuse = set(reduce_flags(_iuse))
- iuse_defaults = defaulted_flags(_iuse)
- return self._analyse(installed, iuse, iuse_defaults)
-
- def _analyse(self, installed, iuse, iuse_defaults):
- """Analyzes the supplied info and returns the flag settings
- that differ from the defaults
-
- @type installed: set
- @param installed: the installed with use flags
- @type iuse: set
- @param iuse: the current ebuilds IUSE
- """
- defaults = self.system.intersection(iuse)
- # update defaults with iuse_defaults
- defaults.update(iuse_defaults['+'])
- defaults = defaults.difference(iuse_defaults['-'])
- usedflags = iuse.intersection(set(installed))
- if self.filter_defaults:
- plus = usedflags.difference(defaults)
- else:
- plus = usedflags
- minus = defaults.difference(usedflags)
- unset = iuse.difference(defaults, plus, minus)
- cleaned_unset = self.remove_expanding(unset)
- return (plus, minus, cleaned_unset)
-
- def analyse_pkg(self, pkg):
- """Gets all relevent USE flag info for a pkg and breaks them down
- into 3 sets, plus (package.use enabled), minus ( package.use disabled),
- unset.
-
- @param pkg: gentoolkit.package.Package object
- @rtype tuple of sets
- @return (plus, minus, unset) sets of USE flags
- """
- installed = set(self.pkg_used(pkg))
- #print("installed =", installed)
- _iuse = self.pkg_flags(pkg)
- iuse = set(reduce_flags(_iuse))
- iuse_defaults = defaulted_flags(_iuse)
- #print("iuse =", iuse)
- return self._analyse(installed, iuse, iuse_defaults)
-
- def pkg_used(self, pkg):
- if self.target == "USE":
- return pkg.use().split()
- return pkg.environment(self.target).split()
-
- def pkg_flags(self, pkg):
- final_use, use_expand_hidden, usemasked, useforced = \
- get_all_cpv_use(pkg.cpv)
- flags = pkg.environment("IUSE", prefer_vdb=False).split()
- return filter_flags(flags, use_expand_hidden, usemasked, useforced)
-
- def redundant(self, cpv, iuse):
- """Checks for redundant settings.
- future function. Not yet implemented.
- """
- pass
-
- def remove_expanding(self, flags):
- """Remove unwanted USE_EXPAND flags
- from unset IUSE sets
-
- @param flags: short list or set of USE flags
- @rtype set
- @return USE flags
- """
- _flags = set(flags)
- for expander in self.use_expand:
- for flag in flags:
- if expander in flag:
- _flags.remove(flag)
- if not _flags:
- break
- return _flags
+ """Specialty functions for analysing an installed package's
+ USE flags. Can be used for single or mulitple use without
+ needing to be reset unless the system USE flags are changed.
+
+ @type system: list or set
+ @param system: the default system USE flags.
+ @type _get_flags: function
+ @param _get_flags: Normally defaulted, can be overriden for testing
+ @type _get_used: function
+ @param _get_used: Normally defaulted, can be overriden for testing
+ """
+
+ def __init__(
+ self,
+ system,
+ filter_defaults=False,
+ target="USE",
+ _get_flags=get_flags,
+ _get_used=get_installed_use,
+ ):
+ self.get_flags = _get_flags
+ self.get_used = _get_used
+ self.filter_defaults = filter_defaults
+ self.target = target
+ self.reset(system)
+
+ def reset(self, system):
+ """Resets the internal system USE flags and use_expand variables
+ to the new setting. The use_expand variable is handled internally.
+
+ @type system: list or set
+ @param system: the default system USE flags.
+ """
+ self.system = set(system)
+ self.use_expand = portage.settings["USE_EXPAND"].lower().split()
+
+ def analyse_cpv(self, cpv):
+ """Gets all relavent USE flag info for a cpv and breaks them down
+ into 3 sets, plus (package.use enabled), minus ( package.use disabled),
+ unset.
+
+ @param cpv: string. 'cat/pkg-ver'
+ @rtype tuple of sets
+ @return (plus, minus, unset) sets of USE flags
+ """
+ installed = set(self.get_used(cpv, self.target))
+ _iuse = self.get_flags(cpv)
+ iuse = set(reduce_flags(_iuse))
+ iuse_defaults = defaulted_flags(_iuse)
+ return self._analyse(installed, iuse, iuse_defaults)
+
+ def _analyse(self, installed, iuse, iuse_defaults):
+ """Analyzes the supplied info and returns the flag settings
+ that differ from the defaults
+
+ @type installed: set
+ @param installed: the installed with use flags
+ @type iuse: set
+ @param iuse: the current ebuilds IUSE
+ """
+ defaults = self.system.intersection(iuse)
+ # update defaults with iuse_defaults
+ defaults.update(iuse_defaults["+"])
+ defaults = defaults.difference(iuse_defaults["-"])
+ usedflags = iuse.intersection(set(installed))
+ if self.filter_defaults:
+ plus = usedflags.difference(defaults)
+ else:
+ plus = usedflags
+ minus = defaults.difference(usedflags)
+ unset = iuse.difference(defaults, plus, minus)
+ cleaned_unset = self.remove_expanding(unset)
+ return (plus, minus, cleaned_unset)
+
+ def analyse_pkg(self, pkg):
+ """Gets all relevent USE flag info for a pkg and breaks them down
+ into 3 sets, plus (package.use enabled), minus ( package.use disabled),
+ unset.
+
+ @param pkg: gentoolkit.package.Package object
+ @rtype tuple of sets
+ @return (plus, minus, unset) sets of USE flags
+ """
+ installed = set(self.pkg_used(pkg))
+ # print("installed =", installed)
+ _iuse = self.pkg_flags(pkg)
+ iuse = set(reduce_flags(_iuse))
+ iuse_defaults = defaulted_flags(_iuse)
+ # print("iuse =", iuse)
+ return self._analyse(installed, iuse, iuse_defaults)
+
+ def pkg_used(self, pkg):
+ if self.target == "USE":
+ return pkg.use().split()
+ return pkg.environment(self.target).split()
+
+ def pkg_flags(self, pkg):
+ final_use, use_expand_hidden, usemasked, useforced = get_all_cpv_use(pkg.cpv)
+ flags = pkg.environment("IUSE", prefer_vdb=False).split()
+ return filter_flags(flags, use_expand_hidden, usemasked, useforced)
+
+ def redundant(self, cpv, iuse):
+ """Checks for redundant settings.
+ future function. Not yet implemented.
+ """
+ pass
+
+ def remove_expanding(self, flags):
+ """Remove unwanted USE_EXPAND flags
+ from unset IUSE sets
+
+ @param flags: short list or set of USE flags
+ @rtype set
+ @return USE flags
+ """
+ _flags = set(flags)
+ for expander in self.use_expand:
+ for flag in flags:
+ if expander in flag:
+ _flags.remove(flag)
+ if not _flags:
+ break
+ return _flags
class KeywordAnalyser:
- """Specialty functions for analysing the installed package db for
- keyword useage and the packages that used them.
-
- Note: should be initialized with the internal set_order() before use.
- See internal set_order() for more details.
- This class of functions can be used for single cpv checks or
- used repeatedly for an entire package db.
-
- @type arch: string
- @param arch: the system ARCH setting
- @type accept_keywords: list
- @param accept_keywords: eg. ['x86', '~x86']
- @type get_aux: function, defaults to: portage.db[portage.root]["vartree"].dbapi.aux_get
- @param vardb: vardb class of functions, needed=aux_get()
- to return => KEYWORDS & USE flags for a cpv
- = aux_get(cpv, ["KEYWORDS", "USE"])
- """
-
- # parsing order to determine appropriate keyword used for installation
- normal_order = ['stable', 'testing', 'prefix', 'testing_prefix', 'missing']
- prefix_order = ['prefix', 'testing_prefix', 'stable', 'testing', 'missing']
- parse_range = list(range(len(normal_order)))
-
-
- def __init__(self, arch, accept_keywords, vardb=portage.db[portage.root]["vartree"].dbapi):
- self.arch = arch
- self.accept_keywords = accept_keywords
- self.vardb = vardb
- self.prefix = ''
- self.parse_order = None
- self.check_key = {
- 'stable': self._stable,
- 'testing': self._testing,
- 'prefix': self._prefix,
- 'testing_prefix': self._testing_prefix,
- 'missing': self._missing
- }
- self.mismatched = []
-
- def determine_keyword(self, keywords, used, cpv):
- """Determine the keyword from the installed USE flags and
- the KEYWORDS that was used to install a package.
-
- @param keywords: list of keywords available to install a pkg
- @param used: list of USE flalgs recorded for the installed pkg
- @rtype: string
- @return a keyword or null string
- """
- used = set(used)
- kwd = None
- result = ''
- if keywords:
- absolute_kwds = reduce_keywords(keywords)
- kwd = list(used.intersection(absolute_kwds))
- #if keywords == ['~ppc64']:
- #print "Checked keywords for kwd", keywords, used, "kwd =", kwd
- if not kwd:
- #print "Checking for kwd against portage.archlist"
- absolute_kwds = reduce_keywords(keywords)
- # check for one against archlist then re-check
- kwd = list(absolute_kwds.intersection(portage.archlist))
- #print "determined keyword =", kwd
- if len(kwd) == 1:
- key = kwd[0]
- #print "determined keyword =", key
- elif not kwd:
- #print "kwd != 1", kwd, cpv
- result = self._missing(self.keyword, keywords)
- else: # too many, try to narrow them dowm
- #print "too many kwd's, trying to match against arch"
- _kwd = list(set(kwd).intersection(self.arch))
- key = ''
- if _kwd:
- #print "found one! :)", _kwd
- key = _kwd
- else: # try re-running the short list against archlist
- #print "Checking kwd for _kwd against portage.archlist"
- _kwd = list(set(kwd).intersection(portage.archlist))
- if _kwd and len(_kwd) == 1:
- #print "found one! :)", _kwd
- key = _kwd[0]
- else:
- #print " :( didn't work, _kwd =", _kwd, "giving up on:", cpv
- result = self._missing(self.keyword, keywords)
- i = 0
- while not result and i in self.parse_range:
- parsekey = self.parse_order[i]
- result = self.check_key[parsekey](key, keywords)
- i += 1
- return result
-
- def _stable(self, key, keywords):
- """test for a normal stable keyword"""
- if key in keywords:
- return key
- return ''
-
- def _testing(self, key, keywords):
- """test for a normal testing keyword"""
- if ("~" + key) in keywords:
- return "~" + key
- return ''
-
- def _prefix(self, key, keywords):
- """test for a stable prefix keyword"""
- if not self.prefix:
- return ''
- _key = '-'.join([key, self.prefix])
- if _key in keywords:
- #print key, "is in", keywords
- return _key
- return ''
-
- def _testing_prefix(self, key, keywords):
- """test for a testing prefix keyword"""
- if not self.prefix:
- return ''
- _key = "~" +'-'.join([key, self.prefix])
- if _key in keywords:
- #print key, "is in", keywords
- return _key
- return ''
-
- def _missing(self, key, keywords):
- """generates a missing keyword to return"""
- if self.prefix and key != self.keyword:
- _key = '-'.join([key, self.prefix])
- else:
- _key = '-' + key
- #print "_missisng :( _key =", _key
- return _key
-
- def get_inst_keyword_cpv(self, cpv):
- """Determines the installed with keyword for cpv
-
- @type cpv: string
- @param cpv: an installed CAT/PKG-VER
- @rtype: string
- @returns a keyword determined to have been used to install cpv
- """
- keywords, used = self.vardb.aux_get(cpv, ["KEYWORDS", "USE"])
- keywords = keywords.split()
- used = used.split()
- return self._parse(keywords, used, cpv=cpv)
-
- def get_inst_keyword_pkg(self, pkg):
- """Determines the installed with keyword for cpv
-
- @param pkg: gentoolkit.package.Package object
- @rtype: string
- @returns a keyword determined to have been used to install cpv
- """
- keywords, used = pkg.environment(["KEYWORDS", "USE"],
- prefer_vdb=True, fallback=False)
- keywords = keywords.split()
- used = used.split()
- return self._parse(keywords, used, pkg=pkg)
-
- def _parse(self, keywords, used, pkg=None, cpv=None):
- if pkg:
- _cpv = pkg.cpv
- else:
- _cpv = cpv
- if not self.parse_order:
- self.set_order(used)
- keyword = self.keyword
- # sanity check
- if self.arch not in used:
- #print "Found a mismatch = ", cpv, self.arch, used
- self.mismatched.append(_cpv)
- if keyword in keywords:
- #print "keyword", keyword, "is in", keywords
- return keyword
- elif "~"+keyword in keywords:
- #print "~keyword", keyword, "is in", keywords
- return "~"+keyword
- else:
- keyword = self.determine_keyword(keywords, used, _cpv)
- if not keyword:
- raise errors.GentoolkitUnknownKeyword(_cpv, ' '.join(keywords), used)
- return keyword
-
- def set_order(self, used):
- """Used to set the parsing order to determine a keyword
- used for installation.
-
- This is needed due to the way prefix arch's and keywords
- work with portage. It looks for the 'prefix' flag. A positive result
- sets it to the prefix order and keyword.
-
- @type used: list
- @param used: a list of pkg USE flags or the system USE flags"""
- if 'prefix' in used:
- #print "SET_ORDER() Setting parse order to prefix"
- prefix = None
- self.parse_order = self.prefix_order
- for key in self.accept_keywords:
- #print "SET_ORDER() '"+key+"'"
- if '-' in key:
- #print "SET_ORDER()found prefix keyword :", key
- if self.arch in key:
- prefix = key.split('-')[1]
- #print "prefix =", prefix
- self.prefix = prefix
- self.keyword = '-'.join([self.arch, prefix])
- else:
- #print "SET_ORDER() Setting parse order to normal"
- self.parse_order = self.normal_order
- self.keyword = self.arch
- #print "SET_ORDER() completed: prefix =", self.prefix, ", keyword =", \
- # self.keyword, "parse order =",self.parse_order
- #print
-
+ """Specialty functions for analysing the installed package db for
+ keyword useage and the packages that used them.
+
+ Note: should be initialized with the internal set_order() before use.
+ See internal set_order() for more details.
+ This class of functions can be used for single cpv checks or
+ used repeatedly for an entire package db.
+
+ @type arch: string
+ @param arch: the system ARCH setting
+ @type accept_keywords: list
+ @param accept_keywords: eg. ['x86', '~x86']
+ @type get_aux: function, defaults to: portage.db[portage.root]["vartree"].dbapi.aux_get
+ @param vardb: vardb class of functions, needed=aux_get()
+ to return => KEYWORDS & USE flags for a cpv
+ = aux_get(cpv, ["KEYWORDS", "USE"])
+ """
+
+ # parsing order to determine appropriate keyword used for installation
+ normal_order = ["stable", "testing", "prefix", "testing_prefix", "missing"]
+ prefix_order = ["prefix", "testing_prefix", "stable", "testing", "missing"]
+ parse_range = list(range(len(normal_order)))
+
+ def __init__(
+ self, arch, accept_keywords, vardb=portage.db[portage.root]["vartree"].dbapi
+ ):
+ self.arch = arch
+ self.accept_keywords = accept_keywords
+ self.vardb = vardb
+ self.prefix = ""
+ self.parse_order = None
+ self.check_key = {
+ "stable": self._stable,
+ "testing": self._testing,
+ "prefix": self._prefix,
+ "testing_prefix": self._testing_prefix,
+ "missing": self._missing,
+ }
+ self.mismatched = []
+
+ def determine_keyword(self, keywords, used, cpv):
+ """Determine the keyword from the installed USE flags and
+ the KEYWORDS that was used to install a package.
+
+ @param keywords: list of keywords available to install a pkg
+ @param used: list of USE flalgs recorded for the installed pkg
+ @rtype: string
+ @return a keyword or null string
+ """
+ used = set(used)
+ kwd = None
+ result = ""
+ if keywords:
+ absolute_kwds = reduce_keywords(keywords)
+ kwd = list(used.intersection(absolute_kwds))
+ # if keywords == ['~ppc64']:
+ # print "Checked keywords for kwd", keywords, used, "kwd =", kwd
+ if not kwd:
+ # print "Checking for kwd against portage.archlist"
+ absolute_kwds = reduce_keywords(keywords)
+ # check for one against archlist then re-check
+ kwd = list(absolute_kwds.intersection(portage.archlist))
+ # print "determined keyword =", kwd
+ if len(kwd) == 1:
+ key = kwd[0]
+ # print "determined keyword =", key
+ elif not kwd:
+ # print "kwd != 1", kwd, cpv
+ result = self._missing(self.keyword, keywords)
+ else: # too many, try to narrow them dowm
+ # print "too many kwd's, trying to match against arch"
+ _kwd = list(set(kwd).intersection(self.arch))
+ key = ""
+ if _kwd:
+ # print "found one! :)", _kwd
+ key = _kwd
+ else: # try re-running the short list against archlist
+ # print "Checking kwd for _kwd against portage.archlist"
+ _kwd = list(set(kwd).intersection(portage.archlist))
+ if _kwd and len(_kwd) == 1:
+ # print "found one! :)", _kwd
+ key = _kwd[0]
+ else:
+ # print " :( didn't work, _kwd =", _kwd, "giving up on:", cpv
+ result = self._missing(self.keyword, keywords)
+ i = 0
+ while not result and i in self.parse_range:
+ parsekey = self.parse_order[i]
+ result = self.check_key[parsekey](key, keywords)
+ i += 1
+ return result
+
+ def _stable(self, key, keywords):
+ """test for a normal stable keyword"""
+ if key in keywords:
+ return key
+ return ""
+
+ def _testing(self, key, keywords):
+ """test for a normal testing keyword"""
+ if ("~" + key) in keywords:
+ return "~" + key
+ return ""
+
+ def _prefix(self, key, keywords):
+ """test for a stable prefix keyword"""
+ if not self.prefix:
+ return ""
+ _key = "-".join([key, self.prefix])
+ if _key in keywords:
+ # print key, "is in", keywords
+ return _key
+ return ""
+
+ def _testing_prefix(self, key, keywords):
+ """test for a testing prefix keyword"""
+ if not self.prefix:
+ return ""
+ _key = "~" + "-".join([key, self.prefix])
+ if _key in keywords:
+ # print key, "is in", keywords
+ return _key
+ return ""
+
+ def _missing(self, key, keywords):
+ """generates a missing keyword to return"""
+ if self.prefix and key != self.keyword:
+ _key = "-".join([key, self.prefix])
+ else:
+ _key = "-" + key
+ # print "_missisng :( _key =", _key
+ return _key
+
+ def get_inst_keyword_cpv(self, cpv):
+ """Determines the installed with keyword for cpv
+
+ @type cpv: string
+ @param cpv: an installed CAT/PKG-VER
+ @rtype: string
+ @returns a keyword determined to have been used to install cpv
+ """
+ keywords, used = self.vardb.aux_get(cpv, ["KEYWORDS", "USE"])
+ keywords = keywords.split()
+ used = used.split()
+ return self._parse(keywords, used, cpv=cpv)
+
+ def get_inst_keyword_pkg(self, pkg):
+ """Determines the installed with keyword for cpv
+
+ @param pkg: gentoolkit.package.Package object
+ @rtype: string
+ @returns a keyword determined to have been used to install cpv
+ """
+ keywords, used = pkg.environment(
+ ["KEYWORDS", "USE"], prefer_vdb=True, fallback=False
+ )
+ keywords = keywords.split()
+ used = used.split()
+ return self._parse(keywords, used, pkg=pkg)
+
+ def _parse(self, keywords, used, pkg=None, cpv=None):
+ if pkg:
+ _cpv = pkg.cpv
+ else:
+ _cpv = cpv
+ if not self.parse_order:
+ self.set_order(used)
+ keyword = self.keyword
+ # sanity check
+ if self.arch not in used:
+ # print "Found a mismatch = ", cpv, self.arch, used
+ self.mismatched.append(_cpv)
+ if keyword in keywords:
+ # print "keyword", keyword, "is in", keywords
+ return keyword
+ elif "~" + keyword in keywords:
+ # print "~keyword", keyword, "is in", keywords
+ return "~" + keyword
+ else:
+ keyword = self.determine_keyword(keywords, used, _cpv)
+ if not keyword:
+ raise errors.GentoolkitUnknownKeyword(_cpv, " ".join(keywords), used)
+ return keyword
+
+ def set_order(self, used):
+ """Used to set the parsing order to determine a keyword
+ used for installation.
+
+ This is needed due to the way prefix arch's and keywords
+ work with portage. It looks for the 'prefix' flag. A positive result
+ sets it to the prefix order and keyword.
+
+ @type used: list
+ @param used: a list of pkg USE flags or the system USE flags"""
+ if "prefix" in used:
+ # print "SET_ORDER() Setting parse order to prefix"
+ prefix = None
+ self.parse_order = self.prefix_order
+ for key in self.accept_keywords:
+ # print "SET_ORDER() '"+key+"'"
+ if "-" in key:
+ # print "SET_ORDER()found prefix keyword :", key
+ if self.arch in key:
+ prefix = key.split("-")[1]
+ # print "prefix =", prefix
+ self.prefix = prefix
+ self.keyword = "-".join([self.arch, prefix])
+ else:
+ # print "SET_ORDER() Setting parse order to normal"
+ self.parse_order = self.normal_order
+ self.keyword = self.arch
+ # print "SET_ORDER() completed: prefix =", self.prefix, ", keyword =", \
+ # self.keyword, "parse order =",self.parse_order
+ # print