Source code for esptest.config.env_config

import logging
import os
import pathlib
import sys
from typing import Any, List, Optional

import yaml

VAR_NAME_MAPPING = {
    'ap_ssid': ['RUNNER_WIFI_SSID', 'RUNNER_AP_SSID'],
    'ap_password': ['RUNNER_WIFI_PASSWORD', 'RUNNER_AP_PASSWORD'],
    'pc_nic': ['RUNNER_PC_NIC'],
    'dut1': ['ESPPORT1'],
    'dut2': ['ESPPORT2'],
    'dut3': ['ESPPORT3'],
}


[docs] def get_variable_from_env(key: str) -> Any: """Get test variable from shell environment Args: key (str): which variable to get """ if key in VAR_NAME_MAPPING: for var_name in VAR_NAME_MAPPING[key]: var = os.getenv(var_name) if var is not None: logging.debug(f'Got env variable from shell env {var_name}: {var}') return var return None
[docs] class EnvConfig: """Get test environment variables from config file. By default the config file is named "EnvConfig.yml" and put in one of those folders: - env variables: TEST_ENV_CONFIG_DIR - Current working directory - project root directory - ci-test-runner-configs (with runner description) under project root directory - <HOME>/test_env_config/ # non-win32 Support input variables from console if run tests locally other than CI. Example usage: ```python env_config = EnvConfig(env_tag='my_env') var1 = env_config.get_variable('var1') ``` """ # Set env config file directly ENV_CONFIG_FILE_BASE_NAME = 'EnvConfig.yml' TEST_ENV_CONFIG_FILE = os.getenv('TEST_ENV_CONFIG_FILE', '') # Find env config file from project root path # CI_PROJECT_DIR was set by gitlab CI PROJECT_ROOT_DIR = os.getenv('PROJECT_ROOT_DIR') or os.getenv('CI_PROJECT_DIR', '') # allow EnvConfig load shell env variables, default enabled DISABLE_LOAD_SHELL_ENV = os.getenv('ESPTEST_DISABLE_LOAD_SHELL_ENV', '').lower() in ('true', '1', 'yes', 'y') # Allow input variables from terminal during local debugging ALLOW_INPUT = not os.getenv('CI') def __init__(self, env_tag: str = 'default', config_file: Optional[str] = None) -> None: self.env_tag = env_tag if config_file: self.config_file = config_file else: self.config_file = self._get_config_file() self.config_data = {} if self.config_file: if os.path.isfile(self.config_file): with open(self.config_file, 'r', encoding='utf-8') as f: raw_data = yaml.load(f.read(), Loader=yaml.FullLoader) assert isinstance(raw_data, dict) assert env_tag in raw_data assert isinstance(raw_data[env_tag], dict) self.config_data = raw_data[env_tag] elif not self.ALLOW_INPUT: raise FileNotFoundError(f'Could not optn config file: {self.config_file}') else: pass @classmethod def _reload(cls) -> None: """Reload to accept new environment variables. Mainly used in unit tests.""" cls.TEST_ENV_CONFIG_FILE = os.getenv('TEST_ENV_CONFIG_FILE', '') cls.PROJECT_ROOT_DIR = os.getenv('PROJECT_ROOT_DIR') or os.getenv('CI_PROJECT_DIR') cls.ALLOW_INPUT = not os.getenv('CI') @classmethod def _search_dirs(cls) -> List[str]: search_dirs = [] # Add current directory search_dirs.append(pathlib.Path('.')) # Add project root directory if cls.PROJECT_ROOT_DIR: _proj_path = pathlib.Path(cls.PROJECT_ROOT_DIR) search_dirs.append(_proj_path) search_dirs.append(_proj_path / 'ci-test-runner-configs' / os.environ.get('CI_RUNNER_DESCRIPTION', '.')) # Add home directory if sys.platform != 'win32': search_dirs.append(pathlib.Path.home() / 'test_env_config') return [str(d) for d in search_dirs if d.is_dir()] @classmethod def _get_config_file(cls) -> str: config_file = '' if cls.TEST_ENV_CONFIG_FILE: return cls.TEST_ENV_CONFIG_FILE for _dir in cls._search_dirs(): if cls.ENV_CONFIG_FILE_BASE_NAME not in os.listdir(_dir): continue config_file = os.path.join(_dir, cls.ENV_CONFIG_FILE_BASE_NAME) if not config_file: _msg = 'Can not find env config file from:\n ' + ' \n'.join(cls._search_dirs()) logging.warning(_msg) if not cls.ALLOW_INPUT: raise FileNotFoundError(f'Could not find config file: {cls.ENV_CONFIG_FILE_BASE_NAME}') # For local test we support input variables from console return '' return config_file
[docs] def get_variable(self, key: str, default: Any = None) -> Any: """Get environment variable Args: key (str): which variable to get default (Any, optional): default variable if the key not in config file. Raises: ValueError: raise Error if the key is not in config file and default is not given. Returns: Any: variable value """ var = None # do not use dict.get because we can input the variable for local tests if key in self.config_data: var = self.config_data[key] elif default is not None: var = default else: if not self.DISABLE_LOAD_SHELL_ENV: # Try to get from shell environment variables var = get_variable_from_env(key) if var is None: logging.warning(f'Failed to get env variable {self.env_tag}/{key}.') logging.info(self.__doc__) if not self.ALLOW_INPUT: raise ValueError(f'Env variable not found: {self.env_tag}/{key}') # For local test, support input the variable from console var = input('You can input the variable now:') logging.debug(f'Got env variable {self.env_tag}/{key}: {var}') return var