nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 stdenv,
4 buildPythonPackage,
5 fetchFromGitHub,
6 pythonAtLeast,
7 writeScript,
8 writeShellScriptBin,
9 gradio,
10
11 # build-system
12 hatchling,
13 hatch-requirements-txt,
14 hatch-fancy-pypi-readme,
15
16 # web assets
17 zip,
18 nodejs_24,
19 pnpm_10,
20 fetchPnpmDeps,
21 pnpmConfigHook,
22
23 # dependencies
24 aiofiles,
25 anyio,
26 audioop-lts,
27 brotli,
28 fastapi,
29 ffmpy,
30 gradio-client,
31 groovy,
32 httpx,
33 huggingface-hub,
34 jinja2,
35 markupsafe,
36 numpy,
37 orjson,
38 packaging,
39 pandas,
40 pillow,
41 pydantic,
42 python-multipart,
43 pydub,
44 pyyaml,
45 safehttpx,
46 semantic-version,
47 starlette,
48 tomlkit,
49 typer,
50 typing-extensions,
51 uvicorn,
52
53 # oauth
54 authlib,
55 itsdangerous,
56
57 # tests
58 pytestCheckHook,
59 hypothesis,
60 altair,
61 boto3,
62 diffusers,
63 docker,
64 gradio-pdf,
65 ffmpeg,
66 ipython,
67 mcp,
68 polars,
69 pytest-asyncio,
70 respx,
71 scikit-image,
72 torch,
73 tqdm,
74 transformers,
75 vega-datasets,
76 writableTmpDirAsHomeHook,
77}:
78let
79 nodejs = nodejs_24;
80 pnpm = pnpm_10.override { inherit nodejs; };
81in
82buildPythonPackage rec {
83 pname = "gradio";
84 version = "6.4.0";
85 pyproject = true;
86
87 src = fetchFromGitHub {
88 owner = "gradio-app";
89 repo = "gradio";
90 tag = "gradio@${version}";
91 hash = "sha256-XHFhPoYSYmiEqTkknkqikfzdr3RRIagKWFlMgYWHYZ0=";
92 };
93
94 pnpmDeps = fetchPnpmDeps {
95 inherit
96 pname
97 pnpm
98 version
99 src
100 ;
101 fetcherVersion = 3;
102 hash = "sha256-6Cx0hdVd0srhArvck2Kn9U2fT7aKtTZjgV5b/Usrnoo=";
103 };
104
105 pythonRelaxDeps = [
106 "aiofiles"
107 "gradio-client"
108 "markupsafe"
109 "pydantic" # Requests >=2.11.10,<=2.12.4. Staging has it, master doesn't.
110 ];
111
112 pythonRemoveDeps = [
113 # this isn't a real runtime dependency
114 "ruff"
115 ];
116
117 nativeBuildInputs = [
118 zip
119 nodejs
120 pnpm
121 pnpmConfigHook
122 writableTmpDirAsHomeHook
123 ];
124
125 build-system = [
126 hatchling
127 hatch-requirements-txt
128 hatch-fancy-pypi-readme
129 ];
130
131 dependencies = [
132 aiofiles
133 anyio
134 brotli
135 fastapi
136 ffmpy
137 gradio-client
138 groovy
139 httpx
140 huggingface-hub
141 jinja2
142 markupsafe
143 numpy
144 orjson
145 packaging
146 pandas
147 pillow
148 pydantic
149 python-multipart
150 pydub
151 pyyaml
152 safehttpx
153 semantic-version
154 starlette
155 tomlkit
156 typer
157 typing-extensions
158 uvicorn
159 ]
160 ++ lib.optionals (pythonAtLeast "3.13") [
161 audioop-lts
162 ];
163
164 optional-dependencies.oauth = [
165 authlib
166 itsdangerous
167 ];
168
169 nativeCheckInputs = [
170 altair
171 boto3
172 brotli
173 diffusers
174 docker
175 ffmpeg
176 gradio-pdf
177 hypothesis
178 ipython
179 mcp
180 polars
181 pytest-asyncio
182 pytestCheckHook
183 respx
184 # shap is needed as well, but breaks too often
185 scikit-image
186 torch
187 tqdm
188 transformers
189 vega-datasets
190
191 # mock calls to `shutil.which(...)`
192 (writeShellScriptBin "npm" "false")
193 ]
194 ++ optional-dependencies.oauth
195 ++ pydantic.optional-dependencies.email;
196
197 preBuild = ''
198 pnpm build
199 pnpm package
200 '';
201
202 # Add a pytest hook skipping tests that access network, marking them as "Expected fail" (xfail).
203 # We additionally xfail FileNotFoundError, since the gradio devs often fail to upload test assets to pypi.
204 preCheck = ''
205 cat ${./conftest-skip-network-errors.py} >> test/conftest.py
206 ''
207 # OSError: [Errno 24] Too many open files
208 + lib.optionalString stdenv.hostPlatform.isDarwin ''
209 ulimit -n 4096
210 '';
211
212 disabledTests = [
213 # Actually broken
214 "test_mount_gradio_app"
215 "test_processing_utils_backwards_compatibility" # type error
216
217 # requires network, it caught our xfail exception
218 "test_error_analytics_successful"
219
220 # Flaky, tries to pin dependency behaviour. Sensitive to dep versions
221 # These error only affect downstream use of the check dependencies.
222 "test_no_color"
223 "test_in_interface_as_output"
224 "test_should_warn_url_not_having_version"
225
226 # Flaky, unknown reason
227 "test_in_interface"
228
229 # shap is too often broken in nixpkgs
230 "test_shapley_text"
231
232 # fails without network
233 "test_download_if_url_correct_parse"
234 "test_encode_url_to_base64_doesnt_encode_errors"
235
236 # flaky: OSError: Cannot find empty port in range: 7860-7959
237 "test_docs_url"
238 "test_orjson_serialization"
239 "test_dataset_is_updated"
240 "test_multimodal_api"
241 "test_examples_keep_all_suffixes"
242 "test_progress_bar"
243 "test_progress_bar_track_tqdm"
244 "test_info_and_warning_alerts"
245 "test_info_isolation[True]"
246 "test_info_isolation[False]"
247 "test_examples_no_cache_optional_inputs"
248 "test_start_server[127.0.0.1]"
249 "test_start_server[[::1]]"
250 "test_single_request"
251 "test_all_status_messages"
252 "test_default_concurrency_limits[not_set-statuses0]"
253 "test_default_concurrency_limits[None-statuses1]"
254 "test_default_concurrency_limits[1-statuses2]"
255 "test_default_concurrency_limits[2-statuses3]"
256 "test_concurrency_limits"
257
258 # tests if pip and other tools are installed
259 "test_get_executable_path"
260
261 # Flaky test (AssertionError when comparing to a fixed array)
262 # https://github.com/gradio-app/gradio/issues/11620
263 "test_auto_datatype"
264
265 # Failed: DID NOT RAISE <class 'ValueError'>
266 # (because it raises our NixNetworkAccessDeniedError)
267 "test_private_request_fail"
268
269 # TypeError: argument should be a str or an os.PathLike object where __fspath__ returns a str, not 'NoneType'
270 "test_component_example_values"
271 "test_public_request_pass"
272 "test_theme_builder_launches"
273 ]
274 ++ lib.optionals stdenv.hostPlatform.isDarwin [
275 # flaky on darwin (depend on port availability)
276 "test_all_status_messages"
277 "test_analytics_summary"
278 "test_async_generators"
279 "test_async_generators_interface"
280 "test_async_iterator_update_with_new_component"
281 "test_blocks_close_closes_thread_properly"
282 "test_caching"
283 "test_caching_audio_with_progress"
284 "test_caching_image"
285 "test_caching_with_async_generators"
286 "test_caching_with_batch"
287 "test_caching_with_batch_multiple_outputs"
288 "test_caching_with_dict"
289 "test_caching_with_float_numbers"
290 "test_caching_with_generators"
291 "test_caching_with_generators_and_streamed_output"
292 "test_caching_with_mix_update"
293 "test_caching_with_non_io_component"
294 "test_caching_with_update"
295 "test_chat_interface_api_name"
296 "test_chat_interface_api_names_with_additional_inputs"
297 "test_component_returned"
298 "test_css_and_css_paths_parameters"
299 "test_custom_css"
300 "test_default_concurrency_limits"
301 "test_default_flagging_callback"
302 "test_end_to_end"
303 "test_end_to_end_cache_examples"
304 "test_event_data"
305 "test_every_does_not_block_queue"
306 "test_example_caching"
307 "test_example_caching_async"
308 "test_example_caching_relaunch"
309 "test_example_caching_with_additional_inputs"
310 "test_example_caching_with_additional_inputs_already_rendered"
311 "test_example_caching_with_streaming"
312 "test_example_caching_with_streaming_async"
313 "test_exit_called_at_launch"
314 "test_file_component_uploads"
315 "test_files_saved_as_file_paths"
316 "test_flagging_does_not_create_unnecessary_directories"
317 "test_flagging_no_permission_error_with_flagging_disabled"
318 "test_info_and_warning_alerts"
319 "test_info_isolation"
320 "test_launch_analytics_does_not_error_with_invalid_blocks"
321 "test_mcp_streamable_http_client"
322 "test_mcp_streamable_http_client_with_progress_callback"
323 "test_multiple_file_flagging"
324 "test_multiple_messages"
325 "test_no_empty_audio_files"
326 "test_no_empty_image_files"
327 "test_no_empty_video_files"
328 "test_non_streaming_api"
329 "test_non_streaming_api_async"
330 "test_no_postprocessing"
331 "test_no_preprocessing"
332 "test_pil_images_hashed"
333 "test_post_process_file_blocked"
334 "test_progress_bar"
335 "test_progress_bar_track_tqdm"
336 "test_queue_when_using_auth"
337 "test_restart_after_close"
338 "test_set_share_in_colab"
339 "test_setting_cache_dir_env_variable"
340 "test_show_error"
341 "test_simple_csv_flagging_callback"
342 "test_single_request"
343 "test_socket_reuse"
344 "test_start_server"
345 "test_state_holder_is_used_in_postprocess"
346 "test_state_stored_up_to_capacity"
347 "test_static_files_single_app"
348 "test_streaming_api"
349 "test_streaming_api_async"
350 "test_streaming_api_with_additional_inputs"
351 "test_sync_generators"
352 "test_time_to_live_and_delete_callback_for_state"
353 "test_updates_stored_up_to_capacity"
354 "test_use_default_theme_as_fallback"
355 "test_varying_output_forms_with_generators"
356 ];
357
358 disabledTestPaths = [
359 # 100% touches network
360 "test/test_networking.py"
361 "client/python/test/test_client.py"
362 # makes pytest freeze 50% of the time
363 "test/test_interfaces.py"
364
365 # Local network tests dependant on port availability (port 7860-7959)
366 "test/test_routes.py"
367
368 # No module named build.__main__; 'build' is a package and cannot be directly executed
369 "test/test_docker/test_reverse_proxy/test_reverse_proxy.py"
370 "test/test_docker/test_reverse_proxy_fastapi_mount/test_reverse_proxy_fastapi_mount.py"
371 "test/test_docker/test_reverse_proxy_root_path/test_reverse_proxy_root_path.py"
372 ];
373
374 disabledTestMarks = [
375 "flaky"
376 ];
377
378 pytestFlags = [
379 "-x" # abort on first failure
380 # "-Wignore" # uncomment for debugging help
381 # Requires writable media assets in /nix/store
382 "--deselect"
383 "test/components/test_video.py::TestVideo::test_component_functions"
384 ];
385
386 # check the binary works outside the build env
387 postCheck = ''
388 env --ignore-environment $out/bin/gradio environment >/dev/null
389 '';
390
391 pythonImportsCheck = [ "gradio" ];
392
393 # Cyclic dependencies are fun!
394 # This is gradio without gradio-client and gradio-pdf
395 passthru = {
396 sans-reverse-dependencies =
397 (gradio.override {
398 gradio-client = null;
399 gradio-pdf = null;
400 }).overridePythonAttrs
401 (old: {
402 pname = old.pname + "-sans-reverse-dependencies";
403 pythonRemoveDeps = (old.pythonRemoveDeps or [ ]) ++ [ "gradio-client" ];
404 doInstallCheck = false;
405 doCheck = false;
406 postPatch = "";
407 preCheck = "";
408 disabledTests = [ ];
409 disabledTestPaths = [ ];
410 disabledTestMarks = [ ];
411 pytestFlags = [ ];
412 postInstall = ''
413 shopt -s globstar
414 for f in $out/**/*.py; do
415 cp $f "$f"i
416 done
417 shopt -u globstar
418 '';
419 pythonImportsCheck = null;
420 dontCheckRuntimeDeps = true;
421 });
422
423 # We can't use gitUpdater, because we need to update the pnpm hash.
424 # And we can't just use nix-update-script, because it often does not fetch
425 # enough tags for the ones we're looking for to show up.
426 updateScript = writeScript "update-python3Packages.gradio" ''
427 #! /usr/bin/env nix-shell
428 #! nix-shell -i bash -p common-updater-scripts coreutils gnugrep gnused nix-update
429
430 tag=$(list-git-tags \
431 | grep "^gradio@" \
432 | sed -e "s,^gradio@,," \
433 | grep -v -E -e ".*-(beta|dev).*" \
434 | sort --reverse --version-sort \
435 | head -n 1 \
436 | tr -d '\n' \
437 )
438 nix-update --version="$tag"
439 '';
440 };
441
442 meta = {
443 homepage = "https://www.gradio.app/";
444 changelog = "https://github.com/gradio-app/gradio/releases/tag/gradio@${version}";
445 description = "Python library for easily interacting with trained machine learning models";
446 license = lib.licenses.asl20;
447 maintainers = with lib.maintainers; [ pbsds ];
448 };
449}