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