File: base_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 (125 lines) | stat: -rw-r--r-- 4,638 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# Copyright 2019 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os
import sys
import collections
import re
import textwrap
from style_variable_generator import path_overrides
from style_variable_generator.color import Color
from style_variable_generator.opacity import Opacity
from style_variable_generator.model import Model, Modes, VariableType

_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 BaseGenerator:
    '''A generic style variable generator.

    Subclasses should provide format-specific generation templates, filters and
    globals to render their output.
    '''

    @staticmethod
    def GetName():
        return None

    def __init__(self):
        self.out_file_path = None

        self.model = Model()

        # A map of input filepaths to their context object.
        self.in_file_to_context = dict()

        # If specified, only generates the given mode.
        self.generate_single_mode = None

        # A dictionary of options used to alter generator function. See
        # ./README.md for each generators list of options.
        self.generator_options = {}


    # If true, will attempt to resolve all blend() colors to the RGBA values at
    # compile time. Note that json5 files can specify "preblend" to override
    # this setting for specific files.
    def DefaultPreblend(self):
        return True

    def GetInputFiles(self):
        return sorted(self.in_file_to_context.keys())

    def AddJSONFilesToModel(self, paths):
        '''Adds one or more JSON files to the model.
        '''
        for path in paths:
            try:
                with open(path, 'r') as f:
                    self.AddJSONToModel(f.read(), path)
            except ValueError as err:
                raise ValueError(f'Could not add {path}') from err

        self.model.PostProcess(default_preblend=self.DefaultPreblend())

    def AddJSONToModel(self, json_string, in_file=None):
        '''Adds a |json_string| with variable definitions to the model.

        See *test.json5 files for a defacto format reference.

        |in_file| is used to populate a file-to-context map.
        '''
        # TODO(calamity): Add allow_duplicate_keys=False once pyjson5 is
        # rolled.
        data = json5.loads(json_string,
                           object_pairs_hook=collections.OrderedDict)

        context = data.get('options', {})
        context['token_namespace'] = data.get('token_namespace', '')
        self.in_file_to_context[in_file] = context

        # Add variables to the model.
        for name, value in data.get('colors', {}).items():
            self.model.Add(VariableType.COLOR, name, value, context)

        for name, value in data.get('opacities', {}).items():
            self.model.Add(VariableType.OPACITY, name, value, context)

        for name, value in data.get('legacy_mappings', {}).items():
            self.model.Add(VariableType.LEGACY_MAPPING, name, value, context)

        typography = data.get('typography')
        if typography:
            for name, value in typography['font_families'].items():
                self.model.Add(VariableType.FONT_FAMILY, name, value, context)

            for name, value in typography['font_faces'].items():
                self.model.Add(VariableType.FONT_FACE, name, value, context)

            for name, value_obj in typography['typefaces'].items():
                self.model.Add(VariableType.TYPEFACE, name, value_obj, context)

        for group_name, value_obj in data.get('untyped_css', {}).items():
            for var_name, value in value_obj.items():
                self.model.Add(VariableType.UNTYPED_CSS, var_name, value,
                               context)

    def ApplyTemplate(self, style_generator, path_to_template, params):
        loader_root_dir = path_overrides.GetFileSystemLoaderRootDirectory()
        jinja_env = jinja2.Environment(
            loader=jinja2.FileSystemLoader(loader_root_dir),
            keep_trailing_newline=True)
        jinja_env.globals.update(style_generator.GetGlobals())
        jinja_env.filters.update(style_generator.GetFilters())
        template = jinja_env.get_template(
            path_overrides.GetPathToTemplate(path_to_template))
        return template.render(params)