From 9698e57fa6a08d11849332500c988c7c5c4e4ed5 Mon Sep 17 00:00:00 2001 From: Qubasa Date: Tue, 21 Nov 2023 16:44:38 +0100 Subject: [PATCH 01/10] Added more deal tests --- docs/contributing.md | 3 +++ pkgs/clan-cli/clan_cli/async_cmd.py | 8 ++++--- pkgs/clan-cli/clan_cli/nix.py | 11 +++++---- pkgs/clan-cli/clan_cli/task_manager.py | 5 +++- pkgs/clan-cli/tests/test_with_deal.py | 32 +++++++++++++++++++++++--- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index 8e738e47e..91e44acf1 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -78,6 +78,9 @@ Let's get your development environment up and running: ``` - Wait for the frontend to build. + NOTE: If you have the error "@clan/colors.json" you executed `npm install`, please do not do that. `direnv reload` will handle dependency management. Please delete node_modules with `rm -rf node_modules`. + + 9. **Start the Frontend**: - To start the frontend, execute: ```bash diff --git a/pkgs/clan-cli/clan_cli/async_cmd.py b/pkgs/clan-cli/clan_cli/async_cmd.py index 462b2000f..96f4b2a08 100644 --- a/pkgs/clan-cli/clan_cli/async_cmd.py +++ b/pkgs/clan-cli/clan_cli/async_cmd.py @@ -1,8 +1,9 @@ import asyncio import logging +import deal import shlex from pathlib import Path -from typing import Any, Callable, Coroutine, Dict, NamedTuple, Optional +from typing import Any, Callable, Coroutine, Dict, NamedTuple, Optional, Awaitable from .custom_logger import get_caller from .errors import ClanError @@ -15,8 +16,8 @@ class CmdOut(NamedTuple): stderr: str cwd: Optional[Path] = None - -async def run(cmd: list[str], cwd: Optional[Path] = None) -> CmdOut: +@deal.raises(ClanError) +async def run(cmd: list[str], cwd: Optional[Path] = None) -> Awaitable[CmdOut]: cwd_res = None if cwd is not None: if not cwd.exists(): @@ -51,6 +52,7 @@ stdout: return CmdOut(stdout.decode("utf-8"), stderr.decode("utf-8"), cwd=cwd) +@deal.raises(ClanError) def runforcli( func: Callable[..., Coroutine[Any, Any, Dict[str, CmdOut]]], *args: Any ) -> None: diff --git a/pkgs/clan-cli/clan_cli/nix.py b/pkgs/clan-cli/clan_cli/nix.py index e2d7c6a14..6776dd05d 100644 --- a/pkgs/clan-cli/clan_cli/nix.py +++ b/pkgs/clan-cli/clan_cli/nix.py @@ -2,12 +2,13 @@ import json import os import subprocess import tempfile +import deal from pathlib import Path from typing import Any from .dirs import nixpkgs_flake, nixpkgs_source - +@deal.raises(ClanError) def nix_command(flags: list[str]) -> list[str]: return ["nix", "--extra-experimental-features", "nix-command flakes"] + flags @@ -24,7 +25,7 @@ def nix_flake_show(flake_url: str | Path) -> list[str]: ] ) - +@deal.raises(ClanError) def nix_build( flags: list[str], ) -> list[str]: @@ -40,7 +41,7 @@ def nix_build( + flags ) - +@deal.raises(ClanError) def nix_config() -> dict[str, Any]: cmd = nix_command(["show-config", "--json"]) proc = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE) @@ -50,7 +51,7 @@ def nix_config() -> dict[str, Any]: config[key] = value["value"] return config - +@deal.raises(ClanError) def nix_eval(flags: list[str]) -> list[str]: default_flags = nix_command( [ @@ -77,7 +78,7 @@ def nix_eval(flags: list[str]) -> list[str]: ) return default_flags + flags - +@deal.raises(ClanError) def nix_shell(packages: list[str], cmd: list[str]) -> list[str]: # we cannot use nix-shell inside the nix sandbox # in our tests we just make sure we have all the packages diff --git a/pkgs/clan-cli/clan_cli/task_manager.py b/pkgs/clan-cli/clan_cli/task_manager.py index f0fcb3e62..edadef5cb 100644 --- a/pkgs/clan-cli/clan_cli/task_manager.py +++ b/pkgs/clan-cli/clan_cli/task_manager.py @@ -186,10 +186,13 @@ def get_task(uuid: UUID) -> BaseTask: T = TypeVar("T", bound="BaseTask") - +@deal.raises(ClanError) def create_task(task_type: Type[T], *args: Any) -> T: global POOL + # check if task_type is a callable + if not callable(task_type): + raise ClanError("task_type must be callable") uuid = uuid4() task = task_type(uuid, *args) diff --git a/pkgs/clan-cli/tests/test_with_deal.py b/pkgs/clan-cli/tests/test_with_deal.py index 705d401f6..d471e2cba 100644 --- a/pkgs/clan-cli/tests/test_with_deal.py +++ b/pkgs/clan-cli/tests/test_with_deal.py @@ -1,8 +1,34 @@ import deal -from clan_cli.task_manager import get_task +from clan_cli import task_manager +from clan_cli import async_cmd +from clan_cli import nix - -@deal.cases(get_task) +@deal.cases(task_manager.get_task) def test_get_task(case: deal.TestCase) -> None: case() + +@deal.cases(task_manager.create_task) +def test_create_task(case: deal.TestCase) -> None: + case() + + +@deal.cases(nix.nix_command) +def test_nix_command(case: deal.TestCase) -> None: + case() + +@deal.cases(nix.nix_build) +def test_nix_build(case: deal.TestCase) -> None: + case() + +@deal.cases(nix.nix_config) +def test_nix_config(case: deal.TestCase) -> None: + case() + +@deal.cases(nix.nix_eval) +def test_nix_eval(case: deal.TestCase) -> None: + case() + +@deal.cases(nix.nix_shell) +def test_nix_shell(case: deal.TestCase) -> None: + case() \ No newline at end of file From dddbe74d6a77257fdb770d2eb2146b8eaba9b63e Mon Sep 17 00:00:00 2001 From: Qubasa Date: Tue, 21 Nov 2023 18:13:30 +0100 Subject: [PATCH 02/10] Added gtk demo app --- docs/contributing.md | 3 +- pkgs/clan-cli/clan_cli/__init__.py | 5 ++- pkgs/clan-cli/clan_cli/async_cmd.py | 8 ++-- pkgs/clan-cli/clan_cli/gtkui/__init__.py | 10 +++++ pkgs/clan-cli/clan_cli/gtkui/app.glade | 49 ++++++++++++++++++++++++ pkgs/clan-cli/clan_cli/gtkui/app.glade~ | 49 ++++++++++++++++++++++++ pkgs/clan-cli/clan_cli/gtkui/app.py | 19 +++++++++ pkgs/clan-cli/clan_cli/nix.py | 9 ++++- pkgs/clan-cli/clan_cli/task_manager.py | 1 + pkgs/clan-cli/default.nix | 7 +++- pkgs/clan-cli/pyproject.toml | 7 +++- pkgs/clan-cli/tests/test_with_deal.py | 12 ++++-- 12 files changed, 164 insertions(+), 15 deletions(-) create mode 100644 pkgs/clan-cli/clan_cli/gtkui/__init__.py create mode 100644 pkgs/clan-cli/clan_cli/gtkui/app.glade create mode 100644 pkgs/clan-cli/clan_cli/gtkui/app.glade~ create mode 100644 pkgs/clan-cli/clan_cli/gtkui/app.py diff --git a/docs/contributing.md b/docs/contributing.md index 91e44acf1..342d9eddf 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -78,8 +78,7 @@ Let's get your development environment up and running: ``` - Wait for the frontend to build. - NOTE: If you have the error "@clan/colors.json" you executed `npm install`, please do not do that. `direnv reload` will handle dependency management. Please delete node_modules with `rm -rf node_modules`. - + NOTE: If you have the error "@clan/colors.json" you executed `npm install`, please do not do that. `direnv reload` will handle dependency management. Please delete node_modules with `rm -rf node_modules`. 9. **Start the Frontend**: - To start the frontend, execute: diff --git a/pkgs/clan-cli/clan_cli/__init__.py b/pkgs/clan-cli/clan_cli/__init__.py index 597955023..bca16c4ce 100644 --- a/pkgs/clan-cli/clan_cli/__init__.py +++ b/pkgs/clan-cli/clan_cli/__init__.py @@ -5,7 +5,7 @@ from pathlib import Path from types import ModuleType from typing import Any, Optional, Sequence -from . import config, flakes, machines, secrets, vms, webui +from . import config, flakes, gtkui, machines, secrets, vms, webui from .custom_logger import setup_logging from .dirs import get_clan_flake_toplevel from .ssh import cli as ssh_cli @@ -64,6 +64,9 @@ def create_parser(prog: Optional[str] = None) -> argparse.ArgumentParser: subparsers = parser.add_subparsers() + parser_gtkui = subparsers.add_parser("gtkui", help="start gtkui") + gtkui.register_parser(parser_gtkui) + parser_flake = subparsers.add_parser( "flakes", help="create a clan flake inside the current directory" ) diff --git a/pkgs/clan-cli/clan_cli/async_cmd.py b/pkgs/clan-cli/clan_cli/async_cmd.py index 96f4b2a08..462b2000f 100644 --- a/pkgs/clan-cli/clan_cli/async_cmd.py +++ b/pkgs/clan-cli/clan_cli/async_cmd.py @@ -1,9 +1,8 @@ import asyncio import logging -import deal import shlex from pathlib import Path -from typing import Any, Callable, Coroutine, Dict, NamedTuple, Optional, Awaitable +from typing import Any, Callable, Coroutine, Dict, NamedTuple, Optional from .custom_logger import get_caller from .errors import ClanError @@ -16,8 +15,8 @@ class CmdOut(NamedTuple): stderr: str cwd: Optional[Path] = None -@deal.raises(ClanError) -async def run(cmd: list[str], cwd: Optional[Path] = None) -> Awaitable[CmdOut]: + +async def run(cmd: list[str], cwd: Optional[Path] = None) -> CmdOut: cwd_res = None if cwd is not None: if not cwd.exists(): @@ -52,7 +51,6 @@ stdout: return CmdOut(stdout.decode("utf-8"), stderr.decode("utf-8"), cwd=cwd) -@deal.raises(ClanError) def runforcli( func: Callable[..., Coroutine[Any, Any, Dict[str, CmdOut]]], *args: Any ) -> None: diff --git a/pkgs/clan-cli/clan_cli/gtkui/__init__.py b/pkgs/clan-cli/clan_cli/gtkui/__init__.py new file mode 100644 index 000000000..f634e0604 --- /dev/null +++ b/pkgs/clan-cli/clan_cli/gtkui/__init__.py @@ -0,0 +1,10 @@ +import argparse +from typing import Callable, Optional + +start_app: Optional[Callable] = None + +from .app import start_app + + +def register_parser(parser: argparse.ArgumentParser) -> None: + parser.set_defaults(func=start_app) diff --git a/pkgs/clan-cli/clan_cli/gtkui/app.glade b/pkgs/clan-cli/clan_cli/gtkui/app.glade new file mode 100644 index 000000000..65a645d0a --- /dev/null +++ b/pkgs/clan-cli/clan_cli/gtkui/app.glade @@ -0,0 +1,49 @@ + + + + + + False + + + asdasd + True + False + + + May I help you? + asdasd + 100 + 80 + True + True + True + top + + + + 21 + 21 + + + + + 100 + 80 + True + False + Get me some coffe! + 0 + + + 178 + 120 + + + + + + + diff --git a/pkgs/clan-cli/clan_cli/gtkui/app.glade~ b/pkgs/clan-cli/clan_cli/gtkui/app.glade~ new file mode 100644 index 000000000..65a645d0a --- /dev/null +++ b/pkgs/clan-cli/clan_cli/gtkui/app.glade~ @@ -0,0 +1,49 @@ + + + + + + False + + + asdasd + True + False + + + May I help you? + asdasd + 100 + 80 + True + True + True + top + + + + 21 + 21 + + + + + 100 + 80 + True + False + Get me some coffe! + 0 + + + 178 + 120 + + + + + + + diff --git a/pkgs/clan-cli/clan_cli/gtkui/app.py b/pkgs/clan-cli/clan_cli/gtkui/app.py new file mode 100644 index 000000000..0122b9df3 --- /dev/null +++ b/pkgs/clan-cli/clan_cli/gtkui/app.py @@ -0,0 +1,19 @@ +# !/usr/bin/env python3 + +import argparse # noqa +from pathlib import Path # noqa + +import gi # noqa + +gi.require_version("Gtk", "3.0") # noqa +from gi.repository import Gtk # noqa + + +def start_app(args: argparse.Namespace) -> None: + builder = Gtk.Builder() + glade_file = Path(__file__).parent / "app.glade" + builder.add_from_file(str(glade_file)) + window = builder.get_object("main-window") + window.show_all() + + Gtk.main() diff --git a/pkgs/clan-cli/clan_cli/nix.py b/pkgs/clan-cli/clan_cli/nix.py index 6776dd05d..c913928a5 100644 --- a/pkgs/clan-cli/clan_cli/nix.py +++ b/pkgs/clan-cli/clan_cli/nix.py @@ -2,11 +2,14 @@ import json import os import subprocess import tempfile -import deal from pathlib import Path from typing import Any +import deal + from .dirs import nixpkgs_flake, nixpkgs_source +from .errors import ClanError + @deal.raises(ClanError) def nix_command(flags: list[str]) -> list[str]: @@ -25,6 +28,7 @@ def nix_flake_show(flake_url: str | Path) -> list[str]: ] ) + @deal.raises(ClanError) def nix_build( flags: list[str], @@ -41,6 +45,7 @@ def nix_build( + flags ) + @deal.raises(ClanError) def nix_config() -> dict[str, Any]: cmd = nix_command(["show-config", "--json"]) @@ -51,6 +56,7 @@ def nix_config() -> dict[str, Any]: config[key] = value["value"] return config + @deal.raises(ClanError) def nix_eval(flags: list[str]) -> list[str]: default_flags = nix_command( @@ -78,6 +84,7 @@ def nix_eval(flags: list[str]) -> list[str]: ) return default_flags + flags + @deal.raises(ClanError) def nix_shell(packages: list[str], cmd: list[str]) -> list[str]: # we cannot use nix-shell inside the nix sandbox diff --git a/pkgs/clan-cli/clan_cli/task_manager.py b/pkgs/clan-cli/clan_cli/task_manager.py index edadef5cb..451e0b1fb 100644 --- a/pkgs/clan-cli/clan_cli/task_manager.py +++ b/pkgs/clan-cli/clan_cli/task_manager.py @@ -186,6 +186,7 @@ def get_task(uuid: UUID) -> BaseTask: T = TypeVar("T", bound="BaseTask") + @deal.raises(ClanError) def create_task(task_type: Type[T], *args: Any) -> T: global POOL diff --git a/pkgs/clan-cli/default.nix b/pkgs/clan-cli/default.nix index 263812fe0..2db7105d6 100644 --- a/pkgs/clan-cli/default.nix +++ b/pkgs/clan-cli/default.nix @@ -36,12 +36,17 @@ , deal , rope , clan-core-path -, schemathesis +, schemathesis ? null }: let dependencies = [ argcomplete # optional dependency: if not enabled, shell completion will not work + wrapGAppsHook + gtk3 + glib + gobject-introspection + pygobject3 ]; pytestDependencies = runtimeDependencies ++ dependencies ++ [ diff --git a/pkgs/clan-cli/pyproject.toml b/pkgs/clan-cli/pyproject.toml index 927de1d01..0979e0180 100644 --- a/pkgs/clan-cli/pyproject.toml +++ b/pkgs/clan-cli/pyproject.toml @@ -38,6 +38,11 @@ exclude = "clan_cli.nixpkgs" module = "argcomplete.*" ignore_missing_imports = true +[[tool.mypy.overrides]] +module = "gi.*" +ignore_missing_imports = true + + [[tool.mypy.overrides]] module = "jsonschema.*" ignore_missing_imports = true @@ -58,4 +63,4 @@ ignore_missing_imports = true line-length = 88 select = [ "E", "F", "I", "N"] -ignore = [ "E501" ] +ignore = [ "E501", "E402" ] diff --git a/pkgs/clan-cli/tests/test_with_deal.py b/pkgs/clan-cli/tests/test_with_deal.py index d471e2cba..8d1637901 100644 --- a/pkgs/clan-cli/tests/test_with_deal.py +++ b/pkgs/clan-cli/tests/test_with_deal.py @@ -1,13 +1,13 @@ import deal -from clan_cli import task_manager -from clan_cli import async_cmd -from clan_cli import nix +from clan_cli import nix, task_manager + @deal.cases(task_manager.get_task) def test_get_task(case: deal.TestCase) -> None: case() + @deal.cases(task_manager.create_task) def test_create_task(case: deal.TestCase) -> None: case() @@ -17,18 +17,22 @@ def test_create_task(case: deal.TestCase) -> None: def test_nix_command(case: deal.TestCase) -> None: case() + @deal.cases(nix.nix_build) def test_nix_build(case: deal.TestCase) -> None: case() + @deal.cases(nix.nix_config) def test_nix_config(case: deal.TestCase) -> None: case() + @deal.cases(nix.nix_eval) def test_nix_eval(case: deal.TestCase) -> None: case() + @deal.cases(nix.nix_shell) def test_nix_shell(case: deal.TestCase) -> None: - case() \ No newline at end of file + case() From d35229216e7b6b2ff20d75cfb5d6b5a31770deae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 23 Nov 2023 13:56:25 +0100 Subject: [PATCH 03/10] mv clan-vm-manager to its own package --- pkgs/clan-cli/clan_cli/__init__.py | 5 +---- pkgs/clan-cli/default.nix | 2 -- .../gtkui => clan-vm-manager/clan_vm_manager}/__init__.py | 1 + .../gtkui => clan-vm-manager/clan_vm_manager}/app.glade | 0 .../gtkui => clan-vm-manager/clan_vm_manager}/app.py | 0 5 files changed, 2 insertions(+), 6 deletions(-) rename pkgs/{clan-cli/clan_cli/gtkui => clan-vm-manager/clan_vm_manager}/__init__.py (76%) rename pkgs/{clan-cli/clan_cli/gtkui => clan-vm-manager/clan_vm_manager}/app.glade (100%) rename pkgs/{clan-cli/clan_cli/gtkui => clan-vm-manager/clan_vm_manager}/app.py (100%) diff --git a/pkgs/clan-cli/clan_cli/__init__.py b/pkgs/clan-cli/clan_cli/__init__.py index bca16c4ce..597955023 100644 --- a/pkgs/clan-cli/clan_cli/__init__.py +++ b/pkgs/clan-cli/clan_cli/__init__.py @@ -5,7 +5,7 @@ from pathlib import Path from types import ModuleType from typing import Any, Optional, Sequence -from . import config, flakes, gtkui, machines, secrets, vms, webui +from . import config, flakes, machines, secrets, vms, webui from .custom_logger import setup_logging from .dirs import get_clan_flake_toplevel from .ssh import cli as ssh_cli @@ -64,9 +64,6 @@ def create_parser(prog: Optional[str] = None) -> argparse.ArgumentParser: subparsers = parser.add_subparsers() - parser_gtkui = subparsers.add_parser("gtkui", help="start gtkui") - gtkui.register_parser(parser_gtkui) - parser_flake = subparsers.add_parser( "flakes", help="create a clan flake inside the current directory" ) diff --git a/pkgs/clan-cli/default.nix b/pkgs/clan-cli/default.nix index 2db7105d6..439ca6ded 100644 --- a/pkgs/clan-cli/default.nix +++ b/pkgs/clan-cli/default.nix @@ -28,7 +28,6 @@ , tor , git , nixpkgs -, copyDesktopItems , qemu , gnupg , e2fsprogs @@ -134,7 +133,6 @@ python3.pkgs.buildPythonApplication { nativeBuildInputs = [ setuptools installShellFiles - copyDesktopItems ]; propagatedBuildInputs = dependencies; diff --git a/pkgs/clan-cli/clan_cli/gtkui/__init__.py b/pkgs/clan-vm-manager/clan_vm_manager/__init__.py similarity index 76% rename from pkgs/clan-cli/clan_cli/gtkui/__init__.py rename to pkgs/clan-vm-manager/clan_vm_manager/__init__.py index f634e0604..800ddc27d 100644 --- a/pkgs/clan-cli/clan_cli/gtkui/__init__.py +++ b/pkgs/clan-vm-manager/clan_vm_manager/__init__.py @@ -7,4 +7,5 @@ from .app import start_app def register_parser(parser: argparse.ArgumentParser) -> None: + parser = argparse.ArgumentParser(description="clan-vm-manager") parser.set_defaults(func=start_app) diff --git a/pkgs/clan-cli/clan_cli/gtkui/app.glade b/pkgs/clan-vm-manager/clan_vm_manager/app.glade similarity index 100% rename from pkgs/clan-cli/clan_cli/gtkui/app.glade rename to pkgs/clan-vm-manager/clan_vm_manager/app.glade diff --git a/pkgs/clan-cli/clan_cli/gtkui/app.py b/pkgs/clan-vm-manager/clan_vm_manager/app.py similarity index 100% rename from pkgs/clan-cli/clan_cli/gtkui/app.py rename to pkgs/clan-vm-manager/clan_vm_manager/app.py From 1d5e87d407d13e65762f4993f96e6c50299079e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 23 Nov 2023 13:56:45 +0100 Subject: [PATCH 04/10] drop glade backup file --- pkgs/clan-cli/clan_cli/gtkui/app.glade~ | 49 ------------------------- 1 file changed, 49 deletions(-) delete mode 100644 pkgs/clan-cli/clan_cli/gtkui/app.glade~ diff --git a/pkgs/clan-cli/clan_cli/gtkui/app.glade~ b/pkgs/clan-cli/clan_cli/gtkui/app.glade~ deleted file mode 100644 index 65a645d0a..000000000 --- a/pkgs/clan-cli/clan_cli/gtkui/app.glade~ +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - False - - - asdasd - True - False - - - May I help you? - asdasd - 100 - 80 - True - True - True - top - - - - 21 - 21 - - - - - 100 - 80 - True - False - Get me some coffe! - 0 - - - 178 - 120 - - - - - - - From 3f7bb8702115b9375ce51110ecde5ee4f50b7ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 23 Nov 2023 14:00:36 +0100 Subject: [PATCH 05/10] clan-cli: drop dependency on deal --- pkgs/clan-cli/clan_cli/nix.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/nix.py b/pkgs/clan-cli/clan_cli/nix.py index c913928a5..66beb4129 100644 --- a/pkgs/clan-cli/clan_cli/nix.py +++ b/pkgs/clan-cli/clan_cli/nix.py @@ -5,8 +5,7 @@ import tempfile from pathlib import Path from typing import Any -import deal - +from .deal import deal from .dirs import nixpkgs_flake, nixpkgs_source from .errors import ClanError From 47471c666b4d166fc3959459bbc98468552f8e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 23 Nov 2023 14:37:05 +0100 Subject: [PATCH 06/10] clan-vm-manager: add nix package --- flake.nix | 1 - pkgs/clan-cli/.envrc | 11 +--- pkgs/clan-cli/default.nix | 5 -- pkgs/clan-cli/shell.nix | 1 - pkgs/clan-vm-manager/.envrc | 6 ++ pkgs/clan-vm-manager/bin/clan-vm-manager | 12 ++++ .../clan_vm_manager/__init__.py | 4 +- pkgs/clan-vm-manager/default.nix | 57 +++++++++++++++++++ pkgs/clan-vm-manager/flake-module.nix | 12 ++++ pkgs/clan-vm-manager/pyproject.toml | 28 +++++++++ pkgs/clan-vm-manager/shell.nix | 15 +++++ pkgs/flake-module.nix | 1 + 12 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 pkgs/clan-vm-manager/.envrc create mode 100755 pkgs/clan-vm-manager/bin/clan-vm-manager create mode 100644 pkgs/clan-vm-manager/default.nix create mode 100644 pkgs/clan-vm-manager/flake-module.nix create mode 100644 pkgs/clan-vm-manager/pyproject.toml create mode 100644 pkgs/clan-vm-manager/shell.nix diff --git a/flake.nix b/flake.nix index 86afbf86b..a57719c20 100644 --- a/flake.nix +++ b/flake.nix @@ -33,7 +33,6 @@ "aarch64-darwin" ]; imports = [ - ./checks/flake-module.nix ./devShell.nix ./formatter.nix diff --git a/pkgs/clan-cli/.envrc b/pkgs/clan-cli/.envrc index 0ded7613f..0e43ca839 100644 --- a/pkgs/clan-cli/.envrc +++ b/pkgs/clan-cli/.envrc @@ -1,13 +1,6 @@ -# Because we depend on nixpkgs sources, uploading to builders takes a long time - source_up +nix_direnv_watch_file flake-module.nix default.nix -if type nix_direnv_watch_file &>/dev/null; then - nix_direnv_watch_file flake-module.nix - nix_direnv_watch_file default.nix -else - direnv watch flake-module.nix - direnv watch default.nix -fi +# Because we depend on nixpkgs sources, uploading to builders takes a long time use flake .#clan-cli --builders '' diff --git a/pkgs/clan-cli/default.nix b/pkgs/clan-cli/default.nix index 439ca6ded..e8ceb8c42 100644 --- a/pkgs/clan-cli/default.nix +++ b/pkgs/clan-cli/default.nix @@ -41,11 +41,6 @@ let dependencies = [ argcomplete # optional dependency: if not enabled, shell completion will not work - wrapGAppsHook - gtk3 - glib - gobject-introspection - pygobject3 ]; pytestDependencies = runtimeDependencies ++ dependencies ++ [ diff --git a/pkgs/clan-cli/shell.nix b/pkgs/clan-cli/shell.nix index bce7119ab..1bae91900 100644 --- a/pkgs/clan-cli/shell.nix +++ b/pkgs/clan-cli/shell.nix @@ -45,7 +45,6 @@ mkShell { export PATH="$tmp_path/python/bin:${checkScript}/bin:$PATH" export PYTHONPATH="$repo_root:$tmp_path/python/${pythonWithDeps.sitePackages}:" - export XDG_DATA_DIRS="$tmp_path/share''${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}" export fish_complete_path="$tmp_path/share/fish/vendor_completions.d''${fish_complete_path:+:$fish_complete_path}" mkdir -p \ diff --git a/pkgs/clan-vm-manager/.envrc b/pkgs/clan-vm-manager/.envrc new file mode 100644 index 000000000..27620706b --- /dev/null +++ b/pkgs/clan-vm-manager/.envrc @@ -0,0 +1,6 @@ +source_up + +nix_direnv_watch_file flake-module.nix default.nix + +# Because we depend on nixpkgs sources, uploading to builders takes a long time +use flake .#clan-vm-manager --builders '' diff --git a/pkgs/clan-vm-manager/bin/clan-vm-manager b/pkgs/clan-vm-manager/bin/clan-vm-manager new file mode 100755 index 000000000..3b35422b3 --- /dev/null +++ b/pkgs/clan-vm-manager/bin/clan-vm-manager @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 +import os +import sys + +sys.path.insert( + 0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) +) + +from clan_vm_manager import main # NOQA + +if __name__ == "__main__": + main() diff --git a/pkgs/clan-vm-manager/clan_vm_manager/__init__.py b/pkgs/clan-vm-manager/clan_vm_manager/__init__.py index 800ddc27d..3e568be66 100644 --- a/pkgs/clan-vm-manager/clan_vm_manager/__init__.py +++ b/pkgs/clan-vm-manager/clan_vm_manager/__init__.py @@ -6,6 +6,8 @@ start_app: Optional[Callable] = None from .app import start_app -def register_parser(parser: argparse.ArgumentParser) -> None: +def main() -> None: parser = argparse.ArgumentParser(description="clan-vm-manager") parser.set_defaults(func=start_app) + args = parser.parse_args() + args.func(args) diff --git a/pkgs/clan-vm-manager/default.nix b/pkgs/clan-vm-manager/default.nix new file mode 100644 index 000000000..a7277e373 --- /dev/null +++ b/pkgs/clan-vm-manager/default.nix @@ -0,0 +1,57 @@ +{ python3 +, runCommand +, setuptools +, copyDesktopItems +, pygobject3 +, wrapGAppsHook +, gtk3 +, gnome +, gobject-introspection +, clan-cli +}: +let + source = ./.; +in +python3.pkgs.buildPythonApplication { + name = "clan-vm-manager"; + src = source; + format = "pyproject"; + + makeWrapperArgs = [ + # This prevents problems with mixed glibc versions that might occur when the + # cli is called through a browser built against another glibc + "--unset LD_LIBRARY_PATH" + ]; + + nativeBuildInputs = [ + setuptools + copyDesktopItems + wrapGAppsHook + gobject-introspection + ]; + + buildInputs = [ gtk3 gnome.adwaita-icon-theme ]; + propagatedBuildInputs = [ pygobject3 clan-cli ]; + + # also re-expose dependencies so we test them in CI + passthru.tests = { + clan-vm-manager-no-breakpoints = runCommand "clan-vm-manager-no-breakpoints" { } '' + if grep --include \*.py -Rq "breakpoint()" ${source}; then + echo "breakpoint() found in ${source}:" + grep --include \*.py -Rn "breakpoint()" ${source} + exit 1 + fi + touch $out + ''; + }; + + # Don't leak python packages into a devshell. + # It can be very confusing if you `nix run` than load the cli from the devshell instead. + postFixup = '' + rm $out/nix-support/propagated-build-inputs + ''; + checkPhase = '' + PYTHONPATH= $out/bin/clan-vm-manager --help + ''; + meta.mainProgram = "clan"; +} diff --git a/pkgs/clan-vm-manager/flake-module.nix b/pkgs/clan-vm-manager/flake-module.nix new file mode 100644 index 000000000..7264c1302 --- /dev/null +++ b/pkgs/clan-vm-manager/flake-module.nix @@ -0,0 +1,12 @@ +{ ... }: { + perSystem = { config, pkgs, ... }: { + devShells.clan-vm-manager = pkgs.callPackage ./shell.nix { + inherit (config.packages) clan-cli clan-vm-manager; + }; + packages.clan-vm-manager = pkgs.python3.pkgs.callPackage ./default.nix { + inherit (config.packages) clan-cli; + }; + + checks = config.packages.clan-vm-manager.tests; + }; +} diff --git a/pkgs/clan-vm-manager/pyproject.toml b/pkgs/clan-vm-manager/pyproject.toml new file mode 100644 index 000000000..0ec43fce1 --- /dev/null +++ b/pkgs/clan-vm-manager/pyproject.toml @@ -0,0 +1,28 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "clan-vm-manager" +dynamic = ["version"] +scripts = { clan-vm-manager = "clan_vm_manager:main" } + +[tool.setuptools.package-data] +clan_vm_manager = ["*.glade"] + +[tool.mypy] +python_version = "3.10" +warn_redundant_casts = true +disallow_untyped_calls = true +disallow_untyped_defs = true +no_implicit_optional = true + +[[tool.mypy.overrides]] +module = "gi.*" +ignore_missing_imports = true + +[tool.ruff] +line-length = 88 + +select = ["E", "F", "I", "N"] +ignore = ["E501", "E402"] diff --git a/pkgs/clan-vm-manager/shell.nix b/pkgs/clan-vm-manager/shell.nix new file mode 100644 index 000000000..aecc5cd42 --- /dev/null +++ b/pkgs/clan-vm-manager/shell.nix @@ -0,0 +1,15 @@ +{ clan-vm-manager, clan-cli, mkShell, ruff, python3 }: +let + pythonWithDeps = python3.withPackages (ps: clan-vm-manager.propagatedBuildInputs); +in +mkShell { + buildInputs = [ pythonWithDeps ] ++ clan-vm-manager.buildInputs; + nativeBuildInputs = [ + ruff + ] ++ clan-vm-manager.nativeBuildInputs; + + shellHook = '' + rm -f ../clan-cli/clan_cli/nixpkgs + ln -sf ${clan-cli.nixpkgs} ../clan-cli/clan_cli/nixpkgs + ''; +} diff --git a/pkgs/flake-module.nix b/pkgs/flake-module.nix index 5173b5dbe..b3792a8f0 100644 --- a/pkgs/flake-module.nix +++ b/pkgs/flake-module.nix @@ -1,6 +1,7 @@ { ... }: { imports = [ ./clan-cli/flake-module.nix + ./clan-vm-manager/flake-module.nix ./installer/flake-module.nix ./ui/flake-module.nix ./theme/flake-module.nix From ce500066e9c38b8060e69fb701f50cea04995d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 23 Nov 2023 15:07:08 +0100 Subject: [PATCH 07/10] clan-vm-manager: simplify shellHook --- pkgs/clan-cli/shell.nix | 5 ++--- pkgs/clan-vm-manager/shell.nix | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/pkgs/clan-cli/shell.nix b/pkgs/clan-cli/shell.nix index 1bae91900..055154739 100644 --- a/pkgs/clan-cli/shell.nix +++ b/pkgs/clan-cli/shell.nix @@ -38,9 +38,8 @@ mkShell { --prefix "$tmp_path/python" \ --editable $repo_root - rm -f clan_cli/nixpkgs clan_cli/webui/assets - ln -sf ${clan-cli.nixpkgs} clan_cli/nixpkgs - ln -sf ${ui-assets} clan_cli/webui/assets + ln -sfT ${clan-cli.nixpkgs} clan_cli/nixpkgs + ln -sfT ${ui-assets} clan_cli/webui/assets export PATH="$tmp_path/python/bin:${checkScript}/bin:$PATH" export PYTHONPATH="$repo_root:$tmp_path/python/${pythonWithDeps.sitePackages}:" diff --git a/pkgs/clan-vm-manager/shell.nix b/pkgs/clan-vm-manager/shell.nix index aecc5cd42..878ae09c3 100644 --- a/pkgs/clan-vm-manager/shell.nix +++ b/pkgs/clan-vm-manager/shell.nix @@ -9,7 +9,6 @@ mkShell { ] ++ clan-vm-manager.nativeBuildInputs; shellHook = '' - rm -f ../clan-cli/clan_cli/nixpkgs - ln -sf ${clan-cli.nixpkgs} ../clan-cli/clan_cli/nixpkgs + ln -sfT ${clan-cli.nixpkgs} ../clan-cli/clan_cli/nixpkgs ''; } From 1a76cbdace2f0335da24632cb407af59f6bd3261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 23 Nov 2023 15:14:19 +0100 Subject: [PATCH 08/10] clan-vm-manager: prepend local clan-cli to python path --- pkgs/clan-vm-manager/bin/clan-vm-manager | 9 +++++---- pkgs/clan-vm-manager/shell.nix | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pkgs/clan-vm-manager/bin/clan-vm-manager b/pkgs/clan-vm-manager/bin/clan-vm-manager index 3b35422b3..a6c6a17ba 100755 --- a/pkgs/clan-vm-manager/bin/clan-vm-manager +++ b/pkgs/clan-vm-manager/bin/clan-vm-manager @@ -1,10 +1,11 @@ #!/usr/bin/env python3 -import os import sys +from pathlib import Path -sys.path.insert( - 0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) -) +module_path = Path(__file__).parent.parent.absolute() + +sys.path.insert(0, str(module_path)) +sys.path.insert(0, str(module_path.parent / "clan_cli")) from clan_vm_manager import main # NOQA diff --git a/pkgs/clan-vm-manager/shell.nix b/pkgs/clan-vm-manager/shell.nix index 878ae09c3..11296fb73 100644 --- a/pkgs/clan-vm-manager/shell.nix +++ b/pkgs/clan-vm-manager/shell.nix @@ -1,14 +1,14 @@ -{ clan-vm-manager, clan-cli, mkShell, ruff, python3 }: -let - pythonWithDeps = python3.withPackages (ps: clan-vm-manager.propagatedBuildInputs); -in +{ clan-vm-manager, clan-cli, mkShell, ruff }: mkShell { - buildInputs = [ pythonWithDeps ] ++ clan-vm-manager.buildInputs; + inherit (clan-vm-manager) propagatedBuildInputs buildInputs; nativeBuildInputs = [ ruff ] ++ clan-vm-manager.nativeBuildInputs; shellHook = '' ln -sfT ${clan-cli.nixpkgs} ../clan-cli/clan_cli/nixpkgs + + # prepend clan-cli for development + export PYTHONPATH=../clan-cli:$PYTHONPATH ''; } From 7047196b0709cb149294fdbe165f9b513fc841bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 23 Nov 2023 15:19:58 +0100 Subject: [PATCH 09/10] clan-vm-manager: add desktop-icon --- pkgs/clan-vm-manager/default.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkgs/clan-vm-manager/default.nix b/pkgs/clan-vm-manager/default.nix index a7277e373..1ffcbdb6c 100644 --- a/pkgs/clan-vm-manager/default.nix +++ b/pkgs/clan-vm-manager/default.nix @@ -8,6 +8,7 @@ , gnome , gobject-introspection , clan-cli +, makeDesktopItem }: let source = ./.; @@ -54,4 +55,14 @@ python3.pkgs.buildPythonApplication { PYTHONPATH= $out/bin/clan-vm-manager --help ''; meta.mainProgram = "clan"; + desktopItems = [ + (makeDesktopItem { + name = "clan-vm-manager"; + # TODO: this subcommand is not implemented yet + exec = "clan-vm-manager join %u"; + desktopName = "CLan VM Manager"; + startupWMClass = "clan"; + mimeTypes = [ "x-scheme-handler/clan" ]; + }) + ]; } From 595ba1ab23a6133458b24542b8686ecd8e913ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 23 Nov 2023 15:23:07 +0100 Subject: [PATCH 10/10] nix-direnv: update to 2.4.0 --- .envrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.envrc b/.envrc index 503fb6b69..ace8023dc 100644 --- a/.envrc +++ b/.envrc @@ -1,5 +1,5 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" +if ! has nix_direnv_version || ! nix_direnv_version 2.4.0; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.4.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" fi use flake