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:
8
.envrc
8
.envrc
@@ -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="
|
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
|
||||||
fi
|
fi
|
||||||
|
|
||||||
use flake
|
watch_file .direnv/selected-shell
|
||||||
|
|
||||||
|
if [ -e .direnv/selected-shell ]; then
|
||||||
|
use flake .#$(cat .direnv/selected-shell)
|
||||||
|
else
|
||||||
|
use flake
|
||||||
|
fi
|
||||||
|
|||||||
@@ -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).
|
- **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!
|
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
107
devShell-python.nix
Normal 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
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
23
devShell.nix
23
devShell.nix
@@ -4,9 +4,28 @@
|
|||||||
, self'
|
, self'
|
||||||
, config
|
, 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 {
|
devShells.default = pkgs.mkShell {
|
||||||
|
# inputsFrom = [ self'.devShells.python ];
|
||||||
packages = [
|
packages = [
|
||||||
|
select-shell
|
||||||
pkgs.tea
|
pkgs.tea
|
||||||
self'.packages.tea-create-pr
|
self'.packages.tea-create-pr
|
||||||
self'.packages.merge-after-ci
|
self'.packages.merge-after-ci
|
||||||
@@ -17,6 +36,8 @@
|
|||||||
shellHook = ''
|
shellHook = ''
|
||||||
# no longer used
|
# no longer used
|
||||||
rm -f "$(git rev-parse --show-toplevel)/.git/hooks/pre-commit"
|
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}"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
imports = [
|
imports = [
|
||||||
./checks/flake-module.nix
|
./checks/flake-module.nix
|
||||||
./devShell.nix
|
./devShell.nix
|
||||||
|
./devShell-python.nix
|
||||||
./formatter.nix
|
./formatter.nix
|
||||||
./templates/flake-module.nix
|
./templates/flake-module.nix
|
||||||
./clanModules/flake-module.nix
|
./clanModules/flake-module.nix
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ dynamic = ["version"]
|
|||||||
scripts = { clan = "clan_cli:main" }
|
scripts = { clan = "clan_cli:main" }
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
exclude = ["clan_cli.nixpkgs*"]
|
exclude = ["clan_cli.nixpkgs*", "result"]
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
[tool.setuptools.package-data]
|
||||||
clan_cli = ["config/jsonschema/*", "webui/assets/**/*", "vms/mimetypes/**/*"]
|
clan_cli = ["config/jsonschema/*", "webui/assets/**/*", "vms/mimetypes/**/*"]
|
||||||
|
|||||||
@@ -13,6 +13,14 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
source = ./.;
|
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
|
in
|
||||||
python3.pkgs.buildPythonApplication {
|
python3.pkgs.buildPythonApplication {
|
||||||
name = "clan-vm-manager";
|
name = "clan-vm-manager";
|
||||||
@@ -36,15 +44,18 @@ python3.pkgs.buildPythonApplication {
|
|||||||
propagatedBuildInputs = [ pygobject3 clan-cli ];
|
propagatedBuildInputs = [ pygobject3 clan-cli ];
|
||||||
|
|
||||||
# also re-expose dependencies so we test them in CI
|
# also re-expose dependencies so we test them in CI
|
||||||
passthru.tests = {
|
passthru = {
|
||||||
clan-vm-manager-no-breakpoints = runCommand "clan-vm-manager-no-breakpoints" { } ''
|
inherit desktop-file;
|
||||||
if grep --include \*.py -Rq "breakpoint()" ${source}; then
|
tests = {
|
||||||
echo "breakpoint() found in ${source}:"
|
clan-vm-manager-no-breakpoints = runCommand "clan-vm-manager-no-breakpoints" { } ''
|
||||||
grep --include \*.py -Rn "breakpoint()" ${source}
|
if grep --include \*.py -Rq "breakpoint()" ${source}; then
|
||||||
exit 1
|
echo "breakpoint() found in ${source}:"
|
||||||
fi
|
grep --include \*.py -Rn "breakpoint()" ${source}
|
||||||
touch $out
|
exit 1
|
||||||
'';
|
fi
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Don't leak python packages into a devshell.
|
# Don't leak python packages into a devshell.
|
||||||
@@ -56,13 +67,6 @@ python3.pkgs.buildPythonApplication {
|
|||||||
PYTHONPATH= $out/bin/clan-vm-manager --help
|
PYTHONPATH= $out/bin/clan-vm-manager --help
|
||||||
'';
|
'';
|
||||||
desktopItems = [
|
desktopItems = [
|
||||||
(makeDesktopItem {
|
desktop-file
|
||||||
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" ];
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ name = "clan-vm-manager"
|
|||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
scripts = { clan-vm-manager = "clan_vm_manager:main" }
|
scripts = { clan-vm-manager = "clan_vm_manager:main" }
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
exclude = ["result"]
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
[tool.setuptools.package-data]
|
||||||
clan_vm_manager = ["**/assets/*"]
|
clan_vm_manager = ["**/assets/*"]
|
||||||
|
|
||||||
|
|||||||
39
pkgs/scripts/select-shell.py
Normal file
39
pkgs/scripts/select-shell.py
Normal 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")
|
||||||
Reference in New Issue
Block a user