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