Format, lint, type

This commit is contained in:
Abel Luck 2022-12-01 14:20:37 +00:00
parent a1ae717c8f
commit c925079e8b
8 changed files with 159 additions and 91 deletions

View file

@ -14,8 +14,8 @@ def hex_to_rgb(color: str) -> RGB:
step = 1 if len(color) == 3 else 2
try:
r = int(color[0:step], 16)
g = int(color[step:2 * step], 16)
b = int(color[2 * step:3 * step], 16)
g = int(color[step : 2 * step], 16)
b = int(color[2 * step : 3 * step], 16)
except ValueError as e:
raise ValueError("Invalid hex value") from e
return r / 255, g / 255, b / 255
@ -59,4 +59,4 @@ def _linearize(v: float) -> float:
if v <= 0.03928:
return v / 12.92
else:
return ((v + 0.055) / 1.055) ** 2.4
return float(((v + 0.055) / 1.055) ** 2.4)

View file

@ -1,8 +1,10 @@
# Copyright (c) 2022 Tulir Asokan
# # Copyright (c) 2022 Tulir Asokan
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from typing import Any
import commonmark
@ -11,12 +13,12 @@ class HtmlEscapingRenderer(commonmark.HtmlRenderer):
super().__init__()
self.allow_html = allow_html
def lit(self, s):
def lit(self, s: str) -> None:
if self.allow_html:
return super().lit(s)
return super().lit(s.replace("<", "&lt;").replace(">", "&gt;"))
def image(self, node, entering):
def image(self, node: Any, entering: Any) -> None:
prev = self.allow_html
self.allow_html = True
super().image(node, entering)
@ -29,8 +31,8 @@ no_html_renderer = HtmlEscapingRenderer()
def render(message: str, allow_html: bool = False) -> str:
parsed = md_parser.parse(message)
parsed = md_parser.parse(message) # type: ignore
if allow_html:
return yes_html_renderer.render(parsed)
return yes_html_renderer.render(parsed) # type: ignore
else:
return no_html_renderer.render(parsed)
return no_html_renderer.render(parsed) # type: ignore

View file

@ -13,13 +13,16 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Dict, Any, Tuple, Callable, Iterable, List, Union
import os.path
from typing import Any, Callable, Dict, List, Tuple, Union
from jinja2 import Environment as JinjaEnvironment, Template, BaseLoader, TemplateNotFound, FileSystemLoader
from jinja2 import BaseLoader
from jinja2 import Environment as JinjaEnvironment
from jinja2 import Template, TemplateNotFound
from ops_bot.util import markdown
def sync_read_file(path: str) -> str:
with open(path) as file:
return file.read()
@ -28,6 +31,7 @@ def sync_read_file(path: str) -> str:
def sync_list_files(directory: str) -> list[str]:
return os.listdir(directory)
class TemplateUtil:
@staticmethod
def bold_scope(label: str) -> str:
@ -61,20 +65,29 @@ class TemplateUtil:
if minutes > 0:
parts.append(cls.pluralize(minutes, "minute"))
if seconds > 0 or len(parts) == 0:
parts.append(cls.pluralize(seconds + frac_seconds, "second"))
parts.append(cls.pluralize(int(seconds + frac_seconds), "second"))
if len(parts) == 1:
return parts[0]
return ", ".join(parts[:-1]) + f" and {parts[-1]}"
@staticmethod
def join_human_list(data: List[str], *, joiner: str = ", ", final_joiner: str = " and ",
mutate: Callable[[str], str] = lambda val: val) -> str:
def join_human_list(
data: List[str],
*,
joiner: str = ", ",
final_joiner: str = " and ",
mutate: Callable[[str], str] = lambda val: val,
) -> str:
if not data:
return ""
elif len(data) == 1:
return mutate(data[0])
return joiner.join(mutate(val) for val in data[:-1]) + final_joiner + mutate(data[-1])
return (
joiner.join(mutate(val) for val in data[:-1])
+ final_joiner
+ mutate(data[-1])
)
class TemplateProxy:
@ -97,11 +110,13 @@ class PluginTemplateLoader(BaseLoader):
directory: str
macros: str
def __init__(self, base: str, directory: str) -> None:
def __init__(self, base: str, directory: str) -> None:
self.directory = os.path.join("templates", base, directory)
self.macros = sync_read_file(os.path.join("templates", base, "macros.html"))
def get_source(self, environment: Any, name: str) -> Tuple[str, str, Callable[[], bool]]:
def get_source(
self, environment: Any, name: str
) -> Tuple[str, str, Callable[[], bool]]:
path = f"{os.path.join(self.directory, name)}.html"
try:
tpl = sync_read_file(path)
@ -109,21 +124,31 @@ class PluginTemplateLoader(BaseLoader):
raise TemplateNotFound(name)
return self.macros + tpl, name, lambda: True
def list_templates(self) -> Iterable[str]:
return [os.path.splitext(os.path.basename(path))[0]
for path in sync_list_files(self.directory)
if path.endswith(".html")]
def list_templates(self) -> List[str]:
return [
os.path.splitext(os.path.basename(path))[0]
for path in sync_list_files(self.directory)
if path.endswith(".html")
]
class TemplateManager:
_env: JinjaEnvironment
_loader: PluginTemplateLoader
def __init__(self, base: str, directory: str) -> None:
#self._loader = FileSystemLoader(os.path.join("templates/", base))
# self._loader = FileSystemLoader(os.path.join("templates/", base))
self._loader = PluginTemplateLoader(base, directory)
self._env = JinjaEnvironment(loader=self._loader, lstrip_blocks=True, trim_blocks=True,
extensions=["jinja2.ext.do"])
self._env.filters["markdown"] = lambda message: markdown.render(message, allow_html=True)
self._env = JinjaEnvironment( # nosec B701
loader=self._loader,
lstrip_blocks=True,
trim_blocks=True,
autoescape=False,
extensions=["jinja2.ext.do"],
)
self._env.filters["markdown"] = lambda message: markdown.render(
message, allow_html=True
)
def __getitem__(self, item: str) -> Template:
return self._env.get_template(item)