Skip to content

Commit

Permalink
add 'remove_on' argument (#464)
Browse files Browse the repository at this point in the history
* add 'remove_on' argument

* update docstring
  • Loading branch information
PythonFZ authored Dec 15, 2022
1 parent 8f00611 commit c48a4bf
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 1 deletion.
25 changes: 25 additions & 0 deletions tests/integration_tests/test_operating_directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,37 @@ def run(self):
self.file.write_text(f"{text} there")


class RemoveOnError(Node):
data: list = zn.outs()

def run(self):
with self.operating_directory(remove_on=(TypeError, ValueError)):
raise ValueError("Execution was interrupted")


def test_remove_on_error(proj_path):
node = RemoveOnError()
node.write_graph()

node = RemoveOnError.load()
with pytest.raises(ValueError):
node.run_and_save()

nwd_new = node.nwd.with_name(f"ckpt_{node.nwd.name}")
assert not nwd_new.exists()


def test_ListOfDataNode(proj_path):
ListOfDataNode().write_graph()

node = ListOfDataNode.load()

with pytest.raises(exceptions.DVCProcessError):
utils.run_dvc_cmd(["repro"])
nwd_new = node.nwd.with_name(f"ckpt_{node.nwd.name}")
assert nwd_new.exists()
utils.run_dvc_cmd(["repro"])
assert not nwd_new.exists()

assert ListOfDataNode.load().data == list(range(10))

Expand Down
25 changes: 24 additions & 1 deletion zntrack/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@

log = logging.getLogger(__name__)

EXCEPTION_OR_LST_EXCEPTIONS = typing.Union[
typing.Type[Exception], typing.Collection[typing.Type[Exception]]
]


def update_dependency_options(value):
"""Handle Node dependencies.
Expand Down Expand Up @@ -666,7 +670,9 @@ def write_graph( # noqa: C901
utils.run_dvc_cmd(["repro", self.node_name])

@contextlib.contextmanager
def operating_directory(self, prefix="ckpt") -> bool:
def operating_directory(
self, prefix="ckpt", remove_on: EXCEPTION_OR_LST_EXCEPTIONS = None
) -> bool:
"""Work in an operating directory until successfully finished.
This context manager will replace $nwd$ with 'prefix_$nwd$' and move the files
Expand All @@ -680,6 +686,14 @@ def operating_directory(self, prefix="ckpt") -> bool:
- checkpoints are not versioned. If you want to checkpoint e.g., model training,
use 'dvc checkpoints'.
Parameters
----------
prefix: str, default = 'ckpt'
Prefix for the temporary directory
remove_on: Exception or list of Exceptions, default = None
If one of the exceptions in 'remove_on' is raised, the operating directory
will be removed. Otherwise, it will remain and reused upton the next run.
Yields
------
Expand All @@ -690,6 +704,10 @@ def operating_directory(self, prefix="ckpt") -> bool:
nwd_new = self.nwd.with_name(f"{prefix}_{self.nwd.name}")
nwd_is_new = not nwd_new.exists()

remove = False
if not isinstance(remove_on, list):
remove_on = [remove_on] if remove_on else []

if self._run_and_save:
utils.update_gitignore(prefix=prefix)

Expand All @@ -710,11 +728,16 @@ def operating_directory(self, prefix="ckpt") -> bool:
yield nwd_is_new
except Exception as err:
log.warning("Node execution was interrupted.")
if any(isinstance(err, e) for e in remove_on):
remove = True
raise err
finally:
# Save e.g. `zn.outs` before stopping.
self.save(results=True)
self.nwd = nwd
if remove:
log.info(f"Removing operating directory: {nwd_new}")
shutil.rmtree(nwd_new)

log.info(f"Finished successfully. Moving files from {nwd_new} to {nwd}")
shutil.rmtree(nwd)
Expand Down

3 comments on commit c48a4bf

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Report for Python 3.9

name min max mean stddev median iqr outliers ops rounds iterations
0 tests/benchmark/test_benchmark.py::test_InputOutput_load 0.000110603 0.00041411 0.000113106 9.04174e-06 0.000112302 7e-07 19;100 8841.3 1361 1
1 tests/benchmark/test_benchmark.py::test_InputOutput_load_lazy 0.000111803 0.0129666 0.000124974 0.000356793 0.000113102 6.01e-07 2;107 8001.64 1330 1
2 tests/benchmark/test_benchmark.py::test_NodeCollector_load 0.000112103 0.0102555 0.000123088 0.000288815 0.000113602 8e-07 2;98 8124.24 1236 1
3 tests/benchmark/test_benchmark.py::test_NodeCollector_load_lazy 0.000112703 0.00949323 0.000126573 0.000292172 0.000114203 6.99e-07 2;106 7900.57 1181 1
4 tests/benchmark/test_benchmark.py::test_NodeCollector_run_and_save 0.000312507 0.00100993 0.000354045 0.000101976 0.000322008 3.34015e-05 2;6 2824.5 52 1
5 tests/benchmark/test_benchmark.py::test_InputOutput_write_graph 0.00149194 0.0819165 0.0017782 0.00410317 0.00155318 5.32415e-05 1;29 562.365 384 1
6 tests/benchmark/test_benchmark.py::test_InputOutput_run_and_save 0.00161364 0.00375069 0.00173299 0.00021373 0.00169804 7.2002e-05 9;21 577.036 310 1
7 tests/benchmark/test_benchmark.py::test_NodeCollector_write_graph 0.155223 0.438597 0.277917 0.124964 0.227253 0.216833 1;0 3.5982 5 1

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Report for Python 3.8

name min max mean stddev median iqr outliers ops rounds iterations
0 tests/benchmark/test_benchmark.py::test_InputOutput_load_lazy 0.000107902 0.00079481 0.000131848 6.76415e-05 0.000109501 1.2e-06 140;218 7584.51 1307 1
1 tests/benchmark/test_benchmark.py::test_InputOutput_load 0.000108601 0.000137702 0.000110412 2.17709e-06 0.000110002 9e-07 67;80 9056.97 1273 1
2 tests/benchmark/test_benchmark.py::test_NodeCollector_load 0.000110101 0.000572607 0.000113455 1.42275e-05 0.000112102 1.1505e-06 22;97 8814.09 1212 1
3 tests/benchmark/test_benchmark.py::test_NodeCollector_load_lazy 0.000111801 0.000140302 0.000114039 2.59988e-06 0.000113501 9.2575e-07 63;101 8768.97 1261 1
4 tests/benchmark/test_benchmark.py::test_NodeCollector_run_and_save 0.000310004 0.00316064 0.000424426 0.000392667 0.000345005 7.2976e-05 1;5 2356.12 53 1
5 tests/benchmark/test_benchmark.py::test_InputOutput_write_graph 0.00150752 0.0776233 0.00176847 0.00397197 0.00154312 3.5875e-05 1;24 565.461 367 1
6 tests/benchmark/test_benchmark.py::test_InputOutput_run_and_save 0.00163322 0.00262953 0.00173943 9.68968e-05 0.00171817 5.8951e-05 28;24 574.902 336 1
7 tests/benchmark/test_benchmark.py::test_NodeCollector_write_graph 0.177796 0.323425 0.251272 0.0527623 0.245282 0.0593543 2;0 3.97975 5 1

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Report for Python 3.10

name min max mean stddev median iqr outliers ops rounds iterations
0 tests/benchmark/test_benchmark.py::test_NodeCollector_load 9.7301e-05 0.00288044 0.000139034 0.000105886 0.000122101 3.30757e-05 34;76 7192.49 1043 1
1 tests/benchmark/test_benchmark.py::test_InputOutput_load_lazy 0.000102402 0.0086524 0.00015952 0.000366489 0.000124001 3.4051e-05 9;62 6268.79 965 1
2 tests/benchmark/test_benchmark.py::test_NodeCollector_load_lazy 0.000102702 0.000993113 0.000141212 4.59512e-05 0.000126951 3.14e-05 80;63 7081.56 886 1
3 tests/benchmark/test_benchmark.py::test_InputOutput_load 0.000106401 0.00107771 0.000144213 6.85293e-05 0.000124151 3.3501e-05 66;79 6934.18 1048 1
4 tests/benchmark/test_benchmark.py::test_NodeCollector_run_and_save 0.000423905 0.00941192 0.00137607 0.00186009 0.000587908 0.000443705 8;10 726.708 54 1
5 tests/benchmark/test_benchmark.py::test_InputOutput_write_graph 0.0016763 0.00621501 0.00222351 0.000477528 0.0021426 0.00036015 18;10 449.739 271 1
6 tests/benchmark/test_benchmark.py::test_InputOutput_run_and_save 0.0019119 0.0112039 0.00259367 0.000890662 0.0024093 0.000363501 14;19 385.555 250 1
7 tests/benchmark/test_benchmark.py::test_NodeCollector_write_graph 0.194211 0.395266 0.284328 0.0723026 0.271799 0.0683585 2;0 3.51706 5 1

Please sign in to comment.