Skip to content

Commit

Permalink
Issue #20 Initial implementation of zip listing support
Browse files Browse the repository at this point in the history
  • Loading branch information
soxofaan committed Oct 7, 2022
1 parent 31dc4e9 commit ec935ba
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
49 changes: 49 additions & 0 deletions duviz.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class SubprocessException(RuntimeError):
pass


class ParseException(ValueError):
pass


class SizeTree:
"""
Base class for a tree of nodes where each node has a size and zero or more sub-nodes.
Expand Down Expand Up @@ -210,6 +214,51 @@ def pairs(listing: str) -> Iterator[Tuple[List[str], int]]:
return tree


class ZipListingParseException(ParseException):
pass


def size_tree_from_zip_listing(listing: Iterable[str]) -> SizeTree:
def pairs(listing: Iterator[str]) -> Iterator[Tuple[List[str], int]]:
row_regex = re.compile(r"^\s*(\d+)\s+[\d-]+\s+[\d:]+\s+(.*)$")
for line in listing:
if line.startswith("---"):
# Reached table end
return
mo = row_regex.match(line)
if not mo:
raise ZipListingParseException(
f"Failed to parse zip listing line {line}"
)
size, path = mo.group(1, 2)
yield path_split(path), int(size)

listing = iter(listing)
# Try to parse zip listing header
archive_line = next(listing)
mo = re.match(r"^Archive:\s*(.+)$", archive_line)
if not mo:
raise ZipListingParseException(
f"Failed to parse Archive name from {archive_line}."
)
archive_name = mo.group(1)

header_line = next(listing)
table_header = re.split(r"\s+", header_line.strip())
if table_header != ["Length", "Date", "Time", "Name"]:
raise ZipListingParseException(f"Unexpected table header {header_line}.")
header_separator = next(listing)
header_separator_regex = re.compile(r"^[- ]+$")
if not header_separator_regex.match(header_separator):
raise ZipListingParseException(
f"Unexpected table separator {header_separator}."
)

tree = SizeTree.from_path_size_pairs(pairs=pairs(listing), root=archive_name)
tree._recalculate_own_sizes_to_total_sizes()
return tree


class SizeFormatter:
"""Render a (byte) count in compact human-readable way: 12, 34k, 56M, ..."""

Expand Down
56 changes: 53 additions & 3 deletions test_duviz.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,23 @@

import pytest

from duviz import TreeRenderer, SIZE_FORMATTER_COUNT, SIZE_FORMATTER_BYTES, SIZE_FORMATTER_BYTES_BINARY, path_split, \
SizeTree, AsciiDoubleLineBarRenderer, DuTree, InodeTree, get_progress_reporter, AsciiSingleLineBarRenderer, \
ColorDoubleLineBarRenderer, ColorSingleLineBarRenderer, Colorizer
from duviz import (
SIZE_FORMATTER_BYTES,
SIZE_FORMATTER_BYTES_BINARY,
SIZE_FORMATTER_COUNT,
AsciiDoubleLineBarRenderer,
AsciiSingleLineBarRenderer,
ColorDoubleLineBarRenderer,
Colorizer,
ColorSingleLineBarRenderer,
DuTree,
InodeTree,
SizeTree,
TreeRenderer,
get_progress_reporter,
path_split,
size_tree_from_zip_listing,
)


def test_bar_one():
Expand Down Expand Up @@ -644,3 +658,39 @@ def test_get_progress_reporter():
deltas = [i1-i0 for (i0, i1) in zip(indexes[:-1], indexes[1:])]
assert all(d < 5 for d in deltas[:5])
assert all(d > 9 for d in deltas[-5:])


class TestZipListing:
def _check_render(self, listing: str, expected: str, width=40):
tree = size_tree_from_zip_listing(_dedent(listing).split("\n"))
result = AsciiDoubleLineBarRenderer().render(tree, width=width)
assert result == _dedent_and_split(expected)

def test_basic(self):
self._check_render(
listing="""
Archive: tmp.zip
Length Date Time Name
--------- ---------- ----- ----
0 2022-10-08 00:27 docs/
0 2022-10-08 00:27 docs/img/
5456 2022-10-08 00:27 docs/img/logo.png
3634 2022-10-08 00:26 docs/api.txt
1575 2022-10-08 00:26 docs/intro.txt
2244 2022-10-08 00:25 README.md
--------- -------
12909 6 files
""",
expected="""
________________________________________________________________________________
[ tmp.zip ]
[____________________________________12.91k____________________________________]
[ docs ][ README.md ]
[_____________________________10.66k_____________________________][___2.24k____]
[ img ][ api.txt ][intro.tx]
[_____________5.46k_____________][________3.63k________][_1.57k__]
[ logo.png ]
[_____________5.46k_____________]
""",
width=80,
)

0 comments on commit ec935ba

Please sign in to comment.