1
2 """ Data Formatting.
3
4 Copyright (c) 2009, 2011 The PyroScope Project <pyroscope.project@gmail.com>
5 """
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import time
20 import codecs
21 import logging
22 import datetime
23
24 log = logging.getLogger(__name__)
25
26
28 """ Return a human-readable representation of a byte size.
29
30 @param size: Number of bytes as an integer or string.
31 @return: String of length 10 with the formatted result.
32 """
33 if isinstance(size, basestring):
34 size = int(size, 10)
35
36 if size < 0:
37 return "-??? bytes"
38
39 if size < 1024:
40 return "%4d bytes" % size
41 for unit in ("KiB", "MiB", "GiB"):
42 size /= 1024.0
43 if size < 1024:
44 return "%6.1f %s" % (size, unit)
45
46 return "%6.1f GiB" % size
47
48
50 """ Convert UNIX timestamp to ISO datetime string.
51
52 @param timestamp: UNIX epoch value (default: the current time).
53 @return: Timestamp formatted as "YYYY-mm-dd HH:MM:SS".
54 """
55 if timestamp is None:
56 timestamp = time.time()
57 return datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:19]
58
59
61 """ Convert UNIX timestamp to ISO datetime string, or "never".
62
63 @param timestamp: UNIX epoch value.
64 @return: Timestamp formatted as "YYYY-mm-dd HH:MM:SS", or "never" for false values.
65 """
66 if timestamp:
67 return iso_datetime(timestamp)
68 return "never"
69
70
72 """ Return a human-readable representation of a time delta.
73
74 @param time1: Relative time value.
75 @param time2: Time base (C{None} for now; 0 for a duration in C{time1}).
76 @param precision: How many time units to return (0 = all).
77 @param short: Use abbreviations, and right-justify the result to always the same length.
78 @return: Formatted duration.
79 """
80 if time2 is None:
81 time2 = time.time()
82
83 duration = (time1 or 0) - time2
84 direction = (
85 " ago" if duration < 0 else
86 ("+now" if short else " from now") if time2 else ""
87 )
88 duration = abs(duration)
89 parts = [
90 ("weeks", duration // (7*86400)),
91 ("days", duration // 86400 % 7),
92 ("hours", duration // 3600 % 24),
93 ("mins", duration // 60 % 60),
94 ("secs", duration % 60),
95 ]
96
97
98 while len(parts) > 1 and parts[0][1] == 0:
99 parts = parts[1:]
100
101
102 if precision:
103 parts = parts[:precision]
104
105 numfmt = ("%d", "%d"), ("%4d", "%2d")
106 fmt = "%1.1s" if short else " %s"
107 sep = " " if short else ", "
108 result = sep.join((numfmt[bool(short)][bool(idx)] + fmt) % (val, key[:-1] if val == 1 else key)
109 for idx, (key, val) in enumerate(parts)
110 if val
111 ) + direction
112
113 if not time1:
114 result = "never" if time2 else "N/A"
115
116 if precision and short:
117 return result.rjust(1 + precision*4 + (4 if time2 else 0))
118 else:
119 return result
120
121
123 """ Return a decoded unicode string.
124 False values are returned untouched.
125 """
126 if not text or isinstance(text, unicode):
127 return text
128
129 try:
130
131 return text.decode("UTF-8")
132 except UnicodeError:
133 try:
134
135 return text.decode("CP1252")
136 except UnicodeError:
137
138 return text
139
140
142 """ Enforce UTF8 encoding.
143 """
144
145 if not text:
146 if isinstance(text, basestring):
147 text = ""
148 return text
149
150 try:
151
152 return text.encode("utf8")
153 except UnicodeDecodeError:
154 try:
155
156 if text.startswith(codecs.BOM_UTF8):
157 text = text[len(codecs.BOM_UTF8):]
158 return text.decode("utf8").encode("utf8")
159 except UnicodeDecodeError:
160
161 if text.startswith(codecs.BOM_UTF16_LE):
162 encoding = "utf-16le"
163 text = text[len(codecs.BOM_UTF16_LE):]
164 elif text.startswith(codecs.BOM_UTF16_BE):
165 encoding = "utf-16be"
166 text = text[len(codecs.BOM_UTF16_BE):]
167 else:
168
169 encoding = "cp1252"
170
171 try:
172 return text.decode(encoding).encode("utf8")
173 except UnicodeDecodeError, exc:
174 for line in text.splitlines():
175 try:
176 line.decode(encoding).encode("utf8")
177 except UnicodeDecodeError:
178 log.warn("Cannot transcode the following into UTF8 cause of %s: %r" % (exc, line))
179 break
180 return text
181
182
184 """ Return a byte string intended for console output.
185 """
186 if isinstance(text, str):
187
188 return text
189
190
191 return unicode(text).encode("utf8")
192