sync with genscripts rev 343. This adds the initial py3k support and the analyse...
[gentoolkit.git] / pym / gentoolkit / equery / size.py
1 # Copyright(c) 2009, Gentoo Foundation
2 #
3 # Licensed under the GNU General Public License, v2
4 #
5 # $Header: $
6
7 """Print total size of files contained in a given package"""
8
9 from __future__ import print_function
10
11 __docformat__ = 'epytext'
12
13 # =======
14 # Imports
15 # =======
16
17 import sys
18 from getopt import gnu_getopt, GetoptError
19
20 import gentoolkit.pprinter as pp
21 from gentoolkit.equery import format_options, mod_usage, CONFIG
22 from gentoolkit.query import Query
23
24 # =======
25 # Globals
26 # =======
27
28 QUERY_OPTS = {
29         "in_installed": True,
30         "in_porttree": False,
31         "in_overlay": False,
32         "include_masked": True,
33         "is_regex": False,
34         "show_progress": False,
35         "size_in_bytes": False
36 }
37
38 # =========
39 # Functions
40 # =========
41
42 def print_help(with_description=True):
43         """Print description, usage and a detailed help message.
44
45         @type with_description: bool
46         @param with_description: if true, print module's __doc__ string
47         """
48
49         if with_description:
50                 print(__doc__.strip())
51                 print()
52
53         # Deprecation warning added by djanderson, 12/2008
54         depwarning = (
55                 "Default action for this module has changed in Gentoolkit 0.3.",
56                 "Use globbing to simulate the old behavior (see man equery).",
57                 "Use '*' to check all installed packages.",
58                 "Use 'foo-bar/*' to filter by category."
59         )
60         for line in depwarning:
61                 sys.stderr.write(pp.warn(line))
62         print()
63
64         print(mod_usage(mod_name="size"))
65         print()
66         print(pp.command("options"))
67         print(format_options((
68                 (" -h, --help", "display this help message"),
69                 (" -b, --bytes", "report size in bytes"),
70                 (" -f, --full-regex", "query is a regular expression")
71         )))
72
73
74 def display_size(match_set):
75         """Display the total size of all accessible files owned by packages.
76
77         @type match_set: list
78         @param match_set: package cat/pkg-ver strings
79         """
80
81         for pkg in match_set:
82                 size, files, uncounted = pkg.size()
83
84                 if CONFIG['verbose']:
85                         print(" * %s" % pp.cpv(str(pkg.cpv)))
86                         print("Total files : %s".rjust(25) % pp.number(str(files)))
87
88                         if uncounted:
89                                 print(("Inaccessible files : %s".rjust(25) %
90                                         pp.number(str(uncounted))))
91
92                         if QUERY_OPTS["size_in_bytes"]:
93                                 size_str = pp.number(str(size))
94                         else:
95                                 size_str = "%s %s" % format_bytes(size)
96
97                         print("Total size  : %s".rjust(25) % size_str)
98                 else:
99                         info = "%s: total(%d), inaccessible(%d), size(%s)"
100                         print(info % (str(pkg.cpv), files, uncounted, size))
101
102
103 def format_bytes(bytes_, precision=2):
104         """Format bytes into human-readable format (IEC naming standard).
105
106         @see: http://mail.python.org/pipermail/python-list/2008-August/503423.html
107         @rtype: tuple
108         @return: (str(num), str(label))
109         """
110
111         labels = (
112                 (1<<40, 'TiB'),
113                 (1<<30, 'GiB'),
114                 (1<<20, 'MiB'),
115                 (1<<10, 'KiB'),
116                 (1, 'bytes')
117         )
118
119         if bytes_ == 0:
120                 return (pp.number('0'), 'bytes')
121         elif bytes_ == 1:
122                 return (pp.number('1'), 'byte')
123
124         for factor, label in labels:
125                 if not bytes_ >= factor:
126                         continue
127
128                 float_split = str(bytes_/float(factor)).split('.')
129                 integer = float_split[0]
130                 decimal = float_split[1]
131                 if int(decimal[0:precision]):
132                         float_string = '.'.join([integer, decimal[0:precision]])
133                 else:
134                         float_string = integer
135
136                 return (pp.number(float_string), label)
137
138
139 def parse_module_options(module_opts):
140         """Parse module options and update QUERY_OPTS"""
141
142         opts = (x[0] for x in module_opts)
143         for opt in opts:
144                 if opt in ('-h', '--help'):
145                         print_help()
146                         sys.exit(0)
147                 elif opt in ('-b', '--bytes'):
148                         QUERY_OPTS["size_in_bytes"] = True
149                 elif opt in ('-e', '--exact-name'):
150                         sys.stderr.write(pp.warn("-e, --exact-name is now default."))
151                         warning = pp.warn("Use globbing to simulate the old behavior.")
152                         sys.stderr.write(warning)
153                         print()
154                 elif opt in ('-f', '--full-regex'):
155                         QUERY_OPTS['is_regex'] = True
156
157
158 def main(input_args):
159         """Parse input and run the program"""
160
161         # -e, --exact-name is no longer needed. Kept for compatibility.
162         # 04/09 djanderson
163         short_opts = "hbfe"
164         long_opts = ('help', 'bytes', 'full-regex', 'exact-name')
165
166         try:
167                 module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
168         except GetoptError as err:
169                 sys.stderr.write(pp.error("Module %s" % err))
170                 print()
171                 print_help(with_description=False)
172                 sys.exit(2)
173
174         parse_module_options(module_opts)
175
176         if not queries:
177                 print_help()
178                 sys.exit(2)
179
180         first_run = True
181         for query in (Query(x, QUERY_OPTS['is_regex']) for x in queries):
182                 if not first_run:
183                         print()
184
185                 matches = query.smart_find(**QUERY_OPTS)
186
187                 if not matches:
188                         sys.stderr.write(pp.error("No package found matching %s" % query))
189
190                 matches.sort()
191
192                 display_size(matches)
193
194                 first_run = False
195
196 # vim: set ts=4 sw=4 tw=79: