Skip to content

Commit

Permalink
Move utility functions closer to usage (#870)
Browse files Browse the repository at this point in the history
* Inline add_verbosity_arg and remove unnecessary setting.

* Remove verbosity setting exclusive to remove.

* Inline helper function for chunking in update_cache.
  • Loading branch information
vyasr committed Dec 21, 2022
1 parent 444e1d2 commit a363e20
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 93 deletions.
21 changes: 10 additions & 11 deletions signac/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
_locate_config_dir,
_read_config_file,
)
from ._utility import _add_verbosity_argument, _print_err, _query_yes_no, _safe_relpath
from ._utility import _print_err, _query_yes_no, _safe_relpath
from ._vendor.configobj import Section, flatten_errors
from .diff import diff_jobs
from .errors import (
Expand Down Expand Up @@ -222,10 +222,10 @@ def main_remove(args):
continue
if args.clear:
job.clear()
logging.info("Cleared f{job_id}")
else:
job.remove()
if args.verbose:
print(job_id)
logging.info("Removing f{job_id}")


def main_move(args):
Expand Down Expand Up @@ -885,7 +885,13 @@ def main():
parser.add_argument(
"--version", action="store_true", help="Display the version number and exit."
)
_add_verbosity_argument(parser, default=2)
parser.add_argument(
"-v",
"--verbosity",
help="Set level of verbosity.",
action="count",
default=2,
)
parser.add_argument(
"-y",
"--yes",
Expand Down Expand Up @@ -1056,12 +1062,6 @@ def main():
action="store_true",
help="Request confirmation before attempting to remove/clear each job.",
)
parser_remove.add_argument(
"-v",
"--verbose",
action="store_true",
help="Be verbose when removing/clearing files.",
)
parser_remove.set_defaults(func=main_remove)

parser_move = subparsers.add_parser("move")
Expand Down Expand Up @@ -1300,7 +1300,6 @@ def main():
help="Optional: The directory of the project that should be modified for "
"synchronization, defaults to the local project.",
)
_add_verbosity_argument(parser_sync, default=2)

sync_group = parser_sync.add_argument_group("copy options")
sync_group.add_argument(
Expand Down
81 changes: 0 additions & 81 deletions signac/_utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import os.path
import sys
from collections.abc import Mapping
from datetime import timedelta
from time import time


def _print_err(*args, **kwargs):
Expand Down Expand Up @@ -76,32 +74,6 @@ def _query_yes_no(question, default="yes"): # pragma: no cover
print("Please respond with 'yes' or 'no' (or 'y' or 'n').")


def _add_verbosity_argument(parser, default=0):
"""Add a verbosity argument to parser.
Parameters
----------
parser : :class:`argparse.ArgumentParser`
The parser to which to add a verbosity argument.
default : int
The default level, defaults to 0.
Notes
-----
The argument is '-v' or '--verbosity'.
Add multiple '-v' arguments, e.g. '-vv' or '-vvv' to
increase the level of verbosity.
"""
parser.add_argument(
"-v",
"--verbosity",
help="Set level of verbosity.",
action="count",
default=default,
)


def _mkdir_p(path):
"""Make a new directory, or do nothing if the directory already exists.
Expand All @@ -119,59 +91,6 @@ def _mkdir_p(path):
os.makedirs(path, exist_ok=True)


def _split_and_print_progress(iterable, num_chunks=10, write=None, desc="Progress: "):
"""Split the progress and prints it.
Parameters
----------
iterable : list
List of values to be chunked.
num_chunks : int, optional
Number of chunks to split the given iterable (Default value = 10).
write : callable, optional
Callable used to log messages. If None, ``print`` is used (Default
value = None).
desc : str, optional
Prefix of message to log (Default value = 'Progress: ').
Yields
------
iterable
Raises
------
ValueError
If num_chunks <= 0.
"""
if num_chunks <= 0:
raise ValueError("num_chunks must be a positive integer.")
if write is None:
write = print
if num_chunks > 1:
N = len(iterable)
len_chunk = int(N / num_chunks)
intervals = []
show_est = False
for i in range(num_chunks - 1):
if i:
msg = f"{desc}{100 * i / num_chunks:3.0f}%"
if intervals:
mean_interval = sum(intervals) / len(intervals)
est_remaining = int(mean_interval * (num_chunks - i))
if est_remaining > 10 or show_est:
show_est = True
msg += f" (ETR: {timedelta(seconds=est_remaining)}h)"
write(msg)
start = time()
yield iterable[i * len_chunk : (i + 1) * len_chunk]
intervals.append(time() - start)
yield iterable[(i + 1) * len_chunk :]
write(f"{desc}100%")
else:
yield iterable


def _dotted_dict_to_nested_dicts(dotted_dict, delimiter_nested="."):
"""Convert dotted keys in the state point dict to a nested dict.
Expand Down
56 changes: 55 additions & 1 deletion signac/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from collections import defaultdict
from collections.abc import Iterable
from contextlib import contextmanager
from datetime import timedelta
from itertools import groupby
from multiprocessing.pool import ThreadPool
from tempfile import TemporaryDirectory
Expand All @@ -30,7 +31,7 @@
)
from ._search_indexer import _SearchIndexer
from ._synced_collections.backends.collection_json import BufferedJSONAttrDict
from ._utility import _mkdir_p, _nested_dicts_to_dotted_keys, _split_and_print_progress
from ._utility import _mkdir_p, _nested_dicts_to_dotted_keys
from .errors import (
DestinationExistsError,
IncompatibleSchemaVersion,
Expand All @@ -50,6 +51,59 @@
JOB_ID_REGEX = re.compile(f"[a-f0-9]{{{JOB_ID_LENGTH}}}")


def _split_and_print_progress(iterable, num_chunks=10, write=None, desc="Progress: "):
"""Split the progress and prints it.
Parameters
----------
iterable : list
List of values to be chunked.
num_chunks : int, optional
Number of chunks to split the given iterable (Default value = 10).
write : callable, optional
Callable used to log messages. If None, ``print`` is used (Default
value = None).
desc : str, optional
Prefix of message to log (Default value = 'Progress: ').
Yields
------
iterable
Raises
------
ValueError
If num_chunks <= 0.
"""
if num_chunks <= 0:
raise ValueError("num_chunks must be a positive integer.")
if write is None:
write = print
if num_chunks > 1:
N = len(iterable)
len_chunk = int(N / num_chunks)
intervals = []
show_est = False
for i in range(num_chunks - 1):
if i:
msg = f"{desc}{100 * i / num_chunks:3.0f}%"
if intervals:
mean_interval = sum(intervals) / len(intervals)
est_remaining = int(mean_interval * (num_chunks - i))
if est_remaining > 10 or show_est:
show_est = True
msg += f" (ETR: {timedelta(seconds=est_remaining)}h)"
write(msg)
start = time.time()
yield iterable[i * len_chunk : (i + 1) * len_chunk]
intervals.append(time.time() - start)
yield iterable[(i + 1) * len_chunk :]
write(f"{desc}100%")
else:
yield iterable


class _ProjectConfig(_Config):
r"""Extends the project config to make it immutable.
Expand Down

0 comments on commit a363e20

Please sign in to comment.