File: generator.py

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (107 lines) | stat: -rw-r--r-- 4,099 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# Copyright 2022 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import collections
import importlib.util
import os
import re
import sys
from typing import Dict, List

from json_data_generator.util import (GetDirNameFromPath, GetFileNameFromPath,
                                      GetFileNameWithoutExtensionFromPath,
                                      JoinPath)

_FILE_PATH = os.path.dirname(os.path.realpath(__file__))

_JSON5_PATH = os.path.join(_FILE_PATH, os.pardir, os.pardir, 'third_party',
                           'pyjson5', 'src')
sys.path.insert(1, _JSON5_PATH)
import json5

_JINJA2_PATH = os.path.join(_FILE_PATH, os.pardir, os.pardir, 'third_party')
sys.path.insert(1, _JINJA2_PATH)
import jinja2


class JSONDataGenerator(object):
    '''A generic json data generator.'''

    def __init__(self, out_dir: str):
        self.out_dir = out_dir
        self.model: Dict = {}
        # Store all json sources used in the generator.
        self.sources: List[str] = list()

    def AddJSONFilesToModel(self, paths: List[str]):
        '''Adds one or more JSON files to the model.'''
        for path in paths:
            try:
                with open(path, 'r', encoding='utf-8') as f:
                    self.AddJSONToModel(path, f.read())
                    self.sources.append(path)
            except ValueError as err:
                raise ValueError('\n%s:\n    %s' % (path, err))

    def AddJSONToModel(self, json_path: str, json_string: str):
        '''Adds a |json_string| with data to the model.
        Every json file is added to |self.model| with the original file
        name as the key.
        '''
        data = json5.loads(json_string,
                           object_pairs_hook=collections.OrderedDict)
        # Use the json file name as the key of the loaded json data.
        key = GetFileNameWithoutExtensionFromPath(json_path)
        self.model[key] = data

    def GetGlobals(self, template_path: str):
        file_name_without_ext = GetFileNameWithoutExtensionFromPath(
            template_path)
        out_file_path = JoinPath(self.out_dir, file_name_without_ext)
        return {
            'model': self.model,
            'source_json_files': self.sources,
            'out_file_path': out_file_path,
        }

    def GetFilters(self):
        return {
            'to_header_guard': self._ToHeaderGuard,
        }

    def RenderTemplate(self,
                       path_to_template: str,
                       path_to_template_helper: str = None):
        template_dir = GetDirNameFromPath(path_to_template)
        template_name = GetFileNameFromPath(path_to_template)
        jinja_env = jinja2.Environment(
            loader=jinja2.FileSystemLoader(template_dir),
            keep_trailing_newline=True)
        jinja_env.globals.update(self.GetGlobals(path_to_template))
        jinja_env.filters.update(self.GetFilters())
        if path_to_template_helper:
            template_helper_module = self._LoadTemplateHelper(
                path_to_template_helper)
            jinja_env.globals.update(
                template_helper_module.get_custom_globals(self.model))
            jinja_env.filters.update(
                template_helper_module.get_custom_filters(self.model))
        template = jinja_env.get_template(template_name)
        return template.render()

    def _LoadTemplateHelper(self, path_to_template_helper: str):
        template_helper_dir = GetDirNameFromPath(path_to_template_helper)
        try:
            sys.path.append(template_helper_dir)
            spec = importlib.util.spec_from_file_location(
                path_to_template_helper, path_to_template_helper)
            module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(module)
            return module
        finally:
            # Restore sys.path to what it was before.
            sys.path.remove(template_helper_dir)

    def _ToHeaderGuard(self, path: str):
        return re.sub(r'[\\\/\.\-]+', '_', path.upper())