else
This commit is contained in:
parent
0c87e60094
commit
0c561c05c9
3 changed files with 296 additions and 3 deletions
|
@ -143,7 +143,7 @@ from voussoirkit import bytestring
|
|||
from voussoirkit import downloady
|
||||
from voussoirkit import fusker
|
||||
from voussoirkit import treeclass
|
||||
from voussoirkit import pathtree
|
||||
import pathtree
|
||||
sys.path.append('D:\\git\\else\\threadqueue'); import threadqueue
|
||||
|
||||
DOWNLOAD_CHUNK = 16 * bytestring.KIBIBYTE
|
||||
|
|
292
OpenDirDL/pathtree.py
Normal file
292
OpenDirDL/pathtree.py
Normal file
|
@ -0,0 +1,292 @@
|
|||
import argparse
|
||||
import sys
|
||||
import os
|
||||
|
||||
from voussoirkit import bytestring
|
||||
from voussoirkit import treeclass
|
||||
|
||||
HTML_TREE_HEAD = '''
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<script type="text/javascript">
|
||||
function collapse(div, force)
|
||||
{
|
||||
if (force !== "block" && div.style.display != "none")
|
||||
{
|
||||
div.style.display = "none";
|
||||
}
|
||||
else
|
||||
{
|
||||
div.style.display = "block";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
*
|
||||
{
|
||||
font-family: Consolas;
|
||||
}
|
||||
|
||||
.directory_even, .directory_odd
|
||||
{
|
||||
padding: 10px;
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #000;
|
||||
box-shadow: 1px 1px 2px 0px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.directory_even
|
||||
{
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.directory_odd
|
||||
{
|
||||
background-color: #eee;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
function open_all()
|
||||
{
|
||||
var divs = document.getElementsByTagName("div");
|
||||
for (var index = 0; index < divs.length; index += 1)
|
||||
{
|
||||
collapse(divs[index], "block");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<button onclick="open_all()">Expand all</button>
|
||||
'''
|
||||
|
||||
HTML_FORMAT_DIRECTORY = '''
|
||||
<div class="buttonbox">
|
||||
<button onclick="collapse(this.parentElement.nextElementSibling)">{name} ({size})</button>
|
||||
{directory_anchor}
|
||||
</div>
|
||||
<div class="{css}" style="display:none">
|
||||
'''.replace('\n', '')
|
||||
|
||||
HTML_FORMAT_FILE = '<a href="{url}">{name} ({size})</a><br>'
|
||||
|
||||
|
||||
class PathTree(treeclass.Tree):
|
||||
def __init__(
|
||||
self,
|
||||
path,
|
||||
display_name=None,
|
||||
item_type=None,
|
||||
size=None,
|
||||
**kwargs,
|
||||
):
|
||||
self.path = normalize_slash(path)
|
||||
if display_name is None:
|
||||
self.display_name = self.path.split(os.sep)[-1]
|
||||
else:
|
||||
self.display_name = display_name
|
||||
kwargs['identifier'] = self.display_name
|
||||
super(PathTree, self).__init__(**kwargs)
|
||||
self.size = size
|
||||
self.item_type = item_type
|
||||
|
||||
def normalize_slash(path):
|
||||
path = path.replace('/', '\\')
|
||||
path = path.rstrip(os.sep)
|
||||
return path
|
||||
|
||||
def from_paths(path_datas, root_name):
|
||||
all_datas = []
|
||||
for data in path_datas:
|
||||
if isinstance(data, str):
|
||||
data = {'path': data}
|
||||
elif isinstance(data, dict):
|
||||
pass
|
||||
else:
|
||||
raise TypeError(data)
|
||||
data['parts'] = data['path'].split(os.sep)
|
||||
all_datas.append(data)
|
||||
|
||||
#path_parts = path_parts.split('\\')
|
||||
#item = {'url': url, 'size': size, 'path_parts': path_parts}
|
||||
#all_items.append(item)
|
||||
#scheme = url_split(all_items[0]['url'])['scheme']
|
||||
|
||||
all_datas.sort(key=lambda x: x['path'])
|
||||
|
||||
tree_root = PathTree(root_name, item_type='directory')
|
||||
tree_root.unsorted_children = all_datas
|
||||
node_queue = set()
|
||||
node_queue.add(tree_root)
|
||||
|
||||
# In this process, URLs are divided up into their nodes one directory layer at a time.
|
||||
# The root has all URLs as its `unsorted_children` attribute, and creates
|
||||
# nodes for each of the top-level directories.
|
||||
# Those nodes receive all subdirectories, and repeat.
|
||||
while len(node_queue) > 0:
|
||||
node = node_queue.pop()
|
||||
for new_child_data in node.unsorted_children:
|
||||
# Create a new node for the subdirectory, which is path_parts[0]
|
||||
# The rest of the child path is assigned to that node to be further divided.
|
||||
# By popping, we modify the path_parts in place so that the next cycle
|
||||
# only deals with the remaining subpath.
|
||||
path_parts = new_child_data['parts']
|
||||
child_identifier = path_parts.pop(0)
|
||||
|
||||
child = node.children.get(child_identifier)
|
||||
if not child:
|
||||
child = PathTree(child_identifier)
|
||||
child.unsorted_children = []
|
||||
node.add_child(child)
|
||||
|
||||
if len(path_parts) > 0:
|
||||
child.item_type = 'directory'
|
||||
child.unsorted_children.append(new_child_data)
|
||||
else:
|
||||
child.item_type = 'file'
|
||||
child.size = new_child_data.get('size')
|
||||
child.data = new_child_data.get('data')
|
||||
node_queue.add(child)
|
||||
|
||||
if node.parent is not None and node.parent != tree_root:
|
||||
node.path = node.parent.path + os.sep + node.path
|
||||
|
||||
del node.unsorted_children
|
||||
return tree_root
|
||||
|
||||
def recursive_get_size(node):
|
||||
'''
|
||||
Calculate the size of the Directory nodes by summing the sizes of all children.
|
||||
Modifies the nodes in-place.
|
||||
'''
|
||||
return_value = {
|
||||
'size': 0,
|
||||
'unmeasured': 0,
|
||||
}
|
||||
if node.item_type == 'file':
|
||||
if node.size is None:
|
||||
return_value['unmeasured'] = 1
|
||||
# = instead of += because if the node.size is None, we want to propogate
|
||||
# that to the caller, rather than normalizing it to 0.
|
||||
return_value['size'] = node.size
|
||||
|
||||
else:
|
||||
for child in node.list_children():
|
||||
child_details = recursive_get_size(child)
|
||||
return_value['size'] += child_details['size'] or 0
|
||||
return_value['unmeasured'] += child_details['unmeasured']
|
||||
node.size = return_value['size']
|
||||
|
||||
return return_value
|
||||
|
||||
def recursive_print_node(node, depth=0, use_html=False, header=None, footer=None):
|
||||
'''
|
||||
Given a tree node (presumably the root), print it and all of its children.
|
||||
|
||||
use_html:
|
||||
Generate a neat HTML page instead of plain text.
|
||||
header:
|
||||
This text goes at the top of the file, or just below the <body> tag.
|
||||
footer:
|
||||
This text goes at the end of the file, or just above the </body> tag.
|
||||
'''
|
||||
if depth == 0:
|
||||
if use_html:
|
||||
yield '<!DOCTYPE html>\n<html>'
|
||||
yield HTML_TREE_HEAD
|
||||
yield '<body>'
|
||||
if header is not None:
|
||||
yield header
|
||||
|
||||
size = node.size
|
||||
if size is None:
|
||||
size = '???'
|
||||
else:
|
||||
size = bytestring.bytestring(size)
|
||||
|
||||
if use_html:
|
||||
css_class = 'directory_even' if depth % 2 == 0 else 'directory_odd'
|
||||
if node.item_type == 'directory':
|
||||
directory_url = node.path
|
||||
directory_anchor = '<a href="{url}">→</a>' if directory_url else ''
|
||||
directory_anchor = directory_anchor.format(url=directory_url)
|
||||
line = HTML_FORMAT_DIRECTORY.format(
|
||||
css=css_class,
|
||||
directory_anchor=directory_anchor,
|
||||
name=node.display_name,
|
||||
size=size,
|
||||
)
|
||||
else:
|
||||
line = HTML_FORMAT_FILE.format(
|
||||
name=node.display_name,
|
||||
size=size,
|
||||
url=node.path,
|
||||
)
|
||||
else:
|
||||
line = '{space}{bar}{name} : ({size})'
|
||||
line = line.format(
|
||||
space='| ' * (depth-1),
|
||||
bar='|---' if depth > 0 else '',
|
||||
name=node.display_name,
|
||||
size=size
|
||||
)
|
||||
yield line
|
||||
|
||||
# Sort by type (directories first) then subsort by lowercase path
|
||||
customsort = lambda node: (
|
||||
node.item_type == 'file',
|
||||
node.path.lower(),
|
||||
)
|
||||
|
||||
for child in node.list_children(sort=customsort):
|
||||
yield from recursive_print_node(child, depth=depth+1, use_html=use_html)
|
||||
|
||||
if node.item_type == 'directory':
|
||||
if use_html:
|
||||
# Close the directory div
|
||||
yield '</div>'
|
||||
else:
|
||||
# This helps put some space between sibling directories
|
||||
yield '| ' * (depth)
|
||||
|
||||
if depth == 0:
|
||||
if footer is not None:
|
||||
yield footer
|
||||
if use_html:
|
||||
yield '</body>\n</html>'
|
||||
|
||||
|
||||
|
||||
def pathtree_argparse(args):
|
||||
from voussoirkit import safeprint
|
||||
from voussoirkit import spinal
|
||||
paths = spinal.walk_generator()
|
||||
paths = [{'path': path.absolute_path, 'size': path.size} for path in paths]
|
||||
tree = from_paths(paths, '.')
|
||||
recursive_get_size(tree)
|
||||
|
||||
if args.output_file:
|
||||
output_file = open(args.output_file, 'w', encoding='utf-8')
|
||||
else:
|
||||
output_file = None
|
||||
|
||||
for line in recursive_print_node(tree, use_html=args.use_html):
|
||||
if output_file:
|
||||
print(line, file=output_file)
|
||||
else:
|
||||
safeprint.safeprint(line)
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('output_file', nargs='?', default=None)
|
||||
parser.add_argument('--html', dest='use_html', action='store_true')
|
||||
parser.set_defaults(func=pathtree_argparse)
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
args.func(args)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
|
@ -137,6 +137,7 @@ def voxelspheregenerator(WIDTH, HEIGH, DEPTH, WALL_THICKNESS=None, specific=None
|
|||
#layer_image.paste(dot, box=(pixel_coord_x, pixel_coord_y))
|
||||
|
||||
# Mark the corner pieces
|
||||
furthest_y = math.floor(furthest_y)
|
||||
for y in range(furthest_y, math.ceil(RAD_Y-1)):
|
||||
for x in range(furthest_x, math.ceil(RAD_X-1)):
|
||||
is_corner = (
|
||||
|
@ -175,7 +176,7 @@ def voxelspheregenerator(WIDTH, HEIGH, DEPTH, WALL_THICKNESS=None, specific=None
|
|||
# Start at the center top of the circle and walk along the edge.
|
||||
# Every time the walker 'falls' down, mark the distance.
|
||||
def put_counterhelper(start_x, end_x, y):
|
||||
if start_x == end_x:
|
||||
if start_x > end_x:
|
||||
return
|
||||
y = (HEIGH + 1) - y
|
||||
span = end_x - start_x
|
||||
|
@ -187,7 +188,7 @@ def voxelspheregenerator(WIDTH, HEIGH, DEPTH, WALL_THICKNESS=None, specific=None
|
|||
end_x = x
|
||||
start_y = None
|
||||
while x >= y and y < RAD_Y:
|
||||
print(x, y, start_y)
|
||||
#print(x, y, start_y)
|
||||
pixel = layer_matrix[x][y]
|
||||
if pixel is None:
|
||||
y += 1
|
||||
|
|
Loading…
Reference in a new issue