Add cmd line app
This commit is contained in:
parent
68ad80e435
commit
8306fb4c3e
@ -23,5 +23,7 @@ use `--input` and `--output` to specify input and output files respectively.
|
|||||||
|
|
||||||
There's some handy test data in the `tests/data` directory. For example:
|
There's some handy test data in the `tests/data` directory. For example:
|
||||||
```bash
|
```bash
|
||||||
gzip -dc tests/data/fdb_list_compact.gz| qubed --from=fdblist
|
gzip -dc tests/data/fdb_list_compact.gz| qubed convert --from=fdb --to=text --output=qube.txt
|
||||||
|
gzip -dc tests/data/fdb_list_porcelain.gz| qubed convert --from=fdb --to=json --output=qube.json
|
||||||
|
gzip -dc tests/data/fdb_list_compact.gz | qubed convert --from=fdb --to=html --output=qube.html
|
||||||
```
|
```
|
||||||
|
@ -18,6 +18,9 @@ requires-python = ">= 3.11"
|
|||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"frozendict",
|
"frozendict",
|
||||||
|
"rich",
|
||||||
|
"numpy",
|
||||||
|
"click",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Because this is a mixed rust/python project the structure is src/python/qubed rather than the more typical src/qubed
|
# Because this is a mixed rust/python project the structure is src/python/qubed rather than the more typical src/qubed
|
||||||
|
@ -1,82 +1,114 @@
|
|||||||
import argparse
|
import time
|
||||||
import sys
|
|
||||||
|
|
||||||
|
import click
|
||||||
|
import psutil
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
from rich.layout import Layout
|
||||||
|
from rich.live import Live
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.spinner import Spinner
|
||||||
|
from rich.text import Text
|
||||||
|
|
||||||
from qubed import Qube
|
from qubed import Qube
|
||||||
from qubed.convert import parse_fdb_list
|
from qubed.convert import parse_fdb_list
|
||||||
|
|
||||||
console = Console(stderr=True)
|
console = Console(stderr=True)
|
||||||
|
process = psutil.Process()
|
||||||
|
|
||||||
|
PRINT_INTERVAL = 0.25
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
"""Command-line tool for working with trees."""
|
||||||
description="Generate a compressed tree from various inputs."
|
pass
|
||||||
)
|
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(title="subcommands", required=True)
|
|
||||||
parser_convert = subparsers.add_parser(
|
|
||||||
"convert", help="Convert trees from one format to another."
|
|
||||||
)
|
|
||||||
# parser_another = subparsers.add_parser(
|
|
||||||
# "another_subcommand", help="Does something else"
|
|
||||||
# )
|
|
||||||
|
|
||||||
parser_convert.add_argument(
|
@main.command()
|
||||||
|
@click.option(
|
||||||
"--input",
|
"--input",
|
||||||
type=argparse.FileType("r"),
|
type=click.File("r"),
|
||||||
default=sys.stdin,
|
default="-",
|
||||||
help="Specify the input file (default: standard input).",
|
help="Specify the input file (default: standard input).",
|
||||||
)
|
)
|
||||||
parser_convert.add_argument(
|
@click.option(
|
||||||
"--output",
|
"--output",
|
||||||
type=argparse.FileType("w"),
|
type=click.File("w"),
|
||||||
default=sys.stdout,
|
default="-",
|
||||||
help="Specify the output file (default: standard output).",
|
help="Specify the output file (default: standard output).",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
parser_convert.add_argument(
|
"--from",
|
||||||
"--input_format",
|
"from_format",
|
||||||
choices=["fdb", "mars"],
|
type=click.Choice(["fdb", "mars"]),
|
||||||
default="fdb",
|
default="fdb",
|
||||||
help="""Specify the input format:
|
help="Specify the input format: fdb (fdb list --porcelain) or mars (mars list).",
|
||||||
fdb: the output of fdb list --porcelain
|
)
|
||||||
mars: the output of mars list
|
@click.option(
|
||||||
""",
|
"--to",
|
||||||
)
|
"to_format",
|
||||||
|
type=click.Choice(["text", "html", "json"]),
|
||||||
parser_convert.add_argument(
|
|
||||||
"--output_format",
|
|
||||||
choices=["text", "html"],
|
|
||||||
default="text",
|
default="text",
|
||||||
help="Specify the output format (text or html).",
|
help="Specify the output format: text, html, json.",
|
||||||
)
|
)
|
||||||
parser_convert.set_defaults(func=convert)
|
def convert(input, output, from_format, to_format):
|
||||||
|
"""Convert trees from one format to another."""
|
||||||
args = parser.parse_args()
|
|
||||||
args.func(args)
|
|
||||||
|
|
||||||
|
|
||||||
def convert(args):
|
|
||||||
q = Qube.empty()
|
q = Qube.empty()
|
||||||
for datacube in parse_fdb_list(args.input):
|
t = time.time()
|
||||||
|
i0 = 0
|
||||||
|
n0 = 0
|
||||||
|
depth = 5
|
||||||
|
log = Text()
|
||||||
|
summary = Layout()
|
||||||
|
summary.split_column(
|
||||||
|
Layout(name="upper"),
|
||||||
|
Layout(name="qube"),
|
||||||
|
)
|
||||||
|
summary["upper"].split_row(
|
||||||
|
Layout(name="performance"),
|
||||||
|
Layout(log, name="log"),
|
||||||
|
)
|
||||||
|
spinner = Spinner("aesthetic", text="Performance", speed=0.3)
|
||||||
|
|
||||||
|
with Live(summary, auto_refresh=False, transient=True, console=console) as live:
|
||||||
|
for i, datacube in enumerate(parse_fdb_list(input)):
|
||||||
new_branch = Qube.from_datacube(datacube)
|
new_branch = Qube.from_datacube(datacube)
|
||||||
q = q | Qube.from_datacube(datacube)
|
q = q | new_branch
|
||||||
|
|
||||||
# output = match args.output_format:
|
if time.time() - t > PRINT_INTERVAL:
|
||||||
# case "text":
|
tree = q.__str__(depth=depth)
|
||||||
# str(q)
|
if tree.count("\n") > 20:
|
||||||
# case "html":
|
depth -= 1
|
||||||
# q.html()
|
if tree.count("\n") < 5:
|
||||||
output = "fw"
|
depth += 1
|
||||||
|
|
||||||
with open(args.output, "w") as f:
|
summary["performance"].update(
|
||||||
f.write(output)
|
Panel(
|
||||||
|
Text.assemble(
|
||||||
|
f"The Qube has {q.n_leaves} leaves and {q.n_nodes} internal nodes so far.\n",
|
||||||
|
f"{(i - i0) / (time.time() - t) / PRINT_INTERVAL:.0f} lines per second. ",
|
||||||
|
f"{(q.n_leaves - n0) / (time.time() - t):.0f} leaves per second.\n",
|
||||||
|
f"Memory usage: {process.memory_info().rss / 1024 / 1024:.0f} MB\n",
|
||||||
|
),
|
||||||
|
title=spinner.render(time.time()),
|
||||||
|
border_style="blue",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
summary["qube"].update(
|
||||||
|
Panel(tree, title=f"Qube (depth {depth})", border_style="blue")
|
||||||
|
)
|
||||||
|
summary["log"].update(
|
||||||
|
Panel(
|
||||||
|
f"{datacube}", border_style="blue", title="Last Datacube Added"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
live.refresh()
|
||||||
|
i0 = i
|
||||||
|
n0 = q.n_leaves
|
||||||
|
t = time.time()
|
||||||
|
|
||||||
console.print([1, 2, 3])
|
output_content = str(q) if to_format == "text" else q.html().html
|
||||||
console.print("[blue underline]Looks like a link")
|
output.write(output_content)
|
||||||
console.print(locals())
|
|
||||||
console.print("FOO", style="white on blue")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Loading…
x
Reference in New Issue
Block a user