From af251a19c623dc371c959c75e823ef11aeeccdf2 Mon Sep 17 00:00:00 2001 From: Dmitrii Agibov Date: Wed, 15 Feb 2023 09:08:14 +0000 Subject: MLIA-813 Change default output directory - If no output directory provided then create one in the current working directory - Update documentation and tests Change-Id: Id1f2acef14e1bd2edffbfa6139a961a5c5018211 --- .gitignore | 2 +- src/mlia/cli/options.py | 4 ++-- src/mlia/core/context.py | 35 ++++++++++++++++++++++++----------- tests/test_cli_main.py | 4 ++-- tests/test_core_context.py | 37 ++++++++++++++++++++++++++++++++++--- 5 files changed, 63 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index ddb2afe..f6282e7 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ src/*.egg-info .vscode venv e2e_config -mlia_output +mlia-output report .ipynb_checkpoints .tox diff --git a/src/mlia/cli/options.py b/src/mlia/cli/options.py index b16f77f..d40aa88 100644 --- a/src/mlia/cli/options.py +++ b/src/mlia/cli/options.py @@ -233,8 +233,8 @@ def add_output_directory(parser: argparse.ArgumentParser) -> None: type=Path, help="Path to the directory where MLIA " "stores artifacts, e.g. logs, target profiles and model files. " - "If not specified then MLIA will use temporary " - "directory instead.", + "If not specified then MLIA will use " + "directory 'mlia-output' in the current working directory instead.", ) diff --git a/src/mlia/core/context.py b/src/mlia/core/context.py index c0267f1..e8c8a2c 100644 --- a/src/mlia/core/context.py +++ b/src/mlia/core/context.py @@ -10,9 +10,9 @@ parameters). from __future__ import annotations import logging -import tempfile from abc import ABC from abc import abstractmethod +from datetime import datetime from pathlib import Path from typing import Any from typing import Mapping @@ -97,6 +97,18 @@ class Context(ABC): self.event_publisher.register_event_handlers(self.event_handlers) +def create_output_dir_with_timestamp() -> Path: + """Generate output directory for the MLIA.""" + base_dir = Path.cwd() / "mlia-output" + base_dir.mkdir(exist_ok=True) + + timestamp = datetime.now().isoformat().replace(":", "") + output_dir = base_dir / f"mlia-output-{timestamp}" + output_dir.mkdir() + + return output_dir + + class ExecutionContext(Context): """Execution context.""" @@ -120,7 +132,7 @@ class ExecutionContext(Context): :param config_parameters: dictionary like object with input parameters :param output_dir: path to the directory that will be used as a place to store temporary files, logs, models. If not provided then - temporary directory will be used instead + autogenerated directory will be used instead :param event_handlers: optional list of event handlers :param event_publisher: optional event publisher instance. If not provided then default implementation of event publisher will be used @@ -131,15 +143,12 @@ class ExecutionContext(Context): temporary models will be stored :param action_resolver: instance of the action resolver that could make advice actionable + :param output_format: format for the application output """ self._advice_category = advice_category or {AdviceCategory.COMPATIBILITY} self._config_parameters = config_parameters - if output_dir: - self._output_dir_path = Path(output_dir) - self._output_dir_path.mkdir(exist_ok=True) - else: - self._output_dir_path = generate_temp_output_dir() + self._init_output_directory(output_dir) self._event_handlers = event_handlers self._event_publisher = event_publisher or DefaultEventPublisher() @@ -239,8 +248,12 @@ class ExecutionContext(Context): f"output_format={self.output_format}" ) + def _init_output_directory(self, output_dir: str | Path | None) -> None: + """Init output directory for the execution.""" + if output_dir: + output_dir_path = Path(output_dir) + output_dir_path.mkdir(exist_ok=True) + else: + output_dir_path = create_output_dir_with_timestamp() -def generate_temp_output_dir() -> Path: - """Generate a temporary output dir and returns the path.""" - output_dir = tempfile.mkdtemp(suffix=None, prefix="mlia-", dir=None) - return Path(output_dir) + self._output_dir_path = output_dir_path diff --git a/tests/test_cli_main.py b/tests/test_cli_main.py index 3472e31..c129c4b 100644 --- a/tests/test_cli_main.py +++ b/tests/test_cli_main.py @@ -311,7 +311,7 @@ def test_commands_execution_backend_main( MagicMock(side_effect=Exception("Error")), [ "Execution finished with error: Error", - "Please check the log files in the /tmp/mlia-", + "Please check the log files in the", "/logs for more details", ], ], @@ -320,7 +320,7 @@ def test_commands_execution_backend_main( MagicMock(side_effect=Exception("Error")), [ "Execution finished with error: Error", - "Please check the log files in the /tmp/mlia-", + "Please check the log files in the", "/logs for more details, or enable debug mode (--debug)", ], ], diff --git a/tests/test_core_context.py b/tests/test_core_context.py index 814cb6a..09b34e9 100644 --- a/tests/test_core_context.py +++ b/tests/test_core_context.py @@ -3,13 +3,16 @@ """Tests for the module context.""" from __future__ import annotations +import re from pathlib import Path import pytest from mlia.core.common import AdviceCategory +from mlia.core.context import create_output_dir_with_timestamp from mlia.core.context import ExecutionContext from mlia.core.events import DefaultEventPublisher +from mlia.utils.filesystem import working_directory @pytest.mark.parametrize( @@ -39,9 +42,8 @@ def test_execution_context_category_enabled( ) -> None: """Test category enabled method of execution context.""" for category in expected_enabled_categories: - assert ExecutionContext( - advice_category=context_advice_category - ).category_enabled(category) + ctx = ExecutionContext(advice_category=context_advice_category) + assert ctx.category_enabled(category) def test_execution_context(tmpdir: str) -> None: @@ -79,6 +81,9 @@ def test_execution_context(tmpdir: str) -> None: "output_format=json" ) + +def test_execution_context_with_default_params(tmpdir: str) -> None: + """Test execution context with the default parameters.""" context_with_default_params = ExecutionContext(output_dir=tmpdir) assert context_with_default_params.advice_category == {AdviceCategory.COMPATIBILITY} assert context_with_default_params.config_parameters is None @@ -101,3 +106,29 @@ def test_execution_context(tmpdir: str) -> None: "output_format=plain_text" ) assert str(context_with_default_params) == expected_str + + +def test_create_output_dir_with_timestamp(tmp_path: Path) -> None: + """Test function generate_output_dir_with_timestamp.""" + working_dir = tmp_path / "sample" + with working_directory(working_dir, create_dir=True): + create_output_dir_with_timestamp() + + working_dir_content = list(working_dir.iterdir()) + assert len(working_dir_content) == 1 + + parent_dir = working_dir_content[0] + assert parent_dir.is_dir() + assert parent_dir.name == "mlia-output" + + parent_dir_content = list(parent_dir.iterdir()) + assert len(parent_dir_content) == 1 + + output_dir = parent_dir_content[0] + assert output_dir.is_dir() + + pattern = re.compile(r"mlia-output-\d{4}-\d{2}-\d{2}T\d+[.]\d+") + assert pattern.match(output_dir.name) + + output_dir_content = list(output_dir.iterdir()) + assert not output_dir_content -- cgit v1.2.1