211 lines
5.5 KiB
Nix
211 lines
5.5 KiB
Nix
{ lib
|
|
, stdenv
|
|
, alembic
|
|
, async-generator
|
|
, beautifulsoup4
|
|
, buildPythonPackage
|
|
, certipy
|
|
, configurable-http-proxy
|
|
, cryptography
|
|
, entrypoints
|
|
, fetchPypi
|
|
, fetchzip
|
|
, importlib-metadata
|
|
, jinja2
|
|
, jsonschema
|
|
, jupyter-telemetry
|
|
, jupyterlab
|
|
, jupyter-core
|
|
, jupyter-server
|
|
, mock
|
|
, nbclassic
|
|
, nodePackages
|
|
, notebook
|
|
, oauthlib
|
|
, packaging
|
|
, pamela
|
|
, playwright
|
|
, prometheus-client
|
|
, pytest-asyncio
|
|
, pytestCheckHook
|
|
, python-dateutil
|
|
, pythonOlder
|
|
, requests
|
|
, requests-mock
|
|
, selenium
|
|
, sqlalchemy
|
|
, tornado
|
|
, traitlets
|
|
, virtualenv
|
|
}:
|
|
|
|
let
|
|
# js/css assets that setup.py tries to fetch via `npm install` when building
|
|
# from source. https://github.com/jupyterhub/jupyterhub/blob/master/package.json
|
|
bootstrap =
|
|
fetchzip {
|
|
url = "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz";
|
|
sha256 = "1ywmxqdccg0mgx0xknrn1hlrfnhcwphc12y9l91zizx26fqfmzgc";
|
|
};
|
|
font-awesome =
|
|
fetchzip {
|
|
url = "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz";
|
|
sha256 = "1xnxbdlfdd60z5ix152m8r2kk9dkwlqwpypky1mm3dv64ajnzdbk";
|
|
};
|
|
jquery =
|
|
fetchzip {
|
|
url = "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz";
|
|
sha256 = "0yi9ql493din1qa1s923nd5zvd0klk1sx00xj1wx2yambmq86vm9";
|
|
};
|
|
moment =
|
|
fetchzip {
|
|
url = "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz";
|
|
sha256 = "0ifzzla4zffw23g3xvhwx3fj3jny6cjzxfzl1x0317q8wa0c7w5i";
|
|
};
|
|
requirejs =
|
|
fetchzip {
|
|
url = "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz";
|
|
sha256 = "165hkli3qcd59cjqvli9r5f92i0h7czkmhcg1cgwamw2d0b7xibz";
|
|
};
|
|
|
|
in
|
|
|
|
buildPythonPackage rec {
|
|
pname = "jupyterhub";
|
|
version = "4.0.2";
|
|
format = "setuptools";
|
|
|
|
disabled = pythonOlder "3.7";
|
|
|
|
src = fetchPypi {
|
|
inherit pname version;
|
|
hash = "sha256-1ORQ7tjZDfvPDsoI8A8gk6C8503FH3z8C3BX9gI0Gh0=";
|
|
};
|
|
|
|
# Most of this only applies when building from source (e.g. js/css assets are
|
|
# pre-built and bundled in the official release tarball on pypi).
|
|
#
|
|
# Stuff that's always needed:
|
|
# * At runtime, we need configurable-http-proxy, so we substitute the store
|
|
# path.
|
|
#
|
|
# Other stuff that's only needed when building from source:
|
|
# * js/css assets are fetched from npm.
|
|
# * substitute store path for `lessc` commmand.
|
|
# * set up NODE_PATH so `lessc` can find `less-plugin-clean-css`.
|
|
# * don't run `npm install`.
|
|
preBuild = ''
|
|
export NODE_PATH=${nodePackages.less-plugin-clean-css}/lib/node_modules
|
|
|
|
substituteInPlace jupyterhub/proxy.py --replace \
|
|
"'configurable-http-proxy'" \
|
|
"'${configurable-http-proxy}/bin/configurable-http-proxy'"
|
|
|
|
substituteInPlace jupyterhub/tests/test_proxy.py --replace \
|
|
"'configurable-http-proxy'" \
|
|
"'${configurable-http-proxy}/bin/configurable-http-proxy'"
|
|
|
|
substituteInPlace setup.py --replace \
|
|
"'npm'" "'true'"
|
|
|
|
declare -A deps
|
|
deps[bootstrap]=${bootstrap}
|
|
deps[font-awesome]=${font-awesome}
|
|
deps[jquery]=${jquery}
|
|
deps[moment]=${moment}
|
|
deps[requirejs]=${requirejs}
|
|
|
|
mkdir -p share/jupyter/hub/static/components
|
|
for dep in "''${!deps[@]}"; do
|
|
if [ ! -e share/jupyter/hub/static/components/$dep ]; then
|
|
cp -r ''${deps[$dep]} share/jupyter/hub/static/components/$dep
|
|
fi
|
|
done
|
|
'';
|
|
|
|
propagatedBuildInputs = [
|
|
alembic
|
|
async-generator
|
|
certipy
|
|
python-dateutil
|
|
entrypoints
|
|
jinja2
|
|
jupyter-telemetry
|
|
oauthlib
|
|
packaging
|
|
pamela
|
|
prometheus-client
|
|
requests
|
|
selenium
|
|
sqlalchemy
|
|
tornado
|
|
traitlets
|
|
jupyter-core
|
|
jupyter-server
|
|
] ++ lib.optionals (pythonOlder "3.10") [
|
|
importlib-metadata
|
|
];
|
|
|
|
nativeCheckInputs = [
|
|
beautifulsoup4
|
|
cryptography
|
|
notebook
|
|
jsonschema
|
|
nbclassic
|
|
mock
|
|
jupyterlab
|
|
playwright
|
|
pytest-asyncio
|
|
pytestCheckHook
|
|
requests-mock
|
|
virtualenv
|
|
];
|
|
|
|
preCheck = ''
|
|
substituteInPlace jupyterhub/tests/test_spawner.py --replace \
|
|
"'jupyterhub-singleuser'" "'$out/bin/jupyterhub-singleuser'"
|
|
export PATH="$PATH:$out/bin";
|
|
'';
|
|
|
|
disabledTests = [
|
|
# Tries to install older versions through pip
|
|
"test_upgrade"
|
|
# Testcase fails to find requests import
|
|
"test_external_service"
|
|
# Attempts to do TLS connection
|
|
"test_connection_notebook_wrong_certs"
|
|
# AttributeError: 'coroutine' object...
|
|
"test_valid_events"
|
|
"test_invalid_events"
|
|
"test_user_group_roles"
|
|
];
|
|
|
|
disabledTestPaths = [
|
|
# Not testing with a running instance
|
|
# AttributeError: 'coroutine' object has no attribute 'db'
|
|
"docs/test_docs.py"
|
|
"jupyterhub/tests/browser/test_browser.py"
|
|
"jupyterhub/tests/test_api.py"
|
|
"jupyterhub/tests/test_auth_expiry.py"
|
|
"jupyterhub/tests/test_auth.py"
|
|
"jupyterhub/tests/test_metrics.py"
|
|
"jupyterhub/tests/test_named_servers.py"
|
|
"jupyterhub/tests/test_orm.py"
|
|
"jupyterhub/tests/test_pages.py"
|
|
"jupyterhub/tests/test_proxy.py"
|
|
"jupyterhub/tests/test_scopes.py"
|
|
"jupyterhub/tests/test_services_auth.py"
|
|
"jupyterhub/tests/test_singleuser.py"
|
|
"jupyterhub/tests/test_spawner.py"
|
|
"jupyterhub/tests/test_user.py"
|
|
];
|
|
|
|
meta = with lib; {
|
|
description = "Serves multiple Jupyter notebook instances";
|
|
homepage = "https://jupyter.org/";
|
|
changelog = "https://github.com/jupyterhub/jupyterhub/blob/${version}/docs/source/reference/changelog.md";
|
|
license = licenses.bsd3;
|
|
# darwin: E OSError: dlopen(/nix/store/43zml0mlr17r5jsagxr00xxx91hz9lky-openpam-20170430/lib/libpam.so, 6): image not found
|
|
broken = (stdenv.isLinux && stdenv.isAarch64) || stdenv.isDarwin;
|
|
};
|
|
}
|