+2010-03-09: Paul Varner <fuzzyray@gentoo.org>
+ * gentoolkit: Add inital py3k support.
+ * analyse: Add new analyse utility from dol-sen. This will probably
+ change to a different name for final gentoolkit-0.3.0 release.
+
2010-02-05: Paul Varner <fuzzyray@gentoo.org>
- *revdep-rebuild: Update revdep-rebuild to use extended regular
+ * revdep-rebuild: Update revdep-rebuild to use extended regular
expressions instead of basic regular expressions. (Bug 143498)
2010-02-04: Paul Varner <fuzzyray@gentoo.org>
svn update to pull the tag from subversion
cd to the local tags/gentoolkit-0.3.0 directory
-- Create a source distribution (you need to add VERSION here, too):
+- Create a source distribution (you need to add VERSION here):
VERSION="0.3.0" ./setup.py sdist
Transfer dist/gentoolkit-0.3.0.tar.gz to dev.gentoo.org:/space/distfiles-local
- use ~/.gentoo/gentoolkit/ebump.conf
- use /etc/gentoolkit/ebump.conf
-equery:
+equery (modern):
Add more --debug stuff
Write tests for Dependencies._parser
Profile Dependencies._parser
+ Tighten up CPV.split_cpv, it's slow and bad
+ Extend PackageFormatter usage to everything that outputs packages to
+ allow for purvasive use of -F, --format goodness
+ Add package::repo search syntax to do_lookup
+ _do_repository_lookup?
+ Move do_lookout and all it's silly friends into the new query module
+ and Query class. Essentially, Query, when applied to a pkgspec input
+ should contain most of the common 'helper' methods. So we should be
+ be able to do:
+ Query('portage').find_best(),
+ Query('portage').find_package(),
+ Query('portag*').is_regex() or .uses_globbing(), etc.
Refactor each module to be useful for import. Done modules:
+depends
+belongs
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright 2002-2010 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License v2 or later
+#
+# $Header$
+
+"""'analyse' is a flexible utility for Gentoo linux which can display various
+information about installed packages, such as the USE flags used and the
+packages that use them. It can also be used to help rebuild /etc/portage/package.*
+files in the event of corruption, and possibly more.
+"""
+
+from __future__ import print_function
+
+import sys
+# This block ensures that ^C interrupts are handled quietly.
+try:
+ import signal
+
+ def exithandler(signum,frame):
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
+ print()
+ sys.exit(1)
+
+ signal.signal(signal.SIGINT, exithandler)
+ signal.signal(signal.SIGTERM, exithandler)
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+except KeyboardInterrupt:
+ print()
+ sys.exit(1)
+
+from gentoolkit import analyse, errors
+
+try:
+ analyse.main()
+except errors.GentoolkitException as err:
+ if '--debug' in sys.argv:
+ raise
+ else:
+ from gentoolkit import pprinter as pp
+ sys.stderr.write(pp.error(str(err)))
+ print()
+ print("Add '--debug' to global options for traceback.")
+ sys.exit(1)
#!/usr/bin/python
-# Copyright 2003-2010 Gentoo Foundation
+# Copyright 2003-2005 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
-from __future__ import with_statement
+from __future__ import print_function
+
###############################################################################
# Meta:
# Python imports:
import sys
-import os, stat
+import stat
import re
import time
import getopt
-import fpformat
import signal
import portage
from portage.output import *
+from portage import os
+
+from gentoolkit.helpers import walk
listdir = portage.listdir
###############################################################################
# printVersion:
def printVersion():
- print "%s (%s) - %s" \
- % (__productname__, __version__, __description__)
- print
- print "Author: %s <%s>" % (__author__,__email__)
- print "Copyright 2003-2010 Gentoo Foundation"
- print "Distributed under the terms of the GNU General Public License v2"
+ print("%s (%s) - %s" \
+ % (__productname__, __version__, __description__))
+ print()
+ print("Author: %s <%s>" % (__author__,__email__))
+ print("Copyright 2003-2009 Gentoo Foundation")
+ print("Distributed under the terms of the GNU General Public License v2")
###############################################################################
if not error and not help: help = 'all'
if error == 'time':
eerror("Wrong time specification")
- print >>out, "Time specification should be an integer followed by a"+ \
- " single letter unit."
- print >>out, "Available units are: y (years), m (months), w (weeks), "+ \
- "d (days) and h (hours)."
- print >>out, "For instance: \"1y\" is \"one year\", \"2w\" is \"two"+ \
- " weeks\", etc. "
+ print("Time specification should be an integer followed by a"+ \
+ " single letter unit.", file=out)
+ print("Available units are: y (years), m (months), w (weeks), "+ \
+ "d (days) and h (hours).", file=out)
+ print("For instance: \"1y\" is \"one year\", \"2w\" is \"two"+ \
+ " weeks\", etc. ", file=out)
return
if error == 'size':
eerror("Wrong size specification")
- print >>out, "Size specification should be an integer followed by a"+ \
- " single letter unit."
- print >>out, "Available units are: G, M, K and B."
- print >>out, "For instance: \"10M\" is \"ten megabytes\", \"200K\" "+ \
- "is \"two hundreds kilobytes\", etc."
+ print("Size specification should be an integer followed by a"+ \
+ " single letter unit.", file=out)
+ print("Available units are: G, M, K and B.", file=out)
+ print("For instance: \"10M\" is \"ten megabytes\", \"200K\" "+ \
+ "is \"two hundreds kilobytes\", etc.", file=out)
return
if error in ('global-options', 'packages-options', 'distfiles-options', \
'merged-packages-options', 'merged-distfiles-options',):
eerror("Wrong option on command line.")
- print >>out
+ print(file=out)
elif error == 'actions':
eerror("Wrong or missing action name on command line.")
- print >>out
- print >>out, white("Usage:")
+ print(file=out)
+ print(white("Usage:"), file=out)
if error in ('actions','global-options', 'packages-options', \
'distfiles-options') or help == 'all':
- print >>out, " "+turquoise(__productname__), \
+ print(" "+turquoise(__productname__), \
yellow("[global-option] ..."), \
green("<action>"), \
- yellow("[action-option] ...")
+ yellow("[action-option] ..."), file=out)
if error == 'merged-distfiles-options' or help in ('all','distfiles'):
- print >>out, " "+turquoise(__productname__+'-dist'), \
- yellow("[global-option, distfiles-option] ...")
+ print(" "+turquoise(__productname__+'-dist'), \
+ yellow("[global-option, distfiles-option] ..."), file=out)
if error == 'merged-packages-options' or help in ('all','packages'):
- print >>out, " "+turquoise(__productname__+'-pkg'), \
- yellow("[global-option, packages-option] ...")
+ print(" "+turquoise(__productname__+'-pkg'), \
+ yellow("[global-option, packages-option] ..."), file=out)
if error in ('global-options', 'actions'):
- print >>out, " "+turquoise(__productname__), \
- yellow("[--help, --version]")
+ print(" "+turquoise(__productname__), \
+ yellow("[--help, --version]"), file=out)
if help == 'all':
- print >>out, " "+turquoise(__productname__+"(-dist,-pkg)"), \
- yellow("[--help, --version]")
+ print(" "+turquoise(__productname__+"(-dist,-pkg)"), \
+ yellow("[--help, --version]"), file=out)
if error == 'merged-packages-options' or help == 'packages':
- print >>out, " "+turquoise(__productname__+'-pkg'), \
- yellow("[--help, --version]")
+ print(" "+turquoise(__productname__+'-pkg'), \
+ yellow("[--help, --version]"), file=out)
if error == 'merged-distfiles-options' or help == 'distfiles':
- print >>out, " "+turquoise(__productname__+'-dist'), \
- yellow("[--help, --version]")
- print >>out
+ print(" "+turquoise(__productname__+'-dist'), \
+ yellow("[--help, --version]"), file=out)
+ print(file=out)
if error in ('global-options', 'merged-packages-options', \
'merged-distfiles-options') or help:
- print >>out, "Available global", yellow("options")+":"
- print >>out, yellow(" -C, --nocolor")+ \
- " - turn off colors on output"
- print >>out, yellow(" -d, --destructive")+ \
- " - only keep the minimum for a reinstallation"
- print >>out, yellow(" -e, --exclude-file=<path>")+ \
- " - path to the exclusion file"
- print >>out, yellow(" -i, --interactive")+ \
- " - ask confirmation before deletions"
- print >>out, yellow(" -n, --package-names")+ \
- " - protect all versions (when --destructive)"
- print >>out, yellow(" -p, --pretend")+ \
- " - only display what would be cleaned"
- print >>out, yellow(" -q, --quiet")+ \
- " - be as quiet as possible"
- print >>out, yellow(" -t, --time-limit=<time>")+ \
- " - don't delete files modified since "+yellow("<time>")
- print >>out, " "+yellow("<time>"), "is a duration: \"1y\" is"+ \
- " \"one year\", \"2w\" is \"two weeks\", etc. "
- print >>out, " "+"Units are: y (years), m (months), w (weeks), "+ \
- "d (days) and h (hours)."
- print >>out, yellow(" -h, --help")+ \
- " - display the help screen"
- print >>out, yellow(" -V, --version")+ \
- " - display version info"
- print >>out
+ print("Available global", yellow("options")+":", file=out)
+ print(yellow(" -C, --nocolor")+ \
+ " - turn off colors on output", file=out)
+ print(yellow(" -d, --destructive")+ \
+ " - only keep the minimum for a reinstallation", file=out)
+ print(yellow(" -e, --exclude-file=<path>")+ \
+ " - path to the exclusion file", file=out)
+ print(yellow(" -i, --interactive")+ \
+ " - ask confirmation before deletions", file=out)
+ print(yellow(" -n, --package-names")+ \
+ " - protect all versions (when --destructive)", file=out)
+ print(yellow(" -p, --pretend")+ \
+ " - only display what would be cleaned", file=out)
+ print(yellow(" -q, --quiet")+ \
+ " - be as quiet as possible", file=out)
+ print(yellow(" -t, --time-limit=<time>")+ \
+ " - don't delete files modified since "+yellow("<time>"), file=out)
+ print(" "+yellow("<time>"), "is a duration: \"1y\" is"+ \
+ " \"one year\", \"2w\" is \"two weeks\", etc. ", file=out)
+ print(" "+"Units are: y (years), m (months), w (weeks), "+ \
+ "d (days) and h (hours).", file=out)
+ print(yellow(" -h, --help")+ \
+ " - display the help screen", file=out)
+ print(yellow(" -V, --version")+ \
+ " - display version info", file=out)
+ print(file=out)
if error == 'actions' or help == 'all':
- print >>out, "Available", green("actions")+":"
- print >>out, green(" packages")+ \
- " - clean outdated binary packages from:"
- print >>out, " ",teal(pkgdir)
- print >>out, green(" distfiles")+ \
- " - clean outdated packages sources files from:"
- print >>out, " ",teal(distdir)
- print >>out
+ print("Available", green("actions")+":", file=out)
+ print(green(" packages")+ \
+ " - clean outdated binary packages from:", file=out)
+ print(" ",teal(pkgdir), file=out)
+ print(green(" distfiles")+ \
+ " - clean outdated packages sources files from:", file=out)
+ print(" ",teal(distdir), file=out)
+ print(file=out)
if error in ('packages-options','merged-packages-options') \
or help in ('all','packages'):
- print >>out, "Available", yellow("options"),"for the", \
- green("packages"),"action:"
- print >>out, yellow(" NONE :)")
- print >>out
+ print("Available", yellow("options"),"for the", \
+ green("packages"),"action:", file=out)
+ print(yellow(" NONE :)"), file=out)
+ print(file=out)
if error in ('distfiles-options', 'merged-distfiles-options') \
or help in ('all','distfiles'):
- print >>out, "Available", yellow("options"),"for the", \
- green("distfiles"),"action:"
- print >>out, yellow(" -f, --fetch-restricted")+ \
- " - protect fetch-restricted files (when --destructive)"
- print >>out, yellow(" -s, --size-limit=<size>")+ \
- " - don't delete distfiles bigger than "+yellow("<size>")
- print >>out, " "+yellow("<size>"), "is a size specification: "+ \
- "\"10M\" is \"ten megabytes\", \"200K\" is"
- print >>out, " "+"\"two hundreds kilobytes\", etc. Units are: "+ \
- "G, M, K and B."
- print >>out
- print >>out, "More detailed instruction can be found in", \
- turquoise("`man %s`" % __productname__)
+ print("Available", yellow("options"),"for the", \
+ green("distfiles"),"action:", file=out)
+ print(yellow(" -f, --fetch-restricted")+ \
+ " - protect fetch-restricted files (when --destructive)", file=out)
+ print(yellow(" -s, --size-limit=<size>")+ \
+ " - don't delete distfiles bigger than "+yellow("<size>"), file=out)
+ print(" "+yellow("<size>"), "is a size specification: "+ \
+ "\"10M\" is \"ten megabytes\", \"200K\" is", file=out)
+ print(" "+"\"two hundreds kilobytes\", etc. Units are: "+ \
+ "G, M, K and B.", file=out)
+ print(file=out)
+ print("More detailed instruction can be found in", \
+ turquoise("`man %s`" % __productname__), file=out)
###############################################################################
def einfo(message="", nocolor=False):
if not nocolor: prefix = " "+green('*')
else: prefix = ">>>"
- print prefix,message
+ print(prefix,message)
###############################################################################
def eerror(message="", nocolor=False):
if not nocolor: prefix = " "+red('*')
else: prefix = "!!!"
- print >>sys.stderr,prefix,message
+ print(prefix,message, file=sys.stderr)
###############################################################################
# result. Output is a string.
def prettySize(size,justify=False):
units = [" G"," M"," K"," B"]
- approx = 0
+ fmt = "{0:.0f}"
while len(units) and size >= 1000:
- approx = 1
+ fmt = "{0:.1f}"
size = size / 1024.
units.pop()
- sizestr = fpformat.fix(size,approx)+units[-1]
+ sizestr = fmt.format(size)+units[-1]
if justify:
sizestr = " " + blue("[ ") + " "*(7-len(sizestr)) \
+ green(sizestr) + blue(" ]")
user_string="xxx"
while not user_string.lower() in ["","y","n","a","yes","no","all"]:
eprompt(message+" [Y/n/a]: ", myoptions['nocolor'])
- user_string = raw_input()
+ user_string = sys.stdin.readline()
if user_string.lower() in ["a","all"]:
myoptions['accept_all'] = True
myanswer = user_string.lower() in ["","y","a","yes","all"]
eerror("Please set PKGDIR to a sane value.", myoptions['nocolor'])
eerror("(Check your /etc/make.conf and environment).", myoptions['nocolor'])
exit(1)
- for root, dirs, files in os.walk(pkgdir):
+ for root, dirs, files in walk(pkgdir):
if root[-3:] == 'All': continue
for file in files:
if not file[-5:] == ".tbz2":
if action == 'distfiles': file_type = 'file'
else: file_type = 'binary package'
# sorting helps reading
- clean_keys = clean_dict.keys()
+ clean_keys = list(clean_dict.keys())
clean_keys.sort()
clean_size = 0
# clean all entries one by one
myoptions['nocolor'])
if not myoptions['quiet']:
# pretty print mode
- print prettySize(key_size,True),teal(mykey)
+ print(prettySize(key_size,True),teal(mykey))
elif myoptions['pretend'] or myoptions['interactive']:
# file list mode
- for file in clean_dict[mykey]: print file
+ for file in clean_dict[mykey]: print(file)
#else: actually delete stuff, but don't print anything
if myoptions['pretend']: clean_size += key_size
elif not myoptions['interactive'] \
time_limit=myoptions['time-limit'], \
size_limit=myoptions['size-limit'])
# actually clean files if something was found
- if len(clean_dict.keys()):
+ if clean_dict:
# verbose pretend message
if myoptions['pretend'] and not myoptions['quiet']:
einfo("Here are "+files_type+" that would be deleted:", \
# parse command line options and actions
try: myaction = parseArgs(myoptions)
# filter exception to know what message to display
- except ParseArgsException, e:
+ except ParseArgsException as e:
if e.value == 'help':
printUsage(help='all')
sys.exit(0)
myoptions['exclude-file'] = my_exclude_file
if 'exclude-file' in myoptions:
try: exclude_dict = parseExcludeFile(myoptions['exclude-file'])
- except ParseExcludeFileException, e:
+ except ParseExcludeFileException as e:
eerror(e, myoptions['nocolor'])
eerror("Invalid exclusion file: %s" % myoptions['exclude-file'], \
myoptions['nocolor'])
if __name__ == "__main__":
try: main()
except KeyboardInterrupt:
- print "Aborted."
+ print("Aborted.")
sys.exit(130)
sys.exit(0)
#!/usr/bin/python
#
-# Copyright 2009-2010 Gentoo Technologies, Inc.
+# Copyright 2009 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2 or later
#
# $Header$
"""Shortcut to equery meta"""
+from __future__ import print_function
+
__authors__ = (
'Douglas Anderson <douglasjanderson@gmail.com>: equery meta',
'Ned Ludd <solar@gentoo.org>: first full implimentation'
from gentoolkit.equery.meta import main, print_help
def print_epkginfo_help():
- print mod_usage(mod_name="epkginfo")
- print
+ print(mod_usage(mod_name="epkginfo"))
+ print()
print_help(with_usage=False)
equery.initialize_configuration()
else:
try:
main(args)
- except errors.GentoolkitException, err:
+ except errors.GentoolkitException as err:
from gentoolkit import pprinter as pp
pp.die(1, str(err))
#!/usr/bin/python
#
-# Copyright 2002-2010 Gentoo Technologies, Inc.
+# Copyright 2002-2009 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2 or later
#
# $Header$
the MD5 sum of each file owned by a given package, and many other things.
"""
+from __future__ import print_function
+
import sys
# This block ensures that ^C interrupts are handled quietly.
try:
def exithandler(signum,frame):
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
- print
+ print()
sys.exit(1)
signal.signal(signal.SIGINT, exithandler)
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except KeyboardInterrupt:
- print
+ print()
sys.exit(1)
from gentoolkit import equery, errors
try:
equery.main()
-except errors.GentoolkitException, err:
+except errors.GentoolkitException as err:
if '--debug' in sys.argv:
raise
else:
from gentoolkit import pprinter as pp
sys.stderr.write(pp.error(str(err)))
- print
- print "Add '--debug' to global options for traceback."
+ print()
+ print("Add '--debug' to global options for traceback.")
sys.exit(1)
${PROGRAM_NAME} (${VERSION})
Written by Marius Mauch
-Copyright (C) 2004-2010 Gentoo Foundation, Inc.
+Copyright (C) 2004-2009 Gentoo Foundation, Inc.
This is free software; see the source for copying conditions.
VER
}
# $Header: $
# This program is licensed under the GPL, version 2
-import os
import sys
import codecs
+from functools import reduce
import portage
from portage.output import *
+from portage import os
from getopt import getopt, GetoptError
if args in [o for o in m[:-1]]:
mode = m[1][2:]
-except GetoptError, e:
+except GetoptError as e:
sys.stderr.write("unknown option given: ")
sys.stderr.write(str(e)+"\n")
mode = "HELP"
for x in todolist:
try:
myglsa = Glsa(x, glsaconfig)
- except (GlsaTypeException, GlsaFormatException), e:
+ except (GlsaTypeException, GlsaFormatException) as e:
if verbose:
sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (x, e)))
continue
glsalist.extend([g for g in params if g not in glsalist])
def summarylist(myglsalist, fd1=sys.stdout, fd2=sys.stderr, encoding="utf-8"):
+ # Get to the raw streams in py3k before wrapping them with an encoded writer
+ # to avoid writing bytes to a text stream (stdout/stderr are text streams
+ # by default in py3k)
+ if hasattr(fd1, "buffer"):
+ fd1 = fd1.buffer
+ if hasattr(fd2, "buffer"):
+ fd2 = fd2.buffer
fd1 = codecs.getwriter(encoding)(fd1)
fd2 = codecs.getwriter(encoding)(fd2)
if not quiet:
for myid in myglsalist:
try:
myglsa = Glsa(myid, glsaconfig)
- except (GlsaTypeException, GlsaFormatException), e:
+ except (GlsaTypeException, GlsaFormatException) as e:
if verbose:
fd2.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
continue
fd1.write(color(myglsa.nr) + " " + color(status) + " " + color(access) + myglsa.title + " (")
if not verbose:
- for pkg in myglsa.packages.keys()[:3]:
+ for pkg in list(myglsa.packages.keys())[:3]:
fd1.write(" " + pkg + " ")
if len(myglsa.packages) > 3:
fd1.write("... ")
for myid in glsalist:
try:
myglsa = Glsa(myid, glsaconfig)
- except (GlsaTypeException, GlsaFormatException), e:
+ except (GlsaTypeException, GlsaFormatException) as e:
if verbose:
sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
continue
# see if anything is left that can be upgraded
if mergedict:
sys.stdout.write(">>> Updates that will be performed:\n")
- for (upd, vuln) in mergedict.iteritems():
+ for (upd, vuln) in mergedict.items():
sys.stdout.write(" " + green(upd) + " (vulnerable: " + red(", ".join(vuln)) + ")\n")
if no_upgrades:
for myid in glsalist:
try:
myglsa = Glsa(myid, glsaconfig)
- except (GlsaTypeException, GlsaFormatException), e:
+ except (GlsaTypeException, GlsaFormatException) as e:
if verbose:
sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
continue
import portage_mail
import socket
- from StringIO import StringIO
+ from io import StringIO
try:
from email.mime.text import MIMEText
except ImportError:
for myid in glsalist:
try:
myglsa = Glsa(myid, glsaconfig)
- except (GlsaTypeException, GlsaFormatException), e:
+ except (GlsaTypeException, GlsaFormatException) as e:
if verbose:
sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
continue
myattachments.append(MIMEText(str(myfd.getvalue()), _charset="utf8"))
myfd.close()
- if glsalist or not quiet:
+ if glsalist or not quiet:
mymessage = portage_mail.create_message(myfrom, myrecipient, mysubject, summary, myattachments)
portage_mail.send_mail(glsaconfig, mymessage)
get_search_env() {
local new_env
local old_env
- local uid=$(python -c 'import os; import pwd; print pwd.getpwuid(os.getuid())[0]')
+ local uid=$(python -c 'import os; import pwd; print(pwd.getpwuid(os.getuid())[0])')
# Find a place to put temporary files
if [[ "$uid" == "root" ]]; then
local tmp_target="/var/cache/${APP_NAME}"
--- /dev/null
+.TH "ANALYSE" "22" "Febuary 2010" "GENTOOLKIT"
+.SH "NAME"
+analyse \- Gentoo Installed Package Analysis Tool
+
+.SH "SYNOPSIS"
+.BI "analyse " "[global-options] " "module " "[local-options]" "TARGET"
+
+.SH "DESCRIPTION"
+.B Analyse
+Is a collection of modules for analysing the state of installed Gentoo packages for
+USE flags or keywords used for installation, and their current masking status.
+.br
+It can also optionally (re)generate new /etc/portage/package.* files.
+
+.SH "GLOBAL OPTIONS"
+.HP
+.B \-h, \-\-help
+.br
+Output a help message.
+.HP
+.B \-q, \-\-quiet
+.br
+Be less verbose where possible. In some modules, this option can increase the output speed.
+.HP
+.B \-C, \-\-no-color
+.br
+Do not colorize output.
+.HP
+.B \-N, \-\-no\-pipe
+.br
+Turn off automatic pipe detection. Use this option if you do not want
+.B analyse
+To detect if the output is being directed to the screen or to another program
+and adjust color and verbosity accordingly.
+.HP
+.B \-V, \-\-version
+.br
+Display \fBGentoolkit\fP's version. Please include this in all bug reports. (see
+.B BUGS
+below)
+
+.SH "MODULES"
+.B Analyse
+Uses a system of modules. Each module has both a long and short name.
+The list below uses the notation "\fBmodule (m)\fP", where \fIm\fP is the short name
+and \fImodule\fP is the long name.
+.P
+You can view the
+.B help
+message for a specific module by using
+.BR "-h" ", " "--help "
+as either a global option (after
+.B analyse
+and before the module name) or as a local option (after the module name).
+
+.SS
+.BI "analyse (a) [OPTIONS] TARGET"
+Report on all installed packages for \fITARGET\fP.
+.P
+
+.IR "TARGET" ":"
+.HP
+.B use
+.br
+Will analyse the installed with USE flags for output results.
+.HP
+.B pkguse
+.br
+Will analyse the USE flags information from the installed pkg's 'PKGUSE' file which contains
+only flags settings from /etc/portage/package.use at the time of installation.
+.HP
+.B keywords
+.br
+Will analyse the recorded keywords for output results.
+.HP
+.B unmask
+.br
+Will analyse the installed packages and portage trees for pkgs that require unmasking and report them.
+.br
+.P
+.IR "LOCAL OPTIONS" ":"
+.HP
+.B \-u, \-\-unset
+.br
+Will also include any USE flags used that were not enabled for some packages.
+.HP
+.B \-v, \-\-verebose
+.br
+Gives more detail about the results found and the current task being performed.
+
+.P
+.IR "EXAMPLES" ":"
+.EX
+.HP
+analyse a --verbose --unset use
+.EE
+.br
+Report on all use flags used to install the packages. (--unset) Include in the report all flags
+that have been used but also were not set enabled for some packages.
+(--verbose) Also list the packages that used the USE flag setting.
+The report will break down the useage and report the USE flag up to 3 times indicating its
+setting {"+","-"," "= unset} prepended to the flag name.
+It will also color the output, red = Disabled, blue = Enabled, plain text = unset
+.br
+
+.SS
+.BI "rebuild (r) [OPTIONS] TARGET"
+Create a list all packages for \fITARGET\fP settings that are needed for
+other than the default settings.
+
+.IR "TARGET" ":"
+.HP
+.B use
+.br
+Will analyse the USE flags for output results.
+.HP
+.B keywords
+.br
+Will analyse the keywords for output results.
+.HP
+.B unmask
+.br
+Will analyse the installed packages and portage trees for pkgs that require
+unmasking and produce output/a new /etc/portage/package.unmask file.
+.P
+.IR "LOCAL OPTIONS" ":"
+.HP
+.B \-a, \-\-all
+.br
+Create files/output for all TARGET(s) found to need it. (not Implemented yet)
+.HP
+.B \-e, \-\-excact
+.br
+Will prepend the pkg with = as well as use the version information for the entries.
+.br
+eg.: =CAT/PKG-VER flag1 flag2
+.HP
+.B \-p, \-\-pretend
+.br
+Sends the output to the screen instead of a file.
+.HP
+.B \-v, \-\-verebose
+.br
+Gives more detail about the results found and the current task being performed.
+.P
+.IR "EXAMPLES" ":"
+.EX
+.HP
+analyse rebuild -p use
+.EE
+.br
+Analyse the installed packages database and current system USE flag settings
+ and output the results in the form of:
+.br
+
+.br
+.EX
+CAT/PKG -flag1 -flag2 flag3 flag4...
+
+.SS
+.BI "clean (c) [OPTIONS] TARGET"
+Clean all packages for \fITARGET\fP settings that are found with obsolete settings
+for the current settings and pkg ebuild. (not Implemented yet)
+
+.IR "TARGET" ":"
+.HP
+.B use
+.br
+Will analyse the USE flags and /etc/portage/package.use file(s) for entries that
+are redundant or no longer used by the pkg.
+.HP
+.B keywords
+.br
+Will analyse the keywords and /etc/portage/package.keywords file(s) for entries
+that are no longer needed.
+.HP
+.B unmask
+.br
+Will analyse the installed packages, /etc/portage/package.unmask file(s) and
+portage trees for pkgs that no longer require unmasking.
+.P
+.IR "LOCAL OPTIONS" ":"
+.HP
+.B \-a, \-\-all
+.br
+Clean files/output for all TARGET(s) found to need it. (not Implemented yet)
+.HP
+.B \-p, \-\-pretend
+.br
+Sends the output to the screen instead of a file.
+.HP
+.B \-v, \-\-verebose
+.br
+Gives more detail about the results found and the current task being performed.
+
+
+.SH "BUGS"
+Submit bug reports to http://bugs.gentoo.org.
+
+.SH "AUTHORS"
+.br
+Brian Dolbec <brian.dolbec@gmail.com>, 2010
.HP
.B \-m, \-\-maintainer
.br
-Show the package maintainer(s) email address. If the metadata is available, also show the maintainer's name and/or job description. (shown by default)
+Show the package maintainer(s) email address. If the metadata is available, also show the maitainer's name and/or job description. (shown by default)
.HP
.B \-u, \-\-useflags
.br
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright 2002-2010 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License v2 or later
+#
+# $Header$
+
+"""'analyse' is a flexible utility for Gentoo linux which can display various
+information about installed packages, such as the USE flags used and the
+packages that use them. It can also be used to help rebuild /etc/portage/package.*
+files in the event of corruption, and possibly more.
+"""
+
+import sys
+# This block ensures that ^C interrupts are handled quietly.
+try:
+ import signal
+
+ def exithandler(signum,frame):
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
+ print
+ sys.exit(1)
+
+ signal.signal(signal.SIGINT, exithandler)
+ signal.signal(signal.SIGTERM, exithandler)
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+except KeyboardInterrupt:
+ print
+ sys.exit(1)
+
+from gentoolkit import analyse, errors
+
+try:
+ analyse.main()
+except errors.GentoolkitException, err:
+ if '--debug' in sys.argv:
+ raise
+ else:
+ from gentoolkit import pprinter as pp
+ sys.stderr.write(pp.error(str(err)))
+ print
+ print "Add '--debug' to global options for traceback."
+ sys.exit(1)
#!/usr/bin/python
#
# Copyright 2003-2004 Karl Trygve Kalleberg
-# Copyright 2003-2010 Gentoo Foundation
+# Copyright 2003-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
#
# $Header$
'piping': False if sys.stdout.isatty() else True,
# Set some defaults:
'quiet': False,
+ # verbose is True if not quiet and not piping
+ 'verbose': True,
'debug': False
}
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright(c) 2010, Gentoo Foundation
+# Copyright 2003-2004 Karl Trygve Kalleberg
+# Licensed under the GNU General Public License, v2
+#
+# $Header: $
+
+"""Gentoo's installed packages analysis and repair tool"""
+
+
+# Move to Imports section after Python 2.6 is stable
+
+
+__docformat__ = 'epytext'
+# version is dynamically set by distutils sdist
+__version__ = "svn"
+__productname__ = "analyse"
+__authors__ = (
+ 'Brian Dolbec, <brian.dolbec@gmail.com>'
+
+)
+
+# make an exportable copy of the info for help output
+MODULE_INFO = {
+ "__docformat__": __docformat__,
+ "__doc__": __doc__,
+ "__version__": __version__,
+ "__productname__": __productname__,
+ "__authors__": __authors__
+
+}
+
+import errno
+import sys
+import time
+from getopt import getopt, GetoptError
+
+import portage
+from portage import os
+
+import gentoolkit as gen
+from gentoolkit import errors
+from gentoolkit import pprinter as pp
+from gentoolkit.base import (initialize_configuration, split_arguments,
+ parse_global_options, print_help)
+from gentoolkit.formatters import format_options
+
+
+NAME_MAP = {
+ 'a': 'analyse',
+ 'r': 'rebuild'
+}
+
+FORMATTED_OPTIONS = (
+ (" (a)nalyse",
+ "analyses the installed PKG database USE flag or keyword useage"),
+ (" (r)ebuild",
+ "analyses the Installed PKG database and generates files suitable"),
+ (" ",
+ "to replace corrupted or missing /etc/portage/package.* files")
+ )
+
+def expand_module_name(module_name):
+ """Returns one of the values of NAME_MAP or raises KeyError"""
+
+ if module_name == 'list':
+ # list is a Python builtin type, so we must rename our module
+ return 'list_'
+ elif module_name in NAME_MAP.values():
+ return module_name
+ else:
+ return NAME_MAP[module_name]
+
+
+def main():
+ """Parse input and run the program."""
+
+ short_opts = "hqCNV"
+ long_opts = (
+ 'help', 'quiet', 'nocolor', 'no-color', 'no-pipe', 'version', 'debug'
+ )
+
+ initialize_configuration()
+
+ try:
+ global_opts, args = getopt(sys.argv[1:], short_opts, long_opts)
+ except GetoptError as err:
+ sys.stderr.write(" \n")
+ sys.stderr.write(pp.error("Global %s\n" % err))
+ print_help(MODULE_INFO, FORMATTED_OPTIONS, with_description=False)
+ sys.exit(2)
+
+ # Parse global options
+ need_help = parse_global_options(global_opts, args, MODULE_INFO, FORMATTED_OPTIONS)
+
+ if gen.CONFIG['quiet']:
+ gen.CONFIG['verbose'] = False
+
+ try:
+ module_name, module_args = split_arguments(args)
+ except IndexError:
+ print_help(MODULE_INFO, FORMATTED_OPTIONS)
+ sys.exit(2)
+
+ if need_help:
+ module_args.append('--help')
+
+ try:
+ expanded_module_name = expand_module_name(module_name)
+ except KeyError:
+ sys.stderr.write(pp.error("Unknown module '%s'" % module_name))
+ print_help(MODULE_INFO, FORMATTED_OPTIONS, with_description=False)
+ sys.exit(2)
+
+ try:
+ loaded_module = __import__(
+ expanded_module_name, globals(), locals(), [], -1
+ )
+ loaded_module.main(module_args)
+ except portage.exception.AmbiguousPackageName as err:
+ raise errors.GentoolkitAmbiguousPackage(err)
+ except IOError as err:
+ if err.errno != errno.EPIPE:
+ raise
+
+if __name__ == '__main__':
+ main()
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright(c) 2010, Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+#
+
+"""Provides a breakdown list of USE flags or keywords used and by
+what packages according to the Installed package database"""
+
+from __future__ import print_function
+
+import sys
+
+import gentoolkit
+from gentoolkit.dbapi import PORTDB, VARDB
+from gentoolkit.analyse.base import ModuleBase
+from gentoolkit import pprinter as pp
+from gentoolkit.analyse.lib import (get_installed_use, get_iuse, abs_flag,
+ abs_list, get_all_cpv_use, get_flags, FlagAnalyzer, KeywordAnalyser)
+from gentoolkit.analyse.output import nl, AnalysisPrinter
+from gentoolkit.package import Package
+
+import portage
+
+
+def gather_flags_info(
+ cpvs=None,
+ system_flags=None,
+ include_unset=False,
+ target="USE",
+ use_portage=False,
+ # override-able for testing
+ _get_flags=get_flags,
+ _get_used=get_installed_use
+ ):
+ """Analyse the installed pkgs USE flags for frequency of use
+
+ @param cpvs: optional list of [cat/pkg-ver,...] to analyse or
+ defaults to entire installed pkg db
+ @rtype dict. {flag:{"+":[cat/pkg-ver,...], "-":[cat/pkg-ver,...], "unset":[]}
+ """
+ if cpvs is None:
+ cpvs = VARDB.cpv_all()
+ # pass them in to override for tests
+ flags = FlagAnalyzer(system_flags,
+ _get_flags=_get_flags,
+ _get_used=get_installed_use
+ )
+ flag_users = {}
+ for cpv in cpvs:
+ if cpv.startswith("virtual"):
+ continue
+ if use_portage:
+ plus, minus, unset = flags.analyse_cpv(cpv)
+ else:
+ pkg = Package(cpv)
+ plus, minus, unset = flags.analyse_pkg(pkg)
+ for flag in plus:
+ if flag in flag_users:
+ flag_users[flag]["+"].append(cpv)
+ else:
+ flag_users[flag] = {"+": [cpv], "-": []}
+ for flag in minus:
+ if flag in flag_users:
+ flag_users[flag]["-"].append(cpv)
+ else:
+ flag_users[flag] = {"+":[], "-": [cpv]}
+ if include_unset:
+ for flag in unset:
+ if flag in flag_users:
+ if "unset" in flag_users[flag]:
+ flag_users[flag]["unset"].append(cpv)
+ else:
+ flag_users[flag]["unset"] = [cpv]
+ else:
+ flag_users[flag] = {"+": [], "-": [], "unset": [cpv]}
+ return flag_users
+
+
+def gather_keywords_info(
+ cpvs=None,
+ system_keywords=None,
+ use_portage=False,
+ # override-able for testing
+ keywords=portage.settings["ACCEPT_KEYWORDS"],
+ analyser = None
+ ):
+ """Analyse the installed pkgs 'keywords' for frequency of use
+
+ @param cpvs: optional list of [cat/pkg-ver,...] to analyse or
+ defaults to entire installed pkg db
+ @param system_keywords: list of the system keywords
+ @param keywords: user defined list of keywords to check and report on
+ or reports on all relevant keywords found to have been used.
+ @param _get_kwds: overridable function for testing
+ @param _get_used: overridable function for testing
+ @rtype dict. {keyword:{"stable":[cat/pkg-ver,...], "testing":[cat/pkg-ver,...]}
+ """
+ if cpvs is None:
+ cpvs = VARDB.cpv_all()
+ keyword_users = {}
+ for cpv in cpvs:
+ if cpv.startswith("virtual"):
+ continue
+ if use_portage:
+ keyword = analyser.get_inst_keyword_cpv(cpv)
+ else:
+ pkg = Package(cpv)
+ keyword = analyser.get_inst_keyword_pkg(pkg)
+ #print "returned keyword =", cpv, keyword, keyword[0]
+ key = keyword[0]
+ if key in ["~", "-"]:
+ _kwd = keyword[1:]
+ if _kwd in keyword_users:
+ if key in ["~"]:
+ keyword_users[_kwd]["testing"].append(cpv)
+ elif key in ["-"]:
+ #print "adding cpv to missing:", cpv
+ keyword_users[_kwd]["missing"].append(cpv)
+ else:
+ if key in ["~"]:
+ keyword_users[_kwd] = {"stable": [],
+ "testing": [cpv], "missing": []}
+ elif key in ["-"]:
+ keyword_users[_kwd] = {"stable": [],
+ "testing": [], "missing": [cpv]}
+ else:
+ keyword_users[_kwd] = {"stable": [cpv],
+ "testing": [], "missing": []}
+ elif keyword in keyword_users:
+ keyword_users[keyword]["stable"].append(cpv)
+ else:
+ keyword_users[keyword] = {"stable": [cpv], "testing": [], "missing": []}
+ return keyword_users
+
+
+class Analyse(ModuleBase):
+ """Installed db analysis tool to query the installed databse
+ and produce/output stats for USE flags or keywords/mask.
+ The 'rebuild' action output is in the form suitable for file type output
+ to create a new package.use, package.keywords, package.unmask
+ type files in the event of needing to rebuild the
+ /etc/portage/* user configs
+ """
+ def __init__(self):
+ ModuleBase.__init__(self)
+ self.module_name = "analyse"
+ self.options = {
+ "flags": False,
+ "keywords": False,
+ "unset": False,
+ "verbose": False,
+ "quiet": False,
+ 'prefix': False,
+ 'portage': False
+ }
+ self.module_opts = {
+ "-f": ("flags", "boolean", True),
+ "--flags": ("flags", "boolean", True),
+ "-k": ("keywords", "boolean", True),
+ "--keywords": ("keywords", "boolean", True),
+ "-u": ("unset", "boolean", True),
+ "--unset": ("unset", "boolean", True),
+ "-v": ("verbose", "boolean", True),
+ "--verbose": ("verbose", "boolean", True),
+ "-p": ("prefix", "boolean", True),
+ "--prefix": ("prefix", "boolean", True),
+ "-G": ("portage", "boolean", True),
+ "--portage": ("portage", "boolean", True),
+ }
+ self.formatted_options = [
+ (" -h, --help", "Outputs this useage message"),
+ (" -a, --analyse",
+ "Action, sets the module to gather data and output the"),
+ ("", "formatted stats/information to the screen"),
+ (" -u, --unset",
+ "Additionally include any unset USE flags and the packages"),
+ ("", "that could use them"),
+ (" -v, --verbose",
+ "Used in the analyse action to output more detailed information"),
+ (" -p, --prefix",
+ "Used for testing purposes only, runs report using " +
+ "a prefix keyword and 'prefix' USE flag"),
+ (" -G, --portage",
+ "Use portage directly instead of gentoolkit's Package " +
+ "object for some operations. Usually a little faster."),
+ ]
+ self.formatted_args = [
+ (" use",
+ "causes the action to analyse the installed packages USE flags"),
+ (" pkguse",
+ "causes the action to analyse the installed packages PKGUSE flags"),
+ (" ",
+ "These are flags that have been set in /etc/portage/package.use"),
+ (" keywords",
+ "causes the action to analyse the installed packages keywords"),
+ ]
+ self.short_opts = "huvpG"
+ self.long_opts = ("help", "unset", "verbose", "prefix", "portage")
+ self.need_queries = True
+ self.arg_spec = "Target"
+ self.arg_options = ['use', 'pkguse','keywords']
+ self.arg_option = False
+
+ def run(self, input_args, quiet=False):
+ """runs the module
+
+ @param input_args: input arguments to be parsed
+ """
+ query = self.main_setup(input_args)
+ query = self.validate_query(query)
+ if query in ["use", "pkguse"]:
+ self.analyse_flags(query)
+ elif query in ["keywords"]:
+ self.analyse_keywords()
+
+ def analyse_flags(self, target):
+ """This will scan the installed packages db and analyse the
+ USE flags used for installation and produce a report on how
+ they were used.
+
+ @type target: string
+ @param target: the target to be analysed, one of ["use", "pkguse"]
+ """
+ system_use = portage.settings["USE"].split()
+ self.printer = AnalysisPrinter("use", self.options["verbose"], system_use)
+ if self.options["verbose"]:
+ cpvs = VARDB.cpv_all()
+ #print "Total number of installed ebuilds =", len(cpvs)
+ flag_users = gather_flags_info(cpvs, system_use,
+ self.options["unset"], target=target.upper(),
+ use_portage=self.options['portage'])
+ else:
+ flag_users = gather_flags_info(system_flags=system_use,
+ include_unset=self.options["unset"], target=target.upper(),
+ use_portage=self.options['portage'])
+ #print flag_users
+ flag_keys = list(flag_users.keys())
+ flag_keys.sort()
+ if self.options["verbose"]:
+ print(" Flag System #pkgs cat/pkg-ver")
+ blankline = nl
+ elif not self.options['quiet']:
+ print(" Flag System #pkgs")
+ blankline = lambda: None
+ for flag in flag_keys:
+ flag_pos = flag_users[flag]["+"]
+ if len(flag_pos):
+ self.printer(flag, "+", flag_pos)
+ #blankline()
+ flag_neg = flag_users[flag]["-"]
+ if len(flag_neg):
+ self.printer(flag, "-", flag_neg)
+ #blankline()
+ if "unset" in flag_users[flag] and flag_users[flag]["unset"]:
+ flag_unset = flag_users[flag]["unset"]
+ self.printer(flag, "unset", flag_unset)
+ #blankline()
+ if not self.options['quiet']:
+ print("===================================================")
+ print("Total number of flags in report =", pp.output.red(str(len(flag_keys))))
+ if self.options["verbose"]:
+ print("Total number of installed ebuilds =", pp.output.red(str(len(cpvs))))
+ print()
+
+
+ def analyse_keywords(self, keywords=None):
+ """This will scan the installed packages db and analyse the
+ keywords used for installation and produce a report on them.
+ """
+ print()
+ system_keywords = portage.settings["ACCEPT_KEYWORDS"]
+ arch = portage.settings["ARCH"]
+ if self.options["prefix"]:
+ # build a new keyword for testing
+ system_keywords = "~" + arch + "-linux"
+ if self.options["verbose"] or self.options["prefix"]:
+ print("Current system ARCH =", arch)
+ print("Current system ACCEPT_KEYWORDS =", system_keywords)
+ system_keywords = system_keywords.split()
+ self.printer = AnalysisPrinter("keywords", self.options["verbose"], system_keywords)
+ self.analyser = KeywordAnalyser( arch, system_keywords, VARDB)
+ #self.analyser.set_order(portage.settings["USE"].split())
+ # only for testing
+ test_use = portage.settings["USE"].split()
+ if self.options['prefix'] and 'prefix' not in test_use:
+ print("ANALYSE_KEYWORDS() 'prefix' flag not found in system USE flags!!! appending for testing")
+ print()
+ test_use.append('prefix')
+ self.analyser.set_order(test_use)
+ # /end testing
+
+ if self.options["verbose"]:
+ cpvs = VARDB.cpv_all()
+ #print "Total number of installed ebuilds =", len(cpvs)
+ keyword_users = gather_keywords_info(
+ cpvs=cpvs,
+ system_keywords=system_keywords,
+ use_portage=self.options['portage'],
+ keywords=keywords, analyser = self.analyser
+ )
+ blankline = nl
+ else:
+ keyword_users = gather_keywords_info(
+ system_keywords=system_keywords,
+ use_portage=self.options['portage'],
+ keywords=keywords,
+ analyser = self.analyser
+ )
+ blankline = lambda: None
+ #print keyword_users
+ keyword_keys = list(keyword_users.keys())
+ keyword_keys.sort()
+ if self.options["verbose"]:
+ print(" Keyword System #pkgs cat/pkg-ver")
+ elif not self.options['quiet']:
+ print(" Keyword System #pkgs")
+ for keyword in keyword_keys:
+ kwd_stable = keyword_users[keyword]["stable"]
+ if len(kwd_stable):
+ self.printer(keyword, " ", kwd_stable)
+ blankline()
+ kwd_testing = keyword_users[keyword]["testing"]
+ if len(kwd_testing):
+ self.printer(keyword, "~", kwd_testing)
+ blankline()
+ kwd_missing = keyword_users[keyword]["missing"]
+ if len(kwd_missing):
+ self.printer(keyword, "-", kwd_missing)
+ blankline
+ if not self.options['quiet']:
+ if self.analyser.mismatched:
+ print("_________________________________________________")
+ print(("The following packages were found to have a \n" +
+ "different recorded ARCH than the current system ARCH"))
+ for cpv in self.analyser.mismatched:
+ print("\t", pp.cpv(cpv))
+ print("===================================================")
+ print("Total number of keywords in report =", pp.output.red(str(len(keyword_keys))))
+ if self.options["verbose"]:
+ print("Total number of installed ebuilds =", pp.output.red(str(len(cpvs))))
+ print()
+
+
+def main(input_args):
+ """Common starting method by the analyse master
+ unless all modules are converted to this class method.
+
+ @param input_args: input args as supplied by equery master module.
+ """
+ query_module = Analyse()
+ query_module.run(input_args, gentoolkit.CONFIG['quiet'])
+
+# vim: set ts=4 sw=4 tw=79:
--- /dev/null
+# Copyright(c) 2009, Gentoo Foundation
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright(c) 2010, Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+#
+# $Header: $
+
+"""Analyse Base Module class to hold common module operation functions
+"""
+
+from __future__ import print_function
+
+__docformat__ = 'epytext'
+
+
+import errno
+import sys
+import time
+from getopt import gnu_getopt, GetoptError
+
+from portage import os
+
+import gentoolkit.pprinter as pp
+from gentoolkit.formatters import format_options
+from gentoolkit.base import mod_usage
+
+
+class ModuleBase(object):
+ """Analyse base module class to parse module options print module help, etc.."""
+
+ def __init__(self):
+ self.module_name = None
+ self.options = {}
+ self.formatted_options = None
+ self.short_opts = None
+ self.long_opts = None
+ self.module_opts = {}
+ self.depwarning = None
+ self.need_queries = True
+
+
+ def print_help(self, with_description=True):
+ """Print description, usage and a detailed help message.
+
+ @type with_description: bool
+ @param with_description: if true, print module's __doc__ string
+ """
+
+ if with_description:
+ print()
+ print(__doc__.strip())
+ print()
+ if self.depwarning:
+ print()
+ for line in self.depwarning:
+ sys.stderr.write(pp.warn(line))
+ print()
+ print(mod_usage(mod_name=self.module_name, arg=self.arg_spec, optional=self.arg_option))
+ print()
+ print(pp.command("options"))
+ print(format_options( self.formatted_options ))
+ if self.formatted_args:
+ print()
+ print(pp.command(self.arg_spec))
+ print(format_options(self.formatted_args))
+ print()
+
+ def parse_module_options(self, module_opts):
+ """Parse module options and update self.options"""
+
+ opts = (x[0] for x in module_opts)
+ posargs = (x[1] for x in module_opts)
+ for opt, posarg in zip(opts, posargs):
+ if opt in ('-h', '--help'):
+ self.print_help()
+ sys.exit(0)
+ opt_name, opt_type, opt_setting = self.module_opts[opt]
+ if opt_type == 'boolean':
+ self.options[opt_name] = opt_setting
+ elif opt_type == 'int':
+ if posarg.isdigit():
+ val = int(posarg)
+ else:
+ print()
+ err = "Module option %s requires integer (got '%s')"
+ sys.stdout.write(pp.error(err % (opt,posarg)))
+ print()
+ self.print_help(with_description=False)
+ sys.exit(2)
+ self.options[opt_name] = val
+ if self.options['quiet']:
+ self.options['verbose'] = False
+
+ def validate_query(self, query, depth=0):
+ """check that the query meets the modules TargetSpec
+ If not it attempts to reduce it to a valid TargetSpec
+ or prints the help message and exits
+ """
+ if depth > 1:
+ return []
+ if len(query) > 1:
+ query = list(set(self.arg_options).intersection(query))
+ #print "reduced query =", query
+ query = self.validate_query(query, depth+1)
+ if isinstance(query, list):
+ query = query[0]
+ if query not in self.arg_options:
+ print()
+ print(pp.error(
+ "Error starting module. Incorrect or No TargetSpec specified!"
+ ))
+ print("query = ", query)
+ self.print_help()
+ sys.exit(2)
+ return query
+
+
+ def main_setup(self, input_args):
+ """Parse input and prepares the program"""
+
+ try:
+ module_opts, queries = gnu_getopt(input_args, self.short_opts, self.long_opts)
+ except GetoptError as err:
+ sys.stderr.write(pp.error("Module %s" % err))
+ print()
+ self.print_help(with_description=False)
+ sys.exit(2)
+ self.parse_module_options(module_opts)
+ if self.need_queries and not queries:
+ self.print_help()
+ sys.exit(2)
+ return queries
+
+
+# vim: set ts=4 sw=4 tw=79:
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright(c) 2010, Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+#
+
+
+"""Provides support functions to analyse modules"""
+
+import sys
+
+from gentoolkit.dbapi import PORTDB, VARDB
+from gentoolkit import errors
+from gentoolkit.keyword import abs_keywords
+#from gentoolkit.package import Package
+
+import portage
+
+
+def get_installed_use(cpv, use="USE"):
+ """Gets the installed USE flags from the VARDB
+
+ @type: cpv: string
+ @param cpv: cat/pkg-ver
+ @type use: string
+ @param use: 1 of ["USE", "PKGUSE"]
+ @rtype list
+ @returns [] or the list of IUSE flags
+ """
+ return VARDB.aux_get(cpv,[use])[0].split()
+
+
+def get_iuse(cpv):
+ """Gets the current IUSE flags from the tree
+
+ @type: cpv: string
+ @param cpv: cat/pkg-ver
+ @rtype list
+ @returns [] or the list of IUSE flags
+ """
+ try:
+ return PORTDB.aux_get(cpv, ["IUSE"])[0].split()
+ except:
+ return []
+
+
+def abs_flag(flag):
+ """Absolute value function for a USE flag
+
+ @type flag: string
+ @param flag: the use flag to absolute.
+ @rtype: string
+ @return absolute USE flag
+ """
+ if flag[0] in ["+","-"]:
+ return flag[1:]
+ else:
+ return flag
+
+
+def abs_list(the_list):
+ """Absolute value function for a USE flag list
+
+ @type the_list: list
+ @param the_list: the use flags to absolute.
+ @rtype: list
+ @return absolute USE flags
+ """
+ r=[]
+ for member in the_list:
+ r.append(abs_flag(member))
+ return r
+
+
+def filter_flags(use, use_expand_hidden, usemasked, useforced):
+ """Filter function to remove hidden or otherwise not normally
+ visible USE flags from a list.
+
+ @type use: list
+ @param use: the USE flag list to be filtered.
+ @type use_expand_hidden: list
+ @param use_expand_hidden: list of flags hidden.
+ @type usemasked: list
+ @param usemasked: list of masked USE flags.
+ @type useforced: list
+ @param useforced: the forced USE flags.
+ @rtype: list
+ @return the filtered USE flags.
+ """
+ # clean out some environment flags, since they will most probably
+ # be confusing for the user
+ for f in use_expand_hidden:
+ f=f.lower() + "_"
+ for x in use:
+ if f in x:
+ use.remove(x)
+ # clean out any arch's
+ archlist = portage.settings["PORTAGE_ARCHLIST"].split()
+ for a in use[:]:
+ if a in archlist:
+ use.remove(a)
+ # dbl check if any from usemasked or useforced are still there
+ masked = usemasked + useforced
+ for a in use[:]:
+ if a in masked:
+ use.remove(a)
+ return use
+
+
+def get_all_cpv_use(cpv):
+ """Uses portage to determine final USE flags and settings for an emerge
+
+ @type cpv: string
+ @param cpv: eg cat/pkg-ver
+ @rtype: lists
+ @return use, use_expand_hidden, usemask, useforce
+ """
+ use = None
+ PORTDB.settings.unlock()
+ try:
+ PORTDB.settings.setcpv(cpv, use_cache=True, mydb=portage.portdb)
+ use = portage.settings['PORTAGE_USE'].split()
+ use_expand_hidden = portage.settings["USE_EXPAND_HIDDEN"].split()
+ usemask = list(PORTDB.settings.usemask)
+ useforce = list(PORTDB.settings.useforce)
+ except KeyError:
+ PORTDB.settings.reset()
+ PORTDB.settings.lock()
+ return [], [], [], []
+ # reset cpv filter
+ PORTDB.settings.reset()
+ PORTDB.settings.lock()
+ return use, use_expand_hidden, usemask, useforce
+
+
+def get_flags(cpv, final_setting=False):
+ """Retrieves all information needed to filter out hidded, masked, etc.
+ USE flags for a given package.
+
+ @type cpv: string
+ @param cpv: eg. cat/pkg-ver
+ @type final_setting: boolean
+ @param final_setting: used to also determine the final
+ enviroment USE flag settings and return them as well.
+ @rtype: list or list, list
+ @return IUSE or IUSE, final_flags
+ """
+ final_use, use_expand_hidden, usemasked, useforced = get_all_cpv_use(cpv)
+ iuse_flags = filter_flags(get_iuse(cpv), use_expand_hidden, usemasked, useforced)
+ #flags = filter_flags(use_flags, use_expand_hidden, usemasked, useforced)
+ if final_setting:
+ final_flags = filter_flags(final_use, use_expand_hidden, usemasked, useforced)
+ return iuse_flags, final_flags
+ return iuse_flags
+
+class FlagAnalyzer(object):
+ """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,
+ _get_flags=get_flags,
+ _get_used=get_installed_use
+ ):
+ self.get_flags = _get_flags
+ self.get_used = _get_used
+ 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, "USE"))
+ iuse = set(abs_list(self.get_flags(cpv)))
+ return self._analyse(installed, iuse)
+
+ def _analyse(self, installed, iuse):
+ """Analyses 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)
+ usedflags = iuse.intersection(set(installed))
+ plus = usedflags.difference(defaults)
+ minus = defaults.difference(usedflags)
+ unset = iuse.difference(defaults, plus, minus)
+ cleaned = self.remove_expanding(unset)
+ return (plus, minus, cleaned)
+
+ 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))
+ iuse = set(abs_list(self.pkg_flags(pkg)))
+ return self._analyse(installed, iuse)
+
+ def pkg_used(self, pkg):
+ return pkg.use().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(object):
+ """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: VARDB.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=VARDB):
+ 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 = abs_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 = abs_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
+
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright(c) 2010, Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+#
+
+"""Provides various output classes and functions for
+both screen and file output
+"""
+
+from __future__ import print_function
+
+import gentoolkit
+from gentoolkit import pprinter as pp
+from gentoolkit.textwrap_ import TextWrapper
+from gentoolkit.cpv import split_cpv
+
+
+def nl(lines=1):
+ """small utility function to print blank lines
+
+ @type lines: integer
+ @param lines: optional number of blank lines to print
+ default = 1
+ """
+ print(('\n' * lines))
+
+class AnalysisPrinter(object):
+ """Printing functions"""
+ def __init__(self, target, verbose=True, references=None):
+ """@param references: list of accepted keywords or
+ the system use flags
+ """
+ self.references = references
+ self.set_target(target, verbose)
+
+ def set_target(self, target, verbose=True):
+ if target in ["use"]:
+ if verbose:
+ self.print_fn = self.print_use_verbose
+ else:
+ self.print_fn = self.print_use_quiet
+ elif target in ["keywords"]:
+ if verbose:
+ self.print_fn = self.print_keyword_verbose
+ else:
+ self.print_fn = self.print_keyword_quiet
+
+ def __call__(self, key, active, pkgs):
+ self._format_key(key, active, pkgs)
+
+ def _format_key(self, key, active, pkgs):
+ """Determines the stats for key, formats it and
+ calls the pre-determined print function
+ """
+ occurred = str(len(pkgs))
+ if active in ["-", "~"]:
+ _key = active + key
+ else:
+ _key = key
+ if _key in self.references:
+ default = "default"
+ else:
+ default = "......."
+ count = ' '*(5-len(occurred)) + occurred
+ pkgs.sort()
+ self.print_fn(key, active, default, count, pkgs)
+
+ @staticmethod
+ def print_use_verbose(key, active, default, count, pkgs):
+ """Verbosely prints a set of use flag info. including the pkgs
+ using them.
+ """
+ _pkgs = pkgs[:]
+ if active in ["+", "-"]:
+ _key = pp.useflag((active+key), active=="+")
+ else:
+ _key = (" " + key)
+ cpv = _pkgs.pop(0)
+ print(_key,'.'*(35-len(key)), default, pp.number(count), pp.cpv(cpv))
+ while _pkgs:
+ cpv = _pkgs.pop(0)
+ print(' '*52 + pp.cpv(cpv))
+
+ # W0613: *Unused argument %r*
+ # pylint: disable-msg=W0613
+ @staticmethod
+ def print_use_quiet(key, active, default, count, pkgs):
+ """Quietly prints a subset set of USE flag info..
+ """
+ if active in ["+", "-"]:
+ _key = pp.useflag((active+key), active=="+")
+ else:
+ _key = (" " + key)
+ print(_key,'.'*(35-len(key)), default, pp.number(count))
+
+ @staticmethod
+ def print_keyword_verbose(key, stability, default, count, pkgs):
+ """Verbosely prints a set of keywords info. including the pkgs
+ using them.
+ """
+ _pkgs = pkgs[:]
+ _key = (pp.keyword((stability+key),stable=(stability==" "),
+ hard_masked=stability=="-"))
+ cpv = _pkgs.pop(0)
+ print(_key,'.'*(20-len(key)), default, pp.number(count), pp.cpv(cpv))
+ while _pkgs:
+ cpv = _pkgs.pop(0)
+ print(' '*37 + pp.cpv(cpv))
+
+ # W0613: *Unused argument %r*
+ # pylint: disable-msg=W0613
+ @staticmethod
+ def print_keyword_quiet(key, stability, default, count, pkgs):
+ """Quietly prints a subset set of USE flag info..
+ """
+ _key = (pp.keyword((stability+key), stable=(stability==" "),
+ hard_masked=stability=="-"))
+ print(_key,'.'*(20-len(key)), default, pp.number(count))
+
+
+class RebuildPrinter(object):
+ """Output functions"""
+ def __init__(self, target, pretend=True, exact=False):
+ """@param references: list of accepted keywords or
+ the system use flags
+ """
+ self.target = target
+ self.set_target(target)
+ self.pretend = pretend
+ if pretend:
+ self.twrap = TextWrapper(width=gentoolkit.CONFIG['termWidth'])
+ self.spacer = ' '
+ self.init_indent = len(self.spacer)
+ else:
+ self.spacer = ''
+ self.exact = exact
+ self.data = {}
+
+
+ def set_target(self, target):
+ if target in ["use"]:
+ self.print_fn = self.print_use
+ self.use_lines = [self.header()]
+ elif target in ["keywords"]:
+ self.print_fn = self.print_keyword
+ elif target in ["unmask"]:
+ self.print_fn = self.print_mask
+
+
+ def __call__(self, key, values):
+ self._format_key(key, values)
+
+
+ def _format_key(self, key, values):
+ """Determines the stats for key, formats it and
+ calls the pre-determined print function
+ """
+ if self.exact:
+ _key = "=" + key
+ else:
+ parts = split_cpv(key)
+ _key = '/'.join(parts[:2])
+ values.sort()
+ self.data[_key] = values
+ self.print_fn( _key, values)
+
+ def _format_values(self, key, values):
+ """Format entry values ie. USE flags, keywords,...
+
+ @type key: str
+ @param key: a pre-formatted cpv
+ @type values: list of pre-formatted strings
+ @param values: ['flag1', 'flag2',...]
+ @rtype: str
+ @return: formatted options string
+ """
+
+ result = []
+ self.twrap.initial_indent = pp.cpv(key+" ")
+ self.twrap.subsequent_indent = " " * (len(key)+1)
+ result.append(self.twrap.fill(values))
+ return '\n'.join(result)
+
+ def print_use(self, key, values):
+ """Prints a USE flag string.
+ """
+ if self.pretend:
+ flags = []
+ for flag in values:
+ flags.append(pp.useflag(flag, (flag[0] != '-')))
+ print(self._format_values(self.spacer+key, ' '.join(flags)))
+ else:
+ line = ' '.join([key, ' '.join(values)])
+ self.use_lines.append(line)
+
+
+ def print_keyword(self):
+ pass
+
+
+ def print_unmask(self):
+ pass
+
+ def header(self):
+ """Generates a file header
+ """
+
+ h=("# This package.%s file was generated by "
+ %self.target +
+ "gentoolkit's 'analyse rebuild' module\n"
+ )
+ return h
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright(c) 2010, Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+#
+
+
+"""Provides a rebuild file of USE flags or keywords used and by
+what packages according to the Installed package database"""
+
+from __future__ import print_function
+
+
+# Move to Imports section after Python 2.6 is stable
+
+
+import sys
+
+from portage import os
+
+import gentoolkit
+from gentoolkit.dbapi import PORTDB, VARDB
+from gentoolkit.analyse.base import ModuleBase
+from gentoolkit import pprinter as pp
+from gentoolkit.analyse.lib import (get_installed_use, get_flags,
+ abs_flag, abs_list, FlagAnalyzer)
+from gentoolkit.analyse.output import RebuildPrinter
+
+import portage
+
+
+def cpv_all_diff_use(
+ cpvs=None,
+ system_flags=None,
+ # override-able for testing
+ _get_flags=get_flags,
+ _get_used=get_installed_use
+ ):
+ if cpvs is None:
+ cpvs = VARDB.cpv_all()
+ cpvs.sort()
+ data = {}
+ # pass them in to override for tests
+ flags = FlagAnalyzer(system_flags,
+ _get_flags=_get_flags,
+ _get_used=get_installed_use
+ )
+ for cpv in cpvs:
+ plus, minus, unset = flags.analyse_cpv(cpv)
+ for flag in minus:
+ plus.add("-"+flag)
+ if len(plus):
+ data[cpv] = list(plus)
+ return data
+
+
+class Rebuild(ModuleBase):
+ """Installed db analysis tool to query the installed databse
+ and produce/output stats for USE flags or keywords/mask.
+ The 'rebuild' action output is in the form suitable for file type output
+ to create a new package.use, package.keywords, package.unmask
+ type files in the event of needing to rebuild the
+ /etc/portage/* user configs
+ """
+ def __init__(self):
+ ModuleBase.__init__(self)
+ self.module_name = "rebuild"
+ self.options = {
+ "use": False,
+ "keywords": False,
+ "unmask": False,
+ "verbose": False,
+ "quiet": False,
+ "exact": False,
+ "pretend": False,
+ #"unset": False
+ }
+ self.module_opts = {
+ "-p": ("pretend", "boolean", True),
+ "--pretend": ("pretend", "boolean", True),
+ "-e": ("exact", "boolean", True),
+ "--exact": ("exact", "boolean", True),
+ "-v": ("verbose", "boolean", True),
+ "--verbose": ("verbose", "boolean", True),
+ }
+ self.formatted_options = [
+ (" -h, --help", "Outputs this useage message"),
+ (" -p, --pretend", "Does not actually create the files."),
+ (" ", "It directs the outputs to the screen"),
+ (" -e, --exact", "will atomize the package with a"),
+ (" ", "leading '=' and include the version")
+ ]
+ self.formatted_args = [
+ (" use",
+ "causes the action to analyse the installed packages USE flags"),
+ (" keywords",
+ "causes the action to analyse the installed packages keywords"),
+ (" unmask",
+ "causes the action to analyse the installed packages " + \
+ "current mask status")
+ ]
+ self.short_opts = "hepv"
+ self.long_opts = ("help", "exact", "pretend", "verbose")
+ self.need_queries = True
+ self.arg_spec = "TargetSpec"
+ self.arg_options = ['use', 'keywords', 'unmask']
+ self.arg_option = False
+
+
+
+ def run(self, input_args, quiet=False):
+ """runs the module
+
+ @param input_args: input arguments to be parsed
+ """
+ self.options['quiet'] = quiet
+ query = self.main_setup(input_args)
+ query = self.validate_query(query)
+ if query in ["use"]:
+ self.rebuild_use()
+ elif query in ["keywords"]:
+ self.rebuild_keywords()
+ elif query in ["mask"]:
+ self.rebuild_mask()
+
+
+ def rebuild_use(self):
+ if not self.options["quiet"]:
+ print()
+ print(" -- Scanning installed packages for USE flag settings that")
+ print(" do not match the default settings")
+ system_use = portage.settings["USE"].split()
+ output = RebuildPrinter("use", self.options["pretend"], self.options["exact"])
+ pkgs = cpv_all_diff_use(system_flags=system_use)
+ pkg_count = len(pkgs)
+ if self.options["verbose"]:
+ print()
+ print((pp.emph(" -- Found ") + pp.number(str(pkg_count)) +
+ pp.emph(" packages that need entries")))
+ #print pp.emph(" package.use to maintain their current setting")
+ if pkgs:
+ pkg_keys = list(pkgs.keys())
+ pkg_keys.sort()
+ #print len(pkgs)
+ if self.options["pretend"] and not self.options["quiet"]:
+ print()
+ print(pp.globaloption(
+ " -- These are the installed packages & flags " +
+ "that were detected"))
+ print(pp.globaloption(" to need flag settings other " +
+ "than the defaults."))
+ print()
+ elif not self.options["quiet"]:
+ print(" -- preparing pkgs for file entries")
+ flag_count = 0
+ unique_flags = set()
+ for pkg in pkg_keys:
+ if self.options['verbose']:
+ flag_count += len(pkgs[pkg])
+ unique_flags.update(abs_list(pkgs[pkg]))
+ output(pkg, pkgs[pkg])
+ if self.options['verbose']:
+ message = (pp.emph(" ") +
+ pp.number(str(len(unique_flags))) +
+ pp.emph(" unique flags\n") + " " +
+ pp.number(str(flag_count))+
+ pp.emph(" flag entries\n") + " " +
+ pp.number(str(pkg_count)) +
+ pp.emph(" different packages"))
+ print()
+ print(pp.globaloption(" -- Totals"))
+ print(message)
+ #print
+ #unique = list(unique_flags)
+ #unique.sort()
+ #print unique
+ if not self.options["pretend"]:
+ filepath = os.path.expanduser('~/package.use.test')
+ self.save_file(filepath, output.use_lines)
+
+ def rebuild_keywords(self):
+ print("Module action not yet available")
+ print()
+
+ def rebuild_mask(self):
+ print("Module action not yet available")
+ print()
+
+
+ def save_file(self, filepath, data):
+ """Writes the data to the file determined by filepath
+
+ @param filepath: string. eg. '/path/to/filename'
+ @param data: list of lines to write to filepath
+ """
+ if not self.options["quiet"]:
+ print(' - Saving file: %s' %filepath)
+ #print "Just kidding :) I haven't codded it yet"
+ with open(filepath, "w") as output:
+ output.write('\n'.join(data))
+ print(" - Done")
+
+
+def main(input_args):
+ """Common starting method by the analyse master
+ unless all modules are converted to this class method.
+
+ @param input_args: input args as supplied by equery master module.
+ """
+ query_module = Rebuild()
+ query_module.run(input_args, gentoolkit.CONFIG['quiet'])
+
+# vim: set ts=4 sw=4 tw=79:
+
#!/usr/bin/python
#
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
#return cmp(self.repo_name, other.repo_name)
return True
+ def __hash__(self):
+ return hash(self.atom)
+
def __ne__(self, other):
return not self == other
# return c
if self.slot != other.slot:
+ if self.slot is None:
+ return False
+ elif other.slot is None:
+ return True
return self.slot < other.slot
- this_use = None
+ this_use = []
if self.use is not None:
this_use = sorted(self.use.tokens)
- that_use = None
+ that_use = []
if other.use is not None:
that_use = sorted(other.use.tokens)
if this_use != that_use:
--- /dev/null
+# Copyright(c) 2009, Gentoo Foundation
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright(c) 2010, Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+#
+# $Header: $
+
+"""Analyse Base Module class to hold common module operation functions
+"""
+
+from __future__ import print_function
+
+__docformat__ = 'epytext'
+
+
+import errno
+import sys
+import time
+from getopt import gnu_getopt, GetoptError
+
+from portage import os
+
+import gentoolkit
+from gentoolkit import errors
+#from gentoolkit.textwrap_ import TextWrapper
+import gentoolkit.pprinter as pp
+from gentoolkit.formatters import format_options
+
+
+GLOBAL_OPTIONS = (
+ (" -h, --help", "display this help message"),
+ (" -q, --quiet", "minimal output"),
+ (" -C, --no-color", "turn off colors"),
+ (" -N, --no-pipe", "turn off pipe detection"),
+ (" -V, --version", "display version info")
+)
+
+
+def initialize_configuration():
+ """Setup the standard equery config"""
+
+ # Get terminal size
+ term_width = pp.output.get_term_size()[1]
+ if term_width == -1:
+ # get_term_size() failed. Set a sane default width:
+ term_width = 80
+ # Terminal size, minus a 1-char margin for text wrapping
+ gentoolkit.CONFIG['termWidth'] = term_width - 1
+ # Guess color output
+ if (gentoolkit.CONFIG['color'] == -1 and (not sys.stdout.isatty() or
+ os.getenv("NOCOLOR") in ("yes", "true")) or gentoolkit.CONFIG['color'] == 0):
+ pp.output.nocolor()
+ gentoolkit.CONFIG['verbose'] = not gentoolkit.CONFIG['piping']
+
+
+def split_arguments(args):
+ """Separate module name from module arguments"""
+
+ return args.pop(0), args
+
+
+def main_usage(module_info):
+ """Return the main usage message for analyse"""
+ return "%(usage)s %(product)s [%(g_opts)s] %(mod_name)s [%(mod_opts)s]" % {
+ 'usage': pp.emph("Usage:"),
+ 'product': pp.productname(module_info["__productname__"]),
+ 'g_opts': pp.globaloption("global-options"),
+ 'mod_name': pp.command("module-name"),
+ 'mod_opts': pp.localoption("module-options")
+ }
+
+
+def print_version(module_info):
+ """Print the version of this tool to the console."""
+
+ print("%(product)s (%(version)s) - %(docstring)s" % {
+ "product": pp.productname(module_info["__productname__"]),
+ "version": module_info["__version__"],
+ "docstring": module_info["__doc__"]
+ })
+
+
+def print_help(module_info, formatted_options=None, with_description=True):
+ """Print description, usage and a detailed help message.
+
+ @param with_description (bool): Option to print module's __doc__ or not
+ """
+
+ if with_description:
+ print()
+ print(module_info["__doc__"])
+ print()
+ print(main_usage(module_info))
+ print()
+ print(pp.globaloption("global options"))
+ print(format_options(GLOBAL_OPTIONS))
+ print()
+ if formatted_options:
+ print(pp.command("modules") + " (" + pp.command("short name") + ")")
+ print(format_options(formatted_options))
+ else:
+ print("Error: calling function did not supply formatted options")
+ print()
+
+
+def parse_global_options(global_opts, args, module_info, formatted_options):
+ """Parse global input args and return True if we should display help for
+ the called module, else False (or display help and exit from here).
+ """
+
+ need_help = False
+ opts = (opt[0] for opt in global_opts)
+ for opt in opts:
+ if opt in ('-h', '--help'):
+ if args:
+ need_help = True
+ else:
+ print_help( module_info, formatted_options)
+ sys.exit(0)
+ elif opt in ('-q','--quiet'):
+ gentoolkit.CONFIG['quiet'] = True
+ elif opt in ('-C', '--no-color', '--nocolor'):
+ gentoolkit.CONFIG['color'] = 0
+ pp.output.nocolor()
+ elif opt in ('-N', '--no-pipe'):
+ gentoolkit.CONFIG['piping'] = False
+ elif opt in ('-V', '--version'):
+ print_version(module_info)
+ sys.exit(0)
+ elif opt in ('--debug'):
+ gentoolkit.CONFIG['debug'] = True
+ return need_help
+
+
+def mod_usage(mod_name="module", arg="pkgspec", optional=False):
+ """Provide a consistant usage message to the calling module.
+
+ @type arg: string
+ @param arg: what kind of argument the module takes (pkgspec, filename, etc)
+ @type optional: bool
+ @param optional: is the argument optional?
+ """
+
+ return "%(usage)s: %(mod_name)s [%(opts)s] %(arg)s" % {
+ 'usage': pp.emph("Usage"),
+ 'mod_name': pp.command(mod_name),
+ 'opts': pp.localoption("options"),
+ 'arg': ("[%s]" % pp.emph(arg)) if optional else pp.emph(arg)
+ }
+
#!/usr/bin/python
#
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
"""Provides attributes and methods for a category/package-version string."""
-__all__ = ('CPV',)
+__all__ = (
+ 'CPV',
+ 'compare_strs',
+ 'split_cpv'
+)
# =======
# Imports
# =======
-from portage.versions import catpkgsplit, vercmp
+from portage.versions import catpkgsplit, vercmp, pkgcmp
from gentoolkit import errors
return False
return self.cpv == other.cpv
+ def __hash__(self):
+ return hash(self.cpv)
+
def __ne__(self, other):
return not self == other
# FIXME: this cmp() hack is for vercmp not using -1,0,1
# See bug 266493; this was fixed in portage-2.2_rc31
#return vercmp(self.fullversion, other.fullversion)
- result = cmp(vercmp(self.fullversion, other.fullversion), 0)
- if result == -1:
- return True
- else:
- return False
+ return vercmp(self.fullversion, other.fullversion) < 0
def __gt__(self, other):
if not isinstance(other, self.__class__):
# Functions
# =========
+def compare_strs(pkg1, pkg2):
+ """Similar to the builtin cmp, but for package strings. Usually called
+ as: package_list.sort(cpv.compare_strs)
+
+ An alternative is to use the CPV descriptor from gentoolkit.cpv:
+ >>> cpvs = sorted(CPV(x) for x in package_list)
+
+ @see: >>> help(cmp)
+ """
+
+ pkg1 = catpkgsplit(pkg1)
+ pkg2 = catpkgsplit(pkg2)
+ if pkg1[0] != pkg2[0]:
+ return -1 if pkg1[0] < pkg2[0] else 1
+ elif pkg1[1] != pkg2[1]:
+ return -1 if pkg1[1] < pkg2[1] else 1
+ else:
+ return pkgcmp(pkg1[1:], pkg2[1:])
+
+
def split_cpv(cpv):
"""Split a cpv into category, name, version and revision.
#!/usr/bin/python
#
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright 2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
#
# $Header$
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
from gentoolkit import errors
from gentoolkit.atom import Atom
from gentoolkit.cpv import CPV
-from gentoolkit.helpers import find_best_match, uniqify
+from gentoolkit.helpers import uniqify
from gentoolkit.dbapi import PORTDB, VARDB
+from gentoolkit.query import Query
# =======
# Classes
try:
return self.parser(self.environment(('DEPEND',))[0])
- except portage.exception.InvalidPackageName, err:
+ except portage.exception.InvalidPackageName as err:
raise errors.GentoolkitInvalidCPV(err)
def get_pdepend(self):
try:
return self.parser(self.environment(('PDEPEND',))[0])
- except portage.exception.InvalidPackageName, err:
+ except portage.exception.InvalidPackageName as err:
raise errors.GentoolkitInvalidCPV(err)
def get_rdepend(self):
try:
return self.parser(self.environment(('RDEPEND',))[0])
- except portage.exception.InvalidPackageName, err:
+ except portage.exception.InvalidPackageName as err:
raise errors.GentoolkitInvalidCPV(err)
def get_all_depends(self):
env_vars = ('DEPEND', 'PDEPEND', 'RDEPEND')
try:
return self.parser(' '.join(self.environment(env_vars)))
- except portage.exception.InvalidPackageName, err:
+ except portage.exception.InvalidPackageName as err:
raise errors.GentoolkitInvalidCPV(err)
def graph_depends(
try:
pkgdep = depcache[dep.atom]
except KeyError:
- pkgdep = find_best_match(dep.atom)
+ pkgdep = Query(dep.atom).find_best()
depcache[dep.atom] = pkgdep
if pkgdep and pkgdep.cpv in seen:
continue
#!/usr/bin/python2
#
# Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org>
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
# $Header$
+from __future__ import print_function
+
import warnings
import portage
t = portage.db["/"]["porttree"].dbapi.match(search_key)
t += portage.db["/"]["vartree"].dbapi.match(search_key)
# catch the "amgigous package" Exception
- except ValueError, e:
+ except ValueError as e:
if isinstance(e[0],list):
t = []
for cp in e[0]:
t += portage.db["/"]["vartree"].dbapi.match(cp)
else:
raise ValueError(e)
- except portage_exception.InvalidAtom, e:
- print warn("Invalid Atom: '%s'" % str(e))
+ except portage_exception.InvalidAtom as e:
+ print(warn("Invalid Atom: '%s'" % str(e)))
return []
# Make the list of packages unique
t = unique_array(t)
try:
t = portage.db["/"]["vartree"].dbapi.match(search_key)
# catch the "amgigous package" Exception
- except ValueError, e:
+ except ValueError as e:
if isinstance(e[0],list):
t = []
for cp in e[0]:
t += portage.db["/"]["vartree"].dbapi.match(cp)
else:
raise ValueError(e)
- except portage_exception.InvalidAtom, e:
- print warn("Invalid Atom: '%s'" % str(e))
+ except portage_exception.InvalidAtom as e:
+ print(warn("Invalid Atom: '%s'" % str(e)))
return []
return [Package(x) for x in t]
DeprecationWarning)
t = vartree.dbapi.cpv_all()
if prefilter:
- t = filter(prefilter,t)
+ t = list(filter(prefilter,t))
return [Package(x) for x in t]
def find_all_uninstalled_packages(prefilter=None):
t = porttree.dbapi.cp_all()
t += vartree.dbapi.cp_all()
if prefilter:
- t = filter(prefilter,t)
+ t = list(filter(prefilter,t))
t = unique_array(t)
t2 = []
for x in t:
# return pkglist
if __name__ == "__main__":
- print "This module is for import only"
+ print("This module is for import only")
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
"""Gentoo package query tool"""
+from __future__ import print_function
+
# Move to Imports section after Python 2.6 is stable
-from __future__ import with_statement
+
__all__ = (
'format_options',
# =======
import errno
-import os
import sys
import time
from getopt import getopt, GetoptError
import portage
+from portage import os
import gentoolkit
from gentoolkit import CONFIG
"""
if with_description:
- print __doc__
- print main_usage()
- print
- print pp.globaloption("global options")
- print format_options((
+ print(__doc__)
+ print(main_usage())
+ print()
+ print(pp.globaloption("global options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -q, --quiet", "minimal output"),
(" -C, --no-color", "turn off colors"),
(" -N, --no-pipe", "turn off pipe detection"),
(" -V, --version", "display version info")
- ))
- print
- print pp.command("modules") + " (" + pp.command("short name") + ")"
- print format_options((
+ )))
+ print()
+ print(pp.command("modules") + " (" + pp.command("short name") + ")")
+ print(format_options((
(" (b)elongs", "list what package FILES belong to"),
(" (c)hanges", "list changelog entries for ATOM"),
(" chec(k)", "verify checksums and timestamps for PKG"),
(" (s)ize", "display total size of all files owned by PKG"),
(" (u)ses", "display USE flags for PKG"),
(" (w)hich", "print full path to ebuild for PKG")
- ))
+ )))
def expand_module_name(module_name):
pp.output.nocolor()
elif opt in ('-N', '--no-pipe'):
CONFIG['piping'] = False
- CONFIG['verbose'] = True
elif opt in ('-V', '--version'):
print_version()
sys.exit(0)
def print_version():
"""Print the version of this tool to the console."""
- print "%(product)s (%(version)s) - %(docstring)s" % {
+ print("%(product)s (%(version)s) - %(docstring)s" % {
"product": pp.productname(__productname__),
"version": __version__,
"docstring": __doc__
- }
+ })
def split_arguments(args):
try:
global_opts, args = getopt(sys.argv[1:], short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Global %s" % err))
print_help(with_description=False)
sys.exit(2)
expanded_module_name, globals(), locals(), [], -1
)
loaded_module.main(module_args)
- except portage.exception.AmbiguousPackageName, err:
+ except portage.exception.AmbiguousPackageName as err:
raise errors.GentoolkitAmbiguousPackage(err)
- except IOError, err:
+ except IOError as err:
if err.errno != errno.EPIPE:
raise
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
the same file, it usually constitutes a problem, and should be reported.
"""
+from __future__ import print_function
+
__docformat__ = 'epytext'
# =======
def print_quiet(self, pkg, cfile):
"Format for minimal output."
if self.name_only:
- name = pkg.cpv.cp
+ name = pkg.cp
else:
name = str(pkg.cpv)
- print name
+ print(name)
def print_verbose(self, pkg, cfile):
"Format for full output."
file_str = pp.path(format_filetype(cfile, pkg.parsed_contents()[cfile]))
if self.name_only:
- name = pkg.cpv.cp
+ name = pkg.cp
else:
name = str(pkg.cpv)
- print pp.cpv(name), "(" + file_str + ")"
+ print(pp.cpv(name), "(" + file_str + ")")
# =========
if opt == '--earlyout':
sys.stderr.write(pp.warn("Use of --earlyout is deprecated."))
sys.stderr.write(pp.warn("Please use --early-out."))
- print
+ print()
QUERY_OPTS['earlyOut'] = True
elif opt in ('-f', '--full-regex'):
QUERY_OPTS['fullRegex'] = True
"""
if with_description:
- print __doc__.strip()
- print
- print mod_usage(mod_name="belongs", arg="filename")
- print
- print pp.command("options")
- print format_options((
+ print(__doc__.strip())
+ print()
+ print(mod_usage(mod_name="belongs", arg="filename"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -f, --full-regex", "supplied query is a regex" ),
(" -e, --early-out", "stop when first match is found"),
(" -n, --name-only", "don't print the version")
- ))
+ )))
def main(input_args):
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
sys.exit(2)
if CONFIG['verbose']:
- print " * Searching for %s ... " % (pp.regexpquery(",".join(queries)))
+ print(" * Searching for %s ... " % (pp.regexpquery(",".join(queries))))
printer_fn = BelongsPrinter(
verbose=CONFIG['verbose'], name_only=QUERY_OPTS['nameOnly']
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2 or higher
#
"""Displays the ChangeLog entry for the latest installable version of an atom"""
+from __future__ import print_function
+
# Move to Imports sections when Python 2.6 is stable
-from __future__ import with_statement
+
__docformat__ = 'epytext'
# Imports
# =======
-import os
import sys
from getopt import gnu_getopt, GetoptError
+from portage import os
+
import gentoolkit.pprinter as pp
from gentoolkit import errors
from gentoolkit.atom import Atom
from gentoolkit.equery import format_options, mod_usage
-from gentoolkit.helpers import ChangeLog, find_best_match, find_packages
+from gentoolkit.helpers import ChangeLog
+from gentoolkit.query import Query
# =======
# Globals
"""
if with_description:
- print __doc__.strip()
- print
- print mod_usage(mod_name="changes")
- print
- print pp.emph("examples")
+ print(__doc__.strip())
+ print()
+ print(mod_usage(mod_name="changes"))
+ print()
+ print(pp.emph("examples"))
print (" c portage # show latest visible "
"version's entry")
- print " c portage --full --limit=3 # show 3 latest entries"
- print " c '=sys-apps/portage-2.1.6*' # use atom syntax"
- print " c portage --from=2.2_rc20 --to=2.2_rc30 # use version ranges"
- print
- print pp.command("options")
- print format_options((
+ print(" c portage --full --limit=3 # show 3 latest entries")
+ print(" c '=sys-apps/portage-2.1.6*' # use atom syntax")
+ print(" c portage --from=2.2_rc60 --to=2.2_rc70 # use version ranges")
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -l, --latest", "display only the latest ChangeLog entry"),
(" -f, --full", "display the full ChangeLog"),
"limit the number of entries displayed (with --full)"),
(" --from=VER", "set which version to display from"),
(" --to=VER", "set which version to display to"),
- ))
-
-
-def get_match(query):
- """Find a valid package from which to get the ChangeLog path.
-
- @raise GentoolkitNoMatches: if no matches found
- """
-
- match = matches = None
- match = find_best_match(query)
-
- if not match:
- matches = find_packages(query, include_masked=True)
- else:
- matches = [match]
-
- if not matches:
- raise errors.GentoolkitNoMatches(query)
-
- return matches[0]
-
-
-def is_ranged(atom):
- """Return True if an atom string appears to be ranged, else False."""
-
- return atom.startswith(('~', '<', '>')) or atom.endswith('*')
+ )))
def parse_module_options(module_opts):
for i, entry in enumerate(entries): # , start=1): in py2.6
i += 1
if i < len_entries:
- print entry
+ print(entry)
else:
- print entry.strip()
+ print(entry.strip())
def set_limit(posarg):
else:
err = "Module option --limit requires integer (got '%s')"
sys.stderr.write(pp.error(err % posarg))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
sys.exit(2)
first_run = True
- for query in queries:
+ for query in (Query(x) for x in queries):
if not first_run:
- print
+ print()
- match = get_match(query)
+ match = query.find_best()
changelog_path = os.path.join(match.package_path(), 'ChangeLog')
changelog = ChangeLog(changelog_path)
if (QUERY_OPTS['onlyLatest'] or (
changelog.entries and not changelog.indexed_entries
)):
- print changelog.latest.strip()
+ print(changelog.latest.strip())
else:
end = QUERY_OPTS['limit'] or len(changelog.indexed_entries)
if QUERY_OPTS['to'] or QUERY_OPTS['from']:
print_entries(changelog.full[:end])
else:
# Raises GentoolkitInvalidAtom here if invalid
- atom = Atom(query) if is_ranged(query) else '=' + str(match.cpv)
+ if query.is_ranged():
+ atom = Atom(str(query))
+ else:
+ atom = '=' + str(match.cpv)
print_entries(changelog.entries_matching_atom(atom)[:end])
first_run = False
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
"""Checks timestamps and MD5 sums for files owned by a given installed package"""
+from __future__ import print_function
+
__docformat__ = 'epytext'
# =======
# Imports
# =======
-import os
import sys
from functools import partial
from getopt import gnu_getopt, GetoptError
import portage.checksum as checksum
+from portage import os
import gentoolkit.pprinter as pp
from gentoolkit import errors
from gentoolkit.equery import format_options, mod_usage, CONFIG
-from gentoolkit.helpers import do_lookup
+from gentoolkit.query import Query
# =======
# Globals
# =======
QUERY_OPTS = {
- "includeInstalled": True,
- "includeOverlayTree": False,
- "includePortTree": False,
- "checkMD5sum": True,
- "checkTimestamp" : True,
- "isRegex": False,
- "onlyFailures": False,
- "printMatchInfo": False,
- "showSummary" : True,
- "showPassedFiles" : False,
- "showFailedFiles" : True
+ "in_installed": True,
+ "in_porttree": False,
+ "in_overlay": False,
+ "check_MD5sum": True,
+ "check_timestamp" : True,
+ "is_regex": False,
+ "only_failures": False,
+ "show_progress": False,
}
# =======
"""
if with_description:
- print __doc__.strip()
- print
+ print(__doc__.strip())
+ print()
# Deprecation warning added by djanderson, 12/2008
depwarning = (
)
for line in depwarning:
sys.stderr.write(pp.warn(line))
- print
+ print()
- print mod_usage(mod_name="check")
- print
- print pp.command("options")
- print format_options((
+ print(mod_usage(mod_name="check"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -f, --full-regex", "query is a regular expression"),
(" -o, --only-failures", "only display packages that do not pass"),
- ))
+ )))
def checks_printer(cpv, data, verbose=True, only_failures=False):
else:
if verbose:
if not cpv in seen:
- print "* Checking %s ..." % (pp.emph(str(cpv)))
+ print("* Checking %s ..." % (pp.emph(str(cpv))))
seen.append(cpv)
else:
- print "%s:" % cpv,
+ print("%s:" % cpv, end=' ')
if verbose:
for err in errs:
n_passed = pp.number(str(n_passed))
n_checked = pp.number(str(n_checked))
info = " %(n_passed)s out of %(n_checked)s files passed"
- print info % locals()
+ print(info % locals())
else:
- print "failed(%s)" % n_failed
+ print("failed(%s)" % n_failed)
def parse_module_options(module_opts):
print_help()
sys.exit(0)
elif opt in ('-f', '--full-regex'):
- QUERY_OPTS['isRegex'] = True
+ QUERY_OPTS['is_regex'] = True
elif opt in ('-o', '--only-failures'):
- QUERY_OPTS['onlyFailures'] = True
+ QUERY_OPTS['only_failures'] = True
def main(input_args):
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
sys.exit(2)
first_run = True
- for query in queries:
+ for query in (Query(x, QUERY_OPTS['is_regex']) for x in queries):
if not first_run:
- print
+ print()
- matches = do_lookup(query, QUERY_OPTS)
+ matches = query.smart_find(**QUERY_OPTS)
if not matches:
raise errors.GentoolkitNoMatches(query, in_installed=True)
printer = partial(
checks_printer,
verbose=CONFIG['verbose'],
- only_failures=QUERY_OPTS['onlyFailures']
+ only_failures=QUERY_OPTS['only_failures']
)
check = VerifyContents(printer_fn=printer)
check(matches)
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
"""List all packages that depend on a atom given query"""
+from __future__ import print_function
+
__docformat__ = 'epytext'
# =======
import gentoolkit.pprinter as pp
from gentoolkit.dependencies import Dependencies
from gentoolkit.equery import format_options, mod_usage, CONFIG
-from gentoolkit.helpers import (get_cpvs, get_installed_cpvs,
- compare_package_strings)
+from gentoolkit.helpers import get_cpvs, get_installed_cpvs
+from gentoolkit.cpv import CPV
# =======
# Globals
"""Verbosely prints a set of dep strings."""
sep = ' ? ' if (depatom and use_conditional) else ''
- print indent + pp.cpv(cpv), "(" + use_conditional + sep + depatom + ")"
+ print(indent + pp.cpv(cpv), "(" + use_conditional + sep + depatom + ")")
# W0613: *Unused argument %r*
# pylint: disable-msg=W0613
def print_quiet(indent, cpv, use_conditional, depatom):
"""Quietly prints a subset set of dep strings."""
- print indent + pp.cpv(cpv)
+ print(indent + pp.cpv(cpv))
def format_depend(self, dep, dep_is_displayed):
"""Format a dependency for printing.
"""
if with_description:
- print __doc__.strip()
- print
- print mod_usage(mod_name="depends")
- print
- print pp.command("options")
- print format_options((
+ print(__doc__.strip())
+ print()
+ print(mod_usage(mod_name="depends"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -a, --all-packages",
"include dependencies that are not installed (slow)"),
(" -D, --indirect",
"search both direct and indirect dependencies"),
(" --depth=N", "limit indirect dependency tree to specified depth")
- ))
+ )))
def parse_module_options(module_opts):
else:
err = "Module option --depth requires integer (got '%s')"
sys.stdout.write(pp.error(err % posarg))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
QUERY_OPTS["maxDepth"] = depth
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
first_run = True
for query in queries:
if not first_run:
- print
+ print()
pkg = Dependencies(query)
if QUERY_OPTS['includeMasked']:
pkggetter = get_installed_cpvs
if CONFIG['verbose']:
- print " * These packages depend on %s:" % pp.emph(str(pkg.cpv))
+ print(" * These packages depend on %s:" % pp.emph(pkg.cpv))
pkg.graph_reverse_depends(
- pkgset=sorted(pkggetter(), cmp=compare_package_strings),
+ pkgset=sorted(pkggetter(), key = CPV),
max_depth=QUERY_OPTS["maxDepth"],
only_direct=QUERY_OPTS["onlyDirect"],
printer_fn=dep_print
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
"""Display a direct dependency graph for a given package"""
+from __future__ import print_function
+
__docformat__ = 'epytext'
# =======
from functools import partial
from getopt import gnu_getopt, GetoptError
+import portage
+
import gentoolkit.pprinter as pp
from gentoolkit import errors
from gentoolkit.equery import format_options, mod_usage, CONFIG
-from gentoolkit.helpers import do_lookup
+from gentoolkit.keyword import determine_keyword
+from gentoolkit.query import Query
# =======
# Globals
QUERY_OPTS = {
"depth": 1,
- "noAtom": False,
- "noIndent": False,
- "noUseflags": False,
- "includeInstalled": True,
- "includePortTree": True,
- "includeOverlayTree": True,
- "includeMasked": True,
- "isRegex": False,
- "matchExact": True,
- "printMatchInfo": (not CONFIG['quiet'])
+ "no_atom": False,
+ "no_indent": False,
+ "no_useflags": False,
+ "no_mask": False,
+ "in_installed": True,
+ "in_porttree": True,
+ "in_overlay": True,
+ "include_masked": True,
+ "show_progress": (not CONFIG['quiet'])
}
# =========
"""
if with_description:
- print __doc__.strip()
- print
- print "Default depth is set to 1 (direct only). Use --depth=0 for no max."
- print
- print mod_usage(mod_name="depgraph")
- print
- print pp.command("options")
- print format_options((
+ print(__doc__.strip())
+ print()
+ print("Default depth is set to 1 (direct only). Use --depth=0 for no max.")
+ print()
+ print(mod_usage(mod_name="depgraph"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -A, --no-atom", "do not show dependency atom"),
+ (" -M, --no-mask", "do not show masking status"),
(" -U, --no-useflags", "do not show USE flags"),
(" -l, --linear", "do not format the graph by indenting dependencies"),
(" --depth=N", "limit dependency graph to specified depth")
- ))
+ )))
def parse_module_options(module_opts):
print_help()
sys.exit(0)
if opt in ('-A', '--no-atom'):
- QUERY_OPTS["noAtom"] = True
+ QUERY_OPTS["no_atom"] = True
if opt in ('-U', '--no-useflags'):
- QUERY_OPTS["noUseflags"] = True
+ QUERY_OPTS["no_useflags"] = True
+ if opt in ('-M', '--no-mask'):
+ QUERY_OPTS["no_mask"] = True
if opt in ('-l', '--linear'):
- QUERY_OPTS["noIndent"] = True
+ QUERY_OPTS["no_indent"] = True
if opt in ('--depth'):
if posarg.isdigit():
depth = int(posarg)
else:
err = "Module option --depth requires integer (got '%s')"
sys.stderr.write(pp.error(err % posarg))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
QUERY_OPTS["depth"] = depth
no_use=False,
no_atom=False,
no_indent=False,
- initial_pkg=False
+ initial_pkg=False,
+ no_mask=False
):
"""Display L{gentoolkit.dependencies.Dependencies.graph_depends} results.
indent = '' if no_indent or initial_pkg else ' ' + (' ' * depth)
decorator = '[%3d] ' % depth if no_indent else '`-- '
use = ''
+ atom = ''
+ mask = ''
try:
- atom = '' if no_atom else ' (%s)' % dep.atom
+ if not no_atom:
+ if dep.operator == '=*':
+ atom += ' (=%s*)' % dep.cpv
+ else:
+ atom += ' (%s%s)' % (dep.operator, dep.cpv)
if not no_use and dep is not None and dep.use:
use = ' [%s]' % ' '.join(
pp.useflag(x, enabled=True) for x in dep.use.tokens
)
except AttributeError:
# 'NoneType' object has no attribute 'atom'
- atom = ''
+ pass
+ if pkg and not no_mask:
+ mask = pkg.mask_status()
+ if not mask:
+ mask = [determine_keyword(portage.settings["ARCH"],
+ portage.settings["ACCEPT_KEYWORDS"],
+ pkg.environment('KEYWORDS'))]
+ mask = pp.masking(mask)
try:
- print ''.join((indent, decorator, pp.cpv(str(pkg.cpv)), atom, use))
+ print(' '.join((indent, decorator, pp.cpv(str(pkg.cpv)), atom, mask, use)))
except AttributeError:
# 'NoneType' object has no attribute 'cpv'
- print ''.join((indent, decorator, "(no match for %r)" % dep.atom))
+ print(''.join((indent, decorator, "(no match for %r)" % dep.atom)))
def make_depgraph(pkg, printer_fn):
"""Create and display depgraph for each package."""
if CONFIG['verbose']:
- print " * direct dependency graph for %s:" % pp.cpv(str(pkg.cpv))
+ print() # blank line improves readability & package version separation
+ print(" * " + pp.subsection("dependency graph for ") + pp.cpv(str(pkg.cpv)))
else:
- print "%s:" % str(pkg.cpv)
+ print()
+ print("%s:" % pkg.cpv)
# Print out the first package
printer_fn(0, pkg, None, initial_pkg=True)
n_packages = pp.number(str(len(deps)))
max_seen = pp.number(str(max(x[0] for x in deps)))
info = "[ %s stats: packages (%s), max depth (%s) ]"
- print info % (pkgname, n_packages, max_seen)
+ print(info % (pkgname, n_packages, max_seen))
def main(input_args):
"""Parse input and run the program"""
- short_opts = "hAUl"
- long_opts = ('help', 'no-atom', 'no-useflags', 'depth=')
+ short_opts = "hAMUl"
+ long_opts = ('help', 'no-atom', 'no-useflags', 'no-mask', 'depth=')
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
#
first_run = True
- for query in queries:
+ for query in (Query(x) for x in queries):
if not first_run:
- print
+ print()
- matches = do_lookup(query, QUERY_OPTS)
+ matches = query.smart_find(**QUERY_OPTS)
if not matches:
raise errors.GentoolkitNoMatches(query)
+ matches.sort()
+
if CONFIG['verbose']:
printer = partial(
depgraph_printer,
- no_atom=QUERY_OPTS['noAtom'],
- no_indent=QUERY_OPTS['noIndent'],
- no_use=QUERY_OPTS['noUseflags']
+ no_atom=QUERY_OPTS['no_atom'],
+ no_indent=QUERY_OPTS['no_indent'],
+ no_use=QUERY_OPTS['no_useflags'],
+ no_mask=QUERY_OPTS['no_mask']
)
else:
printer = partial(
depgraph_printer,
no_atom=True,
no_indent=True,
- no_use=True
+ no_use=True,
+ no_mask=True
)
for pkg in matches:
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
# $Header: $
-"""List files owned by a given package"""
+"""List files owned by a given package."""
+
+from __future__ import print_function
__docformat__ = 'epytext'
# Imports
# =======
-import os
import sys
from getopt import gnu_getopt, GetoptError
import portage
+from portage import os
import gentoolkit.pprinter as pp
from gentoolkit.equery import (format_filetype, format_options, mod_usage,
CONFIG)
-from gentoolkit.helpers import do_lookup
+from gentoolkit.query import Query
# =======
# Globals
# =======
QUERY_OPTS = {
- "categoryFilter": None,
- "includeInstalled": True,
- "includePortTree": False,
- "includeOverlayTree": False,
- "includeMasked": True,
- "isRegex": False,
- "matchExact": True,
- "outputTree": False,
- "printMatchInfo": (not CONFIG['quiet']),
- "showType": False,
- "showTimestamp": False,
- "showMD5": False,
- "typeFilter": None
+ "in_installed": True,
+ "in_porttree": False,
+ "in_overlay": False,
+ "include_masked": True,
+ "output_tree": False,
+ "show_progress": (not CONFIG['quiet']),
+ "show_type": False,
+ "show_timestamp": False,
+ "show_MD5": False,
+ "type_filter": None
}
FILTER_RULES = (
"""
if with_description:
- print __doc__.strip()
- print
- print mod_usage(mod_name="files")
- print
- print pp.command("options")
- print format_options((
+ print(__doc__.strip())
+ print()
+ print(mod_usage(mod_name="files"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -m, --md5sum", "include MD5 sum in output"),
(" -s, --timestamp", "include timestamp in output"),
(" -f, --filter=RULES", "filter output by file type"),
(" RULES",
"a comma-separated list (no spaces); choose from:")
- ))
- print " " * 24, ', '.join(pp.emph(x) for x in FILTER_RULES)
+ )))
+ print(" " * 24, ', '.join(pp.emph(x) for x in FILTER_RULES))
# R0912: *Too many branches (%s/%s)*
@param contents: {'path': ['filetype', ...], ...}
"""
- filenames = contents.keys()
+ filenames = list(contents.keys())
filenames.sort()
last = []
for name in filenames:
- if QUERY_OPTS["outputTree"]:
+ if QUERY_OPTS["output_tree"]:
dirdepth = name.count('/')
indent = " "
if dirdepth == 2:
if contents[name][0] == "dir":
if len(last) == 0:
last = basename
- print pp.path(indent + basename[0])
+ print(pp.path(indent + basename[0]))
continue
for i, directory in enumerate(basename):
try:
pass
last = basename
if len(last) == 1:
- print pp.path(indent + last[0])
+ print(pp.path(indent + last[0]))
continue
- print pp.path(indent + "> /" + last[-1])
+ print(pp.path(indent + "> /" + last[-1]))
elif contents[name][0] == "sym":
- print pp.path(indent + "+"),
- print pp.path_symlink(basename[-1] + " -> " + contents[name][2])
+ print(pp.path(indent + "+"), end=' ')
+ print(pp.path_symlink(basename[-1] + " -> " + contents[name][2]))
else:
- print pp.path(indent + "+ ") + basename[-1]
+ print(pp.path(indent + "+ ") + basename[-1])
else:
- print format_filetype(
+ print(format_filetype(
name,
contents[name],
- show_type=QUERY_OPTS["showType"],
- show_md5=QUERY_OPTS["showMD5"],
- show_timestamp=QUERY_OPTS["showTimestamp"]
- )
+ show_type=QUERY_OPTS["show_type"],
+ show_md5=QUERY_OPTS["show_MD5"],
+ show_timestamp=QUERY_OPTS["show_timestamp"]
+ ))
def filter_by_doc(contents, content_filter):
@return: contents with unrequested filetypes stripped
"""
- if QUERY_OPTS['typeFilter']:
- content_filter = QUERY_OPTS['typeFilter']
+ if QUERY_OPTS['type_filter']:
+ content_filter = QUERY_OPTS['type_filter']
else:
return contents
if opt in ('-h', '--help'):
print_help()
sys.exit(0)
- elif opt in ('-e', '--exact-name'):
- QUERY_OPTS["matchExact"] = True
elif opt in ('-m', '--md5sum'):
- QUERY_OPTS["showMD5"] = True
+ QUERY_OPTS["show_MD5"] = True
elif opt in ('-s', '--timestamp'):
- QUERY_OPTS["showTimestamp"] = True
+ QUERY_OPTS["show_timestamp"] = True
elif opt in ('-t', '--type'):
- QUERY_OPTS["showType"] = True
+ QUERY_OPTS["show_type"] = True
elif opt in ('--tree'):
- QUERY_OPTS["outputTree"] = True
+ QUERY_OPTS["output_tree"] = True
elif opt in ('-f', '--filter'):
f_split = posarg.split(',')
content_filter.extend(x.lstrip('=') for x in f_split)
sys.stderr.write(
pp.error("Invalid filter rule '%s'" % rule)
)
- print
+ print()
print_help(with_description=False)
sys.exit(2)
- QUERY_OPTS["typeFilter"] = content_filter
+ QUERY_OPTS["type_filter"] = content_filter
def main(input_args):
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
sys.exit(2)
# Turn off filtering for tree output
- if QUERY_OPTS["outputTree"]:
- QUERY_OPTS["typeFilter"] = None
+ if QUERY_OPTS["output_tree"]:
+ QUERY_OPTS["type_filter"] = None
#
# Output files
first_run = True
for query in queries:
if not first_run:
- print
+ print()
- matches = do_lookup(query, QUERY_OPTS)
+ matches = Query(query).smart_find(**QUERY_OPTS)
if not matches:
sys.stderr.write(
pp.error("No matching packages found for %s" % query)
)
+ matches.sort()
+
for pkg in matches:
if CONFIG['verbose']:
- print " * Contents of %s:" % pp.cpv(str(pkg.cpv))
+ print(" * Contents of %s:" % pp.cpv(str(pkg.cpv)))
contents = pkg.parsed_contents()
display_files(filter_contents(contents))
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2 or higher
#
"""List all installed packages that have a given USE flag"""
+from __future__ import print_function
+
__docformat__ = 'epytext'
# =======
import gentoolkit.pprinter as pp
from gentoolkit import errors
from gentoolkit.equery import format_options, mod_usage, CONFIG
-from gentoolkit.helpers import do_lookup
-from gentoolkit.package import PackageFormatter
+from gentoolkit.package import PackageFormatter, FORMAT_TMPL_VARS
+from gentoolkit.query import Query
# =======
# Globals
# =======
QUERY_OPTS = {
- "categoryFilter": None,
- "includeInstalled": True,
- "includePortTree": False,
- "includeOverlayTree": False,
- "includeMasked": True,
- "isRegex": False, # Necessary for do_lookup, don't change
- "printMatchInfo": False
+ "in_installed": True,
+ "in_porttree": False,
+ "in_overlay": False,
+ "include_masked": True,
+ "show_progress": False,
+ "package_format": None
}
# =========
"""
if with_description:
- print __doc__.strip()
- print
- print mod_usage(mod_name="hasuse", arg="USE-flag")
- print
- print pp.command("options")
- print format_options((
+ print(__doc__.strip())
+ print()
+ print(mod_usage(mod_name="hasuse", arg="USE-flag"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -I, --exclude-installed",
"exclude installed packages from search path"),
(" -o, --overlay-tree", "include overlays in search path"),
- (" -p, --portage-tree", "include entire portage tree in search path")
- ))
+ (" -p, --portage-tree", "include entire portage tree in search path"),
+ (" -F, --format=TMPL", "specify a custom output format"),
+ (" TMPL",
+ "a format template using (see man page):")
+ )))
+ print(" " * 24, ', '.join(pp.emph(x) for x in FORMAT_TMPL_VARS))
def display_useflags(query, pkg):
return
if CONFIG['verbose']:
- fmt_pkg = PackageFormatter(pkg, do_format=True)
+ pkgstr = PackageFormatter(
+ pkg,
+ do_format=True,
+ custom_format=QUERY_OPTS["package_format"]
+ )
else:
- fmt_pkg = PackageFormatter(pkg, do_format=False)
-
- if (QUERY_OPTS["includeInstalled"] and
- not QUERY_OPTS["includePortTree"] and
- not QUERY_OPTS["includeOverlayTree"]):
- if not 'I' in fmt_pkg.location:
+ pkgstr = PackageFormatter(
+ pkg,
+ do_format=False,
+ custom_format=QUERY_OPTS["package_format"]
+ )
+
+ if (QUERY_OPTS["in_installed"] and
+ not QUERY_OPTS["in_porttree"] and
+ not QUERY_OPTS["in_overlay"]):
+ if not 'I' in pkgstr.location:
return
- if (QUERY_OPTS["includePortTree"] and
- not QUERY_OPTS["includeOverlayTree"]):
- if not 'P' in fmt_pkg.location:
+ if (QUERY_OPTS["in_porttree"] and
+ not QUERY_OPTS["in_overlay"]):
+ if not 'P' in pkgstr.location:
return
- if (QUERY_OPTS["includeOverlayTree"] and
- not QUERY_OPTS["includePortTree"]):
- if not 'O' in fmt_pkg.location:
+ if (QUERY_OPTS["in_overlay"] and
+ not QUERY_OPTS["in_porttree"]):
+ if not 'O' in pkgstr.location:
return
- print fmt_pkg
+ print(pkgstr)
# Parse module options
opts = (x[0] for x in module_opts)
- for opt in opts:
+ posargs = (x[1] for x in module_opts)
+ for opt, posarg in zip(opts, posargs):
if opt in ('-h', '--help'):
print_help()
sys.exit(0)
elif opt in ('-I', '--exclue-installed'):
- QUERY_OPTS['includeInstalled'] = False
+ QUERY_OPTS['in_installed'] = False
elif opt in ('-p', '--portage-tree'):
- QUERY_OPTS['includePortTree'] = True
+ QUERY_OPTS['in_porttree'] = True
elif opt in ('-o', '--overlay-tree'):
- QUERY_OPTS['includeOverlayTree'] = True
+ QUERY_OPTS['in_overlay'] = True
+ elif opt in ('-F', '--format'):
+ QUERY_OPTS["package_format"] = posarg
def main(input_args):
"""Parse input and run the program"""
- short_opts = "hiIpo" # -i was option for default action
+ short_opts = "hiIpoF:" # -i was option for default action
# --installed is no longer needed, kept for compatibility (djanderson '09)
long_opts = ('help', 'installed', 'exclude-installed', 'portage-tree',
- 'overlay-tree')
+ 'overlay-tree', 'format=')
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
print_help()
sys.exit(2)
- matches = do_lookup("*", QUERY_OPTS)
+ matches = Query("*").smart_find(**QUERY_OPTS)
matches.sort()
#
first_run = True
for query in queries:
if not first_run:
- print
+ print()
if CONFIG['verbose']:
- print " * Searching for USE flag %s ... " % pp.emph(query)
+ print(" * Searching for USE flag %s ... " % pp.emph(query))
for pkg in matches:
display_useflags(query, pkg)
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2 or higher
#
"""List installed packages matching the query pattern"""
+from __future__ import print_function
+
__docformat__ = 'epytext'
# =======
import gentoolkit
import gentoolkit.pprinter as pp
from gentoolkit.equery import format_options, mod_usage, CONFIG
-from gentoolkit.helpers import do_lookup, get_installed_cpvs
-from gentoolkit.package import Package, PackageFormatter
+from gentoolkit.helpers import get_installed_cpvs
+from gentoolkit.package import PackageFormatter, FORMAT_TMPL_VARS
+from gentoolkit.query import Query
# =======
# Globals
QUERY_OPTS = {
"duplicates": False,
- "includeInstalled": True,
- "includePortTree": False,
- "includeOverlayTree": False,
- "includeMasked": True,
- "includeMaskReason": False,
- "isRegex": False,
- "printMatchInfo": (not CONFIG['quiet'])
+ "in_installed": True,
+ "in_porttree": False,
+ "in_overlay": False,
+ "include_mask_reason": False,
+ "is_regex": False,
+ "show_progress": (not CONFIG['quiet']),
+ "package_format": None
}
# =========
"""
if with_description:
- print __doc__.strip()
- print
+ print(__doc__.strip())
+ print()
# Deprecation warning added by djanderson, 12/2008
depwarning = (
)
for line in depwarning:
sys.stderr.write(pp.warn(line))
- print
+ print()
- print mod_usage(mod_name="list")
- print
- print pp.command("options")
- print format_options((
+ print(mod_usage(mod_name="list"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -d, --duplicates", "list only installed duplicate packages"),
(" -f, --full-regex", "query is a regular expression"),
(" -I, --exclude-installed",
"exclude installed packages from output"),
(" -o, --overlay-tree", "list packages in overlays"),
- (" -p, --portage-tree", "list packages in the main portage tree")
- ))
+ (" -p, --portage-tree", "list packages in the main portage tree"),
+ (" -F, --format=TMPL", "specify a custom output format"),
+ (" TMPL",
+ "a format template using (see man page):")
+ )))
+ print(" " * 24, ', '.join(pp.emph(x) for x in FORMAT_TMPL_VARS))
def get_duplicates(matches):
dups = {}
result = []
for pkg in matches:
- if pkg.cpv.cp in dups:
- dups[pkg.cpv.cp].append(pkg)
+ if pkg.cp in dups:
+ dups[pkg.cp].append(pkg)
else:
- dups[pkg.cpv.cp] = [pkg]
+ dups[pkg.cp] = [pkg]
for cpv in dups.values():
if len(cpv) > 1:
print_help()
sys.exit(0)
elif opt in ('-I', '--exclude-installed'):
- QUERY_OPTS['includeInstalled'] = False
+ QUERY_OPTS['in_installed'] = False
elif opt in ('-p', '--portage-tree'):
- QUERY_OPTS['includePortTree'] = True
+ QUERY_OPTS['in_porttree'] = True
elif opt in ('-o', '--overlay-tree'):
- QUERY_OPTS['includeOverlayTree'] = True
+ QUERY_OPTS['in_overlay'] = True
elif opt in ('-f', '--full-regex'):
- QUERY_OPTS['isRegex'] = True
+ QUERY_OPTS['is_regex'] = True
elif opt in ('-m', '--mask-reason'):
- QUERY_OPTS['includeMaskReason'] = True
+ QUERY_OPTS['include_mask_reason'] = True
elif opt in ('-e', '--exact-name'):
sys.stderr.write(pp.warn("-e, --exact-name is now default."))
sys.stderr.write(
pp.warn("Use globbing to simulate the old behavior.")
)
- print
+ print()
elif opt in ('-d', '--duplicates'):
QUERY_OPTS['duplicates'] = True
+ elif opt in ('-F', '--format'):
+ QUERY_OPTS["package_format"] = posarg
def main(input_args):
"""Parse input and run the program"""
- short_opts = "hdefiImop" # -i, -e were options for default actions
+ short_opts = "hdefiImopF:" # -i, -e were options for default actions
# 04/09: djanderson
# --all is no longer needed. Kept for compatibility.
# --installed is no longer needed. Kept for compatibility.
# --exact-name is no longer needed. Kept for compatibility.
long_opts = ('help', 'all', 'installed', 'exclude-installed',
- 'mask-reason', 'portage-tree', 'overlay-tree', 'full-regex', 'exact-name',
- 'duplicates')
+ 'mask-reason', 'portage-tree', 'overlay-tree', 'format=', 'full-regex',
+ 'exact-name', 'duplicates')
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
# Only search installed packages when listing duplicate packages
if QUERY_OPTS["duplicates"]:
- QUERY_OPTS["includeInstalled"] = True
- QUERY_OPTS["includePortTree"] = False
- QUERY_OPTS["includeOverlayTree"] = False
- QUERY_OPTS["includeMaskReason"] = False
+ QUERY_OPTS["in_installed"] = True
+ QUERY_OPTS["in_porttree"] = False
+ QUERY_OPTS["in_overlay"] = False
+ QUERY_OPTS["include_mask_reason"] = False
if not queries:
print_help()
sys.exit(2)
first_run = True
- for query in queries:
+ for query in (Query(x, QUERY_OPTS['is_regex']) for x in queries):
if not first_run:
- print
+ print()
- matches = do_lookup(query, QUERY_OPTS)
+ matches = query.smart_find(**QUERY_OPTS)
# Find duplicate packages
if QUERY_OPTS["duplicates"]:
for pkg in matches:
if CONFIG['verbose']:
- pkgstr = PackageFormatter(pkg, do_format=True)
+ pkgstr = PackageFormatter(
+ pkg,
+ do_format=True,
+ custom_format=QUERY_OPTS["package_format"]
+ )
else:
- pkgstr = PackageFormatter(pkg, do_format=False)
-
- if (QUERY_OPTS["includeInstalled"] and
- not QUERY_OPTS["includePortTree"] and
- not QUERY_OPTS["includeOverlayTree"]):
+ pkgstr = PackageFormatter(
+ pkg,
+ do_format=False,
+ custom_format=QUERY_OPTS["package_format"]
+ )
+
+ if (QUERY_OPTS["in_installed"] and
+ not QUERY_OPTS["in_porttree"] and
+ not QUERY_OPTS["in_overlay"]):
if not 'I' in pkgstr.location:
continue
- if (QUERY_OPTS["includePortTree"] and
- not QUERY_OPTS["includeOverlayTree"]):
+ if (QUERY_OPTS["in_porttree"] and
+ not QUERY_OPTS["in_overlay"]):
if not 'P' in pkgstr.location:
continue
- if (QUERY_OPTS["includeOverlayTree"] and
- not QUERY_OPTS["includePortTree"]):
+ if (QUERY_OPTS["in_overlay"] and
+ not QUERY_OPTS["in_porttree"]):
if not 'O' in pkgstr.location:
continue
- print pkgstr
+ print(pkgstr)
- if QUERY_OPTS["includeMaskReason"]:
+ if QUERY_OPTS["include_mask_reason"]:
ms_int, ms_orig = pkgstr.format_mask_status()
if not ms_int > 2:
# ms_int is a number representation of mask level.
# Package not on system or not masked
continue
elif not any(mask_reason):
- print " * No mask reason given"
+ print(" * No mask reason given")
else:
status = ', '.join(ms_orig)
explanation = mask_reason[0]
mask_location = mask_reason[1]
- print " * Masked by %r" % status
- print " * %s:" % mask_location
- print '\n'.join(
+ print(" * Masked by %r" % status)
+ print(" * %s:" % mask_location)
+ print('\n'.join(
[' * %s' % line.lstrip(' #')
for line in explanation.splitlines()]
- )
+ ))
first_run = False
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2 or higher
#
# $Header: $
-"""Display metadata about a given package"""
+"""Display metadata about a given package."""
-# Move to Imports section after Python-2.6 is stable
-from __future__ import with_statement
+from __future__ import print_function
__docformat__ = 'epytext'
# Imports
# =======
-import os
import re
import sys
from getopt import gnu_getopt, GetoptError
+from portage import os
+
import gentoolkit.pprinter as pp
from gentoolkit import errors
from gentoolkit.equery import format_options, mod_usage, CONFIG
-from gentoolkit.helpers import find_packages, print_sequence, print_file
+from gentoolkit.helpers import print_sequence, print_file
from gentoolkit.textwrap_ import TextWrapper
+from gentoolkit.query import Query
# =======
# Globals
"""
if with_description:
- print __doc__.strip()
- print
+ print(__doc__.strip())
+ print()
if with_usage:
- print mod_usage(mod_name="meta")
- print
- print pp.command("options")
- print format_options((
+ print(mod_usage(mod_name="meta"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -d, --description", "show an extended package description"),
(" -H, --herd", "show the herd(s) for the package"),
(" -u, --useflags", "show per-package USE flag descriptions"),
(" -U, --upstream", "show package's upstream information"),
(" -x, --xml", "show the plain metadata.xml file")
- ))
+ )))
def filter_keywords(matches):
# R0912: *Too many branches (%s/%s)*
# pylint: disable-msg=R0912
-def call_format_functions(matches):
+def call_format_functions(best_match, matches):
"""Call information gathering functions and display the results."""
- # Choose a good package to reference metadata from
- ref_pkg = get_reference_pkg(matches)
-
if CONFIG['verbose']:
- repo = ref_pkg.repo_name()
- print " * %s [%s]" % (pp.cpv(ref_pkg.cp), pp.section(repo))
+ repo = best_match.repo_name()
+ print(" * %s [%s]" % (pp.cpv(best_match.cp), pp.section(repo)))
got_opts = False
if any(QUERY_OPTS.values()):
got_opts = True
if QUERY_OPTS["herd"] or not got_opts:
- herds = format_herds(ref_pkg.metadata.herds(include_email=True))
+ herds = format_herds(best_match.metadata.herds(include_email=True))
if QUERY_OPTS["herd"]:
print_sequence(format_list(herds))
else:
for herd in herds:
- print format_line(herd, "Herd: ", " " * 13)
+ print(format_line(herd, "Herd: ", " " * 13))
if QUERY_OPTS["maintainer"] or not got_opts:
- maints = format_maintainers(ref_pkg.metadata.maintainers())
+ maints = format_maintainers(best_match.metadata.maintainers())
if QUERY_OPTS["maintainer"]:
print_sequence(format_list(maints))
else:
if not maints:
- print format_line([], "Maintainer: ", " " * 13)
+ print(format_line([], "Maintainer: ", " " * 13))
else:
for maint in maints:
- print format_line(maint, "Maintainer: ", " " * 13)
+ print(format_line(maint, "Maintainer: ", " " * 13))
if QUERY_OPTS["upstream"] or not got_opts:
- upstream = format_upstream(ref_pkg.metadata.upstream())
+ upstream = format_upstream(best_match.metadata.upstream())
if QUERY_OPTS["upstream"]:
upstream = format_list(upstream)
else:
print_sequence(upstream)
if not got_opts:
- pkg_loc = ref_pkg.package_path()
- print format_line(pkg_loc, "Location: ", " " * 13)
+ pkg_loc = best_match.package_path()
+ print(format_line(pkg_loc, "Location: ", " " * 13))
if QUERY_OPTS["keywords"] or not got_opts:
# Get {<Package 'dev-libs/glib-2.20.5'>: [u'ia64', u'm68k', ...], ...}
match, fmtd_keywords, slot, verstr_len
)
if QUERY_OPTS["keywords"]:
- print keywords_line
+ print(keywords_line)
else:
indent = " " * (16 + verstr_len)
- print format_line(keywords_line, "Keywords: ", indent)
+ print(format_line(keywords_line, "Keywords: ", indent))
if QUERY_OPTS["description"]:
- desc = ref_pkg.metadata.descriptions()
+ desc = best_match.metadata.descriptions()
print_sequence(format_list(desc))
if QUERY_OPTS["useflags"]:
- useflags = format_useflags(ref_pkg.metadata.use())
+ useflags = format_useflags(best_match.metadata.use())
print_sequence(format_list(useflags))
if QUERY_OPTS["xml"]:
- print_file(os.path.join(ref_pkg.package_path(), 'metadata.xml'))
+ print_file(os.path.join(best_match.package_path(), 'metadata.xml'))
def format_line(line, first="", subsequent="", force_quiet=False):
return result
-def get_reference_pkg(matches):
- """Find a package in the Portage tree to reference."""
-
- pkg = None
- rev_matches = list(reversed(matches))
- while rev_matches:
- pkg = rev_matches.pop()
- if not pkg.is_overlay():
- break
-
- return pkg
-
-
def parse_module_options(module_opts):
"""Parse module options and update QUERY_OPTS"""
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
sys.exit(2)
first_run = True
- for query in queries:
- matches = find_packages(query, include_masked=True)
+ for query in (Query(x) for x in queries):
+ best_match = query.find_best()
+ matches = query.find(include_masked=True)
if not matches:
raise errors.GentoolkitNoMatches(query)
if not first_run:
- print
+ print()
matches.sort()
- call_format_functions(matches)
+ call_format_functions(best_match, matches)
first_run = False
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
"""Print total size of files contained in a given package"""
+from __future__ import print_function
+
__docformat__ = 'epytext'
# =======
import gentoolkit.pprinter as pp
from gentoolkit.equery import format_options, mod_usage, CONFIG
-from gentoolkit.helpers import do_lookup
+from gentoolkit.query import Query
# =======
# Globals
# =======
QUERY_OPTS = {
- "includeInstalled": True,
- "includePortTree": False,
- "includeOverlayTree": False,
- "includeMasked": True,
- "isRegex": False,
- "matchExact": False,
- "printMatchInfo": False,
- "sizeInBytes": False
+ "in_installed": True,
+ "in_porttree": False,
+ "in_overlay": False,
+ "include_masked": True,
+ "is_regex": False,
+ "show_progress": False,
+ "size_in_bytes": False
}
# =========
"""
if with_description:
- print __doc__.strip()
- print
+ print(__doc__.strip())
+ print()
# Deprecation warning added by djanderson, 12/2008
depwarning = (
)
for line in depwarning:
sys.stderr.write(pp.warn(line))
- print
+ print()
- print mod_usage(mod_name="size")
- print
- print pp.command("options")
- print format_options((
+ print(mod_usage(mod_name="size"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -b, --bytes", "report size in bytes"),
(" -f, --full-regex", "query is a regular expression")
- ))
+ )))
def display_size(match_set):
size, files, uncounted = pkg.size()
if CONFIG['verbose']:
- print " * %s" % pp.cpv(str(pkg.cpv))
- print "Total files : %s".rjust(25) % pp.number(str(files))
+ print(" * %s" % pp.cpv(str(pkg.cpv)))
+ print("Total files : %s".rjust(25) % pp.number(str(files)))
if uncounted:
- print ("Inaccessible files : %s".rjust(25) %
- pp.number(str(uncounted)))
+ print(("Inaccessible files : %s".rjust(25) %
+ pp.number(str(uncounted))))
- if QUERY_OPTS["sizeInBytes"]:
+ if QUERY_OPTS["size_in_bytes"]:
size_str = pp.number(str(size))
else:
size_str = "%s %s" % format_bytes(size)
- print "Total size : %s".rjust(25) % size_str
+ print("Total size : %s".rjust(25) % size_str)
else:
info = "%s: total(%d), inaccessible(%d), size(%s)"
- print info % (str(pkg.cpv), files, uncounted, size)
+ print(info % (str(pkg.cpv), files, uncounted, size))
def format_bytes(bytes_, precision=2):
"""
labels = (
- (1<<40L, 'TiB'),
- (1<<30L, 'GiB'),
- (1<<20L, 'MiB'),
- (1<<10L, 'KiB'),
+ (1<<40, 'TiB'),
+ (1<<30, 'GiB'),
+ (1<<20, 'MiB'),
+ (1<<10, 'KiB'),
(1, 'bytes')
)
print_help()
sys.exit(0)
elif opt in ('-b', '--bytes'):
- QUERY_OPTS["sizeInBytes"] = True
+ QUERY_OPTS["size_in_bytes"] = True
elif opt in ('-e', '--exact-name'):
sys.stderr.write(pp.warn("-e, --exact-name is now default."))
warning = pp.warn("Use globbing to simulate the old behavior.")
sys.stderr.write(warning)
- print
+ print()
elif opt in ('-f', '--full-regex'):
- QUERY_OPTS['isRegex'] = True
+ QUERY_OPTS['is_regex'] = True
def main(input_args):
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
sys.exit(2)
first_run = True
- for query in queries:
+ for query in (Query(x, QUERY_OPTS['is_regex']) for x in queries):
if not first_run:
- print
+ print()
- matches = do_lookup(query, QUERY_OPTS)
+ matches = query.smart_find(**QUERY_OPTS)
if not matches:
sys.stderr.write(pp.error("No package found matching %s" % query))
+ matches.sort()
+
display_size(matches)
first_run = False
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
"""Display USE flags for a given package"""
+from __future__ import print_function
+
# Move to imports section when Python 2.6 is stable
-from __future__ import with_statement
+
__docformat__ = 'epytext'
# Imports
# =======
-import os
import sys
from functools import partial
from getopt import gnu_getopt, GetoptError
from glob import glob
-from portage import settings
+from portage import os, settings
import gentoolkit.pprinter as pp
from gentoolkit import errors
from gentoolkit.equery import format_options, mod_usage, CONFIG
-from gentoolkit.helpers import find_best_match, find_packages, uniqify
+from gentoolkit.helpers import uniqify
from gentoolkit.textwrap_ import TextWrapper
+from gentoolkit.query import Query
# =======
# Globals
"""
if with_description:
- print __doc__.strip()
- print
- print mod_usage(mod_name=__name__.split('.')[-1])
- print
- print pp.command("options")
- print format_options((
+ print(__doc__.strip())
+ print()
+ print(mod_usage(mod_name=__name__.split('.')[-1]))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -a, --all", "include all package versions")
- ))
+ )))
def display_useflags(output):
restrict = "(%s %s)" % (pp.emph("Restricted to"),
pp.cpv(restrict))
twrap.initial_indent = flag_name
- print twrap.fill(restrict)
+ print(twrap.fill(restrict))
if desc:
twrap.initial_indent = twrap.subsequent_indent
- print twrap.fill(desc)
+ print(twrap.fill(desc))
else:
- print " : <unknown>"
+ print(" : <unknown>")
else:
if desc:
twrap.initial_indent = flag_name
desc = twrap.fill(desc)
- print desc
+ print(desc)
else:
twrap.initial_indent = flag_name
- print twrap.fill("<unknown>")
+ print(twrap.fill("<unknown>"))
else:
- print markers[in_makeconf] + flag
+ print(markers[in_makeconf] + flag)
def get_global_useflags():
return global_usedesc
-def get_matches(query):
- """Get packages matching query."""
-
- if not QUERY_OPTS["allVersions"]:
- matches = [find_best_match(query)]
- if None in matches:
- matches = find_packages(query, include_masked=False)
- if matches:
- matches.sort()
- else:
- matches = find_packages(query, include_masked=True)
-
- if not matches:
- raise errors.GentoolkitNoMatches(query)
-
- return matches
-
-
def get_output_descriptions(pkg, global_usedesc):
"""Prepare descriptions and usage information for each USE flag."""
def print_legend():
"""Print a legend to explain the output format."""
- print "[ Legend : %s - flag is set in make.conf ]" % pp.emph("U")
- print "[ : %s - package is installed with flag ]" % pp.emph("I")
- print "[ Colors : %s, %s ]" % (
- pp.useflag("set", enabled=True), pp.useflag("unset", enabled=False))
+ print("[ Legend : %s - flag is set in make.conf ]" % pp.emph("U"))
+ print("[ : %s - package is installed with flag ]" % pp.emph("I"))
+ print("[ Colors : %s, %s ]" % (
+ pp.useflag("set", enabled=True), pp.useflag("unset", enabled=False)))
def main(input_args):
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
first_run = True
legend_printed = False
- for query in queries:
+ for query in (Query(x) for x in queries):
if not first_run:
- print
+ print()
- if CONFIG['verbose']:
- print " * Searching for %s ..." % pp.pkgquery(query)
+ if QUERY_OPTS["allVersions"]:
+ matches = query.find(include_masked=True)
+ else:
+ matches = [query.find_best()]
+
+ if not matches:
+ raise errors.GentoolkitNoMatches(query)
- matches = get_matches(query)
matches.sort()
global_usedesc = get_global_useflags()
if not legend_printed:
print_legend()
legend_printed = True
- print (" * Found these USE flags for %s:" %
- pp.cpv(str(pkg.cpv)))
- print pp.emph(" U I")
+ print((" * Found these USE flags for %s:" %
+ pp.cpv(str(pkg.cpv))))
+ print(pp.emph(" U I"))
display_useflags(output)
else:
if CONFIG['verbose']:
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
configuration
"""
+from __future__ import print_function
+
__docformat__ = 'epytext'
# =======
# Imports
# =======
-import os
import sys
from getopt import gnu_getopt, GetoptError
+from portage import os
+
import gentoolkit.pprinter as pp
from gentoolkit import errors
from gentoolkit.equery import format_options, mod_usage
-from gentoolkit.helpers import find_packages
+from gentoolkit.query import Query
# =======
# Globals
# =======
-QUERY_OPTS = {"includeMasked": False}
+QUERY_OPTS = {"include_masked": False}
# =========
# Functions
"""
if with_description:
- print __doc__.strip()
- print
- print mod_usage(mod_name="which")
- print
- print pp.command("options")
- print format_options((
+ print(__doc__.strip())
+ print()
+ print(mod_usage(mod_name="which"))
+ print()
+ print(pp.command("options"))
+ print(format_options((
(" -h, --help", "display this help message"),
(" -m, --include-masked", "return highest version ebuild available")
- ))
+ )))
def parse_module_options(module_opts):
print_help()
sys.exit(0)
elif opt in ('-m', '--include-masked'):
- QUERY_OPTS['includeMasked'] = True
+ QUERY_OPTS['include_masked'] = True
def main(input_args):
try:
module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
- except GetoptError, err:
+ except GetoptError as err:
sys.stderr.write(pp.error("Module %s" % err))
- print
+ print()
print_help(with_description=False)
sys.exit(2)
print_help()
sys.exit(2)
- for query in queries:
-
- matches = find_packages(query, QUERY_OPTS['includeMasked'])
+ for query in (Query(x) for x in queries):
+ matches = query.find(
+ include_masked=QUERY_OPTS['include_masked'],
+ in_installed=False
+ )
if matches:
pkg = sorted(matches).pop()
ebuild_path = pkg.ebuild_path()
if ebuild_path:
- print os.path.normpath(ebuild_path)
+ print(os.path.normpath(ebuild_path))
else:
sys.stderr.write(
- pp.warn("No ebuilds to satisfy %s" % pkg.cpv.name)
+ pp.warn("No ebuilds to satisfy %s" % pkg.cpv)
)
else:
raise errors.GentoolkitNoMatches(query)
-# Copyright(c) 2004-2010, Gentoo Foundation
+# Copyright(c) 2004-2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2 or later
'GentoolkitInvalidCPV',
'GentoolkitInvalidRegex',
'GentoolkitInvalidVersion',
- 'GentoolkitNoMatches'
+ 'GentoolkitNoMatches',
+ 'GentoolkitSetNotFound',
+ 'GentoolkitUnknownKeyword'
)
# ==========
return "Invalid atom: '%s'" % self.atom
+class GentoolkitSetNotFound(GentoolkitException):
+ """Got unknown set."""
+ def __init__(self, setname):
+ self.setname = setname
+
+ def __str__(self):
+ return "Unknown set: '%s'" % self.setname
+
+
class GentoolkitInvalidCategory(GentoolkitException):
"""The category was not listed in portage.settings.categories."""
def __init__(self, category):
return "No %spackages matching '%s'" % (inst, self.query)
+class GentoolkitUnknownKeyword(GentoolkitException):
+ """No packages were found matching the search query."""
+ def __init__(self, query, keywords, use):
+ self.query = query
+ self.keywords = keywords
+ self.use = use
+
+ def __str__(self):
+ return ("Unable to determine the install keyword for:\n" +
+ "'%s', KEYWORDS = '%s'\nUSE flags = '%s'"
+ % (self.query, self.keywords, self.use))
+
# vim: set ts=4 sw=4 tw=79:
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org>
+# Copyright(c) 2010, Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+#
+# $Header$
+
+import errno
+import sys
+import time
+
+from portage import os
+
+import gentoolkit
+from gentoolkit.textwrap_ import TextWrapper
+import gentoolkit.pprinter as pp
+
+
+def format_options(options):
+ """Format module options.
+
+ @type options: list
+ @param options: [('option 1', 'description 1'), ('option 2', 'des... )]
+ @rtype: str
+ @return: formatted options string
+ """
+
+ result = []
+ twrap = TextWrapper(width=gentoolkit.CONFIG['termWidth'])
+ opts = (x[0] for x in options)
+ descs = (x[1] for x in options)
+ for opt, desc in zip(opts, descs):
+ twrap.initial_indent = pp.emph(opt.ljust(25))
+ twrap.subsequent_indent = " " * 25
+ result.append(twrap.fill(desc))
+ return '\n'.join(result)
+
+
+def format_filetype(path, fdesc, show_type=False, show_md5=False,
+ show_timestamp=False):
+ """Format a path for printing.
+
+ @type path: str
+ @param path: the path
+ @type fdesc: list
+ @param fdesc: [file_type, timestamp, MD5 sum/symlink target]
+ file_type is one of dev, dir, obj, sym.
+ If file_type is dir, there is no timestamp or MD5 sum.
+ If file_type is sym, fdesc[2] is the target of the symlink.
+ @type show_type: bool
+ @param show_type: if True, prepend the file's type to the formatted string
+ @type show_md5: bool
+ @param show_md5: if True, append MD5 sum to the formatted string
+ @type show_timestamp: bool
+ @param show_timestamp: if True, append time-of-creation after pathname
+ @rtype: str
+ @return: formatted pathname with optional added information
+ """
+
+ ftype = fpath = stamp = md5sum = ""
+ if fdesc[0] == "obj":
+ ftype = "file"
+ fpath = path
+ stamp = format_timestamp(fdesc[1])
+ md5sum = fdesc[2]
+ elif fdesc[0] == "dir":
+ ftype = "dir"
+ fpath = pp.path(path)
+ elif fdesc[0] == "sym":
+ ftype = "sym"
+ stamp = format_timestamp(fdesc[1])
+ tgt = fdesc[2].split()[0]
+ if CONFIG["piping"]:
+ fpath = path
+ else:
+ fpath = pp.path_symlink(path + " -> " + tgt)
+ elif fdesc[0] == "dev":
+ ftype = "dev"
+ fpath = path
+ else:
+ sys.stderr.write(
+ pp.error("%s has unknown type: %s" % (path, fdesc[0]))
+ )
+ result = ""
+ if show_type:
+ result += "%4s " % ftype
+ result += fpath
+ if show_timestamp:
+ result += " " + stamp
+ if show_md5:
+ result += " " + md5sum
+ return result
+
+
+
+def format_timestamp(timestamp):
+ """Format a timestamp into, e.g., '2009-01-31 21:19:44' format"""
+
+ return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(timestamp)))
+
# - getting GLSAs from http/ftp servers (not really useful without the fixed ebuilds)
# - GPG signing/verification (until key policy is clear)
+from __future__ import unicode_literals
+
__author__ = "Marius Mauch <genone@gentoo.org>"
-import os
+
import sys
-import urllib
+try:
+ from urllib import urlopen
+except ImportError:
+ from urllib.request import urlopen
import codecs
import re
import operator
import xml.dom.minidom
-from StringIO import StringIO
+from io import StringIO
+from functools import reduce
if sys.version_info[0:2] < (2,3):
raise NotImplementedError("Python versions below 2.3 have broken XML code " \
sys.path.insert(0, "/usr/lib/portage/pym")
import portage
+from portage import os
+
# Note: the space for rgt and rlt is important !!
opMapping = {"le": "<=", "lt": "<", "eq": "=", "gt": ">", "ge": ">=",
"rge": ">=~", "rle": "<=~", "rgt": " >~", "rlt": " <~"}
myurl = "file://"+self.nr
else:
myurl = repository + self.config["GLSA_PREFIX"] + str(self.nr) + self.config["GLSA_SUFFIX"]
- self.parse(urllib.urlopen(myurl))
+ self.parse(urlopen(myurl))
return None
def parse(self, myfile):
self.synopsis = getText(myroot.getElementsByTagName("synopsis")[0], format="strip")
self.announced = format_date(getText(myroot.getElementsByTagName("announced")[0], format="strip"))
- count = 1
# Support both formats of revised:
# <revised>December 30, 2007: 02</revised>
# <revised count="2">2007-12-30</revised>
revisedEl = myroot.getElementsByTagName("revised")[0]
self.revised = getText(revisedEl, format="strip")
- if (revisedEl.attributes.has_key("count")):
- count = revisedEl.getAttribute("count")
- elif (self.revised.find(":") >= 0):
- (self.revised, count) = self.revised.split(":")
+ count = revisedEl.attributes.get("count")
+ if count is None:
+ if self.revised.find(":") >= 0:
+ (self.revised, count) = self.revised.split(":")
+ else:
+ count = 1
self.revised = format_date(self.revised)
self.packages = {}
for p in self.affected.getElementsByTagName("package"):
name = p.getAttribute("name")
- if not self.packages.has_key(name):
+ if name not in self.packages:
self.packages[name] = []
tmp = {}
tmp["arch"] = p.getAttribute("arch")
pass
if len(self.bugs) > 0:
outstream.write("\nRelated bugs: ")
- outstream.write(", ".join(self.bugs))
- outstream.write("\n")
+ outstream.write(", ".join(self.bugs))
+ outstream.write("\n")
if self.background:
outstream.write("\n"+wrap(self.background, width, caption="Background: "))
outstream.write("\n"+wrap(self.description, width, caption="Description: "))
outstream.write("\n"+wrap(self.impact_text, width, caption="Impact: "))
outstream.write("\n"+wrap(self.workaround, width, caption="Workaround: "))
outstream.write("\n"+wrap(self.resolution, width, caption="Resolution: "))
- myreferences = " ".join(r.replace(" ", SPACE_ESCAPE)+NEWLINE_ESCAPE for r in self.references)
+ myreferences = " ".join(r.replace(" ", SPACE_ESCAPE)+NEWLINE_ESCAPE for r in self.references)
outstream.write("\n"+wrap(myreferences, width, caption="References: "))
outstream.write("\n")
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright(c) 2009-2010, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2 or higher
#
# $Header$
-"""Improved versions of the original helpers functions.
+"""Miscellaneous helper functions and classes.
-As a convention, functions ending in '_packages' or '_match{es}' return
-Package objects, while functions ending in 'cpvs' return a sequence of strings.
-Functions starting with 'get_' return a set of packages by default and can be
-filtered, while functions starting with 'find_' return nothing unless the
-query matches one or more packages.
+@note: find_* functions that previously lived here have moved to
+ the query module, where they are called as: Query('portage').find_*().
"""
-# Move to Imports section after Python 2.6 is stable
-from __future__ import with_statement
+from __future__ import print_function
__all__ = (
'ChangeLog',
'FileOwner',
- 'compare_package_strings',
- 'do_lookup',
- 'find_best_match',
- 'find_installed_packages',
- 'find_packages',
'get_cpvs',
'get_installed_cpvs',
'get_uninstalled_cpvs',
'uniqify',
- 'uses_globbing',
- 'split_cpv'
+ 'walk'
)
__docformat__ = 'epytext'
# Imports
# =======
-import fnmatch
-import os
import re
from functools import partial
from itertools import chain
-import portage
-from portage.versions import catpkgsplit, pkgcmp
+from portage import os, _unicode_decode, _encodings
from gentoolkit import pprinter as pp
-from gentoolkit import CONFIG
from gentoolkit import errors
from gentoolkit.atom import Atom
from gentoolkit.cpv import CPV
if from_restriction and not from_restriction.match(i):
continue
if to_restriction and not to_restriction.match(i):
+ # TODO: is it safe to break here?
continue
result.append(entry)
query_re_string = self._prepare_search_regex(queries)
try:
query_re = re.compile(query_re_string)
- except (TypeError, re.error), err:
+ except (TypeError, re.error) as err:
raise errors.GentoolkitInvalidRegex(err)
use_match = False
break
return results
+ @staticmethod
+ def expand_abspaths(paths):
+ """Expand any relative paths (./file) to their absolute paths.
+
+ @type paths: list
+ @param paths: file path strs
+ @rtype: list
+ @return: the original list with any relative paths expanded
+ @raise AttributeError: if paths does not have attribute 'extend'
+ """
+
+ osp = os.path
+ expanded_paths = []
+ for p in paths:
+ if p.startswith('./'):
+ expanded_paths.append(osp.abspath(p))
+ else:
+ expanded_paths.append(p)
+
+ return expanded_paths
+
@staticmethod
def extend_realpaths(paths):
"""Extend a list of paths with the realpaths for any symlinks.
result = []
# Trim trailing and multiple slashes from queries
slashes = re.compile('/+')
+ queries = self.expand_abspaths(queries)
queries = self.extend_realpaths(queries)
for query in queries:
query = slashes.sub('/', query).rstrip('/')
# Functions
# =========
-def compare_package_strings(pkg1, pkg2):
- """Similar to the builtin cmp, but for package strings. Usually called
- as: package_list.sort(compare_package_strings)
-
- An alternative is to use the CPV descriptor from gentoolkit.cpv:
- >>> cpvs = sorted(CPV(x) for x in package_list)
-
- @see: >>> help(cmp)
- """
-
- pkg1 = catpkgsplit(pkg1)
- pkg2 = catpkgsplit(pkg2)
- if pkg1[0] != pkg2[0]:
- return cmp(pkg1[0], pkg2[0])
- elif pkg1[1] != pkg2[1]:
- return cmp(pkg1[1], pkg2[1])
- else:
- return pkgcmp(pkg1[1:], pkg2[1:])
-
-
-def do_lookup(query, query_opts):
- """A high-level wrapper around gentoolkit package-finder functions.
-
- @type query: str
- @param query: pkg, cat/pkg, pkg-ver, cat/pkg-ver, atom, glob or regex
- @type query_opts: dict
- @param query_opts: user-configurable options from the calling module
- Currently supported options are:
-
- includeInstalled = bool
- includePortTree = bool
- includeOverlayTree = bool
- isRegex = bool
- printMatchInfo = bool # Print info about the search
-
- @rtype: list
- @return: Package objects matching query
- """
-
- if query_opts["includeInstalled"]:
- if query_opts["includePortTree"] or query_opts["includeOverlayTree"]:
- simple_package_finder = partial(find_packages, include_masked=True)
- complex_package_finder = get_cpvs
- else:
- simple_package_finder = find_installed_packages
- complex_package_finder = get_installed_cpvs
- elif query_opts["includePortTree"] or query_opts["includeOverlayTree"]:
- simple_package_finder = partial(find_packages, include_masked=True)
- complex_package_finder = get_uninstalled_cpvs
- else:
- raise errors.GentoolkitFatalError(
- "Not searching in installed, Portage tree, or overlay. "
- "Nothing to do."
- )
-
- is_simple_query = True
- if query_opts["isRegex"] or uses_globbing(query):
- is_simple_query = False
-
- if is_simple_query:
- matches = _do_simple_lookup(query, simple_package_finder, query_opts)
- else:
- matches = _do_complex_lookup(query, complex_package_finder, query_opts)
-
- return matches
-
-
-def _do_complex_lookup(query, package_finder, query_opts):
- """Find matches for a query which is a regex or includes globbing."""
-
- # FIXME: Remove when lazyimport supports objects:
- from gentoolkit.package import Package
-
- result = []
-
- if query_opts["printMatchInfo"] and not CONFIG["piping"]:
- print_query_info(query, query_opts)
-
- cat = split_cpv(query)[0]
-
- pre_filter = []
- # The "get_" functions can pre-filter against the whole package key,
- # but since we allow globbing now, we run into issues like:
- # >>> portage.dep.dep_getkey("sys-apps/portage-*")
- # 'sys-apps/portage-'
- # So the only way to guarantee we don't overrun the key is to
- # prefilter by cat only.
- if cat:
- if query_opts["isRegex"]:
- cat_re = cat
- else:
- cat_re = fnmatch.translate(cat)
- # [::-1] reverses a sequence, so we're emulating an ".rreplace()"
- # except we have to put our "new" string on backwards
- cat_re = cat_re[::-1].replace('$', '*./', 1)[::-1]
- predicate = lambda x: re.match(cat_re, x)
- pre_filter = package_finder(predicate=predicate)
-
- # Post-filter
- if query_opts["isRegex"]:
- predicate = lambda x: re.search(query, x)
- else:
- if cat:
- query_re = fnmatch.translate(query)
- else:
- query_re = fnmatch.translate("*/%s" % query)
- predicate = lambda x: re.search(query_re, x)
- if pre_filter:
- result = [x for x in pre_filter if predicate(x)]
- else:
- result = package_finder(predicate=predicate)
-
- return [Package(x) for x in result]
-
-
-def _do_simple_lookup(query, package_finder, query_opts):
- """Find matches for a query which is an atom or string."""
-
- result = []
-
- if query_opts["printMatchInfo"] and CONFIG['verbose']:
- print_query_info(query, query_opts)
-
- result = package_finder(query)
- if not query_opts["includeInstalled"]:
- result = [x for x in result if not x.is_installed()]
-
- return result
-
-
-def find_best_match(query):
- """Return the highest unmasked version of a package matching query.
-
- @type query: str
- @param query: can be of the form: pkg, pkg-ver, cat/pkg, cat/pkg-ver, atom
- @rtype: str or None
- @raise portage.exception.InvalidAtom: if query is not valid input
- """
- # FIXME: Remove when lazyimport supports objects:
- from gentoolkit.package import Package
-
- try:
- match = PORTDB.xmatch("bestmatch-visible", query)
- except portage.exception.InvalidAtom, err:
- raise errors.GentoolkitInvalidAtom(err)
-
- return Package(match) if match else None
-
-
-def find_installed_packages(query):
- """Return a list of Package objects that matched the search key."""
- # FIXME: Remove when lazyimport supports objects:
- from gentoolkit.package import Package
-
- try:
- matches = VARDB.match(query)
- # catch the ambiguous package Exception
- except portage.exception.AmbiguousPackageName, err:
- matches = []
- for pkgkey in err[0]:
- matches.extend(VARDB.match(pkgkey))
- except portage.exception.InvalidAtom, err:
- raise errors.GentoolkitInvalidAtom(err)
-
- return [Package(x) for x in matches]
-
-
-def find_packages(query, include_masked=False):
- """Returns a list of Package objects that matched the query.
-
- @type query: str
- @param query: can be of the form: pkg, pkg-ver, cat/pkg, cat/pkg-ver, atom
- @type include_masked: bool
- @param include_masked: include masked packages
- @rtype: list
- @return: matching Package objects
- """
- # FIXME: Remove when lazyimport supports objects:
- from gentoolkit.package import Package
-
- if not query:
- return []
-
- try:
- if include_masked:
- matches = PORTDB.xmatch("match-all", query)
- else:
- matches = PORTDB.match(query)
- matches.extend(VARDB.match(query))
- except portage.exception.InvalidAtom, err:
- raise errors.GentoolkitInvalidAtom(str(err))
-
- return [Package(x) for x in set(matches)]
-
-
def get_cpvs(predicate=None, include_installed=True):
"""Get all packages in the Portage tree and overlays. Optionally apply a
predicate.
all_cps = PORTDB.cp_all()
all_cpvs = chain.from_iterable(PORTDB.cp_list(x) for x in all_cps)
- all_installed_cpvs = get_installed_cpvs(predicate)
+ all_installed_cpvs = set(get_installed_cpvs(predicate))
if include_installed:
- for cpv in chain(all_cpvs, all_installed_cpvs):
+ for cpv in all_cpvs:
+ if cpv in all_installed_cpvs:
+ all_installed_cpvs.remove(cpv)
+ yield cpv
+ for cpv in all_installed_cpvs:
yield cpv
else:
- # Consume the smaller pkg set:
- installed_cpvs = set(all_installed_cpvs)
for cpv in all_cpvs:
- if cpv not in installed_cpvs:
+ if cpv not in all_installed_cpvs:
yield cpv
yield cpv
-def print_query_info(query, query_opts):
- """Print info about the query to the screen."""
-
- cat, pkg = split_cpv(query)[:2]
- if cat and not query_opts["isRegex"]:
- cat_str = "in %s " % pp.emph(cat.lstrip('><=~!'))
- else:
- cat_str = ""
-
- if query_opts["isRegex"]:
- pkg_str = query
- else:
- pkg_str = pkg
-
- print " * Searching for %s %s..." % (pp.emph(pkg_str), cat_str)
-
-
def print_file(path):
"""Display the contents of a file."""
with open(path) as open_file:
lines = open_file.read()
- print lines.strip()
+ print(lines.strip())
def print_sequence(seq):
"""Print every item of a sequence."""
for item in seq:
- print item
-
-
-def split_cpv(query):
- """Split a cpv into category, name, version and revision.
-
- @type query: str
- @param query: pkg, cat/pkg, pkg-ver, cat/pkg-ver, atom or regex
- @rtype: tuple
- @return: (category, pkg_name, version, revision)
- Each tuple element is a string or empty string ("").
- """
-
- result = catpkgsplit(query)
-
- if result:
- result = list(result)
- if result[0] == 'null':
- result[0] = ''
- if result[3] == 'r0':
- result[3] = ''
- else:
- result = query.split("/")
- if len(result) == 1:
- result = ['', query, '', '']
- else:
- result = result + ['', '']
-
- if len(result) != 4:
- raise errors.GentoolkitInvalidPackageName(query)
-
- return tuple(result)
+ print(item)
def uniqify(seq, preserve_order=True):
return result
-def uses_globbing(query):
- """Check the query to see if it is using globbing.
-
- @type query: str
- @param query: user input package query
- @rtype: bool
- @return: True if query uses globbing, else False
- """
-
- if set('!*?[]').intersection(query):
- # Is query an atom such as '=sys-apps/portage-2.2*'?
- if query[0] != '=':
- return True
-
- return False
+def walk(top, topdown = True, onerror = None, followlinks = False):
+ """Variant of os.walk that always returns unicode filenames"""
+ for root, dirs, files in os.walk(top, topdown, onerror, followlinks):
+ root = _unicode_decode(root, _encodings["fs"], errors = "strict")
+ dirs = [
+ _unicode_decode(x, _encodings["fs"], errors = "strict")
+ for x in dirs
+ ]
+ files = [
+ _unicode_decode(x, _encodings["fs"], errors = "strict")
+ for x in files
+ ]
+ # XXX: in contrast with os.walk we ignore modifications to dirs here
+ yield root, dirs, files
# vim: set ts=4 sw=4 tw=79:
--- /dev/null
+#!/usr/bin/python
+#
+# Copyright(c) 2004-2010, Gentoo Foundation
+#
+# Licensed under the GNU General Public License, v2
+#
+# $Header$
+
+"""Provides common methods on Gentoo GLEP 53 keywords.
+
+http://www.gentoo.org/proj/en/glep/glep-0053.html
+"""
+
+__all__ = (
+ 'Keyword',
+ 'compare_strs'
+)
+
+# =======
+# Imports
+# =======
+
+
+# =======
+# Classes
+# =======
+
+class Keyword(object):
+ """Provides common methods on a GLEP 53 keyword."""
+
+ def __init__(self, keyword):
+ self.keyword = keyword
+
+ def __str__(self):
+ return self.keyword
+
+ def __repr__(self):
+ return "<Keyword {0.keyword!r}>".format(self)
+
+# =========
+# Functions
+# =========
+
+def compare_strs(kw1, kw2):
+ """Similar to the builtin cmp, but for keyword strings. Usually called
+ as: keyword_list.sort(keyword.compare_strs)
+
+ An alternative is to use the Keyword descriptor directly:
+ >>> kwds = sorted(Keyword(x) for x in keyword_list)
+
+ @see: >>> help(cmp)
+ """
+
+ pass
+
+
+def reduce_keywords(keywords):
+ """Reduce a list of keywords to a unique set of stable keywords.
+
+ Example usage:
+ >>> reduce_keywords(['~amd64', 'x86', '~x86'])
+ set(['amd64', 'x86'])
+
+ @type keywords: array
+ @rtype: set
+ """
+ return set(x.lstrip('~') for x in keywords)
+
+
+abs_keywords = reduce_keywords
+
+
+# FIXME: this is unclear
+# dj, how about 'deduce_keyword'
+# I was trying to avoid a 2nd use of determine_keyword name (in analyse.lib)
+# but that one is a little different and not suitable for this task.
+def determine_keyword(arch, accepted, keywords):
+ """Determine a keyword from matching a dep's KEYWORDS
+ list against the ARCH & ACCEPT_KEYWORDS provided.
+
+ @type arch: string
+ @param arch: portage.settings["ARCH"]
+ @type accepted: string
+ @param accepted: portage.settings["ACCEPT_KEYWORDS"]
+ @type keywords: string
+ @param keywords: the pkg ebuilds keywords
+ """
+ if not keywords:
+ return ''
+ keys = keywords.split()
+ if arch in keys:
+ return arch
+ keyworded = "~" + arch
+ if keyworded in keys:
+ return keyworded
+ match = list(set(accepted.split(" ")).intersection(keys))
+ if len(match) > 1:
+ if arch in match:
+ return arch
+ if keyworded in match:
+ return keyworded
+ return 'unknown'
+ if match:
+ return match[0]
+ return 'unknown'
#!/usr/bin/python
#
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
"""
# Move to Imports section after Python-2.6 is stable
-from __future__ import with_statement
+
__all__ = ('MetaData',)
__docformat__ = 'epytext'
# =======
import re
-import os
import xml.etree.cElementTree as etree
-from portage import settings
+from portage import os, settings
# =======
# Classes
#!/usr/bin/python
#
-# Copyright 2004, Karl Trygve Kalleberg <karltk@gentoo.org>
-# Copyright 2004-2010 Gentoo Foundation
+# Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org>
+# Copyright(c) 2004-2010, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
__all__ = (
'Package',
- 'PackageFormatter'
+ 'PackageFormatter',
+ 'FORMAT_TMPL_VARS'
)
+# =======
+# Globals
+# =======
+
+FORMAT_TMPL_VARS = (
+ '$location', '$mask', '$cp', '$cpv', '$category', '$name', '$version', '$revision',
+ '$fullversion', '$slot', '$repo'
+)
+
# =======
# Imports
# =======
-import os
+from string import Template
import portage
-from portage import settings
+from portage import os, settings
+from portage.util import LazyItemsDict
import gentoolkit.pprinter as pp
from gentoolkit import errors
from gentoolkit.cpv import CPV
from gentoolkit.dbapi import PORTDB, VARDB
-from gentoolkit.dependencies import Dependencies
-from gentoolkit.metadata import MetaData
+from gentoolkit.keyword import determine_keyword
# =======
# Classes
def metadata(self):
"""Instantiate a L{gentoolkit.metadata.MetaData} object here."""
+ from gentoolkit.metadata import MetaData
+
if self._metadata is None:
metadata_path = os.path.join(
self.package_path(), 'metadata.xml'
def deps(self):
"""Instantiate a L{gentoolkit.dependencies.Dependencies} object here."""
+ from gentoolkit.dependencies import Dependencies
+
if self._deps is None:
self._deps = Dependencies(self.cpv)
"""
got_string = False
- if isinstance(envvars, basestring):
+ if isinstance(envvars, str):
got_string = True
envvars = (envvars,)
if prefer_vdb:
@param fallback: if the repo_name file does not exist, return the
repository name from the path
@rtype: str
- @return: output of the repository metadata file, which stores the
+ @return: output of the repository metadata file, which stores the
repo_name variable, or try to get the name of the repo from
the path.
@raise GentoolkitFatalError: if fallback is False and repo_name is
"""
seen = set()
- content_stats = (os.lstat(x) for x in self.parsed_contents())
- # Remove hardlinks by checking for duplicate inodes. Bug #301026.
- unique_file_stats = (x for x in content_stats if x.st_ino not in seen
- and not seen.add(x.st_ino))
- size = n_uncounted = n_files = 0
- for st in unique_file_stats:
+ size = n_files = n_uncounted = 0
+ for f in self.parsed_contents():
+ try:
+ st = os.lstat(f)
+ except OSError:
+ pass
+
+ # Remove hardlinks by checking for duplicate inodes. Bug #301026.
+ file_inode = st.st_ino
+ if file_inode in seen:
+ pass
+ seen.add(file_inode)
+
try:
size += st.st_size
n_files += 1
except OSError:
n_uncounted += 1
+
return (size, n_files, n_uncounted)
def is_installed(self):
- """Returns True if this package is installed (merged)"""
+ """Returns True if this package is installed (merged)."""
return self.dblink.exists()
return (tree and tree != self._portdir_path)
def is_masked(self):
- """Returns true if this package is masked against installation.
- Note: We blindly assume that the package actually exists on disk
- somewhere."""
+ """Returns True if this package is masked against installation.
+
+ @note: We blindly assume that the package actually exists on disk.
+ """
unmasked = PORTDB.xmatch("match-visible", self.cpv)
return self.cpv not in unmasked
@type pkg: L{gentoolkit.package.Package}
@param pkg: package to format
- @type format: L{bool}
- @param format: Whether to format the package name or not.
- Essentially C{format} should be set to False when piping or when
+ @type do_format: bool
+ @param do_format: Whether to format the package name or not.
+ Essentially C{do_format} should be set to False when piping or when
quiet output is desired. If C{do_format} is False, only the location
attribute will be created to save time.
"""
- def __init__(self, pkg, do_format=True):
- self.pkg = pkg
+ _tmpl_verbose = "[$location] [$mask] $cpv:$slot"
+ _tmpl_quiet = "$cpv:$slot"
+
+ def __init__(self, pkg, do_format=True, custom_format=None, fill_sizes = None):
+ self._pkg = None
self.do_format = do_format
- self.location = self.format_package_location() or ''
+ self._str = None
+ self._location = None
+ if not custom_format:
+ if do_format:
+ custom_format = self._tmpl_verbose
+ else:
+ custom_format = self._tmpl_quiet
+ self.tmpl = Template(custom_format)
+ self.format_vars = LazyItemsDict()
+ self.pkg = pkg
+ if fill_sizes:
+ self.fill_sizes = fill_sizes
+ else:
+ self.fill_sizes = {
+ 'cpv': 50,
+ 'keyword': 10,
+ 'mask': 10,
+ }
+
def __repr__(self):
return "<%s %s @%#8x>" % (self.__class__.__name__, self.pkg, id(self))
def __str__(self):
- if self.do_format:
- maskmodes = [' ', ' ~', ' -', 'M ', 'M~', 'M-', '??']
- maskmode = maskmodes[self.format_mask_status()[0]]
- return "[%(location)s] [%(mask)s] %(package)s:%(slot)s" % {
- 'location': self.location,
- 'mask': pp.keyword(
- maskmode,
- stable=not maskmode.strip(),
- hard_masked=set(('M', '?', '-')).intersection(maskmode)
- ),
- 'package': pp.cpv(str(self.pkg.cpv)),
- 'slot': pp.slot(self.pkg.environment("SLOT"))
- }
- else:
- return str(self.pkg.cpv)
+ if self._str is None:
+ self._str = self.tmpl.safe_substitute(self.format_vars)
+ return self._str
+
+ @property
+ def location(self):
+ if self._location is None:
+ self._location = self.format_package_location()
+ return self._location
+
+ @property
+ def pkg(self):
+ """Package to format"""
+ return self._pkg
+
+ @pkg.setter
+ def pkg(self, value):
+ if self._pkg == value:
+ return
+ self._pkg = value
+ self._location = None
+
+ fmt_vars = self.format_vars
+ self.format_vars.clear()
+ fmt_vars.addLazySingleton("location",
+ lambda: getattr(self, "location"))
+ fmt_vars.addLazySingleton("mask", self.format_mask)
+ fmt_vars.addLazySingleton("mask2", self.format_mask_status2)
+ fmt_vars.addLazySingleton("cpv", self.format_cpv)
+ fmt_vars.addLazySingleton("cpv_fill", self.format_cpv, fill=True)
+ fmt_vars.addLazySingleton("cp", self.format_cpv, "cp")
+ fmt_vars.addLazySingleton("category", self.format_cpv, "category")
+ fmt_vars.addLazySingleton("name", self.format_cpv, "name")
+ fmt_vars.addLazySingleton("version", self.format_cpv, "version")
+ fmt_vars.addLazySingleton("revision", self.format_cpv, "revision")
+ fmt_vars.addLazySingleton("fullversion", self.format_cpv,
+ "fullversion")
+ fmt_vars.addLazySingleton("slot", self.format_slot)
+ fmt_vars.addLazySingleton("repo", self.pkg.repo_name)
def format_package_location(self):
- """Get the install status (in /var/db/?) and origin (from and overlay
+ """Get the install status (in /var/db/?) and origin (from an overlay
and the Portage tree?).
@rtype: str
return (result, masking_status)
+ def format_mask_status2(self):
+ """Get the mask status of a given package.
+ """
+ mask = self.pkg.mask_status()
+ if mask:
+ return pp.masking(mask)
+ else:
+ arch = self.pkg.settings("ARCH")
+ keywords = self.pkg.environment('KEYWORDS')
+ mask = [determine_keyword(arch,
+ portage.settings["ACCEPT_KEYWORDS"],
+ keywords)]
+ return pp.masking(mask)
+
+ def format_mask(self):
+ maskmodes = [' ', ' ~', ' -', 'M ', 'M~', 'M-', '??']
+ maskmode = maskmodes[self.format_mask_status()[0]]
+ return pp.keyword(
+ maskmode,
+ stable=not maskmode.strip(),
+ hard_masked=set(('M', '?', '-')).intersection(maskmode)
+ )
+
+ def format_cpv(self, attr = None, fill=False):
+ if attr is None:
+ value = self.pkg.cpv
+ else:
+ value = getattr(self.pkg, attr)
+ if self.do_format:
+ if fill:
+ trail = '.'*(self.fill_sizes['cpv']-len(value))
+ return pp.cpv(value) + trail
+ else:
+ return pp.cpv(value)
+ else:
+ return value
+
+ def format_slot(self):
+ value = self.pkg.environment("SLOT")
+ if self.do_format:
+ return pp.slot(value)
+ else:
+ return value
+
# vim: set ts=4 sw=4 tw=79:
#!/usr/bin/python
#
# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org>
-# Copyright 2004-2010 Gentoo Foundation
+# Copyright 2004-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
#
# $Header$
import sys
import portage.output as output
+from portage import archlist
# =========
# Functions
# keyword masked:
return output.blue(string)
+def masking(mask):
+ """Returns a 'masked by' string."""
+ if 'package.mask' in mask or 'profile' in mask:
+ # use porthole wrap style to help clarify meaning
+ return output.red("M["+mask[0]+"]")
+ if mask is not []:
+ for status in mask:
+ if 'keyword' in status:
+ # keyword masked | " [missing keyword] " <=looks better
+ return output.blue("["+status+"]")
+ if status in archlist:
+ return output.green(status)
+ if 'unknown' in status:
+ return output.yellow(status)
+ return output.red(status)
+ return ''
+
def warn(string):
"""Returns a warning string."""
return "!!! " + string + "\n"
#!/usr/bin/python
#
-# Copyright 2004-2010, Gentoo Foundation
+# Copyright(c) 2004-2010, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
# Imports
# =======
+import fnmatch
+import re
+from functools import partial
+
+import portage
+
+from gentoolkit import CONFIG
+from gentoolkit import errors
+from gentoolkit import helpers
+from gentoolkit import pprinter as pp
from gentoolkit.cpv import CPV
+from gentoolkit.dbapi import PORTDB, VARDB
+from gentoolkit.package import Package
+from gentoolkit.sets import get_set_atoms, SETPREFIX
#from gentoolkit.helpers import *
# =======
# Classes
# =======
-class Query(CPV):
+class Query(object):
"""Provides common methods on a package query."""
- def __init__(self, cpv):
- if isinstance(cpv, CPV):
- self.cpv = cpv
+ def __init__(self, query, is_regex=False):
+ """Create query object.
+
+ @type is_regex: bool
+ @param is_regex: query is a regular expression
+ """
+
+ # Separate repository
+ repository = None
+ if query.count(':') == 2:
+ query, repository = query.rsplit(':', 1)
+ self.query = query.rstrip(':') # Don't leave dangling colon
+ self.repo_filter = repository
+ self.is_regex = is_regex
+ self.query_type = self._get_query_type()
+
+ def __repr__(self):
+ rx = ''
+ if self.is_regex:
+ rx = ' regex'
+ repo = ''
+ if self.repo_filter:
+ repo = ' in %s' % self.repo_filter
+ return "<%s%s %r%s>" % (self.__class__.__name__, rx, self.query, repo)
+
+ def __str__(self):
+ return self.query
+
+ def print_summary(self):
+ """Print a summary of the query."""
+
+ cpv = CPV(self.query)
+ cat, pkg = cpv.category, cpv.name + cpv.fullversion
+ if cat and not self.is_regex:
+ cat_str = "in %s " % pp.emph(cat.lstrip('><=~!'))
+ else:
+ cat_str = ""
+
+ if self.is_regex:
+ pkg_str = pp.emph(self.query)
+ else:
+ pkg_str = pp.emph(pkg)
+
+ repo = ''
+ if self.repo_filter is not None:
+ repo = ' %s' % pp.section(self.repo_filter)
+
+ print(" * Searching%s for %s %s..." % (repo, pkg_str, cat_str))
+
+ def smart_find(
+ self,
+ in_installed=True,
+ in_porttree=True,
+ in_overlay=True,
+ include_masked=True,
+ show_progress=True,
+ **kwargs
+ ):
+ """A high-level wrapper around gentoolkit package-finder functions.
+
+ @type in_installed: bool
+ @param in_installed: search for query in VARDB
+ @type in_porttree: bool
+ @param in_porttree: search for query in PORTDB
+ @type in_overlay: bool
+ @param in_overlay: search for query in overlays
+ @type show_progress: bool
+ @param show_progress: output search progress
+ @rtype: list
+ @return: Package objects matching query
+ """
+
+ if in_installed:
+ if in_porttree or in_overlay:
+ simple_package_finder = partial(
+ self.find,
+ include_masked=include_masked
+ )
+ complex_package_finder = helpers.get_cpvs
+ else:
+ simple_package_finder = self.find_installed
+ complex_package_finder = helpers.get_installed_cpvs
+ elif in_porttree or in_overlay:
+ simple_package_finder = partial(
+ helpers.find_packages,
+ include_masked=include_masked
+ )
+ complex_package_finder = helpers.get_uninstalled_cpvs
+ else:
+ raise errors.GentoolkitFatalError(
+ "Not searching in installed, Portage tree, or overlay. "
+ "Nothing to do."
+ )
+
+ if self.query_type == "set":
+ self.package_finder = simple_package_finder
+ matches = self._do_set_lookup(show_progress=show_progress)
+ elif self.query_type == "simple":
+ self.package_finder = simple_package_finder
+ matches = self._do_simple_lookup(
+ in_installed=in_installed,
+ show_progress=show_progress
+ )
+ else:
+ self.package_finder = complex_package_finder
+ matches = self._do_complex_lookup(show_progress=show_progress)
+
+ if self.repo_filter is not None:
+ matches = self._filter_by_repository(matches)
+
+ return matches
+
+ def find(self, in_installed=True, include_masked=True):
+ """Returns a list of Package objects that matched the query.
+
+ @rtype: list
+ @return: matching Package objects
+ """
+
+ if not self.query:
+ return []
+
+ try:
+ if include_masked:
+ matches = PORTDB.xmatch("match-all", self.query)
+ else:
+ matches = PORTDB.match(self.query)
+ if in_installed:
+ matches.extend(VARDB.match(self.query))
+ except portage.exception.InvalidAtom as err:
+ raise errors.GentoolkitInvalidAtom(str(err))
+
+ return [Package(x) for x in set(matches)]
+
+ def find_installed(self):
+ """Return a list of Package objects that matched the search key."""
+
+ try:
+ matches = VARDB.match(self.query)
+ # catch the ambiguous package Exception
+ except portage.exception.AmbiguousPackageName as err:
+ matches = []
+ for pkgkey in err[0]:
+ matches.extend(VARDB.match(pkgkey))
+ except portage.exception.InvalidAtom as err:
+ raise errors.GentoolkitInvalidAtom(err)
+
+ return [Package(x) for x in set(matches)]
+
+ def find_best(self, include_keyworded=True, include_masked=True):
+ """Returns the "best" version available.
+
+ Order of preference:
+ highest available stable =>
+ highest available keyworded =>
+ highest available masked
+
+ @rtype: Package object or None
+ @return: best of up to three options
+ @raise errors.GentoolkitInvalidAtom: if query is not valid input
+ """
+
+ best = keyworded = masked = None
+ try:
+ best = PORTDB.xmatch("bestmatch-visible", self.query)
+ except portage.exception.InvalidAtom as err:
+ raise errors.GentoolkitInvalidAtom(err)
+ # xmatch can return an empty string, so checking for None is not enough
+ if not best:
+ if not include_keyworded or include_masked:
+ return None
+ try:
+ matches = PORTDB.xmatch("match-all", self.query)
+ except portage.exception.InvalidAtom as err:
+ raise errors.GentoolkitInvalidAtom(err)
+ masked = portage.best(matches)
+ keywordable = []
+ for m in matches:
+ status = portage.getmaskingstatus(m)
+ if 'package.mask' not in status or 'profile' not in status:
+ keywordable.append(m)
+ if matches:
+ keyworded = portage.best(keywordable)
+ else:
+ return Package(best)
+ if include_keyworded and keyworded:
+ return Package(keyworded)
+ if include_masked and masked:
+ return Package(masked)
+ return None
+
+ def uses_globbing(self):
+ """Check the query to see if it is using globbing.
+
+ @rtype: bool
+ @return: True if query uses globbing, else False
+ """
+
+ if set('!*?[]').intersection(self.query):
+ # Is query an atom such as '=sys-apps/portage-2.2*'?
+ if self.query[0] != '=':
+ return True
+
+ return False
+
+ def is_ranged(self):
+ """Return True if the query appears to be ranged, else False."""
+
+ q = self.query
+ return q.startswith(('~', '<', '>')) or q.endswith('*')
+
+ def _do_simple_lookup(self, in_installed=True, show_progress=True):
+ """Find matches for a query which is an atom or cpv."""
+
+ result = []
+
+ if show_progress and CONFIG['verbose']:
+ self.print_summary()
+
+ result = self.package_finder()
+ if not in_installed:
+ result = [x for x in result if not x.is_installed()]
+
+ return result
+
+ def _do_complex_lookup(self, show_progress=True):
+ """Find matches for a query which is a regex or includes globbing."""
+
+ result = []
+
+ if show_progress and not CONFIG["piping"]:
+ self.print_summary()
+
+ cat = CPV(self.query).category
+
+ pre_filter = []
+ # The "get_" functions can pre-filter against the whole package key,
+ # but since we allow globbing now, we run into issues like:
+ # >>> portage.dep.dep_getkey("sys-apps/portage-*")
+ # 'sys-apps/portage-'
+ # So the only way to guarantee we don't overrun the key is to
+ # prefilter by cat only.
+ if cat:
+ if self.is_regex:
+ cat_re = cat
+ else:
+ cat_re = fnmatch.translate(cat)
+ # [::-1] reverses a sequence, so we're emulating an ".rreplace()"
+ # except we have to put our "new" string on backwards
+ cat_re = cat_re[::-1].replace('$', '*./', 1)[::-1]
+ predicate = lambda x: re.match(cat_re, x)
+ pre_filter = self.package_finder(predicate=predicate)
+
+ # Post-filter
+ if self.is_regex:
+ predicate = lambda x: re.search(self.query, x)
+ else:
+ if cat:
+ query_re = fnmatch.translate(self.query)
+ else:
+ query_re = fnmatch.translate("*/%s" % self.query)
+ predicate = lambda x: re.search(query_re, x)
+ if pre_filter:
+ result = [x for x in pre_filter if predicate(x)]
else:
- self.cpv = CPV(cpv)
- del cpv
+ result = self.package_finder(predicate=predicate)
+
+ return [Package(x) for x in result]
+
+ def _do_set_lookup(self, show_progress=True):
+ """Find matches for a query that is a package set."""
+
+ if show_progress and not CONFIG["piping"]:
+ self.print_summary()
+
+ setname = self.query[len(SETPREFIX):]
+ result = []
+ try:
+ atoms = get_set_atoms(setname)
+ except errors.GentoolkitSetNotFound:
+ return result
+
+ q = self.query
+ for atom in atoms:
+ self.query = atom
+ result.extend(self._do_simple_lookup(show_progress=False))
+ self.query = q
+
+ return result
+
+ def _filter_by_repository(self, matches):
+ """Filter out packages which do not belong to self.repo_filter."""
+
+ result = []
+ for match in matches:
+ repo_name = match.repo_name()
+ if repo_name == self.repo_filter:
+ result.append(match)
+ elif (not repo_name and
+ self.repo_filter in ('unknown', 'null')):
+ result.append(match)
+
+ return result
+
+ def _get_query_type(self):
+ """Determine of what type the query is."""
+
+ if self.query.startswith(SETPREFIX):
+ return "set"
+ elif self.is_regex or self.uses_globbing():
+ return "complex"
+ return "simple"
+
--- /dev/null
+# Copyright(c) 2010, Gentoo Foundation
+#
+# Licensed under the GNU General Public License, v2 or higher
+#
+# $Header$
+
+"""Provides access to Portage sets api"""
+
+__docformat__ = 'epytext'
+
+import portage
+try:
+ import portage.sets
+ _sets_available = True
+ SETPREFIX = portage.sets.SETPREFIX
+except ImportError:
+ _sets_available = False
+ SETPREFIX = "@"
+
+from gentoolkit import errors
+from gentoolkit.atom import Atom
+
+
+_set_config = None
+def _init_set_config():
+ global _set_config
+ if _set_config is None:
+ _set_config = portage.sets.load_default_config(
+ portage.settings, portage.db[portage.root])
+
+def get_available_sets():
+ """Returns all available sets."""
+
+ if _sets_available:
+ _init_set_config()
+ return _set_config.getSets()
+ return {}
+
+def get_set_atoms(setname):
+ """Return atoms belonging to the given set
+
+ @type setname: string
+ @param setname: Name of the set
+ @rtype list
+ @return: List of atoms in the given set
+ """
+
+ if _sets_available:
+ _init_set_config()
+ try:
+ return set([Atom(str(x))
+ for x in _set_config.getSetAtoms(setname)])
+ except portage.sets.PackageSetNotFound:
+ raise errors.GentoolkitSetNotFound(setname)
+ raise errors.GentoolkitSetNotFound(setname)
+
+# vim: set ts=4 sw=4 tw=79:
#!/usr/bin/python
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright 2009 Gentoo Foundation
#
# Distributed under the terms of the GNU General Public License v2
#
# $Header$
+
+__all__ = ['cmp']
+
+# py3k doesn't have cmp emulate it in order to keep testing cmp
+# in python-2.x
+#XXX: not sure if this is the best place for this
+try:
+ cmp = cmp
+except NameError:
+ def cmp(a, b):
+ if a == b:
+ return 0
+ elif a < b:
+ return -1
+ elif a > b:
+ return 1
+ # just to be safe, __lt__/ __gt__ above should have thrown
+ # something like this already
+ raise TypeError("Comparison between onorderable types")
#!/usr/bin/python
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright 2009 Gentoo Foundation
#
# Distributed under the terms of the GNU General Public License v2
#
import unittest
-from test import test_support
+try:
+ from test import test_support
+except ImportError:
+ from test import support as test_support
from gentoolkit import equery
-# Copyright(c) 2009-2010, Gentoo Foundation, Inc.
+# Copyright(c) 2009, Gentoo Foundation
# Copyright: 2006-2008 Brian Harring <ferringb@gmail.com>
#
# License: GPL2/BSD
# $Header$
import unittest
-from test import test_support
+try:
+ from test import test_support
+except ImportError:
+ from test import support as test_support
from gentoolkit.atom import *
+from gentoolkit.test import cmp
"""Atom test suite (verbatim) from pkgcore."""
#!/usr/bin/python
#
-# Copyright(c) 2009-2010, Gentoo Foundation
+# Copyright(c) 2009, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2
#
# $Header$
import unittest
-from test import test_support
+try:
+ from test import test_support
+except ImportError:
+ from test import support as test_support
from gentoolkit.cpv import *
+from gentoolkit.test import cmp
class TestGentoolkitCPV(unittest.TestCase):
self.assertEqual2(CPV('cat/pkg-1_rc2'), CPV('cat/pkg-1_rc2'))
self.assertNotEqual2(CPV('cat/pkg-2_rc2-r1'), CPV('cat/pkg-2_rc1-r1'))
+ def test_compare_strs(self):
+ # Test ordering of package strings, Portage has test for vercmp,
+ # so just do the rest
+ version_tests = [
+ # different categories
+ ('sys-apps/portage-2.1.6.8', 'sys-auth/pambase-20080318'),
+ # different package names
+ ('sys-apps/pkgcore-0.4.7.15-r1', 'sys-apps/portage-2.1.6.8'),
+ # different package versions
+ ('sys-apps/portage-2.1.6.8', 'sys-apps/portage-2.2_rc25')
+ ]
+ # Check less than
+ for vt in version_tests:
+ self.failUnless(compare_strs(vt[0], vt[1]) == -1)
+ # Check greater than
+ for vt in version_tests:
+ self.failUnless(compare_strs(vt[1], vt[0]) == 1)
+ # Check equal
+ vt = ('sys-auth/pambase-20080318', 'sys-auth/pambase-20080318')
+ self.failUnless(compare_strs(vt[0], vt[1]) == 0)
+
+
def test_main():
test_support.run_unittest(TestGentoolkitCPV)
-import os
import unittest
import warnings
-from tempfile import NamedTemporaryFile
-from test import test_support
+from tempfile import NamedTemporaryFile, mktemp
+try:
+ from test import test_support
+except ImportError:
+ from test import support as test_support
+
+from portage import os
from gentoolkit import helpers
def tearDown(self):
pass
+ def test_expand_abspaths(self):
+ expand_abspaths = helpers.FileOwner.expand_abspaths
+
+ initial_file_list = ['foo0', '/foo1', '~/foo2', './foo3']
+ # This function should only effect foo3, and not ordering:
+
+ final_file_list = [
+ 'foo0',
+ '/foo1',
+ '~/foo2',
+ os.path.join(os.getcwd(), os.path.normpath(initial_file_list[3]))
+ ]
+
+ self.failUnlessEqual(expand_abspaths(initial_file_list), final_file_list)
+
def test_extend_realpaths(self):
extend_realpaths = helpers.FileOwner.extend_realpaths
f3 = NamedTemporaryFile(prefix='equeryunittest')
with warnings.catch_warnings():
warnings.simplefilter("ignore")
- sym1 = os.tmpnam()
+ sym1 = mktemp()
os.symlink(f1.name, sym1)
- sym2 = os.tmpnam()
+ sym2 = mktemp()
os.symlink(f3.name, sym2)
# We've created 3 files and 2 symlinks for testing. We're going to pass
# in only the first two files and both symlinks. sym1 points to f1.
class TestGentoolkitHelpers(unittest.TestCase):
- def test_compare_package_strings(self):
- # Test ordering of package strings, Portage has test for vercmp,
- # so just do the rest
- version_tests = [
- # different categories
- ('sys-apps/portage-2.1.6.8', 'sys-auth/pambase-20080318'),
- # different package names
- ('sys-apps/pkgcore-0.4.7.15-r1', 'sys-apps/portage-2.1.6.8'),
- # different package versions
- ('sys-apps/portage-2.1.6.8', 'sys-apps/portage-2.2_rc25')
- ]
- # Check less than
- for vt in version_tests:
- self.failUnless(
- helpers.compare_package_strings(vt[0], vt[1]) == -1
- )
- # Check greater than
- for vt in version_tests:
- self.failUnless(
- helpers.compare_package_strings(vt[1], vt[0]) == 1
- )
- # Check equal
- vt = ('sys-auth/pambase-20080318', 'sys-auth/pambase-20080318')
- self.failUnless(
- helpers.compare_package_strings(vt[0], vt[1]) == 0
- )
-
def test_uses_globbing(self):
globbing_tests = [
('sys-apps/portage-2.1.6.13', False),
--- /dev/null
+import unittest
+import warnings
+from tempfile import NamedTemporaryFile
+try:
+ from test import test_support
+except ImportError:
+ from test import support as test_support
+
+from portage import os
+
+from gentoolkit import keyword
+
+class TestGentoolkitKeyword(unittest.TestCase):
+
+ def test_compare_strs(self):
+ compare_strs = keyword.compare_strs
+
+ # Test ordering of keyword strings
+ version_tests = [
+ # different archs
+ ('amd64', 'x86'),
+ # stable vs. unstable
+ ('amd64-linux', '~amd64-linux'),
+ # different OSes
+ ('~x86-linux', '~x86-solaris')
+ ]
+ # Check less than
+ for vt in version_tests:
+ self.failUnless(compare_strs(vt[0], vt[1]) == -1)
+ # Check greater than
+ for vt in version_tests:
+ self.failUnless(compare_strs(vt[1], vt[0]) == 1)
+ # Check equal
+ vt = ('~amd64-linux', '~amd64-linux')
+ self.failUnless(compare_strs(vt[0], vt[1]) == 0)
+
+
+def test_main():
+ test_support.run_unittest(TestGentoolkitHelpers2)
+
+
+if __name__ == '__main__':
+ test_main()
-import os
-import os.path as osp
import unittest
import py_compile
+from portage import os
+osp = os.path
+
+from gentoolkit.helpers import walk
+
"""Does a basic syntax check by compiling all modules. From Portage."""
-pym_dirs = os.walk(osp.dirname(osp.dirname(osp.dirname(__file__))))
+pym_dirs = walk(osp.dirname(osp.dirname(osp.dirname(__file__))))
blacklist_dirs = frozenset(('.svn', 'test'))
class TestForSyntaxErrors(unittest.TestCase):
#! /usr/bin/python
#
-# Copyright 2009-2010 Gentoo Foundation
+# Copyright(c) 2009 Gentoo Foundation
# Licensed under the GNU General Public License, v2
#
-# Copyright 2005-2007 Brian Harring <ferringb@gmail.com>
+# Copyright: 2005-2007 Brian Harring <ferringb@gmail.com>
# License: GPL2/BSD
#
# $Header$
_convert_op2int = {(-1,):"<", (-1, 0): "<=", (0,):"=",
(0, 1):">=", (1,):">"}
- _convert_int2op = dict([(v, k) for k, v in _convert_op2int.iteritems()])
+ _convert_int2op = dict([(v, k) for k, v in _convert_op2int.items()])
def __init__(self, cpv, op='='):
"""Initialize a VersionMatch instance.
#!/usr/bin/env python
-from __future__ import with_statement
+from __future__ import print_function
+
-import os
import re
import sys
import distutils
from distutils import core, log
from glob import glob
+from portage import os
+
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'pym'))
+from gentoolkit.helpers import walk
+
__version__ = os.getenv('VERSION', default='9999')
cwd = os.getcwd()
def run(self):
ver = 'svn' if __version__ == '9999' else __version__
- print "Setting version to %s" % ver
+ print("Settings version to %s" % ver)
def sub(files, pattern):
for f in files:
updated_file = []
packages = [
- '.'.join(root.split(os.sep)[1:])
- for root, dirs, files in os.walk('pym/gentoolkit')
+ str('.'.join(root.split(os.sep)[1:]))
+ for root, dirs, files in walk('pym/gentoolkit')
if '__init__.py' in files
]