Implement CLI framework and refactor main logic; add YAML support in utils
This commit is contained in:
parent
b9761e5f13
commit
c9176dbbce
@ -1,11 +1,28 @@
|
||||
import sys
|
||||
from .utils import zip_dir
|
||||
from cli import CLI
|
||||
|
||||
def main() -> int:
|
||||
for arg in sys.argv[1:]:
|
||||
print(arg)
|
||||
def main():
|
||||
cli = CLI("nut")
|
||||
|
||||
cli.command("run") \
|
||||
.flag("debug", "d") \
|
||||
.handle(cmd_run)
|
||||
|
||||
cli.command("build") \
|
||||
.handle(cmd_build)
|
||||
|
||||
return cli.run()
|
||||
|
||||
def cmd_run(subcommands, flags):
|
||||
print("RUN")
|
||||
print("sub:", subcommands)
|
||||
print("flags:", flags)
|
||||
return 0
|
||||
|
||||
def cmd_build(subcommands, flags):
|
||||
print("BUILD")
|
||||
print("sub:", subcommands)
|
||||
print("flags:", flags)
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
51
nut/cli.py
Normal file
51
nut/cli.py
Normal file
@ -0,0 +1,51 @@
|
||||
import argparse
|
||||
|
||||
class CLI:
|
||||
def __init__(self, prog="nut"):
|
||||
self.parser = argparse.ArgumentParser(prog=prog)
|
||||
self.subparsers = self.parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
def command(self, name):
|
||||
parser = self.subparsers.add_parser(name)
|
||||
|
||||
cmd = _Command(parser)
|
||||
return cmd
|
||||
|
||||
def run(self):
|
||||
args = self.parser.parse_args()
|
||||
|
||||
# extract structured data
|
||||
sub_args = getattr(args, "_args", [])
|
||||
flags = {
|
||||
k: v for k, v in vars(args).items()
|
||||
if k not in ("command", "func", "_args")
|
||||
}
|
||||
|
||||
return args.func(sub_args, flags)
|
||||
|
||||
class _Command:
|
||||
def __init__(self, parser):
|
||||
self.parser = parser
|
||||
self.parser.set_defaults(func=self._missing)
|
||||
|
||||
# default catch-all args
|
||||
self.parser.add_argument("_args", nargs="*")
|
||||
|
||||
def arg(self, name, **kwargs):
|
||||
self.parser.add_argument(name, **kwargs)
|
||||
return self
|
||||
|
||||
def flag(self, name, short=None):
|
||||
flags = [f"--{name}"]
|
||||
if short:
|
||||
flags.append(f"-{short}")
|
||||
|
||||
self.parser.add_argument(*flags, action="store_true")
|
||||
return self
|
||||
|
||||
def handle(self, func):
|
||||
self.parser.set_defaults(func=func)
|
||||
return self
|
||||
|
||||
def _missing(self, *_):
|
||||
raise RuntimeError("No handler defined for command")
|
||||
0
nut/templates/Nutfile
Normal file
0
nut/templates/Nutfile
Normal file
@ -8,15 +8,12 @@ class _Jump:
|
||||
def __init__(self, target):
|
||||
self.target = target
|
||||
|
||||
|
||||
class _Jmp(_Jump):
|
||||
pass
|
||||
|
||||
|
||||
class _Call(_Jump):
|
||||
RETURN = object()
|
||||
|
||||
|
||||
class _VM:
|
||||
def __init__(self, entry, ctx=None):
|
||||
self.current = entry
|
||||
@ -31,7 +28,6 @@ class _VM:
|
||||
print(f"Error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def loop(self):
|
||||
action = self.current(self.ctx)
|
||||
|
||||
23
nut/utils.py
23
nut/utils.py
@ -2,9 +2,9 @@ import os
|
||||
import zipfile
|
||||
import json
|
||||
import fnmatch
|
||||
import yaml
|
||||
|
||||
|
||||
def _should_ignore(rel_path, patterns):
|
||||
def _should_ignore(rel_path: str, patterns: list) -> bool:
|
||||
"""
|
||||
Check if a file should be ignored based on patterns.
|
||||
"""
|
||||
@ -25,8 +25,7 @@ def _should_ignore(rel_path, patterns):
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def zip_dir(source_dir, output_zip_path, metadata=None, ignore_patterns=None):
|
||||
def zip_dir(source_dir: str, output_zip_path: str, metadata: dict = None, ignore_patterns: list = None) -> None:
|
||||
"""
|
||||
Compress a directory into a zip file with ignore support.
|
||||
|
||||
@ -63,16 +62,14 @@ def zip_dir(source_dir, output_zip_path, metadata=None, ignore_patterns=None):
|
||||
if metadata:
|
||||
zipf.writestr("_meta.json", json.dumps(metadata, indent=2))
|
||||
|
||||
|
||||
def unzip_to_dir(zip_path, output_dir):
|
||||
def unzip_to_dir(zip_path: str, output_dir: str) -> None:
|
||||
"""
|
||||
Extract zip file to a directory.
|
||||
"""
|
||||
with zipfile.ZipFile(zip_path, 'r') as zipf:
|
||||
zipf.extractall(output_dir)
|
||||
|
||||
|
||||
def unzip_in_memory(zip_path):
|
||||
def unzip_in_memory(zip_path: str) -> dict:
|
||||
"""
|
||||
Read zip contents into memory only.
|
||||
|
||||
@ -94,3 +91,13 @@ def unzip_in_memory(zip_path):
|
||||
"files": data,
|
||||
"metadata": metadata
|
||||
}
|
||||
|
||||
def read_yaml(path: str) -> dict:
|
||||
"""
|
||||
:param path: path to yaml file
|
||||
:return: parsed dict
|
||||
"""
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
data = yaml.safe_load(f)
|
||||
|
||||
return data
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user