• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3#
4# Copyright (c) 2025 Huawei Device Co., Ltd.
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18from pathlib import Path
19from typing import ClassVar
20
21from runner.utils import write_2_file
22
23MustExist = bool
24PropName = str
25PropValue = str
26MandatoryProps = dict[PropName, tuple[PropValue | None, MustExist]]
27
28
29class InitRunner:
30    # Number of repeats to type a value for one variable
31    attempts: ClassVar[int] = 3
32    init_option: ClassVar[str] = "--init"
33    urunner_env_default: ClassVar[Path] = Path.home() / ".urunner.env"
34
35    def __init__(self, urunner_env: Path = urunner_env_default):
36        self.urunner_env_path: Path = urunner_env
37
38    @staticmethod
39    def input_value(prop: str, must_exist: bool, attempts: int) -> PropValue:
40        for i in range(1, attempts + 1):
41            main_text = f"Attempt #{i} of {attempts}: type the value of the mandatory variable {prop}: "
42            next_text = f"Empty or not-existing path are NOT suitable!\n{main_text}"
43            value = input(main_text if i == 1 else next_text)
44            if value and (Path(value).expanduser().exists() or not must_exist):
45                return value
46        raise FileNotFoundError(f"All {attempts} attempts to enter value for '{prop}' are out.")
47
48    @classmethod
49    def should_runner_initialize(cls, argv: list[str]) -> bool:
50        return cls.init_option in argv
51
52    def is_runner_initialized(self) -> bool:
53        return self.urunner_env_path.exists()
54
55    def initialize(self, mandatory_props: MandatoryProps) -> None:
56        """
57        Create a global environment file and save there the mandatory environment variables.
58        If any mandatory variable is not specified (None or empty) or does not exist but must,
59        it will ask the user to type path from the console
60        """
61        props: dict[PropName, PropValue] = {}
62        for prop, (value, must_exist) in mandatory_props.items():
63            if value is None:
64                props[prop] = self.init_property(prop, value, must_exist)
65            else:
66                props[prop] = value
67
68        result = [f"{prop}={value}" for prop, value in props.items()]
69        write_2_file(self.urunner_env_path, "\n".join(result))
70
71    def init_property(self, prop: str, value: str | None, must_exist: bool) -> str:
72        """
73        Initialize the property under name `prop` with provided `value`
74        if it is None - ask for user to type the value from the console
75        """
76        if value is None or len(value) == 0 or (not Path(value).expanduser().exists() and must_exist):
77            value = self.input_value(prop, must_exist, self.attempts)
78            path_value = Path(value).expanduser().resolve()
79            value = path_value.as_posix()
80        return value
81