1bf215546Sopenharmony_cifrom __future__ import annotations 2bf215546Sopenharmony_ci 3bf215546Sopenharmony_ciimport re 4bf215546Sopenharmony_cifrom dataclasses import dataclass, field 5bf215546Sopenharmony_cifrom datetime import datetime, timedelta 6bf215546Sopenharmony_cifrom typing import TYPE_CHECKING, Optional 7bf215546Sopenharmony_ci 8bf215546Sopenharmony_cifrom lava.utils.console_format import CONSOLE_LOG 9bf215546Sopenharmony_ci 10bf215546Sopenharmony_ciif TYPE_CHECKING: 11bf215546Sopenharmony_ci from lava.utils.log_section import LogSectionType 12bf215546Sopenharmony_ci 13bf215546Sopenharmony_ci 14bf215546Sopenharmony_ci@dataclass 15bf215546Sopenharmony_ciclass GitlabSection: 16bf215546Sopenharmony_ci id: str 17bf215546Sopenharmony_ci header: str 18bf215546Sopenharmony_ci type: LogSectionType 19bf215546Sopenharmony_ci start_collapsed: bool = False 20bf215546Sopenharmony_ci escape: str = "\x1b[0K" 21bf215546Sopenharmony_ci colour: str = f"{CONSOLE_LOG['BOLD']}{CONSOLE_LOG['FG_GREEN']}" 22bf215546Sopenharmony_ci __start_time: Optional[datetime] = field(default=None, init=False) 23bf215546Sopenharmony_ci __end_time: Optional[datetime] = field(default=None, init=False) 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci @classmethod 26bf215546Sopenharmony_ci def section_id_filter(cls, value) -> str: 27bf215546Sopenharmony_ci return str(re.sub(r"[^\w_-]+", "-", value)) 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci def __post_init__(self): 30bf215546Sopenharmony_ci self.id = self.section_id_filter(self.id) 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci @property 33bf215546Sopenharmony_ci def has_started(self) -> bool: 34bf215546Sopenharmony_ci return self.__start_time is not None 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci @property 37bf215546Sopenharmony_ci def has_finished(self) -> bool: 38bf215546Sopenharmony_ci return self.__end_time is not None 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci def get_timestamp(self, time: datetime) -> str: 41bf215546Sopenharmony_ci unix_ts = datetime.timestamp(time) 42bf215546Sopenharmony_ci return str(int(unix_ts)) 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci def section(self, marker: str, header: str, time: datetime) -> str: 45bf215546Sopenharmony_ci preamble = f"{self.escape}section_{marker}" 46bf215546Sopenharmony_ci collapse = marker == "start" and self.start_collapsed 47bf215546Sopenharmony_ci collapsed = "[collapsed=true]" if collapse else "" 48bf215546Sopenharmony_ci section_id = f"{self.id}{collapsed}" 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci timestamp = self.get_timestamp(time) 51bf215546Sopenharmony_ci before_header = ":".join([preamble, timestamp, section_id]) 52bf215546Sopenharmony_ci colored_header = f"{self.colour}{header}\x1b[0m" if header else "" 53bf215546Sopenharmony_ci header_wrapper = "\r" + f"{self.escape}{colored_header}" 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci return f"{before_header}{header_wrapper}" 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci def __enter__(self): 58bf215546Sopenharmony_ci print(self.start()) 59bf215546Sopenharmony_ci return self 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci def __exit__(self, exc_type, exc_val, exc_tb): 62bf215546Sopenharmony_ci print(self.end()) 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci def start(self) -> str: 65bf215546Sopenharmony_ci assert not self.has_finished, "Starting an already finished section" 66bf215546Sopenharmony_ci self.__start_time = datetime.now() 67bf215546Sopenharmony_ci return self.section(marker="start", header=self.header, time=self.__start_time) 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci def end(self) -> str: 70bf215546Sopenharmony_ci assert self.has_started, "Ending an uninitialized section" 71bf215546Sopenharmony_ci self.__end_time = datetime.now() 72bf215546Sopenharmony_ci assert ( 73bf215546Sopenharmony_ci self.__end_time >= self.__start_time 74bf215546Sopenharmony_ci ), "Section execution time will be negative" 75bf215546Sopenharmony_ci return self.section(marker="end", header="", time=self.__end_time) 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci def delta_time(self) -> Optional[timedelta]: 78bf215546Sopenharmony_ci if self.__start_time and self.__end_time: 79bf215546Sopenharmony_ci return self.__end_time - self.__start_time 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci if self.has_started: 82bf215546Sopenharmony_ci return datetime.now() - self.__start_time 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci return None 85