Added gtk demo app
This commit is contained in:
@@ -78,8 +78,7 @@ Let's get your development environment up and running:
|
|||||||
```
|
```
|
||||||
- Wait for the frontend to build.
|
- 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**:
|
9. **Start the Frontend**:
|
||||||
- To start the frontend, execute:
|
- To start the frontend, execute:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Any, Optional, Sequence
|
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 .custom_logger import setup_logging
|
||||||
from .dirs import get_clan_flake_toplevel
|
from .dirs import get_clan_flake_toplevel
|
||||||
from .ssh import cli as ssh_cli
|
from .ssh import cli as ssh_cli
|
||||||
@@ -64,6 +64,9 @@ def create_parser(prog: Optional[str] = None) -> argparse.ArgumentParser:
|
|||||||
|
|
||||||
subparsers = parser.add_subparsers()
|
subparsers = parser.add_subparsers()
|
||||||
|
|
||||||
|
parser_gtkui = subparsers.add_parser("gtkui", help="start gtkui")
|
||||||
|
gtkui.register_parser(parser_gtkui)
|
||||||
|
|
||||||
parser_flake = subparsers.add_parser(
|
parser_flake = subparsers.add_parser(
|
||||||
"flakes", help="create a clan flake inside the current directory"
|
"flakes", help="create a clan flake inside the current directory"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import deal
|
|
||||||
import shlex
|
import shlex
|
||||||
from pathlib import Path
|
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 .custom_logger import get_caller
|
||||||
from .errors import ClanError
|
from .errors import ClanError
|
||||||
@@ -16,8 +15,8 @@ class CmdOut(NamedTuple):
|
|||||||
stderr: str
|
stderr: str
|
||||||
cwd: Optional[Path] = None
|
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
|
cwd_res = None
|
||||||
if cwd is not None:
|
if cwd is not None:
|
||||||
if not cwd.exists():
|
if not cwd.exists():
|
||||||
@@ -52,7 +51,6 @@ stdout:
|
|||||||
return CmdOut(stdout.decode("utf-8"), stderr.decode("utf-8"), cwd=cwd)
|
return CmdOut(stdout.decode("utf-8"), stderr.decode("utf-8"), cwd=cwd)
|
||||||
|
|
||||||
|
|
||||||
@deal.raises(ClanError)
|
|
||||||
def runforcli(
|
def runforcli(
|
||||||
func: Callable[..., Coroutine[Any, Any, Dict[str, CmdOut]]], *args: Any
|
func: Callable[..., Coroutine[Any, Any, Dict[str, CmdOut]]], *args: Any
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|||||||
10
pkgs/clan-cli/clan_cli/gtkui/__init__.py
Normal file
10
pkgs/clan-cli/clan_cli/gtkui/__init__.py
Normal file
@@ -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)
|
||||||
49
pkgs/clan-cli/clan_cli/gtkui/app.glade
Normal file
49
pkgs/clan-cli/clan_cli/gtkui/app.glade
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.40.0 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.24"/>
|
||||||
|
<object class="GtkApplicationWindow" id="main-window">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFixed">
|
||||||
|
<property name="name">asdasd</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="help_button">
|
||||||
|
<property name="label" translatable="yes">May I help you?</property>
|
||||||
|
<property name="name">asdasd</property>
|
||||||
|
<property name="width-request">100</property>
|
||||||
|
<property name="height-request">80</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">True</property>
|
||||||
|
<property name="image-position">top</property>
|
||||||
|
<signal name="clicked" handler="on_help_button_clicked" object="coffee_label" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="x">21</property>
|
||||||
|
<property name="y">21</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="coffee_label">
|
||||||
|
<property name="width-request">100</property>
|
||||||
|
<property name="height-request">80</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Get me some coffe! </property>
|
||||||
|
<property name="width-chars">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="x">178</property>
|
||||||
|
<property name="y">120</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<style>
|
||||||
|
<class name="asdasd"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
49
pkgs/clan-cli/clan_cli/gtkui/app.glade~
Normal file
49
pkgs/clan-cli/clan_cli/gtkui/app.glade~
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.40.0 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.24"/>
|
||||||
|
<object class="GtkApplicationWindow" id="main-window">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFixed">
|
||||||
|
<property name="name">asdasd</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="help_button">
|
||||||
|
<property name="label" translatable="yes">May I help you?</property>
|
||||||
|
<property name="name">asdasd</property>
|
||||||
|
<property name="width-request">100</property>
|
||||||
|
<property name="height-request">80</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">True</property>
|
||||||
|
<property name="image-position">top</property>
|
||||||
|
<signal name="clicked" handler="on_help_button_clicked" object="coffee_label" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="x">21</property>
|
||||||
|
<property name="y">21</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="coffee_label">
|
||||||
|
<property name="width-request">100</property>
|
||||||
|
<property name="height-request">80</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Get me some coffe! </property>
|
||||||
|
<property name="width-chars">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="x">178</property>
|
||||||
|
<property name="y">120</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<style>
|
||||||
|
<class name="asdasd"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
19
pkgs/clan-cli/clan_cli/gtkui/app.py
Normal file
19
pkgs/clan-cli/clan_cli/gtkui/app.py
Normal file
@@ -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()
|
||||||
@@ -2,11 +2,14 @@ import json
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import deal
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
import deal
|
||||||
|
|
||||||
from .dirs import nixpkgs_flake, nixpkgs_source
|
from .dirs import nixpkgs_flake, nixpkgs_source
|
||||||
|
from .errors import ClanError
|
||||||
|
|
||||||
|
|
||||||
@deal.raises(ClanError)
|
@deal.raises(ClanError)
|
||||||
def nix_command(flags: list[str]) -> list[str]:
|
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)
|
@deal.raises(ClanError)
|
||||||
def nix_build(
|
def nix_build(
|
||||||
flags: list[str],
|
flags: list[str],
|
||||||
@@ -41,6 +45,7 @@ def nix_build(
|
|||||||
+ flags
|
+ flags
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@deal.raises(ClanError)
|
@deal.raises(ClanError)
|
||||||
def nix_config() -> dict[str, Any]:
|
def nix_config() -> dict[str, Any]:
|
||||||
cmd = nix_command(["show-config", "--json"])
|
cmd = nix_command(["show-config", "--json"])
|
||||||
@@ -51,6 +56,7 @@ def nix_config() -> dict[str, Any]:
|
|||||||
config[key] = value["value"]
|
config[key] = value["value"]
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
@deal.raises(ClanError)
|
@deal.raises(ClanError)
|
||||||
def nix_eval(flags: list[str]) -> list[str]:
|
def nix_eval(flags: list[str]) -> list[str]:
|
||||||
default_flags = nix_command(
|
default_flags = nix_command(
|
||||||
@@ -78,6 +84,7 @@ def nix_eval(flags: list[str]) -> list[str]:
|
|||||||
)
|
)
|
||||||
return default_flags + flags
|
return default_flags + flags
|
||||||
|
|
||||||
|
|
||||||
@deal.raises(ClanError)
|
@deal.raises(ClanError)
|
||||||
def nix_shell(packages: list[str], cmd: list[str]) -> list[str]:
|
def nix_shell(packages: list[str], cmd: list[str]) -> list[str]:
|
||||||
# we cannot use nix-shell inside the nix sandbox
|
# we cannot use nix-shell inside the nix sandbox
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ def get_task(uuid: UUID) -> BaseTask:
|
|||||||
|
|
||||||
T = TypeVar("T", bound="BaseTask")
|
T = TypeVar("T", bound="BaseTask")
|
||||||
|
|
||||||
|
|
||||||
@deal.raises(ClanError)
|
@deal.raises(ClanError)
|
||||||
def create_task(task_type: Type[T], *args: Any) -> T:
|
def create_task(task_type: Type[T], *args: Any) -> T:
|
||||||
global POOL
|
global POOL
|
||||||
|
|||||||
@@ -36,12 +36,17 @@
|
|||||||
, deal
|
, deal
|
||||||
, rope
|
, rope
|
||||||
, clan-core-path
|
, clan-core-path
|
||||||
, schemathesis
|
, schemathesis ? null
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
argcomplete # optional dependency: if not enabled, shell completion will not work
|
argcomplete # optional dependency: if not enabled, shell completion will not work
|
||||||
|
wrapGAppsHook
|
||||||
|
gtk3
|
||||||
|
glib
|
||||||
|
gobject-introspection
|
||||||
|
pygobject3
|
||||||
];
|
];
|
||||||
|
|
||||||
pytestDependencies = runtimeDependencies ++ dependencies ++ [
|
pytestDependencies = runtimeDependencies ++ dependencies ++ [
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ exclude = "clan_cli.nixpkgs"
|
|||||||
module = "argcomplete.*"
|
module = "argcomplete.*"
|
||||||
ignore_missing_imports = true
|
ignore_missing_imports = true
|
||||||
|
|
||||||
|
[[tool.mypy.overrides]]
|
||||||
|
module = "gi.*"
|
||||||
|
ignore_missing_imports = true
|
||||||
|
|
||||||
|
|
||||||
[[tool.mypy.overrides]]
|
[[tool.mypy.overrides]]
|
||||||
module = "jsonschema.*"
|
module = "jsonschema.*"
|
||||||
ignore_missing_imports = true
|
ignore_missing_imports = true
|
||||||
@@ -58,4 +63,4 @@ ignore_missing_imports = true
|
|||||||
line-length = 88
|
line-length = 88
|
||||||
|
|
||||||
select = [ "E", "F", "I", "N"]
|
select = [ "E", "F", "I", "N"]
|
||||||
ignore = [ "E501" ]
|
ignore = [ "E501", "E402" ]
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import deal
|
import deal
|
||||||
|
|
||||||
from clan_cli import task_manager
|
from clan_cli import nix, task_manager
|
||||||
from clan_cli import async_cmd
|
|
||||||
from clan_cli import nix
|
|
||||||
|
|
||||||
@deal.cases(task_manager.get_task)
|
@deal.cases(task_manager.get_task)
|
||||||
def test_get_task(case: deal.TestCase) -> None:
|
def test_get_task(case: deal.TestCase) -> None:
|
||||||
case()
|
case()
|
||||||
|
|
||||||
|
|
||||||
@deal.cases(task_manager.create_task)
|
@deal.cases(task_manager.create_task)
|
||||||
def test_create_task(case: deal.TestCase) -> None:
|
def test_create_task(case: deal.TestCase) -> None:
|
||||||
case()
|
case()
|
||||||
@@ -17,18 +17,22 @@ def test_create_task(case: deal.TestCase) -> None:
|
|||||||
def test_nix_command(case: deal.TestCase) -> None:
|
def test_nix_command(case: deal.TestCase) -> None:
|
||||||
case()
|
case()
|
||||||
|
|
||||||
|
|
||||||
@deal.cases(nix.nix_build)
|
@deal.cases(nix.nix_build)
|
||||||
def test_nix_build(case: deal.TestCase) -> None:
|
def test_nix_build(case: deal.TestCase) -> None:
|
||||||
case()
|
case()
|
||||||
|
|
||||||
|
|
||||||
@deal.cases(nix.nix_config)
|
@deal.cases(nix.nix_config)
|
||||||
def test_nix_config(case: deal.TestCase) -> None:
|
def test_nix_config(case: deal.TestCase) -> None:
|
||||||
case()
|
case()
|
||||||
|
|
||||||
|
|
||||||
@deal.cases(nix.nix_eval)
|
@deal.cases(nix.nix_eval)
|
||||||
def test_nix_eval(case: deal.TestCase) -> None:
|
def test_nix_eval(case: deal.TestCase) -> None:
|
||||||
case()
|
case()
|
||||||
|
|
||||||
|
|
||||||
@deal.cases(nix.nix_shell)
|
@deal.cases(nix.nix_shell)
|
||||||
def test_nix_shell(case: deal.TestCase) -> None:
|
def test_nix_shell(case: deal.TestCase) -> None:
|
||||||
case()
|
case()
|
||||||
|
|||||||
Reference in New Issue
Block a user