1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2021-2024 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 18import os 19from dataclasses import dataclass 20from pathlib import Path 21from typing import Dict, Any, List, Tuple 22 23import yaml 24from jinja2 import Environment, select_autoescape, TemplateSyntaxError 25from runner.plugins.ets.utils.constants import META_COPYRIGHT, META_START_STRING, \ 26 META_END_STRING, META_START_COMMENT, META_END_COMMENT 27from runner.plugins.ets.utils.exceptions import \ 28 InvalidFileFormatException, UnknownTemplateException, InvalidMetaException 29from runner.utils import read_file 30 31ROOT_PATH = Path(os.path.realpath(os.path.dirname(__file__))) 32BENCH_PATH = ROOT_PATH / "test_template.tpl" 33COPYRIGHT_PATH = ROOT_PATH / "copyright.txt" 34 35 36@dataclass 37class Meta: 38 config: Dict[str, Any] 39 code: str 40 41 42class Template: 43 def __init__(self, test_path: Path, params: Dict[str, Any]) -> None: 44 self.test_path = str(test_path) 45 self.text = read_file(test_path) 46 self.__params = params 47 self.__jinja_env = Environment(autoescape=select_autoescape()) 48 49 if self.is_copyright: 50 self.__copyright = read_file(COPYRIGHT_PATH) 51 else: 52 self.__copyright, out_content = self.__get_in_out_content(self.text, META_START_COMMENT, META_END_COMMENT) 53 self.text = out_content.strip() 54 55 @property 56 def is_copyright(self) -> bool: 57 return META_COPYRIGHT not in self.text 58 59 @staticmethod 60 def __replace_symbols(text: str) -> str: 61 codes = [(''', "'"), ('"', '"'), ('>', '>'), ('<', '<'), ('&', '&')] 62 for old, new in codes: 63 text = text.replace(old, new) 64 return text 65 66 @staticmethod 67 def __get_in_out_content(text: str, meta_start: str, meta_end: str) -> Tuple[str, str]: 68 start, end = text.find(meta_start), text.find(meta_end) 69 if start > end or start == -1 or end == -1: 70 raise InvalidMetaException("Invalid meta or meta does not exist") 71 inside_content = text[start + len(meta_start):end] 72 outside_content = text[:start] + text[end + len(meta_end):] 73 return inside_content, outside_content 74 75 def render_template(self) -> List[str]: 76 try: 77 template = self.__jinja_env.from_string(self.text) 78 rendered = template.render(**self.__params).strip() 79 except TemplateSyntaxError as exc: 80 raise InvalidFileFormatException(message=f"Template Syntax Error: {exc.message}", 81 filepath=self.test_path) from exc 82 except Exception as exc: 83 raise UnknownTemplateException(filepath=self.test_path, exception=exc) from exc 84 85 meta_start = META_START_STRING if self.is_copyright else META_START_COMMENT 86 return [meta_start + e for e in rendered.split(meta_start) if e] 87 88 def generate_test(self, test: str, fullname: str) -> str: 89 meta = self.__get_meta(test) 90 meta.config["name"] = fullname 91 yaml_content = yaml.dump(meta.config) 92 93 bench_template = read_file(BENCH_PATH) 94 bench_code = bench_template.format( 95 copyright=self.__copyright.strip(), 96 description=yaml_content.strip(), 97 code=meta.code.strip()) 98 return bench_code 99 100 def __get_meta(self, text: str) -> Meta: 101 test_text = self.__replace_symbols(text) 102 inside_content, outside_content = self.__get_in_out_content(test_text, META_START_STRING, META_END_STRING) 103 return Meta(config=self.__parse_yaml(inside_content), code=outside_content) 104 105 def __parse_yaml(self, text: str) -> Dict[str, Any]: 106 try: 107 result: Dict[str, Any] = yaml.safe_load(text) 108 except Exception as exc: 109 raise InvalidFileFormatException(message=f"Could not load YAML in test params: {str(exc)}", 110 filepath=self.test_path) from exc 111 return result 112