small linting

This commit is contained in:
Aleksey 2024-08-17 08:02:19 +04:00 committed by Aleksey Chubukov
parent 830cd1f2bd
commit 7257a32810
Signed by: tea
GPG Key ID: D9C68D34A3CAE37A

186
tkdu.py
View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# This is tkdu.py, an interactive program to display disk usage # This is tkdu.py, an interactive program to display disk usage
# Copyright 2004 Jeff Epler <jepler@unpythonic.net> # Copyright 2004 Jeff Epler <jepler@unpythonic.net>
@ -19,7 +19,13 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import math, tkinter, sys, os, stat, string, time, gzip, tkinter.filedialog import tkinter
import sys
import os
import stat
import time
import gzip
import tkinter.filedialog
from tkinter.filedialog import askdirectory from tkinter.filedialog import askdirectory
MIN_PSZ = 1000 MIN_PSZ = 1000
@ -29,19 +35,23 @@ MIN_H = 15
VERTICAL = "vertical" VERTICAL = "vertical"
HORIZONTAL = "horizontal" HORIZONTAL = "horizontal"
NUM_QUEUE = 25 NUM_QUEUE = 25
FONT_FACE = ("helvetica", 12) FONT_FACE = ("sans-serif", 8)
BORDER = 2 BORDER = 2
FONT_HEIGHT = 12 FONT_HEIGHT = 14
FONT_HEIGHT2 = 20 FONT_HEIGHT2 = 20
dircolors = ['#ff7070', '#70ff70', '#7070ff'] dircolors = ['#ff7070', '#70ff70', '#7070ff']
leafcolors = ['#bf5454', '#54bf54', '#5454bf'] leafcolors = ['#bf5454', '#54bf54', '#5454bf']
def allocate(path, files, canvas, x, y, w, h, first, depth): def allocate(path, files, canvas, x, y, w, h, first, depth):
# TODO: refactor to less complex functions
tk_call = canvas.tk.call tk_call = canvas.tk.call
if w < MIN_W or h < MIN_H: return if w < MIN_W or h < MIN_H:
return
psz = w*h psz = w*h
if psz < MIN_PSZ: return if psz < MIN_PSZ:
return
if path and path[-1] == "/": if path and path[-1] == "/":
basename_idx = len(path) basename_idx = len(path)
nslashes = path.count(os.sep) - 1 nslashes = path.count(os.sep) - 1
@ -53,52 +63,57 @@ def allocate(path, files, canvas, x, y, w, h, first, depth):
colors = (leafcolor, dircolor) colors = (leafcolor, dircolor)
totsz = 0 totsz = 0
ff = getkids(files, path) ff = getkids(files, path)
if not ff: return if not ff:
if ff[0][1] == '/': del ff[0] return
if ff[0][1] == '/':
del ff[0]
ff = ff[first:] ff = ff[first:]
for item in ff: for item in ff:
totsz = totsz + item[0] totsz = totsz + item[0]
item[2] = None item[2] = None
if totsz == 0: return if totsz == 0:
return
i = 0 i = 0
ratio = psz*1./totsz ratio = psz*1./totsz
while i < len(ff) and w>2*BORDER and h>2*BORDER: while i < len(ff) and w > 2*BORDER and h > 2*BORDER:
if w > h: if w > h:
orient = VERTICAL orient = VERTICAL
usew = w - h*2./3 usew = w - h*2./3
if usew < 50: usew = 50 if usew < 50:
if usew > 200: usew = 200 usew = 50
if usew > 200:
usew = 200
first_height = ff[i][0]/usew*ratio first_height = ff[i][0]/usew*ratio
while first_height < .65 * usew: while first_height < .65 * usew:
usew = usew / 1.5 usew = usew / 1.5
first_height = ff[i][0]/usew*ratio first_height = ff[i][0]/usew*ratio
want = usew * h / ratio want = usew * h / ratio
maxcnt = h/30
else: else:
orient = HORIZONTAL orient = HORIZONTAL
useh = h - w*2./3 useh = h - w*2./3
if useh < 50: useh = 50 if useh < 50:
if useh > 100: useh = 100 useh = 50
if useh > 100:
useh = 100
first_width = ff[i][0]/useh*ratio first_width = ff[i][0]/useh*ratio
while first_width < .65 * useh: while first_width < .65 * useh:
useh = useh / 1.5 useh = useh / 1.5
first_width = ff[i][0]/useh*ratio first_width = ff[i][0]/useh*ratio
want = useh * w / ratio want = useh * w / ratio
maxcnt = w/30
j = i+1 j = i+1
use = ff[i][0] use = ff[i][0]
while j < len(ff) and use < want: #and j < i + maxcnt: while j < len(ff) and use < want: # and j < i + maxcnt:
use = use + ff[j][0] use = use + ff[j][0]
j=j+1 j = j+1
if orient is VERTICAL: if orient is VERTICAL:
usew = use * ratio / h usew = use * ratio / h
if usew <= 2*BORDER: break if usew <= 2*BORDER:
break
y0 = y y0 = y
for item in ff[i:j]: for item in ff[i:j]:
dy = item[0]/usew*ratio dy = item[0]/usew*ratio
@ -108,7 +123,8 @@ def allocate(path, files, canvas, x, y, w, h, first, depth):
w = w - usew w = w - usew
else: else:
useh = use * ratio / w useh = use * ratio / w
if useh <= 2*BORDER: break if useh <= 2*BORDER:
break
x0 = x x0 = x
for item in ff[i:j]: for item in ff[i:j]:
dx = item[0]/useh*ratio dx = item[0]/useh*ratio
@ -123,19 +139,20 @@ def allocate(path, files, canvas, x, y, w, h, first, depth):
name = item[1] name = item[1]
haskids = bool(getkids(files, name)) haskids = bool(getkids(files, name))
color = colors[haskids] color = colors[haskids]
if item[2] is None: continue if item[2] is None:
continue
x, y, w, h = pos = item[2] x, y, w, h = pos = item[2]
if w > 3*BORDER and h > 3*BORDER: if w > 3*BORDER and h > 3*BORDER:
tk_call(canvas._w, tk_call(canvas._w,
"create", "rectangle", "create", "rectangle",
x+BORDER+2, y+BORDER+2, x+w-BORDER+1, y+h-BORDER+1, x+BORDER+2, y+BORDER+2, x+w-BORDER+1, y+h-BORDER+1,
"-fill", "#3f3f3f", "-fill", "#3f3f3f",
"-outline", "#3f3f3f") "-outline", "#3f3f3f")
i = tk_call(canvas._w, i = tk_call(canvas._w,
"create", "rectangle", "create", "rectangle",
x+BORDER, y+BORDER, x+w-BORDER, y+h-BORDER, x+BORDER, y+BORDER, x+w-BORDER, y+h-BORDER,
"-fill", color) "-fill", color)
canvas.map[int(i)] = name canvas.map[int(i)] = name
if h > FONT_HEIGHT+2*BORDER: if h > FONT_HEIGHT+2*BORDER:
@ -152,31 +169,32 @@ def allocate(path, files, canvas, x, y, w, h, first, depth):
if tw < w1: if tw < w1:
text = "%s\n%s" % (stem, ssz) text = "%s\n%s" % (stem, ssz)
i = tk_call(canvas._w, "create", "text", i = tk_call(canvas._w, "create", "text",
x+BORDER+2, y+BORDER, x+BORDER+2, y+BORDER,
"-text", text, "-text", text,
"-font", FONT_FACE, "-anchor", "nw") "-font", FONT_FACE, "-anchor", "nw")
canvas.map[int(i)] = name canvas.map[int(i)] = name
y = y + FONT_HEIGHT2 y = y + FONT_HEIGHT2
h = h - FONT_HEIGHT2 h = h - FONT_HEIGHT2
if w*h > MIN_PSZ and haskids and depth != 1: if w*h > MIN_PSZ and haskids and depth != 1:
queue(canvas, allocate, name, files, canvas, queue(canvas, allocate, name, files, canvas,
x+2*BORDER, y+2*BORDER, x+2*BORDER, y+2*BORDER,
w-4*BORDER, h-4*BORDER, 0, depth-1) w-4*BORDER, h-4*BORDER, 0, depth-1)
continue continue
text = stem text = stem
tw = int(tk_call("font", "measure", FONT_FACE, text)) tw = int(tk_call("font", "measure", FONT_FACE, text))
if tw < w1: if tw < w1:
i = tk_call(canvas._w, "create", "text", i = tk_call(canvas._w, "create", "text",
x+BORDER+2, y+BORDER, x+BORDER+2, y+BORDER,
"-text", text, "-text", text,
"-font", FONT_FACE, "-anchor", "nw") "-font", FONT_FACE, "-anchor", "nw")
canvas.map[int(i)] = name canvas.map[int(i)] = name
y = y + FONT_HEIGHT y = y + FONT_HEIGHT
h = h - FONT_HEIGHT h = h - FONT_HEIGHT
if w*h > MIN_PSZ and haskids and depth != 1: if w*h > MIN_PSZ and haskids and depth != 1:
queue(canvas, allocate, name, files, canvas, queue(canvas, allocate, name, files, canvas,
x+2*BORDER, y+2*BORDER, x+2*BORDER, y+2*BORDER,
w-4*BORDER, h-4*BORDER, 0, depth-1) w-4*BORDER, h-4*BORDER, 0, depth-1)
def queue(c, *args): def queue(c, *args):
if c.aid is None: if c.aid is None:
@ -184,6 +202,7 @@ def queue(c, *args):
c.configure(cursor="watch") c.configure(cursor="watch")
c.queue.append(args) c.queue.append(args)
def run_queue(c): def run_queue(c):
queue = c.queue queue = c.queue
end = time.time() + .5 end = time.time() + .5
@ -192,20 +211,23 @@ def run_queue(c):
c.aid = None c.aid = None
c.configure(cursor="") c.configure(cursor="")
break break
if time.time() > end: break if time.time() > end:
break
item = queue[0] item = queue[0]
del queue[0] del queue[0]
item[0](*item[1:]) item[0](*item[1:])
if queue: if queue:
c.aid = c.after_idle(run_queue, c) c.aid = c.after_idle(run_queue, c)
def chroot(e, r): def chroot(e, r):
c = e.widget c = e.widget
if r is None: if r is None:
return return
if not getkids(c.files, r): if not getkids(c.files, r):
r = os.path.dirname(r) r = os.path.dirname(r)
if r == c.cur: return if r == c.cur:
return
if not r.startswith(c.root): if not r.startswith(c.root):
c.bell() c.bell()
return return
@ -215,24 +237,27 @@ def chroot(e, r):
e.height = c.winfo_height() e.height = c.winfo_height()
reconfigure(e) reconfigure(e)
def item_under_cursor(e): def item_under_cursor(e):
c = e.widget c = e.widget
try: try:
item = c.find_overlapping(e.x, e.y, e.x, e.y)[-1] item = c.find_overlapping(e.x, e.y, e.x, e.y)[-1]
except IndexError: except IndexError:
return None return None
return c.map.get(item, None) return c.map.get(item, None)
def descend(e): def descend(e):
c = e.widget
item = item_under_cursor(e) item = item_under_cursor(e)
chroot(e, item) chroot(e, item)
def ascend(e): def ascend(e):
c = e.widget c = e.widget
parent = os.path.dirname(c.cur) parent = os.path.dirname(c.cur)
chroot(e, parent) chroot(e, parent)
def size(n): def size(n):
if n > 1024*1024*1024: if n > 1024*1024*1024:
return "%.1fGB" % (n/1024./1024/1024) return "%.1fGB" % (n/1024./1024/1024)
@ -242,26 +267,32 @@ def size(n):
return "%.1fKB" % (n/1024.) return "%.1fKB" % (n/1024.)
return "%d" % n return "%d" % n
def scroll(e, dir): def scroll(e, dir):
c = e.widget c = e.widget
offset = c.first + 5*dir offset = c.first + 5*dir
l = len(getkids(c.files, c.cur)) length = len(getkids(c.files, c.cur))
if offset + 5 > l: offset = l-5 if offset + 5 > length:
if offset < 0: offset = 0 offset = length-5
if offset < 0:
offset = 0
if offset != c.first: if offset != c.first:
c.first = offset c.first = offset
e.width = c.winfo_width() e.width = c.winfo_width()
e.height = c.winfo_height() e.height = c.winfo_height()
reconfigure(e) reconfigure(e)
def schedule_tip(e): def schedule_tip(e):
c = e.widget c = e.widget
s = item_under_cursor(e) s = item_under_cursor(e)
if not s: return if not s:
return
sz = getname(c.files, s) sz = getname(c.files, s)
s = "%s (%s)" % (s, size(sz)) s = "%s (%s)" % (s, size(sz))
c.tipa = c.after(500, make_tip, e, s) c.tipa = c.after(500, make_tip, e, s)
def make_tip(e, s): def make_tip(e, s):
c = e.widget c = e.widget
c.tipa = None c.tipa = None
@ -269,6 +300,7 @@ def make_tip(e, s):
c.tip.wm_geometry("+%d+%d" % (e.x_root+5, e.y_root+5)) c.tip.wm_geometry("+%d+%d" % (e.x_root+5, e.y_root+5))
c.tip.wm_deiconify() c.tip.wm_deiconify()
def cancel_tip(e, c=None): def cancel_tip(e, c=None):
if c is None: if c is None:
c = e.widget c = e.widget
@ -278,6 +310,7 @@ def cancel_tip(e, c=None):
else: else:
c.tip.wm_withdraw() c.tip.wm_withdraw()
def reconfigure(e): def reconfigure(e):
c = e.widget c = e.widget
w = e.width w = e.width
@ -295,18 +328,19 @@ def reconfigure(e):
nslashes = -1 nslashes = -1
else: else:
nslashes = c.cur.count(os.sep) - 1 nslashes = c.cur.count(os.sep) - 1
parent = os.path.dirname(c.cur)
color = dircolors[nslashes % len(dircolors)] color = dircolors[nslashes % len(dircolors)]
c.configure(background=color) c.configure(background=color)
c.queue = [(allocate, c.cur, c.files, c, 0, 0, w, h, c.first, c.depth)] c.queue = [(allocate, c.cur, c.files, c, 0, 0, w, h, c.first, c.depth)]
run_queue(c) run_queue(c)
def putname_base(dict, name, base, size): def putname_base(dict, name, base, size):
try: try:
dict[base][name] = size dict[base][name] = size
except: except:
dict[base] = {name: size} dict[base] = {name: size}
def putname(dict, name, size): def putname(dict, name, size):
base = os.path.dirname(name) base = os.path.dirname(name)
try: try:
@ -314,13 +348,16 @@ def putname(dict, name, size):
except: except:
dict[base] = {name: size} dict[base] = {name: size}
def getname(dict, name): def getname(dict, name):
base = os.path.dirname(name) base = os.path.dirname(name)
return dict[base][0][name] return dict[base][0][name]
def getkids(dict, path): def getkids(dict, path):
return dict.get(path, ((), {}))[1] return dict.get(path, ((), {}))[1]
def doit(dir, files): def doit(dir, files):
sorted_files = {} sorted_files = {}
for k, v in files.items(): for k, v in files.items():
@ -355,11 +392,13 @@ def doit(dir, files):
c.bind("<Button-3>", ascend) c.bind("<Button-3>", ascend)
else: else:
c.bind("<Button-2>", ascend) c.bind("<Button-2>", ascend)
c.bind("<u>", ascend)
c.tag_bind("all", "<Button-1>", descend) c.tag_bind("all", "<Button-1>", descend)
c.tag_bind("all", "<Enter>", schedule_tip) c.tag_bind("all", "<Enter>", schedule_tip)
c.tag_bind("all", "<Leave>", cancel_tip) c.tag_bind("all", "<Leave>", cancel_tip)
c.mainloop() c.mainloop()
def setdepth(e, c, i): def setdepth(e, c, i):
e.widget = c e.widget = c
e.width = c.winfo_width() e.width = c.winfo_width()
@ -367,23 +406,26 @@ def setdepth(e, c, i):
c.depth = i c.depth = i
reconfigure(e) reconfigure(e)
def main(f = sys.stdin):
def main(f=sys.stdin):
files = {} files = {}
firstfile = None
for line in f.readlines(): for line in f.readlines():
sz, name = line[:-1].split(None, 1) sz, name = line[:-1].split(None, 1)
# name = name.split("/")
sz = int(sz)*1024 sz = int(sz)*1024
putname(files, name, sz) putname(files, name, sz)
doit(name, files) doit(name, files)
def du(dir, files, fs=0, ST_MODE=stat.ST_MODE, ST_SIZE = stat.ST_SIZE, S_IFMT = 0o170000, S_IFDIR = 0o040000, lstat = os.lstat, putname_base = putname_base, fmt="%%s%s%%s" % os.sep):
def du(dir, files, fs=0, ST_MODE=stat.ST_MODE, ST_SIZE=stat.ST_SIZE, S_IFMT=0o170000, S_IFDIR=0o040000, lstat=os.lstat, putname_base=putname_base, fmt="%%s%s%%s" % os.sep):
tsz = 0 tsz = 0
try: fns = os.listdir(dir) try:
except: return 0 fns = os.listdir(dir)
except:
return 0
if not files.has_key(dir): files[dir] = {} if not files.has_key(dir):
files[dir] = {}
d = files[dir] d = files[dir]
for fn in fns: for fn in fns:
@ -402,9 +444,11 @@ def du(dir, files, fs=0, ST_MODE=stat.ST_MODE, ST_SIZE = stat.ST_SIZE, S_IFMT =
tsz = tsz + sz tsz = tsz + sz
return tsz return tsz
def abspath(p): def abspath(p):
return os.path.normpath(os.path.join(os.getcwd(), p)) return os.path.normpath(os.path.join(os.getcwd(), p))
class DirDialog(tkinter.filedialog.LoadFileDialog): class DirDialog(tkinter.filedialog.LoadFileDialog):
def __init__(self, master, title=None): def __init__(self, master, title=None):
tkinter.filedialog.LoadFileDialog.__init__(self, master, title) tkinter.filedialog.LoadFileDialog.__init__(self, master, title)
@ -419,7 +463,7 @@ class DirDialog(tkinter.filedialog.LoadFileDialog):
self.quit(file) self.quit(file)
def filter_command(self, event=None): def filter_command(self, event=None):
END="end" END = "end"
dir, pat = self.get_filter() dir, pat = self.get_filter()
try: try:
names = os.listdir(dir) names = os.listdir(dir)
@ -439,11 +483,12 @@ class DirDialog(tkinter.filedialog.LoadFileDialog):
for name in subdirs: for name in subdirs:
self.dirs.insert(END, name) self.dirs.insert(END, name)
head, tail = os.path.split(self.get_selection()) head, tail = os.path.split(self.get_selection())
if tail == os.curdir: tail = '' if tail == os.curdir:
tail = ''
self.set_selection(tail) self.set_selection(tail)
def main_builtin_du(args): def main_builtin_du(args):
import sys
if len(args) > 1: if len(args) > 1:
p = args[1] p = args[1]
else: else:
@ -459,19 +504,19 @@ def main_builtin_du(args):
if p == '-h' or p == '--help' or p == '-?': if p == '-h' or p == '--help' or p == '-?':
base = os.path.basename(args[0]) base = os.path.basename(args[0])
print ('Usage:') print('Usage:')
print (' ', base, '<file.gz> interpret file as gzipped du -ak output and visualize it') print(' ', base, '<file.gz> interpret file as gzipped du -ak output and visualize it')
print (' ', base, '<file> interpret file as du -ak output and visualize it') print(' ', base, '<file> interpret file as du -ak output and visualize it')
print (' ', base, '<folder> analyze disk usage in that folder') print(' ', base, '<folder> analyze disk usage in that folder')
print (' ', base, '- interpret stdin input as du -ak output and visualize it') print(' ', base, '- interpret stdin input as du -ak output and visualize it')
print (' ', base, ' ask for folder to analyze') print(' ', base, ' ask for folder to analyze')
print print
print ('Controls:') print('Controls:')
print (' * Press `q` to quit') print(' * Press `q` to quit')
print (' * LMB: zoom in to item') print(' * LMB: zoom in to item')
print (' * RMB: zoom out one level') print(' * RMB: zoom out one level')
print (' * Press `1`..`9`: Show that many nested levels') print(' * Press `1`..`9`: Show that many nested levels')
print (' * Press `0`: Show man nested levels') print(' * Press `0`: Show man nested levels')
return return
if p == "-": if p == "-":
@ -488,6 +533,7 @@ def main_builtin_du(args):
putname(files, p, du(p, files)) putname(files, p, du(p, files))
doit(p, files) doit(p, files)
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
main_builtin_du(sys.argv) main_builtin_du(sys.argv)