Skip to content

Commit 53ee8a4

Browse files
committed
shelephant_diff: unify and simplify implementation
1 parent 35557fb commit 53ee8a4

5 files changed

Lines changed: 51 additions & 60 deletions

File tree

‎docs/copying.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,4 @@ and you would like to keep a backup of certain files (e.g. ``*.h5``) in
179179
180180
shelephant_diff containerinfo.yaml localinfo.yaml
181181
182-
(You can also use ``shelephant_cp`` to copy. In that case the copy-plan can be based purely on *sha256*.)
182+
(You can also use ``shelephant_cp`` to copy. In that case the copy-plan can be based purely on *sha256* if you set ``--mode=sha256``.)

‎shelephant/cli.py‎

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
import click
1111
import numpy as np
12-
import prettytable
1312

1413
from . import dataset
1514
from . import local
@@ -342,6 +341,7 @@ def shelephant_cp(args: list[str], paths: list[str] = None, filter_paths: bool =
342341
if suffix_source != pathlib.Path(""):
343342
files = [os.path.relpath(p, suffix_source) for p in files]
344343

344+
# interaction not directly with command-line
345345
if len(paths) > 0:
346346
if (common_prefix / deepest) != pathlib.Path(""):
347347
strip = common_prefix / deepest
@@ -660,7 +660,17 @@ def _shelephant_diff_parser():
660660
shelephant_diff <sourceinfo.yaml> <destinfo.yaml> --filter "?=, !="
661661
shelephant_diff <sourceinfo.yaml> <destinfo.yaml> -o <diff.yaml>
662662
663-
Note that if filter contains only one operation the output YAML-file will be a list.
663+
.. note::
664+
665+
``--filter`` allows to output only a limited number of directions.
666+
For convenience, and to bypass syntax limitations, the following aliases are available:
667+
668+
- ``<``: ``<-``
669+
- ``>``: ``->``
670+
- ``!``: ``!=``
671+
- ``~``: ``!=``
672+
- ``?``: ``?=``
673+
- ``=``: ``==``
664674
"""
665675
)
666676

@@ -679,14 +689,13 @@ class MyFmt(
679689
parser.add_argument(
680690
"--mode", type=str, help="Use 'sha256', 'rsync', or 'basic'.", default="sha256"
681691
)
682-
parser.add_argument("--sort", type=str, help="Sort printed table by column.")
683-
parser.add_argument("--table", type=str, default="SINGLE_BORDER", help="Select print style.")
684-
parser.add_argument("--filter", type=str, help="Filter to direction (separated by ',').")
685-
parser.add_argument("-o", "--output", type=pathlib.Path, help="Dump as YAML file.")
686-
parser.add_argument("-f", "--force", action="store_true", help="Force overwrite output.")
692+
parser.add_argument("--list", action="store_true", help="Output list instead of dictionary")
693+
parser.add_argument("--filter", type=str, help="Filter to directions separated by ','")
694+
parser.add_argument("-o", "--output", type=pathlib.Path, help="Dump as YAML file")
695+
parser.add_argument("-f", "--force", action="store_true", help="Force overwrite output file")
687696
parser.add_argument("--version", action="version", version=version)
688-
parser.add_argument("source", type=pathlib.Path, help="Source information.")
689-
parser.add_argument("dest", type=pathlib.Path, help="Destination directory/information.")
697+
parser.add_argument("source", type=pathlib.Path, help="Source information")
698+
parser.add_argument("dest", type=pathlib.Path, help="Destination directory/information")
690699
return parser
691700

692701

@@ -704,17 +713,17 @@ def shelephant_diff(args: list[str]):
704713
assert len(args.mode) == 1, "Only one mode allowed."
705714
assert shutil.which("rsync") is not None or "rsync" not in args.mode, "rsync not available."
706715

707-
source = dataset.Location.from_yaml(args.source)
708-
files = source.files(info=False)
709-
710716
if args.dest.is_file():
711717
dest = dataset.Location.from_yaml(args.dest)
712718
else:
713719
dest = dataset.Location(root=args.dest, ssh=args.ssh)
714720

721+
source = dataset.Location.from_yaml(args.source)
722+
715723
if "sha256" in args.mode:
716724
status = source.diff(dest)
717725
elif "rsync" in args.mode:
726+
files = source.files(info=False)
718727
left = source.diff(dest)["<-"]
719728
[files.remove(file) for file in left]
720729
status = rsync.diff(source.hostpath, dest.hostpath, files)
@@ -726,51 +735,26 @@ def shelephant_diff(args: list[str]):
726735
raise ValueError(f"Unknown mode '{args.mode}'.")
727736

728737
if args.filter:
729-
keys = [key.strip() for key in args.filter.split(",")]
738+
alias = {">": "->", "<": "<-", "!": "!=", "~": "!=", "?": "?=", "=": "=="}
739+
alias = {**alias, **{v: v for v in alias.values()}}
740+
filters = [alias[i.strip()] for i in args.filter.split(",")]
741+
keys = [key.strip() for key in filters]
730742
keys = [key for key in keys if key in status]
731743
status = {key: status[key] for key in keys}
732744

733745
for key in list(status.keys()):
734746
if len(status[key]) == 0:
735747
del status[key]
736748

749+
if args.list:
750+
assert len(status) == 1, "--list output only works if only one direction is selected."
751+
status = status[list(status.keys())[0]]
752+
737753
if args.output:
738-
if len(status) == 1:
739-
status = status[list(status.keys())[0]]
740754
yaml.dump(args.output, status, force=args.force)
741755
return
742756

743-
out = prettytable.PrettyTable()
744-
if args.table == "PLAIN_COLUMNS":
745-
out.set_style(prettytable.PLAIN_COLUMNS)
746-
elif args.table == "SINGLE_BORDER":
747-
out.set_style(prettytable.SINGLE_BORDER)
748-
out.field_names = ["source", "sync", "dest"]
749-
out.align["source"] = "l"
750-
out.align["sync"] = "c"
751-
out.align["dest"] = "l"
752-
753-
left = status.pop("->", [])
754-
right = status.pop("<-", [])
755-
equal = status.pop("==", [])
756-
757-
for key in status:
758-
for item in status[key]:
759-
out.add_row([item, key, item])
760-
761-
for item in left:
762-
out.add_row([item, "->", ""])
763-
764-
for item in right:
765-
out.add_row(["", "<-", item])
766-
767-
for item in equal:
768-
out.add_row([item, "==", item])
769-
770-
if args.sort is None:
771-
print(out.get_string())
772-
else:
773-
print(out.get_string(sortby=args.sort))
757+
output.diff(status, colors=args.colors)
774758

775759

776760
def _shelephant_main_parser():

‎shelephant/output.py‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ def diff(
192192
color = _theme(colors.lower())
193193
sio = io.StringIO()
194194

195+
if isinstance(status, list):
196+
sio.write("\n".join(status))
197+
if not display:
198+
return sio.getvalue()
199+
else:
200+
autoprint(sio.getvalue())
201+
195202
skip = status.pop("==", [])
196203
right = status.pop("->", [])
197204
left = status.pop("<-", [])
@@ -256,5 +263,5 @@ def diff(
256263

257264
if not display:
258265
return sio.getvalue()
259-
260-
autoprint(sio.getvalue())
266+
else:
267+
autoprint(sio.getvalue())

‎shelephant/rsync.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ def copy(
4949
cmd = 'rsync {options:s} --files-from="{files:s}" "{src:s}" "{dest:s}"'.format(
5050
options=options, src=str(source_dir), dest=str(dest_dir), files=temp_file
5151
)
52-
5352
return exec_cmd(cmd, verbose)
5453

5554
# Run while printing output

‎tests/test_cli.py‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ def test_output_filter_list(self):
636636
shelephant_dump(["-i"] + files)
637637
shelephant_hostinfo(["../dest", "-d", "--info"])
638638
args = [f_dump, f_hostinfo]
639-
shelephant_diff(args + ["-o", "foo.yaml", "--filter", "<-"])
639+
shelephant_diff(args + ["-o", "foo.yaml", "--filter", "<-", "--list"])
640640
data = shelephant.yaml.read("foo.yaml")
641641

642642
self.assertEqual(data, ["receive.txt"])
@@ -650,27 +650,28 @@ def test_table(self):
650650
pathlib.Path("dest").mkdir()
651651

652652
with cwd("dest"):
653-
create_dummy_files(["foo.txt"])
654-
create_dummy_files(["bar.txt"], keep=slice(2, None, None))
655-
create_dummy_files(["receive.txt"], keep=slice(6, None, None))
656-
shelephant_dump(["-i", "foo.txt", "bar.txt", "receive.txt"])
653+
files = ["foo.txt", "bar.txt", "receive.txt"]
654+
create_dummy_files([files[0]])
655+
create_dummy_files([files[1]], keep=slice(2, None, None))
656+
create_dummy_files([files[2]], keep=slice(6, None, None))
657+
shelephant_dump(["-i"] + files)
657658

658659
with cwd("src"):
659660
files = ["foo.txt", "bar.txt", "more.txt", "even_more.txt"]
660661
create_dummy_files(files)
661662
shelephant_dump(["-i"] + files)
662663
shelephant_hostinfo(["../dest", "-d"])
663-
shelephant_diff([f_dump, f_hostinfo, "--table", "PLAIN_COLUMNS"])
664+
shelephant_diff([f_dump, f_hostinfo, "--colors", "none"])
664665

665666
expect = [
666667
"bar.txt != bar.txt",
667-
"even_more.txt ->",
668-
"more.txt ->",
669-
"<- receive.txt",
668+
"receive.txt <- receive.txt",
669+
"even_more.txt -> even_more.txt",
670+
"more.txt -> more.txt",
670671
"foo.txt == foo.txt",
671672
]
672673

673-
ret = _plain(sio.getvalue())[1:]
674+
ret = _plain(sio.getvalue())
674675
self.assertEqual(ret, expect)
675676

676677

0 commit comments

Comments
 (0)