1
+ #!/usr/bin/env python3
2
+
3
+ """Implements tooling for formatting df command columns"""
4
+
5
+ from enum import Enum
6
+
7
+
8
+ def convert_bytes (size , unit = '' , always_append_unit = False ):
9
+ """Converts size in bytes to closest power of 1024: Ki, Mi, Gi, etc.
10
+ """
11
+ single_unit = '' if always_append_unit else unit
12
+ appendix = unit if always_append_unit else ''
13
+ for x in [single_unit , 'Ki' , 'Mi' , 'Gi' , 'Ti' ]:
14
+ if size < 1024.0 :
15
+ return "%3.1f%s%s" % (size , x , appendix )
16
+ size /= 1024.0
17
+
18
+ return size
19
+
20
+ def convert_bytes_si (size , unit = '' , always_append_unit = False ):
21
+ """Converts size in bytes to closest power of 1000: K, M, G, etc.
22
+ """
23
+ single_unit = '' if always_append_unit else unit
24
+ appendix = unit if always_append_unit else ''
25
+ for x in [single_unit , 'K' , 'M' , 'G' , 'T' ]:
26
+ if size < 1000.0 :
27
+ return "%3.1f%s%s" % (size , x , appendix )
28
+ size /= 1000.0
29
+
30
+ return size
31
+
32
+
33
+ class DByteFormat (Enum ):
34
+ """Enum for selecting the formatting for size in bytes
35
+ """
36
+
37
+ BYTES = 1
38
+ """Output in bytes
39
+ """
40
+
41
+ HUMAN = 2
42
+ """Output in human readable format: powers of 1024
43
+ """
44
+
45
+ HUMAN_SI = 3
46
+ """Output in human readable format: powers of 1000
47
+ """
48
+
49
+
50
+ class DfColumn :
51
+
52
+ def title (self ):
53
+ pass
54
+
55
+ def formatted (statvfs , dev_name , dir ):
56
+ pass
57
+
58
+
59
+ class DfNumColumn (DfColumn ):
60
+
61
+ def __init__ (self , num_format = '{:d}' ):
62
+ self .num_format = num_format
63
+
64
+ def formatted (self , statvfs , dev_name , dir ):
65
+ value = self .get_num_value (statvfs )
66
+ return self .num_format .format (value )
67
+
68
+ def get_num_value (self , statvfs ):
69
+ pass
70
+
71
+
72
+ class DfByteColumn (DfNumColumn ):
73
+
74
+ def __init__ (self , byte_format ):
75
+ self .byte_format = byte_format
76
+ super ().__init__ ('{:d}B' )
77
+
78
+ def formatted (self , statvfs , dev_name , dir ):
79
+ value = self .get_num_value (statvfs )
80
+ if self .byte_format == DByteFormat .HUMAN :
81
+ return convert_bytes (value , 'B' )
82
+ elif self .byte_format == DByteFormat .HUMAN_SI :
83
+ return convert_bytes_si (value , 'B' )
84
+ else : # fallback to bytes as default
85
+ return super ().formatted (statvfs , dev_name , dir )
86
+
87
+
88
+ class DfFilesystem (DfColumn ):
89
+
90
+ def title (self ):
91
+ return 'Filesystem'
92
+
93
+ def formatted (self , statvfs , dev_name , dir ):
94
+ return '{:s}@{:s}' .format (dir [:- 1 ], dev_name )
95
+ # format: /${dir_name}/@${device_name}
96
+ # e.g. /flash@pyboard
97
+
98
+
99
+ class DfMountedOn (DfColumn ):
100
+
101
+ def title (self ):
102
+ return 'Mounted on'
103
+
104
+ def formatted (self , statvfs , dev_name , dir ):
105
+ return '/{}{}' .format (dev_name , dir )[:- 1 ]
106
+ # format: /${device_name}/${dir_name}
107
+ # e.g. /pyboard/flash
108
+
109
+
110
+ class DfNumBlocks (DfNumColumn ):
111
+
112
+ def title (self ):
113
+ return 'Blocks'
114
+
115
+ def get_num_value (self , statvfs ):
116
+ return statvfs [2 ]
117
+ # f_blocks
118
+
119
+
120
+ class DfBlockSize (DfNumColumn ):
121
+
122
+ def title (self ):
123
+ return 'Block size'
124
+
125
+ def get_num_value (self , statvfs ):
126
+ return statvfs [1 ]
127
+ # f_frsize
128
+
129
+
130
+ class DfUsedBlocks (DfNumColumn ):
131
+
132
+ def title (self ):
133
+ return 'Used'
134
+
135
+ def get_num_value (self , statvfs ):
136
+ return statvfs [2 ] - statvfs [3 ]
137
+ # f_blocks - f_used
138
+
139
+
140
+ class DfAvailBlocks (DfNumColumn ):
141
+
142
+ def title (self ):
143
+ return 'Available'
144
+
145
+ def get_num_value (self , statvfs ):
146
+ return statvfs [4 ]
147
+ # f_bavail
148
+
149
+
150
+ class DfCapacityBlocks (DfNumColumn ):
151
+
152
+ def __init__ (self ):
153
+ super ().__init__ ('{:.0f}%' )
154
+
155
+ def title (self ):
156
+ return 'Capacity'
157
+
158
+ def get_num_value (self , statvfs ):
159
+ return 100 * (statvfs [2 ] - statvfs [3 ]) / statvfs [2 ] if statvfs [2 ] > 0 else 0
160
+ # 100 * (f_blocks - f_used) / f_blocks
161
+ # or 0 if 0 blocks
162
+
163
+
164
+ class DfSizeBytes (DfByteColumn ):
165
+
166
+ def __init__ (self , byte_format ):
167
+ super ().__init__ (byte_format )
168
+
169
+ def title (self ):
170
+ return 'Size'
171
+
172
+ def get_num_value (self , statvfs ):
173
+ return statvfs [1 ] * statvfs [2 ]
174
+ # f_frsize * f_blocks
175
+
176
+
177
+ class DfUsedBytes (DfByteColumn ):
178
+
179
+ def __init__ (self , byte_format ):
180
+ super ().__init__ (byte_format )
181
+
182
+ def title (self ):
183
+ return 'Used'
184
+
185
+ def get_num_value (self , statvfs ):
186
+ return statvfs [1 ] * (statvfs [2 ] - statvfs [3 ])
187
+ # f_frsize * (f_blocks - f_used)
188
+
189
+
190
+ class DfAvailBytes (DfByteColumn ):
191
+
192
+ def __init__ (self , byte_format ):
193
+ super ().__init__ (byte_format )
194
+
195
+ def title (self ):
196
+ return 'Available'
197
+
198
+ def get_num_value (self , statvfs ):
199
+ return statvfs [1 ] * statvfs [4 ]
200
+ # f_frsize * f_bavail
201
+
202
+ class DfCapacityBytes (DfNumColumn ):
203
+
204
+ def __init__ (self ):
205
+ super ().__init__ ('{:.0f}%' )
206
+
207
+ def title (self ):
208
+ return 'Capacity'
209
+
210
+ def get_num_value (self , statvfs ):
211
+ return 100 * (statvfs [2 ] - statvfs [3 ]) / statvfs [2 ] if statvfs [2 ] > 0 else 0
212
+ # 100 * (f_blocks - f_used) / f_blocks
213
+ # or 0 if 0 blocks
214
+
215
+
216
+ def create_byte_sizes_columns (byte_format ):
217
+ """Returns standard set of columns for df command output
218
+ in bytes in different formats
219
+ """
220
+ return [
221
+ DfFilesystem (),
222
+ DfSizeBytes (byte_format ),
223
+ DfUsedBytes (byte_format ),
224
+ DfAvailBytes (byte_format ),
225
+ DfCapacityBytes (),
226
+ DfMountedOn (),
227
+ ]
228
+
229
+
230
+ def create_block_sizes_columns ():
231
+ """Returns standard set of columns for df command output
232
+ in blocks
233
+ """
234
+ return [
235
+ DfFilesystem (),
236
+ DfBlockSize (),
237
+ DfNumBlocks (),
238
+ DfUsedBlocks (),
239
+ DfAvailBlocks (),
240
+ DfCapacityBlocks (),
241
+ DfMountedOn (),
242
+ ]
0 commit comments