• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = [('&#39;', "'"), ('&#34;', '"'), ('&gt;', '>'), ('&lt;', '<'), ('&amp;', '&')]
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