1{ lib
2, stdenv
3, buildPythonPackage
4, pythonOlder
5, fetchPypi
6, fetchzip
7, alembic
8, async_generator
9, certipy
10, python-dateutil
11, entrypoints
12, jinja2
13, jupyter-telemetry
14, oauthlib
15, pamela
16, prometheus-client
17, requests
18, sqlalchemy
19, tornado
20, traitlets
21, nodePackages
22, beautifulsoup4
23, cryptography
24, notebook
25, pytest-asyncio
26, pytestCheckHook
27, requests-mock
28, virtualenv
29}:
30
31let
32 # js/css assets that setup.py tries to fetch via `npm install` when building
33 # from source. https://github.com/jupyterhub/jupyterhub/blob/master/package.json
34 bootstrap =
35 fetchzip {
36 url = "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz";
37 sha256 = "1ywmxqdccg0mgx0xknrn1hlrfnhcwphc12y9l91zizx26fqfmzgc";
38 };
39 font-awesome =
40 fetchzip {
41 url = "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz";
42 sha256 = "1xnxbdlfdd60z5ix152m8r2kk9dkwlqwpypky1mm3dv64ajnzdbk";
43 };
44 jquery =
45 fetchzip {
46 url = "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz";
47 sha256 = "0yi9ql493din1qa1s923nd5zvd0klk1sx00xj1wx2yambmq86vm9";
48 };
49 moment =
50 fetchzip {
51 url = "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz";
52 sha256 = "0ifzzla4zffw23g3xvhwx3fj3jny6cjzxfzl1x0317q8wa0c7w5i";
53 };
54 requirejs =
55 fetchzip {
56 url = "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz";
57 sha256 = "165hkli3qcd59cjqvli9r5f92i0h7czkmhcg1cgwamw2d0b7xibz";
58 };
59
60in
61
62buildPythonPackage rec {
63 pname = "jupyterhub";
64 version = "1.3.0";
65 disabled = pythonOlder "3.6";
66
67 src = fetchPypi {
68 inherit pname version;
69 sha256 = "13pf6qhimpaxj20871ff5rvwwan59320cdhhrn9cfh6314971zq5";
70 };
71
72 # Most of this only applies when building from source (e.g. js/css assets are
73 # pre-built and bundled in the official release tarball on pypi).
74 #
75 # Stuff that's always needed:
76 # * At runtime, we need configurable-http-proxy, so we substitute the store
77 # path.
78 #
79 # Other stuff that's only needed when building from source:
80 # * js/css assets are fetched from npm.
81 # * substitute store path for `lessc` commmand.
82 # * set up NODE_PATH so `lessc` can find `less-plugin-clean-css`.
83 # * don't run `npm install`.
84 preBuild = ''
85 export NODE_PATH=${nodePackages.less-plugin-clean-css}/lib/node_modules
86
87 substituteInPlace jupyterhub/proxy.py --replace \
88 "'configurable-http-proxy'" \
89 "'${nodePackages.configurable-http-proxy}/bin/configurable-http-proxy'"
90
91 substituteInPlace jupyterhub/tests/test_proxy.py --replace \
92 "'configurable-http-proxy'" \
93 "'${nodePackages.configurable-http-proxy}/bin/configurable-http-proxy'"
94
95 substituteInPlace setup.py --replace \
96 "'npm'" "'true'"
97
98 declare -A deps
99 deps[bootstrap]=${bootstrap}
100 deps[font-awesome]=${font-awesome}
101 deps[jquery]=${jquery}
102 deps[moment]=${moment}
103 deps[requirejs]=${requirejs}
104
105 mkdir -p share/jupyter/hub/static/components
106 for dep in "''${!deps[@]}"; do
107 if [ ! -e share/jupyter/hub/static/components/$dep ]; then
108 cp -r ''${deps[$dep]} share/jupyter/hub/static/components/$dep
109 fi
110 done
111 '';
112
113 propagatedBuildInputs = [
114 # https://github.com/jupyterhub/jupyterhub/blob/master/requirements.txt
115 alembic
116 async_generator
117 certipy
118 python-dateutil
119 entrypoints
120 jinja2
121 jupyter-telemetry
122 oauthlib
123 pamela
124 prometheus-client
125 requests
126 sqlalchemy
127 tornado
128 traitlets
129 ];
130
131 preCheck = ''
132 substituteInPlace jupyterhub/tests/test_spawner.py --replace \
133 "'jupyterhub-singleuser'" "'$out/bin/jupyterhub-singleuser'"
134 '';
135
136 checkInputs = [
137 # https://github.com/jupyterhub/jupyterhub/blob/master/dev-requirements.txt
138 beautifulsoup4
139 cryptography
140 notebook
141 pytest-asyncio
142 pytestCheckHook
143 requests-mock
144 virtualenv
145 ];
146
147 disabledTests = [
148 # Tries to install older versions through pip
149 "test_upgrade"
150 # Testcase fails to find requests import
151 "test_external_service"
152 ];
153
154 meta = with lib; {
155 description = "Serves multiple Jupyter notebook instances";
156 homepage = "https://jupyter.org/";
157 license = licenses.bsd3;
158 maintainers = with maintainers; [ ixxie cstrahan ];
159 # E OSError: dlopen(/nix/store/43zml0mlr17r5jsagxr00xxx91hz9lky-openpam-20170430/lib/libpam.so, 6): image not found
160 broken = stdenv.isDarwin;
161 };
162}