1# Copyright 2018 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from typing import Union, List 16from pathlib import Path 17 18import jinja2 19import re 20 21from synthtool import log 22from synthtool import tmp 23 24 25PathOrStr = Union[str, Path] 26 27 28def _make_env(location): 29 env = jinja2.Environment( 30 loader=jinja2.FileSystemLoader(str(location)), 31 autoescape=False, 32 keep_trailing_newline=True, 33 ) 34 env.filters["release_quality_badge"] = release_quality_badge 35 env.filters["language_pretty"] = language_pretty 36 env.filters["slugify"] = slugify 37 env.filters["syntax_highlighter"] = syntax_highlighter 38 return env 39 40 41def _render_to_path(env, template_name, dest, params): 42 template = env.get_template(template_name) 43 44 output = template.stream(**params) 45 46 if template_name.endswith(".j2"): 47 template_name = template.name[:-3] 48 49 dest = dest / template_name 50 dest.parent.mkdir(parents=True, exist_ok=True) 51 52 with dest.open("w") as fh: 53 output.dump(fh) 54 55 # Copy file mode over 56 source_path = Path(template.filename) 57 mode = source_path.stat().st_mode 58 dest.chmod(mode) 59 60 return dest 61 62 63class Templates: 64 def __init__(self, location: PathOrStr) -> None: 65 self.env = _make_env(location) 66 self.source_path = Path(location) 67 self.dir = tmp.tmpdir() 68 69 def render(self, template_name: str, subdir: PathOrStr = ".", **kwargs) -> Path: 70 return _render_to_path(self.env, template_name, self.dir / subdir, kwargs) 71 72 73class TemplateGroup: 74 def __init__(self, location: PathOrStr, excludes: List[str] = []) -> None: 75 self.env = _make_env(location) 76 self.dir = tmp.tmpdir() 77 self.excludes = excludes 78 79 def render(self, subdir: PathOrStr = ".", **kwargs) -> Path: 80 for template_name in self.env.list_templates(): 81 if template_name not in self.excludes: 82 print(template_name) 83 _render_to_path(self.env, template_name, self.dir / subdir, kwargs) 84 else: 85 print(f"Skipping: {template_name}") 86 87 return self.dir 88 89 90def release_quality_badge(input: str) -> str: 91 """Generates a markdown badge for displaying a "Release Quality'.""" 92 if not input: 93 log.error("ensure you pass a string 'quality' to release_quality_badge") 94 return "" 95 96 release_quality = input.upper() 97 badge = "" 98 99 if release_quality == "GA": 100 badge = "general%20availability%20%28GA%29-brightgreen" 101 elif release_quality == "STABLE": 102 badge = "stable-brightgreen" 103 elif release_quality == "PREVIEW": 104 badge = "preview-yellow" 105 elif release_quality == "BETA": 106 badge = "beta-yellow" 107 elif release_quality == "ALPHA": 108 badge = "alpha-orange" 109 elif release_quality == "EAP": 110 badge = "EAP-yellow" 111 elif release_quality == "DEPRECATED": 112 badge = "deprecated-red" 113 else: 114 log.error( 115 "Expected 'release_quality' to be one of: (ga, stable, preview, beta, alpha, eap, deprecated)" 116 ) 117 return "" 118 return f"[](https://cloud.google.com/terms/launch-stages)" 119 120 121def language_pretty(input: str) -> str: 122 """.repo-metadata.json language field to pretty language.""" 123 if input == "nodejs": 124 return "Node.js" 125 return input 126 127 128def slugify(input: str) -> str: 129 """Converts Foo Bar into foo-bar, for use wih anchor links.""" 130 input = re.sub(r"([() ]+)", "-", input.lower()) 131 return re.sub(r"-$", "", input) 132 133 134def syntax_highlighter(input: str) -> str: 135 """.repo-metadata.json language field to syntax highlighter name.""" 136 if input == "nodejs": 137 return "javascript" 138 return input 139