1*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2024, The Android Open Source Project 2*c2e18aaaSAndroid Build Coastguard Worker# 3*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*c2e18aaaSAndroid Build Coastguard Worker# 7*c2e18aaaSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*c2e18aaaSAndroid Build Coastguard Worker# 9*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License. 14*c2e18aaaSAndroid Build Coastguard Worker 15*c2e18aaaSAndroid Build Coastguard Worker"""Classes used to handle banners.""" 16*c2e18aaaSAndroid Build Coastguard Worker 17*c2e18aaaSAndroid Build Coastguard Workerfrom __future__ import annotations 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard Workerfrom datetime import date 20*c2e18aaaSAndroid Build Coastguard Workerimport json 21*c2e18aaaSAndroid Build Coastguard Workerimport logging 22*c2e18aaaSAndroid Build Coastguard Workerfrom pathlib import Path 23*c2e18aaaSAndroid Build Coastguard Workerfrom typing import Any, Callable 24*c2e18aaaSAndroid Build Coastguard Worker 25*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_utils 26*c2e18aaaSAndroid Build Coastguard Workerfrom atest import constants 27*c2e18aaaSAndroid Build Coastguard Worker 28*c2e18aaaSAndroid Build Coastguard Worker 29*c2e18aaaSAndroid Build Coastguard Workerclass BannerHistory: 30*c2e18aaaSAndroid Build Coastguard Worker """A history for banner handling.""" 31*c2e18aaaSAndroid Build Coastguard Worker 32*c2e18aaaSAndroid Build Coastguard Worker _LAST_BANNER_PROMPT_DATE = 'last_banner_prompt_date' 33*c2e18aaaSAndroid Build Coastguard Worker 34*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 35*c2e18aaaSAndroid Build Coastguard Worker def create(config_dir: Path) -> BannerHistory: 36*c2e18aaaSAndroid Build Coastguard Worker config_dir.mkdir(parents=True, exist_ok=True) 37*c2e18aaaSAndroid Build Coastguard Worker history_file = config_dir.joinpath('banner.json') 38*c2e18aaaSAndroid Build Coastguard Worker 39*c2e18aaaSAndroid Build Coastguard Worker if not history_file.exists(): 40*c2e18aaaSAndroid Build Coastguard Worker history_file.touch() 41*c2e18aaaSAndroid Build Coastguard Worker history = {} 42*c2e18aaaSAndroid Build Coastguard Worker else: 43*c2e18aaaSAndroid Build Coastguard Worker try: 44*c2e18aaaSAndroid Build Coastguard Worker history = json.loads(history_file.read_text()) 45*c2e18aaaSAndroid Build Coastguard Worker except json.JSONDecodeError as e: 46*c2e18aaaSAndroid Build Coastguard Worker atest_utils.print_and_log_error( 47*c2e18aaaSAndroid Build Coastguard Worker 'Banner history json file is in a bad format: %s', e 48*c2e18aaaSAndroid Build Coastguard Worker ) 49*c2e18aaaSAndroid Build Coastguard Worker history = {} 50*c2e18aaaSAndroid Build Coastguard Worker 51*c2e18aaaSAndroid Build Coastguard Worker return BannerHistory(history_file, history) 52*c2e18aaaSAndroid Build Coastguard Worker 53*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, history_file: Path, history: dict): 54*c2e18aaaSAndroid Build Coastguard Worker self._history_file = history_file 55*c2e18aaaSAndroid Build Coastguard Worker self._history = history 56*c2e18aaaSAndroid Build Coastguard Worker 57*c2e18aaaSAndroid Build Coastguard Worker def get_last_banner_prompt_date(self) -> str: 58*c2e18aaaSAndroid Build Coastguard Worker """Get the last date when banner was prompt.""" 59*c2e18aaaSAndroid Build Coastguard Worker return self._history.get(BannerHistory._LAST_BANNER_PROMPT_DATE, '') 60*c2e18aaaSAndroid Build Coastguard Worker 61*c2e18aaaSAndroid Build Coastguard Worker def set_last_banner_prompt_date(self, date: str): 62*c2e18aaaSAndroid Build Coastguard Worker """Set the last date when banner was prompt.""" 63*c2e18aaaSAndroid Build Coastguard Worker self._history[BannerHistory._LAST_BANNER_PROMPT_DATE] = date 64*c2e18aaaSAndroid Build Coastguard Worker self._history_file.write_text(json.dumps(self._history)) 65*c2e18aaaSAndroid Build Coastguard Worker 66*c2e18aaaSAndroid Build Coastguard Worker 67*c2e18aaaSAndroid Build Coastguard Workerclass BannerPrinter: 68*c2e18aaaSAndroid Build Coastguard Worker """A printer used to collect and print banners.""" 69*c2e18aaaSAndroid Build Coastguard Worker 70*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 71*c2e18aaaSAndroid Build Coastguard Worker def create() -> BannerPrinter: 72*c2e18aaaSAndroid Build Coastguard Worker return BannerPrinter(atest_utils.get_config_folder()) 73*c2e18aaaSAndroid Build Coastguard Worker 74*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, config_dir: Path): 75*c2e18aaaSAndroid Build Coastguard Worker self._messages = [] 76*c2e18aaaSAndroid Build Coastguard Worker self._config_dir = config_dir 77*c2e18aaaSAndroid Build Coastguard Worker 78*c2e18aaaSAndroid Build Coastguard Worker def register(self, message: str): 79*c2e18aaaSAndroid Build Coastguard Worker """Register a banner message.""" 80*c2e18aaaSAndroid Build Coastguard Worker self._messages.append(message) 81*c2e18aaaSAndroid Build Coastguard Worker 82*c2e18aaaSAndroid Build Coastguard Worker def print(self, print_func: Callable = None, date_supplier: Callable = None): 83*c2e18aaaSAndroid Build Coastguard Worker """Print the banners.""" 84*c2e18aaaSAndroid Build Coastguard Worker 85*c2e18aaaSAndroid Build Coastguard Worker if not self._messages: 86*c2e18aaaSAndroid Build Coastguard Worker return 87*c2e18aaaSAndroid Build Coastguard Worker 88*c2e18aaaSAndroid Build Coastguard Worker if not print_func: 89*c2e18aaaSAndroid Build Coastguard Worker print_func = lambda m: atest_utils.colorful_print(m, constants.MAGENTA) 90*c2e18aaaSAndroid Build Coastguard Worker 91*c2e18aaaSAndroid Build Coastguard Worker if not date_supplier: 92*c2e18aaaSAndroid Build Coastguard Worker date_supplier = lambda: str(date.today()) 93*c2e18aaaSAndroid Build Coastguard Worker 94*c2e18aaaSAndroid Build Coastguard Worker today = date_supplier() 95*c2e18aaaSAndroid Build Coastguard Worker history = BannerHistory.create(self._config_dir) 96*c2e18aaaSAndroid Build Coastguard Worker if history.get_last_banner_prompt_date() != today: 97*c2e18aaaSAndroid Build Coastguard Worker for message in self._messages: 98*c2e18aaaSAndroid Build Coastguard Worker print_func(message) 99*c2e18aaaSAndroid Build Coastguard Worker 100*c2e18aaaSAndroid Build Coastguard Worker history.set_last_banner_prompt_date(today) 101