Hi, folks!
I’m working on creating a development environment using nix-direnv
that includes otter-grader
. However, otter-grader
and two of its dependencies (fica
and ipylab
) are not currently available in nixpkgs
, so I’ve had to create custom derivations for them.
The problem I’m encountering is that otter-grader
does not seem to recognize ipylab
during its pythonRuntimeDepsCheckHook
. However, when I build the flake without otter-grader
, it works correctly, and I can load ipylab
as a Python module in the resulting environment.
To summarize:
Issue
The build process for otter-grader
consistently fails at the pythonRuntimeDepsCheckHook
, with the error message indicating that ipylab
is not installed.
The resulting error from `direnv reload`
error: builder for '/nix/store/vp51ffmi1lfbr7fa77qv37mdwlqvb6ij-otter-grader-5.5.0.drv' failed with exit code 1;
last 10 log lines:
> Running phase: pythonRuntimeDepsCheckHook
> Executing pythonRuntimeDepsCheck
> Checking runtime dependencies for otter_grader-5.5.0-py3-none-any.whl
> - ipylab not installed
For full logs, run 'nix log /nix/store/vp51ffmi1lfbr7fa77qv37mdwlqvb6ij-otter-grader-5.5.0.drv'.
error: 1 dependencies of derivation '/nix/store/xlpb90a1n44bvymgnvkcfhnsgq3qklh5-nix-shell-env.drv' failed to build
flake.nix (used by direnv)
{
description = "A flake to manage dependencies for otter-grader and related packages";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (
system: let
pkgs = import nixpkgs {inherit system;};
in {
packages = {
fica = pkgs.callPackage ./pkgs/fica/default.nix {};
ipylab = pkgs.callPackage ./pkgs/ipylab/default.nix {};
otter-grader = pkgs.callPackage ./pkgs/otter-grader/default.nix {
inherit (pkgs) lib python3 fetchFromGitHub;
fica = self.packages.${system}.fica;
ipylab = self.packages.${system}.ipylab;
};
};
devShells.default = pkgs.mkShell {
buildInputs = [
pkgs.python3
pkgs.nodejs
pkgs.git
pkgs.curl
pkgs.wget
pkgs.zsh
pkgs.direnv
self.packages.${system}.fica
self.packages.${system}.ipylab
self.packages.${system}.otter-grader
pkgs.python3.pkgs.ipykernel
pkgs.python3.pkgs.pandas
pkgs.python3.pkgs.matplotlib
pkgs.python3.pkgs.scipy
pkgs.python3.pkgs.scikit-learn
pkgs.python3.pkgs.jupyter
pkgs.python3.pkgs.jupyterlab
pkgs.python3.pkgs.numpy
pkgs.python3.pkgs.notebook
pkgs.python3.pkgs.plotly
pkgs.python3.pkgs.seaborn
pkgs.python3.pkgs.statsmodels
pkgs.python3.pkgs.beautifulsoup4
pkgs.python3.pkgs.requests
pkgs.python3.pkgs.lxml
pkgs.python3.pkgs.sqlalchemy
pkgs.python3.pkgs.nbconvert
pkgs.python3.pkgs.jupytext
pkgs.python3.pkgs.tqdm
pkgs.python3.pkgs.pytest
pkgs.python3.pkgs.sphinx
];
};
}
);
}
default.nix (otter-grader derivation)
{
lib,
python3,
fetchFromGitHub,
fica,
ipylab,
}:
python3.pkgs.buildPythonApplication rec {
pname = "otter-grader";
version = "5.5.0";
pyproject = true;
src = fetchFromGitHub {
owner = "ucbds-infra";
repo = "otter-grader";
rev = "v${version}";
hash = "sha256-RXdZDtTaSkkS0oahjOoMVXMbUlidC3EoP36FqIwdqvo=";
};
nativeBuildInputs = [
python3.pkgs.setuptools
python3.pkgs.wheel
];
propagatedBuildInputs =
(with python3.pkgs; [
astunparse
click
dill
fica
ipylab
ipython
ipywidgets
jinja2
jupytext
nbconvert
nbformat
pandas
python-on-whales
pyyaml
requests
wrapt
])
++ [
fica
ipylab
];
pythonImportsCheck = ["otter_grader"];
# Phases
preBuild = ''
export PYTHONPATH=$PYTHONPATH:${ipylab}/${python3.sitePackages}
'';
preCheck = ''
echo "Checking runtime dependencies for otter_grader..."
python3 -c "import ipylab; print(ipylab.__version__)"
'';
meta = with lib; {
description = "A Python and R autograding solution";
homepage = "https://github.com/ucbds-infra/otter-grader";
changelog = "https://github.com/ucbds-infra/otter-grader/blob/${src.rev}/CHANGELOG.md";
license = licenses.bsd3;
maintainers = with maintainers; [];
mainProgram = "otter-grader";
};
}
Suspected Culprit
I suspect the issue may be related to how dependencies are being referenced or propagated, but I’m not sure.
Request for Help
-
Build Order: How can I ensure
ipylab
is built and available beforeotter-grader
starts its build process? (I would have though the fact that it is a dependency would ensure this.) - Dependency Propagation: Are there any better ways to handle the dependency propagation in my setup? General ‘best practices’ derivation tips after reading my half-baked nix code would be wonderful too!
- Debugging Tips: Any tips on how to better debug this issue would be appreciated.
This is my first foray into making a custom derivation. I’d like to eventually contribute these to nixpkgs if I can get all the bugs worked out
Thanks for your help!