Skip to content

Commit 05d8e0c

Browse files
authored
Merge pull request #1514 from cmu-delphi/delete-validation-failures
Delete validation failures
2 parents b712169 + df8fd83 commit 05d8e0c

File tree

4 files changed

+57
-3
lines changed

4 files changed

+57
-3
lines changed

_delphi_utils_python/delphi_utils/runner.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from typing import Any, Callable, Dict, Optional
55
from .archive import ArchiveDiffer, archiver_from_params
66
from .logger import get_structured_logger
7-
from .utils import read_params, transfer_files
7+
from .utils import read_params, transfer_files, delete_move_files
88
from .validator.validate import Validator
99
from .validator.run import validator_from_params
1010

@@ -46,6 +46,9 @@ def run_indicator_pipeline(indicator_fn: Callable[[Params], None],
4646
if validator:
4747
validation_report = validator.validate()
4848
validation_report.log(logger)
49+
# Validators on dry-run always return success
50+
if not validation_report.success():
51+
delete_move_files()
4952
if (not validator or validation_report.success()):
5053
if archiver:
5154
archiver.run(logger)

_delphi_utils_python/delphi_utils/utils.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,33 @@ def transfer_files():
9595
delivery_dir = params["delivery"].get("delivery_dir", None)
9696
files_to_export = os.listdir(export_dir)
9797
for file_name in files_to_export:
98+
if file_name.lower().endswith(".csv"):
99+
move(os.path.join(export_dir, file_name), os.path.join(delivery_dir, file_name))
100+
101+
def delete_move_files():
102+
"""Delete or move output files depending on dir settings provided in params.
103+
104+
1. Delete files in export-dir if delivery-dir is specified and is different
105+
from export_dir (aka only delete files produced by the most recent run)
106+
2. If validation-failures-dir is specified, move failed files there instead
107+
If dry-run tag is True, then this function should not (and currently does not) get called
108+
"""
109+
params = read_params()
110+
export_dir = params["common"].get("export_dir", None)
111+
delivery_dir = params["delivery"].get("delivery_dir", None)
112+
validation_failure_dir = params["validation"]["common"].get("validation_failure_dir", None)
113+
# Create validation_failure_dir if it doesn't exist
114+
if (validation_failure_dir is not None) and (not os.path.exists(validation_failure_dir)):
115+
os.mkdir(validation_failure_dir)
116+
# Double-checking that export-dir is not delivery-dir
117+
# Throw assertion error if delivery_dir or export_dir is unspecified
118+
assert(delivery_dir is not None and export_dir is not None)
119+
assert export_dir != delivery_dir
120+
files_to_delete = os.listdir(export_dir)
121+
for file_name in files_to_delete:
98122
if file_name.endswith(".csv") or file_name.endswith(".CSV"):
99-
move(os.path.join(export_dir, file_name), delivery_dir)
123+
if validation_failure_dir is not None:
124+
move(os.path.join(export_dir, file_name),
125+
os.path.join(validation_failure_dir, file_name))
126+
else:
127+
os.remove(os.path.join(export_dir, file_name))

_delphi_utils_python/delphi_utils/validator/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,27 @@ deactivate
4343
rm -r env
4444
```
4545

46+
### Using the runner
47+
48+
The validator can also be called using the runner, which performs the entire pipeline:
49+
50+
1. Calling the indicator's `run` module
51+
2. Running the validator on newly obtained CSV files, if validator is specified
52+
3. If validation is unsuccessful, remove or transfer current files in the run
53+
4. Archive files if archiver is specified and there are no validation failures
54+
5. Transfer files to delivery directory if specified in params
55+
56+
The following truth table describes behavior of item (3):
57+
58+
| case | dry_run | validation failure | export dir | delivery dir | v failure dir | action |
59+
| - | - | - | - | - | - | - |
60+
| 1 | true | never | * | * | * | no effect |
61+
| 2 | false | no | * | * | * | no effect |
62+
| 3 | false | yes | X | X | * | throw assertion exception |
63+
| 4 | false | yes | X | None | * | throw assertion exception |
64+
| 5 | false | yes | X | Y != X | None | delete CSV from X |
65+
| 6 | false | yes | X | Y != X | Z | move CSV from X to Z |
66+
4667
### Customization
4768

4869
All of the user-changable parameters are stored in the `validation` field of the indicator's `params.json` file. If `params.json` does not already include a `validation` field, please copy that provided in this module's `params.json.template`.

_delphi_utils_python/tests/test_runner.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ def test_full_run(self, mock_read_params,
5555
mock_validator_fn.return_value.validate.assert_called_once()
5656
mock_archiver_fn.return_value.run.assert_called_once()
5757

58+
@mock.patch("delphi_utils.runner.delete_move_files")
5859
@mock.patch("delphi_utils.runner.read_params")
59-
def test_failed_validation(self, mock_read_params,
60+
def test_failed_validation(self, mock_read_params, mock_delete_move_files,
6061
mock_indicator_fn, mock_validator_fn, mock_archiver_fn):
6162
"""Test that archiving is not called when validation fails."""
6263
mock_read_params.return_value = self.PARAMS
@@ -65,6 +66,7 @@ def test_failed_validation(self, mock_read_params,
6566

6667
run_indicator_pipeline(mock_indicator_fn, mock_validator_fn, mock_archiver_fn)
6768

69+
mock_delete_move_files.assert_called_once()
6870
mock_indicator_fn.assert_called_once_with(self.PARAMS)
6971
mock_validator_fn.assert_called_once_with(self.PARAMS)
7072
mock_archiver_fn.assert_called_once_with(self.PARAMS)

0 commit comments

Comments
 (0)