3 from pysize_global_fs_cache
import get_dev_ino
, cache_add_dir
, \
4 cache_add_hardlink
, cache_get_dir_size
6 def _size_fast(path
, dir_ino
):
9 if stat
.S_ISDIR(st
.st_mode
):
10 dev_ino
= (st
.st_dev
, st
.st_ino
)
11 cached_size
= cache_get_dir_size(dev_ino
)
12 if cached_size
== None:
13 prev
= os
.open('.', os
.O_RDONLY
)
15 size
= st
.st_blocks
* 512
17 for p
in os
.listdir('.'):
18 size
+= _size_fast(p
, dir_ino
)
21 cache_add_dir(dev_ino
, size
)
25 if cache_add_hardlink(st
.st_dev
, st
.st_ino
, dir_ino
, path
):
26 size
= st
.st_blocks
* 512
30 size
= st
.st_blocks
* 512
38 elements
= path
.split('/')
39 length
= len(elements
)
41 for i
in xrange(length
- 1, -1, -1):
42 if elements
[i
] not in ('', '.'):
45 return '/'.join(elements
)
49 if os
.path
.samefile(path
, '.'):
50 return os
.path
.dirname(os
.getcwd())
52 parent
= parent_path()
53 return _size_fast(path
, get_dev_ino(parent
)[1])
56 def __init__(self
, parent
, basename
):
57 self
.rectangle
= (0, 0, 0, 0)
60 self
.basename
= basename
61 self
.size
= _size(basename
)
63 def _compute_height(self
):
66 def _compute_depth(self
):
80 def get_children(self
):
83 def get_fullpath(self
):
84 fullpath
= self
.basename
87 fullpath
= os
.path
.join(parent
.basename
, fullpath
)
88 parent
= parent
.parent
93 for child
in self
.get_children():
97 def contains_point(self
, p
):
98 (x0
, x1
, y0
, y1
) = self
.rectangle
99 return x0
< p
.x
and p
.x
< x1
and y0
< p
.y
and p
.y
< y1
101 class _pysize_node_remaining(_pysize_node
):
102 def __init__(self
, parent
, size
):
103 _pysize_node
.__init
__(self
, parent
, None)
104 self
.basename
= '..///..'
110 class _pysize_node_dir(_pysize_node
):
111 def __init__(self
, parent
, basename
, max_depth
, min_size
):
112 _pysize_node
.__init
__(self
, parent
, basename
)
116 prev
= os
.open('.', os
.O_RDONLY
)
118 for child
in os
.listdir('.'):
119 node
= _create_node(self
, child
, max_depth
- 1, min_size
)
121 self
.children
.append(node
)
122 children_size
+= node
.size
125 self
.children
.sort(key
=lambda t
: t
.size
, reverse
=True)
126 self
.size
= max(children_size
, self
.size
)
127 remaining_size
= self
.size
- children_size
128 if remaining_size
> min_size
:
129 rem
= _pysize_node_remaining(self
, remaining_size
)
130 self
.children
.append(rem
)
132 def _compute_height(self
):
134 children_height
= max([c
._compute
_height
() for c
in self
.children
])
135 return children_height
+ 1
141 def get_children(self
):
144 class _pysize_node_file(_pysize_node
):
145 def __init__(self
, parent
, basename
):
146 _pysize_node
.__init
__(self
, parent
, basename
)
148 class _pysize_node_hardlink(_pysize_node_file
):
149 def __init__(self
, parent
, basename
):
150 _pysize_node_file
.__init
__(self
, parent
, basename
)
152 def _create_node(parent
, basename
, max_depth
, min_size
):
153 if _size(basename
) < min_size
:
155 st
= os
.lstat(basename
)
156 if stat
.S_ISDIR(st
.st_mode
):
157 node
= _pysize_node_dir(parent
, basename
, max_depth
, min_size
)
158 elif st
.st_nlink
> 1:
159 node
= _pysize_node_hardlink(parent
, basename
)
161 node
= _pysize_node_file(parent
, basename
)
164 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/231503
166 def _breadth_first(tree
,children
=iter):
167 """Traverse the nodes of a tree in breadth-first order.
168 The first argument should be the tree root; children
169 should be a function taking as argument a tree node and
170 returning an iterator of the node's children.
174 for node
in _breadth_first(tree
,children
):
175 for child
in children(node
):
182 def __init__(self
, path
, max_depth
, min_size_ratio
):
184 min_size
= int(min_size_ratio
* _size(path
))
185 self
.root
= _create_node(None, path
, max_depth
, min_size
)
187 self
.height
= self
.root
._compute
_height
()
191 def get_next_sibling(self
, node
):
193 for child
in _breadth_first(self
.root
, lambda c
: c
.get_children()):
195 if child
._compute
_depth
() == node
._compute
_depth
():
198 is_next
= child
is node
200 def get_previous_sibling(self
, node
):
202 for child
in _breadth_first(self
.root
, lambda c
: c
.get_children()):
204 if prev
._compute
_depth
() == node
._compute
_depth
():
209 def get_first_child(self
, node
):
210 children
= node
.get_children()
214 def get_parent(self
, node
):
218 tree
= pysize_tree('/usr/share/doc', 4, 0.1)
219 print 'height', tree
.height
221 if __name__
== '__main__':