1
0
forked from clan/clan-core

devShells: one global python devshell + activation via command

- this adds devShells.{system}.python
- a 'select-shell' command to switch between devshells
This commit is contained in:
DavHau 2024-03-01 18:15:44 +07:00
parent 3acc4b4d25
commit d1e8b1ed96
9 changed files with 206 additions and 20 deletions

8
.envrc
View File

@ -2,4 +2,10 @@ if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
fi
use flake
watch_file .direnv/selected-shell
if [ -e .direnv/selected-shell ]; then
use flake .#$(cat .direnv/selected-shell)
else
use flake
fi

View File

@ -21,3 +21,8 @@ We welcome contributions from the community, and we've prepared a comprehensive
- **Contribution Guidelines**: Find out how to contribute and make a meaningful impact on the cLAN project by reading [contributing.md](docs/contributing/contributing.md).
Whether you're a newcomer or a seasoned developer, we look forward to your contributions and collaboration on the cLAN project. Let's build amazing things together!
### development environment
Setup `direnv` and `nix-direnv` and execute `dienv allow`.
To switch between different dev environments execute `select-shell`.

107
devShell-python.nix Normal file
View File

@ -0,0 +1,107 @@
{
perSystem =
{ pkgs
, self'
, lib
, ...
}:
let
python3 = pkgs.python3;
pypkgs = python3.pkgs;
clan-cli = self'.packages.clan-cli;
clan-vm-manager = self'.packages.clan-vm-manager;
pythonWithDeps = python3.withPackages (
ps:
clan-cli.propagatedBuildInputs
++ clan-cli.devDependencies
++ [
ps.pip
# clan-vm-manager deps
ps.pygobject3
]
);
linuxOnlyPackages = lib.optionals pkgs.stdenv.isLinux [
pkgs.xdg-utils
];
in
{
devShells.python = pkgs.mkShell {
inputsFrom = [ self'.devShells.default ];
packages =
[
pythonWithDeps
pypkgs.mypy
pypkgs.ipdb
pkgs.desktop-file-utils
pkgs.gtk4.dev
pkgs.ruff
pkgs.libadwaita.devdoc # has the demo called 'adwaita-1-demo'
]
++ linuxOnlyPackages
++ clan-vm-manager.nativeBuildInputs
++ clan-vm-manager.buildInputs
++ clan-cli.nativeBuildInputs;
PYTHONBREAKPOINT = "ipdb.set_trace";
shellHook = ''
ln -sfT ${clan-cli.nixpkgs} ./pkgs/clan-cli/clan_cli/nixpkgs
## PYTHON
tmp_path=$(realpath ./.direnv)
repo_root=$(realpath .)
mkdir -p "$tmp_path/python/${pythonWithDeps.sitePackages}"
# local dependencies
localPackages=(
$repo_root/pkgs/clan-cli
$repo_root/pkgs/clan-vm-manager
)
# Install the package in editable mode
# This allows executing `clan` from within the dev-shell using the current
# version of the code and its dependencies.
# TODO: this is slow. get rid of pip or add better caching
echo "==== Installing local python packages in editable mode ===="
for package in "''${localPackages[@]}"; do
${pythonWithDeps}/bin/pip install \
--quiet \
--disable-pip-version-check \
--no-index \
--no-build-isolation \
--prefix "$tmp_path/python" \
--editable "$package"
done
export PATH="$tmp_path/python/bin:$PATH"
export PYTHONPATH="''${PYTHONPATH:+$PYTHONPATH:}$tmp_path/python/${pythonWithDeps.sitePackages}"
# export PYTHONPATH="$tmp_path/python/${pythonWithDeps.sitePackages}"
for package in "''${localPackages[@]}"; do
export PYTHONPATH="$package:$PYTHONPATH"
done
if ! command -v xdg-mime &> /dev/null; then
echo "Warning: 'xdg-mime' is not available. The desktop file cannot be installed."
fi
# install desktop file
set -eou pipefail
DESKTOP_FILE_NAME=lol.clan.vm.manager.desktop
DESKTOP_DST=~/.local/share/applications/$DESKTOP_FILE_NAME
DESKTOP_SRC=${clan-vm-manager.desktop-file}/share/applications/$DESKTOP_FILE_NAME
UI_BIN="clan-vm-manager"
cp -f $DESKTOP_SRC $DESKTOP_DST
sleep 2
sed -i "s|Exec=.*clan-vm-manager|Exec=$UI_BIN|" $DESKTOP_DST
xdg-mime default $DESKTOP_FILE_NAME x-scheme-handler/clan
echo "==== Validating desktop file installation ===="
set -x
desktop-file-validate $DESKTOP_DST
set +xeou pipefail
'';
};
};
}

View File

@ -4,9 +4,28 @@
, self'
, config
, ...
}: {
}:
let
writers = pkgs.callPackage ./pkgs/builders/script-writers.nix { };
ansiEscapes = {
reset = ''\033[0m'';
green = ''\033[32m'';
};
# a python program using argparse to enable and disable dev shells
# synopsis: select-shell enable|disable shell-name
# enabled devshells are written as a newline separated list into ./.direnv/selected-shells
select-shell = writers.writePython3Bin "select-shell"
{
flakeIgnore = [ "E501" ];
} ./pkgs/scripts/select-shell.py;
in
{
devShells.default = pkgs.mkShell {
# inputsFrom = [ self'.devShells.python ];
packages = [
select-shell
pkgs.tea
self'.packages.tea-create-pr
self'.packages.merge-after-ci
@ -17,6 +36,8 @@
shellHook = ''
# no longer used
rm -f "$(git rev-parse --show-toplevel)/.git/hooks/pre-commit"
echo -e "${ansiEscapes.green}switch to another dev-shell using: select-shell${ansiEscapes.reset}"
'';
};
};

View File

@ -30,6 +30,7 @@
imports = [
./checks/flake-module.nix
./devShell.nix
./devShell-python.nix
./formatter.nix
./templates/flake-module.nix
./clanModules/flake-module.nix

View File

@ -9,7 +9,7 @@ dynamic = ["version"]
scripts = { clan = "clan_cli:main" }
[tool.setuptools.packages.find]
exclude = ["clan_cli.nixpkgs*"]
exclude = ["clan_cli.nixpkgs*", "result"]
[tool.setuptools.package-data]
clan_cli = ["config/jsonschema/*", "webui/assets/**/*", "vms/mimetypes/**/*"]

View File

@ -13,6 +13,14 @@
}:
let
source = ./.;
desktop-file = makeDesktopItem {
name = "lol.clan.vm.manager";
exec = "clan-vm-manager %u";
icon = ./clan_vm_manager/assets/clan_white.png;
desktopName = "cLAN Manager";
startupWMClass = "clan";
mimeTypes = [ "x-scheme-handler/clan" ];
};
in
python3.pkgs.buildPythonApplication {
name = "clan-vm-manager";
@ -36,15 +44,18 @@ python3.pkgs.buildPythonApplication {
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
'';
passthru = {
inherit desktop-file;
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.
@ -56,13 +67,6 @@ python3.pkgs.buildPythonApplication {
PYTHONPATH= $out/bin/clan-vm-manager --help
'';
desktopItems = [
(makeDesktopItem {
name = "lol.clan.vm.manager";
exec = "clan-vm-manager %u";
icon = ./clan_vm_manager/assets/clan_white.png;
desktopName = "cLAN Manager";
startupWMClass = "clan";
mimeTypes = [ "x-scheme-handler/clan" ];
})
desktop-file
];
}

View File

@ -9,6 +9,9 @@ name = "clan-vm-manager"
dynamic = ["version"]
scripts = { clan-vm-manager = "clan_vm_manager:main" }
[tool.setuptools.packages.find]
exclude = ["result"]
[tool.setuptools.package-data]
clan_vm_manager = ["**/assets/*"]

View File

@ -0,0 +1,39 @@
import argparse
import json
import pathlib
import subprocess
import sys
parser = argparse.ArgumentParser(description="Select a devshell")
parser.add_argument("shell", help="the name of the devshell to select", nargs="?")
parser.add_argument("--list", action="store_true", help="list available devshells")
args = parser.parse_args()
selected_shell_file = pathlib.Path(".direnv/selected-shell")
if not args.list and not args.shell:
parser.print_help()
exit(0)
if args.list:
flake_show = subprocess.run(
["nix", "flake", "show", "--json", "--no-write-lock-file"],
stdout=subprocess.PIPE,
)
data = json.loads(flake_show.stdout.decode())
print("Available devshells:")
print("\n".join(data["devShells"]["x86_64-linux"].keys()))
exit(0)
if selected_shell_file.exists():
with open(selected_shell_file) as f:
current_shell = f.read().strip()
else:
current_shell = ""
if current_shell == args.shell:
print(f"{args.shell} devshell already selected. No changes made.")
sys.exit(0)
with open(selected_shell_file, "w") as f:
f.write(args.shell)
print(f"{args.shell} devshell selected")