include ChangeLog
include COPYING
include CREDITS
+include DEVELOPING
include NEWS
include README
include TODO
">=dev-lang/python-2.4" and "dev-lang/python" but not
"<dev-lang/python-2.3"
- @type other: Any "Intersectable" object
+ @type other: L{gentoolkit.atom.Atom} or
+ L{gentoolkit.versionmatch.VersionMatch}
@param other: other package to compare
@see: L{pkgcore.ebuild.atom}
"""
Optionally gather indirect dependencies.
@type max_depth: int
- @param max_depth: Maximum depth to recurse if.
+ @keyword max_depth: Maximum depth to recurse if.
<1 means no maximum depth
>0 means recurse only this depth;
@type printer_fn: callable
- @param printer_fn: If None, no effect. If set, it will be applied to
+ @keyword printer_fn: If None, no effect. If set, it will be applied to
each result.
@rtype: list
@return: [(depth, pkg), ...]
44
@type pkgset: iterable
- @param pkgset: sorted pkg cpv strings or any 'intersectable' objects to
- use for calculate our revdep graph.
+ @keyword pkgset: sorted pkg cpv strings or anything sublassing
+ L{gentoolkit.cpv.CPV} to use for calculate our revdep graph.
@type max_depth: int
- @param max_depth: Maximum depth to recurse if only_direct=False.
+ @keyword max_depth: Maximum depth to recurse if only_direct=False.
-1 means no maximum depth;
0 is the same as only_direct=True;
>0 means recurse only this many times;
@type only_direct: bool
- @param only_direct: to recurse or not to recurse
+ @keyword only_direct: to recurse or not to recurse
@type printer_fn: callable
- @param printer_fn: If None, no effect. If set, it will be applied to
- each L{gentoolkit.atom.Atom} object as it is added to
- the results.
+ @keyword printer_fn: If None, no effect. If set, it will be applied to
+ each L{gentoolkit.atom.Atom} object as it is added to the results.
@rtype: list
@return: L{gentoolkit.dependencies.Dependencies} objects
"""
))
+def filter_keywords(matches):
+ """Filter non-unique keywords per slot.
+
+ This view apparently makes version bumps easier for package maintainers.
+
+ @type matches: array
+ @param matches: set of L{gentoolkit.package.Package} instances whose
+ 'key' are all the same.
+ @rtype: dict
+ @return: a dict with L{gentoolkit.package.Package} instance keys and
+ 'array of keywords not found in a higher version of pkg within the
+ same slot' values.
+ """
+
+ result = {}
+ slot_map = {}
+ # Start from the newest
+ rev_matches = reversed(matches)
+ for pkg in rev_matches:
+ keywords_str, slot = pkg.get_env_vars(('KEYWORDS', 'SLOT'))
+ keywords = keywords_str.split()
+ result[pkg] = [x for x in keywords if x not in slot_map.get(slot, [])]
+ try:
+ slot_map[slot].update(keywords)
+ except KeyError:
+ slot_map[slot] = set(keywords)
+
+ return result
+
+
def format_herds(herds):
"""Format herd information for display."""
return result
-def format_keywords(match):
- """Format keywords information for display."""
+def format_keywords(keywords):
+ """Sort and colorize keywords for display."""
+
+ result = []
- kwsplit = match.get_env_var('KEYWORDS').split()
- ver = match.cpv.fullversion
- keywords = ''
- for kw in kwsplit:
- if kw.startswith('~'):
- keywords += " %s" % pp.useflag(kw, enabled=True)
+ for kw in sorted(keywords):
+ if kw.startswith(('~', '-')):
+ # keyword (~) or arch (-) masked, color red
+ kw = pp.useflag(kw, enabled=True)
else:
- keywords += " %s" % pp.useflag(kw, enabled=False)
+ # unmasked, color blue
+ kw = pp.useflag(kw, enabled=False)
+ result.append(kw)
+
+ return ' '.join(result)
+
+
+def format_keywords_line(pkg, fmtd_keywords):
+ """Format the entire keywords line for display."""
+
+ slot = pkg.get_env_var('SLOT')
+ ver = pkg.cpv.fullversion
+ verstr_len = len(ver) + 1 + len(slot) # +1 for ':'
if CONFIG['verbose']:
result = format_line(
- keywords, "%s: " % pp.cpv(ver), " " * (len(ver) + 2)
- )
+ fmtd_keywords, "%s:%s: " % (pp.cpv(ver), pp.slot(slot)),
+ " " * (verstr_len + 2)
+ )
else:
- result = "%s:%s" % (ver, keywords)
+ result = "%s:%s: %s" % (ver, slot, fmtd_keywords)
return result
+
# R0912: *Too many branches (%s/%s)*
# pylint: disable-msg=R0912
def call_format_functions(matches):
print_sequence(upstream)
if QUERY_OPTS["keywords"] or not got_opts:
+ # Get {<Package 'dev-libs/glib-2.20.5'>: [u'ia64', u'm68k', ...], ...}
+ keyword_map = filter_keywords(matches)
+
for match in matches:
- kwds = format_keywords(match)
+ fmtd_keywords = format_keywords(keyword_map[match])
+ keywords_line = format_keywords_line(match, fmtd_keywords)
if QUERY_OPTS["keywords"]:
- print kwds
+ print keywords_line
else:
- indent = " " * (15 + len(match.cpv.fullversion))
- print format_line(kwds, "Keywords: ", indent)
+ # FIXME: duplicate code
+ slot = match.get_env_var('SLOT')
+ verstr_len = len(match.cpv.fullversion) + len(slot)
+ indent = " " * (16 + verstr_len)
+ print format_line(keywords_line, "Keywords: ", indent)
if QUERY_OPTS["description"]:
desc = ref_pkg.metadata.get_descriptions()
"""Find a package in the Portage tree to reference."""
pkg = None
- while list(reversed(matches)):
- pkg = matches[-1]
+ rev_matches = list(reversed(matches))
+ while rev_matches:
+ pkg = rev_matches.pop()
if not pkg.is_overlay():
break
"""Parse a valid metadata.xml file.
@type metadata_path: str
- @ivar metadata_path: path to a valid metadata.xml file
- @raise IOError: if C{matadata_path} can not be read
+ @param metadata_path: path to a valid metadata.xml file
+ @raise IOError: if C{metadata_path} can not be read
"""
self.metadata_path = metadata_path
if self._descriptions is not None:
return self._descriptions
- self._descriptions = [
- e.text for e in self._xml_tree.findall("longdescription")
- ]
+ long_descriptions = self._xml_tree.findall("longdescription")
+ self._descriptions = [e.text for e in long_descriptions]
return self._descriptions
def get_maintainers(self):
return result
- def get_provide(self):
- """Return a list of provides, if any"""
-
- if self.is_installed():
- result = VARDB.get_provide(str(self.cpv))
- else:
- try:
- result = [self.get_env_var('PROVIDE')]
- except KeyError:
- result = []
- return result
-
def get_ebuild_path(self, in_vartree=False):
"""Returns the complete path to the .ebuild file.
return self.get_package_path().split(os.sep)[-3]
- def get_env_var(self, var, tree=None):
- """Returns one of the predefined env vars DEPEND, SRC_URI, etc."""
+ def get_env_vars(self, envvars, tree=None):
+ """Returns one or more of the predefined environment variables.
+
+ @type envvars: array
+ @param envvars: one or more of (DEPEND, SRC_URI, etc.)"""
if tree is None:
tree = self._get_trees()[0]
try:
- result = tree.aux_get(str(self.cpv), [var])
- if len(result) != 1:
- raise errors.GentoolkitFatalError
+ result = tree.aux_get(str(self.cpv), envvars)
except (KeyError, errors.GentoolkitFatalError):
err = "aux_get returned unexpected results"
raise errors.GentoolkitFatalError(err)
- return result[0]
+ return result
+
+ def get_env_var(self, *args, **kwargs):
+ """Returns one of the predefined environment variables."""
+
+ return self.get_env_vars(args, **kwargs)[0]
def get_use_flags(self):
"""Returns the USE flags active at time of installation."""
def is_installed(self):
"""Returns True if this package is installed (merged)"""
- return VARDB.cpv_exists(str(self.cpv))
+ return self.dblink.exists()
def is_overlay(self):
"""Returns True if the package is in an overlay."""
import unittest
import py_compile
+"""Does a basic syntax check by compiling all modules. From Portage."""
+
pym_dirs = os.walk(osp.dirname(osp.dirname(osp.dirname(__file__))))
-blacklist_dirs = frozenset(('.svn', 'tests'))
+blacklist_dirs = frozenset(('.svn', 'test'))
class TestForSyntaxErrors(unittest.TestCase):