Compare commits

...
2 Commits
5 changed files with 137 additions and 15 deletions

No files matched your search

@@ -76,7 +76,7 @@ class MainsailThemeInstallerExtension(BaseExtension):
# noinspection PyMethodMayBeStatic
class MainsailThemeInstallMenu(BaseMenu):
THEMES_URL: str = (
"https://raw.githubusercontent.com/mainsail-crew/gb-docs/main/_data/themes.csv"
"https://raw.githubusercontent.com/mainsail-crew/docs/zensical/_data/themes.csv"
)
def __init__(self, instances: List[Klipper]):
@@ -94,8 +94,9 @@ class MainsailThemeInstallMenu(BaseMenu):
)
def set_options(self) -> None:
# Menu numbers start at 1 to match the theme IDs on the Mainsail docs page
self.options = {
f"{index}": Option(self.install_theme, opt_index=f"{index}")
f"{index + 1}": Option(self.install_theme, opt_index=f"{index}")
for index in range(len(self.themes))
}
@@ -107,11 +108,12 @@ class MainsailThemeInstallMenu(BaseMenu):
f"""
╟───────────────────────────────────────────────────────╢
║ {line1:<62} ║
║ https://docs.mainsail.xyz/theming/themes ║
║ https://docs.mainsail.xyz/features/custom- ║
║ themes/community-themes/ ║
╟───────────────────────────────────────────────────────╢
"""
)[1:]
for i, theme in enumerate(self.themes):
for i, theme in enumerate(self.themes, start=1):
j: str = f" {i}" if i < 10 else f"{i}"
row: str = f"{j}) [{theme.name}]"
menu += f"║ {row:<53} ║\n"
@@ -123,12 +125,19 @@ class MainsailThemeInstallMenu(BaseMenu):
themes: List[ThemeData] = []
content: str = response.read().decode()
csv_data: List[str] = content.splitlines()
fieldnames = ["name", "short_note", "author", "repo"]
csv_reader = csv.DictReader(csv_data, fieldnames=fieldnames, delimiter=",")
next(csv_reader) # skip the header of the csv file
# read columns by the csv header, so extra columns in the list
# (e.g. "branch" and "preview", used by the docs page) are ignored
csv_reader = csv.DictReader(csv_data, delimiter=",")
for row in csv_reader:
row: Dict[str, str] # type: ignore
theme: ThemeData = ThemeData(**row)
if not row.get("author") or not row.get("repo"):
continue
theme: ThemeData = ThemeData(
name=row.get("name") or row["repo"],
short_note=row.get("short_note") or "",
author=row["author"],
repo=row["repo"],
)
themes.append(theme)
return themes
@@ -5,7 +5,7 @@
"maintained_by": "dw-0",
"display_name": "Mainsail Theme Installer",
"description": ["Install Mainsail Themes maintained by the Mainsail community."],
"website": "https://docs.mainsail.xyz/theming/themes",
"website": "https://docs.mainsail.xyz/features/custom-themes/community-themes/",
"updates": false
}
}
+2 -3
View File
@@ -5,9 +5,8 @@
"maintained_by": "PEEKYPAUL",
"display_name": "Moongate for Klipper",
"description": [
"Pair this printer with the Moongate Android app for secure remote",
"access and print monitoring. Installs cloudflared, a Cloudflare",
"quick-tunnel and an EdDSA auth gate in front of Moonraker."
"Pair this printer with the Moongate app on Android or iPhone for secure remote access and print monitoring.",
"Installs cloudflared, a Cloudflare quick-tunnel and an EdDSA auth gate in front of Moonraker."
],
"repo": "https://github.com/PEEKYPAUL/Moongate",
"updates": true
@@ -134,7 +134,8 @@ class MoongateExtension(BaseExtension):
"Moongate installed successfully!",
"\n\n",
"Next steps:",
"● Install the Moongate app on your Android device.",
"● Install the Moongate app on your phone (Google Play for "
"Android, the App Store for iPhone).",
(
"● In the app: Add printer > Direct (LAN/VPN), then run "
"MOONGATE_PAIR in the Klipper console and scan the QR (or "
@@ -224,8 +225,8 @@ class MoongateExtension(BaseExtension):
Logger.print_dialog(
DialogType.ATTENTION,
[
"Moongate pairs this printer with the Moongate Android app for "
"secure remote access and print monitoring.",
"Moongate pairs this printer with the Moongate app on Android or "
"iPhone for secure remote access and print monitoring.",
"\n\n",
"This is a heavier install than most extensions. It will:",
"● clone the Moongate repo to ~/moongate",
@@ -0,0 +1,113 @@
# ======================================================================= #
# Copyright (C) 2020 - 2026 Dominik Willner <dev.dw-0@proton.me> #
# #
# This file is part of KIAUH - Klipper Installation And Update Helper #
# https://github.com/dw-0/kiauh #
# #
# This file may be distributed under the terms of the GNU GPLv3 license #
# ======================================================================= #
from __future__ import annotations
import pytest
from extensions.mainsail_theme_installer.mainsail_theme_installer_extension import (
MainsailThemeInstallMenu,
ThemeData,
)
MODULE = "extensions.mainsail_theme_installer.mainsail_theme_installer_extension"
# current format of the list in mainsail-crew/docs
DOCS_CSV = (
"name,short_note,author,repo,branch,preview\n"
"Dracula,,steadyjaw,dracula-mainsail-theme,master,screenshot.jpg\n"
"Printables,(unofficial),8bitmcu,mainsail-printables,main,screenshot.jpg\n"
)
# legacy format of the list in mainsail-crew/gb-docs
LEGACY_CSV = (
"name,short_note,author,repo\n"
"Dracula,,steadyjaw,dracula-mainsail-theme\n"
"Printables,(unofficial),8bitmcu,mainsail-printables\n"
)
EXPECTED_THEMES = [
ThemeData("Dracula", "", "steadyjaw", "dracula-mainsail-theme"),
ThemeData("Printables", "(unofficial)", "8bitmcu", "mainsail-printables"),
]
class _FakeResponse:
def __init__(self, body: str) -> None:
self._body = body.encode()
def __enter__(self):
return self
def __exit__(self, *args):
return None
def read(self) -> bytes:
return self._body
def _patch_themes_csv(monkeypatch: pytest.MonkeyPatch, body: str) -> None:
class FakeUrlLib:
@staticmethod
def urlopen(url: str):
return _FakeResponse(body)
monkeypatch.setattr(f"{MODULE}.urllib.request", FakeUrlLib())
@pytest.fixture
def menu(monkeypatch: pytest.MonkeyPatch) -> MainsailThemeInstallMenu:
_patch_themes_csv(monkeypatch, DOCS_CSV)
return MainsailThemeInstallMenu([])
class TestLoadThemes:
def test_parses_docs_format_and_ignores_extra_columns(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
_patch_themes_csv(monkeypatch, DOCS_CSV)
assert MainsailThemeInstallMenu([]).themes == EXPECTED_THEMES
def test_parses_legacy_format(self, monkeypatch: pytest.MonkeyPatch) -> None:
_patch_themes_csv(monkeypatch, LEGACY_CSV)
assert MainsailThemeInstallMenu([]).themes == EXPECTED_THEMES
def test_skips_blank_and_incomplete_rows(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
_patch_themes_csv(monkeypatch, DOCS_CSV + "\n" + "Broken,,,,,\n")
assert MainsailThemeInstallMenu([]).themes == EXPECTED_THEMES
class TestThemeMenuNumbering:
def test_options_start_at_one_to_match_docs_ids(
self, menu: MainsailThemeInstallMenu
) -> None:
menu.set_options()
assert list(menu.options) == ["1", "2"]
assert menu.options["1"].opt_index == "0"
assert menu.options["2"].opt_index == "1"
def test_menu_lists_themes_from_one(
self, menu: MainsailThemeInstallMenu, capsys
) -> None:
menu.print_menu()
out = capsys.readouterr().out
assert " 1) [Dracula]" in out
assert " 2) [Printables]" in out
assert " 0) [" not in out
def test_menu_links_to_current_docs(
self, menu: MainsailThemeInstallMenu, capsys
) -> None:
menu.print_menu()
out = capsys.readouterr().out
# the url is too long for the menu box, so it is wrapped over two lines
assert "║ https://docs.mainsail.xyz/features/custom- ║" in out
assert "║ themes/community-themes/ ║" in out
assert "theming/themes" not in out