3 # Copyright 2003-2010 Gentoo Foundation
4 # Distributed under the terms of the GNU General Public License v2
7 from __future__ import print_function
12 from portage.output import *
13 from gentoolkit.pprinter import cpv, number, emph
16 class OutputControl(object):
17 """Outputs data according to predetermined options and handles any user
20 @param options: dictionary of boolean options as determined in cli.py
21 used here: interactive, pretend, quiet, accept_all, nocolor.
24 def __init__(self, options):
27 self.options['interactive'] = False
28 self.options['pretend'] = True
29 self.options['quiet'] = False
30 self.options['accept_all'] = False
31 self.options['nocolor'] = False
33 self.options = options
34 self.set_colors("normal")
36 def set_colors(self, mode):
37 """Sets the colors for the progress_controller
40 @param mode: string, 1 of ["normal", "deprecated"]
43 self.pkg_color = cpv # green
44 self.numbers = number # turquoise
46 elif mode == "deprecated":
47 self.pkg_color = yellow
48 self.numbers = teal # darkgreen
51 def einfo(self, message=""):
52 """Display an info message depending on a color mode.
54 @param message: text string to display
58 if not self.options['nocolor']:
59 prefix = " "+green('*')
64 def eprompt(self, message):
65 """Display a user question depending on a color mode.
67 @param message: text string to display
71 if not self.options['nocolor']:
72 prefix = " "+red('>')+" "
75 sys.stdout.write(prefix+message)
78 def prettySize(self, size, justify=False, color=None):
79 """int -> byte/kilo/mega/giga converter. Optionally
80 justify the result. Output is a string.
83 @param justify: optional boolean, defaults to False
84 @param color: optional color, defaults to green
85 as defined in portage.output
87 @returns a formatted and (escape sequenced)
92 units = [" G"," M"," K"," B"]
94 # by using 1000 as the changeover, the integer portion
95 # of the number will never be more than 3 digits long
96 # but the true base 2 value of 1024 is used for the actual
97 # calulation to maintain better accuracy.
98 while len(units) and size >= 1000:
102 sizestr = "%.1f" %(round(size,1)) + units[-1]
104 sizestr = " " + self.brace("[ ") + \
105 color(sizestr.rjust(8)) + self.brace(" ]")
108 def yesNoAllPrompt(self, message="Do you want to proceed?"):
109 """Print a prompt until user answer in yes/no/all. Return a
110 boolean for answer, and also may affect the 'accept_all' option.
112 @param message: optional different input string from the default
113 message of: "Do you want to proceed?"
115 @modifies class var options['accept_all']
119 while not user_string.lower() in ["","y","n","a","yes","no","all"]:
120 self.eprompt(message+" [Y/n/a]: ")
121 user_string = sys.stdin.readline().rstrip('\n')
122 user_string = user_string.strip()
123 if user_string.lower() in ["a","all"]:
124 self.options['accept_all'] = True
125 answer = user_string.lower() in ["","y","a","yes","all"]
128 def progress_controller(self, size, key, clean_list, file_type):
129 """Callback function for doCleanup. It outputs data according to the
131 Alternatively it handles user interaction for decisions that are
134 @param size: Integer of the file(s) size
135 @param key: the filename/pkgname currently being processed
136 @param clean_list: list of files being processed.
138 if not self.options['quiet']:
140 print(self.prettySize(size,True), self.pkg_color(key))
141 elif self.options['pretend'] or self.options['interactive']:
143 for file_ in clean_list:
145 if self.options['pretend']:
147 elif not self.options['interactive'] \
148 or self.options['accept_all'] \
149 or self.yesNoAllPrompt("Do you want to delete this " + file_type + "?"):
153 def total(self, mode, size, num_files, verb, action):
154 """outputs the formatted totals to stdout
156 @param mode: sets color and message. 1 of ['normal', 'deprecated']
157 @param size: total space savings
158 @param num_files: total number of files
159 @param verb: string eg. 1 of ["would be", "has been"]
160 @param action: string eg 1 of ['distfiles', 'packages']
162 self.set_colors(mode)
164 message="Total space from "+red(str(num_files))+" files "+\
165 verb+" freed in the " + action + " directory"
166 print( " ===========")
167 print( self.prettySize(size, True, red), message)
168 elif mode == "deprecated":
169 message = "Total space from "+red(str(num_files))+" package files\n"+\
170 " Re-run the last command with the -D " +\
171 "option to clean them as well"
172 print( " ===========")
173 print( self.prettySize(size, True, red), message)
175 def list_pkgs(self, pkgs):
176 """outputs the packages to stdout
178 @param pkgs: dict. of {cat/pkg-ver: src_uri,}
181 keys = list(pkgs.keys())
187 saved = " ...distfile name(s) not known/saved"
188 print( indent,self.pkg_color(key) + saved)