pybiolib 1.2.1187__tar.gz → 1.2.1232__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/PKG-INFO +4 -2
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/push_application.py +8 -6
- pybiolib-1.2.1232/biolib/_internal/utils/__init__.py +43 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/experiments/experiment.py +76 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/jobs/job.py +43 -3
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/jobs/job_result.py +6 -27
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/pyproject.toml +1 -1
- pybiolib-1.2.1187/biolib/_internal/utils/__init__.py +0 -18
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/LICENSE +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/PYPI_README.md +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_data_record/data_record.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/add_copilot_prompts.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/add_gui_files.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/data_record/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/data_record/data_record.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/data_record/push_data.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/data_record/remote_storage_endpoint.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/errors.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/file_utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/fuse_mount/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/fuse_mount/experiment_fuse_mount.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/http_client.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/lfs/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/lfs/cache.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/libs/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/libs/fusepy/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/runtime.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/string_utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/copilot_template/.github/instructions/general-app-knowledge.instructions.md +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/copilot_template/.github/instructions/style-general.instructions.md +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/copilot_template/.github/instructions/style-python.instructions.md +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/copilot_template/.github/instructions/style-react-ts.instructions.md +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/copilot_template/.github/prompts/biolib_app_inputs.prompt.md +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/copilot_template/.github/prompts/biolib_onboard_repo.prompt.md +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/copilot_template/.github/prompts/biolib_run_apps.prompt.md +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/.yarnrc.yml +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/App.tsx +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/Dockerfile +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/index.css +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/index.html +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/index.tsx +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/package.json +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/tsconfig.json +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/vite.config.mts +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/.biolib/config.yml +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/.github/workflows/biolib.yml +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/.gitignore +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/Dockerfile +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/requirements.txt +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/run.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/run.sh +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/templates.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/tree_utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/account.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/account_member.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/app.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/data_record.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/experiment.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/file_node.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/push.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/resource.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/resource_permission.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/resource_version.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/result.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/typing.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/types/user.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/utils/multinode.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_runtime/runtime.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_session/session.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/api/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/api/client.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/app/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/app/app.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/app/search_apps.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/api_client.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/app_types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/auth.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/biolib_app_api.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/biolib_job_api.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/common_types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/job_types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/lfs_types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_api_client/user_state.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/base_bbf_package.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/file_in_container.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/module_input.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/module_output_v2.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/remote_endpoints.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/remote_stream_seeker.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/saved_job.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/stdout_and_stderr.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/system_exception.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/system_status_update.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_binary_format/utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_docker_client/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_download_container.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_errors.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/biolib_logging.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/auth.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/data_record.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/download_container.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/init.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/lfs.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/push.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/run.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/runtime.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/sdk.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/cli/start.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/.gitignore +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/cloud_utils/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/cloud_utils/cloud_utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/cache_state.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/cache_types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/docker_image_cache.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/docker_executor.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/docker_types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/tars/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/job_legacy_input_wait_timeout_thread.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/job_max_runtime_timer_thread.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/job_storage.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/job_worker.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/large_file_system.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/mappings.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/utilization_reporter_thread.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/remote_host_proxy.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/socker_listener_thread.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/socket_sender_thread.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/compute_node_results_proxy.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/gunicorn_flask_application.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/proxy_utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/webserver.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/webserver_types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/webserver_utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/worker_thread.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/experiments/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/jobs/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/jobs/types.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/py.typed +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/runtime/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/sdk/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/tables.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/typing_utils.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/user/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/user/sign_in.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/utils/__init__.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/utils/app_uri.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/utils/cache_state.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/utils/multipart_uploader.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/utils/seq_util.py +0 -0
- {pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/utils/zip/remote_zip.py +0 -0
@@ -1,8 +1,9 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: pybiolib
|
3
|
-
Version: 1.2.
|
3
|
+
Version: 1.2.1232
|
4
4
|
Summary: BioLib Python Client
|
5
5
|
License: MIT
|
6
|
+
License-File: LICENSE
|
6
7
|
Keywords: biolib
|
7
8
|
Author: biolib
|
8
9
|
Author-email: hello@biolib.com
|
@@ -17,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
17
18
|
Classifier: Programming Language :: Python :: 3.11
|
18
19
|
Classifier: Programming Language :: Python :: 3.12
|
19
20
|
Classifier: Programming Language :: Python :: 3.13
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
20
22
|
Provides-Extra: compute-node
|
21
23
|
Requires-Dist: appdirs (>=1.4.3)
|
22
24
|
Requires-Dist: click (>=8.0.0)
|
@@ -248,13 +248,15 @@ def push_application(
|
|
248
248
|
f'(str, int, float, bool, list, dict, null) are used. Original error: {e}'
|
249
249
|
) from e
|
250
250
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
251
|
+
if 'assets' in config and 'app_data' not in config:
|
252
|
+
config['app_data'] = config.pop('assets')
|
253
|
+
elif 'assets' in config and 'app_data' in config:
|
254
|
+
raise BioLibError(
|
255
|
+
'In .biolib/config.yml you cannot specify both "app_data" and "assets" fields. Please use only one.'
|
256
|
+
)
|
257
257
|
|
258
|
+
app_data = config.get('app_data')
|
259
|
+
if app_data:
|
258
260
|
field_name = 'app_data' if 'app_data' in config else 'assets'
|
259
261
|
if not isinstance(app_data, str):
|
260
262
|
raise BioLibError(
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import time
|
2
|
+
import uuid
|
3
|
+
from fnmatch import fnmatch
|
4
|
+
|
5
|
+
from biolib.biolib_binary_format.utils import LazyLoadedFile
|
6
|
+
from biolib.typing_utils import Callable, List, Union, cast
|
7
|
+
|
8
|
+
PathFilter = Union[str, Callable[[str], bool]]
|
9
|
+
|
10
|
+
|
11
|
+
def filter_lazy_loaded_files(files: List[LazyLoadedFile], path_filter: PathFilter) -> List[LazyLoadedFile]:
|
12
|
+
if not (isinstance(path_filter, str) or callable(path_filter)):
|
13
|
+
raise Exception('Expected path_filter to be a string or a function')
|
14
|
+
|
15
|
+
if callable(path_filter):
|
16
|
+
return list(filter(lambda x: path_filter(x.path), files)) # type: ignore
|
17
|
+
|
18
|
+
glob_filter = cast(str, path_filter)
|
19
|
+
|
20
|
+
# since all file paths start with /, make sure filter does too
|
21
|
+
if not glob_filter.startswith('/'):
|
22
|
+
glob_filter = '/' + glob_filter
|
23
|
+
|
24
|
+
def _filter_function(file: LazyLoadedFile) -> bool:
|
25
|
+
return fnmatch(file.path, glob_filter)
|
26
|
+
|
27
|
+
return list(filter(_filter_function, files))
|
28
|
+
|
29
|
+
|
30
|
+
def open_browser_window_from_notebook(url_to_open: str) -> None:
|
31
|
+
try:
|
32
|
+
from IPython.display import ( # type:ignore # pylint: disable=import-error, import-outside-toplevel
|
33
|
+
Javascript,
|
34
|
+
display,
|
35
|
+
update_display,
|
36
|
+
)
|
37
|
+
except ImportError as error:
|
38
|
+
raise Exception('Unexpected environment. This function can only be called from a notebook.') from error
|
39
|
+
|
40
|
+
display_id = str(uuid.uuid4())
|
41
|
+
display(Javascript(f'window.open("{url_to_open}");'), display_id=display_id)
|
42
|
+
time.sleep(1)
|
43
|
+
update_display(Javascript(''), display_id=display_id)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import time
|
2
2
|
from collections import OrderedDict
|
3
|
+
from pathlib import Path
|
3
4
|
|
4
5
|
from biolib import api
|
5
6
|
from biolib._internal.types.experiment import DeprecatedExperimentDict, ExperimentDict
|
@@ -8,6 +9,7 @@ from biolib._internal.utils import open_browser_window_from_notebook
|
|
8
9
|
from biolib.biolib_api_client import BiolibApiClient
|
9
10
|
from biolib.biolib_errors import BioLibError
|
10
11
|
from biolib.jobs.job import Job
|
12
|
+
from biolib.jobs.job_result import PathFilter
|
11
13
|
from biolib.jobs.types import JobsPaginatedResponse
|
12
14
|
from biolib.tables import BioLibTable
|
13
15
|
from biolib.typing_utils import Dict, List, Optional, Union
|
@@ -223,6 +225,80 @@ class Experiment:
|
|
223
225
|
"""
|
224
226
|
return self.get_jobs(status=status)
|
225
227
|
|
228
|
+
def save_completed_results(
|
229
|
+
self,
|
230
|
+
output_dir: Optional[str] = None,
|
231
|
+
path_filter: Optional[PathFilter] = None,
|
232
|
+
skip_file_if_exists: bool = False,
|
233
|
+
overwrite: bool = False,
|
234
|
+
) -> None:
|
235
|
+
r"""Save all completed results in this experiment to local folders.
|
236
|
+
|
237
|
+
Creates a folder structure with the experiment name as the root directory,
|
238
|
+
containing a subfolder for each completed result. Only results with
|
239
|
+
'completed' status will be saved.
|
240
|
+
|
241
|
+
Args:
|
242
|
+
output_dir (str, optional): Base directory where the experiment folder
|
243
|
+
will be created. If None, uses the current working directory.
|
244
|
+
path_filter (PathFilter, optional): Filter to select which files in the results to save.
|
245
|
+
Can be a glob pattern string or a callable function.
|
246
|
+
skip_file_if_exists (bool, optional): Whether to skip files that already exist
|
247
|
+
locally instead of raising an error. Defaults to False.
|
248
|
+
overwrite (bool, optional): Whether to overwrite existing files.
|
249
|
+
Defaults to False.
|
250
|
+
|
251
|
+
Example::
|
252
|
+
|
253
|
+
>>> # Save all completed results to current directory
|
254
|
+
>>> experiment.save_completed_results()
|
255
|
+
>>> # This creates: ./experiment_name/result_1/, ./experiment_name/result_2/, etc.
|
256
|
+
|
257
|
+
>>> # Save to specific directory
|
258
|
+
>>> experiment.save_completed_results(output_dir="/path/to/save")
|
259
|
+
>>> # This creates: /path/to/save/experiment_name/result_1/, etc.
|
260
|
+
"""
|
261
|
+
base_dir = Path(output_dir) if output_dir else Path.cwd()
|
262
|
+
|
263
|
+
if base_dir == Path('/'):
|
264
|
+
raise BioLibError("Cannot save experiment results to root directory '/'")
|
265
|
+
|
266
|
+
experiment_folder = base_dir / self.name
|
267
|
+
experiment_folder.mkdir(parents=True, exist_ok=True)
|
268
|
+
|
269
|
+
completed_results: List[Job] = []
|
270
|
+
failed_results = False
|
271
|
+
print('Getting experiment status...')
|
272
|
+
for result in self.get_results():
|
273
|
+
if result.get_status() == 'completed':
|
274
|
+
completed_results.append(result)
|
275
|
+
elif result.get_status() != 'in_progress':
|
276
|
+
failed_results = True
|
277
|
+
|
278
|
+
if failed_results:
|
279
|
+
print(
|
280
|
+
'WARNING: Found failed or cancelled results in the experiment. '
|
281
|
+
'Please verify you have all your results, and consider removing the failed ones.'
|
282
|
+
)
|
283
|
+
if not completed_results:
|
284
|
+
print(f"No completed results found in experiment '{self.name}'")
|
285
|
+
return
|
286
|
+
|
287
|
+
print(f"Saving {len(completed_results)} completed results from experiment '{self.name}' to {experiment_folder}")
|
288
|
+
|
289
|
+
for result in completed_results:
|
290
|
+
result_name = result.get_name()
|
291
|
+
result_folder = experiment_folder / result_name
|
292
|
+
|
293
|
+
result_folder.mkdir(parents=True, exist_ok=True)
|
294
|
+
|
295
|
+
result.save_files(
|
296
|
+
output_dir=str(result_folder),
|
297
|
+
path_filter=path_filter,
|
298
|
+
skip_file_if_exists=skip_file_if_exists,
|
299
|
+
overwrite=overwrite,
|
300
|
+
)
|
301
|
+
|
226
302
|
def rename(self, destination: str) -> None:
|
227
303
|
api.client.patch(f'/resources/{self.uuid}/', data={'uri': destination})
|
228
304
|
self._refetch()
|
@@ -10,7 +10,7 @@ import biolib.api.client
|
|
10
10
|
from biolib import utils
|
11
11
|
from biolib._internal.http_client import HttpClient
|
12
12
|
from biolib._internal.tree_utils import build_tree_from_files, build_tree_str
|
13
|
-
from biolib._internal.utils import open_browser_window_from_notebook
|
13
|
+
from biolib._internal.utils import PathFilter, filter_lazy_loaded_files, open_browser_window_from_notebook
|
14
14
|
from biolib.api.client import ApiClient
|
15
15
|
from biolib.biolib_api_client import BiolibApiClient, CreatedJobDict
|
16
16
|
from biolib.biolib_api_client.biolib_app_api import BiolibAppApi
|
@@ -18,11 +18,12 @@ from biolib.biolib_api_client.biolib_job_api import BiolibJobApi
|
|
18
18
|
from biolib.biolib_binary_format import LazyLoadedFile, ModuleInput, ModuleInputDict, ModuleOutputV2
|
19
19
|
from biolib.biolib_binary_format.remote_endpoints import RemoteJobStorageEndpoint
|
20
20
|
from biolib.biolib_binary_format.stdout_and_stderr import StdoutAndStderr
|
21
|
+
from biolib.biolib_binary_format.utils import InMemoryIndexableBuffer
|
21
22
|
from biolib.biolib_errors import BioLibError, CloudJobFinishedError
|
22
23
|
from biolib.biolib_logging import logger, logger_no_user_data
|
23
24
|
from biolib.compute_node.job_worker.job_storage import JobStorage
|
24
25
|
from biolib.compute_node.utils import SystemExceptionCodeMap, SystemExceptionCodes
|
25
|
-
from biolib.jobs.job_result import JobResult
|
26
|
+
from biolib.jobs.job_result import JobResult
|
26
27
|
from biolib.jobs.types import CloudJobDict, CloudJobStartedDict, JobDict
|
27
28
|
from biolib.tables import BioLibTable
|
28
29
|
from biolib.typing_utils import Dict, List, Optional, Union, cast
|
@@ -187,6 +188,45 @@ class Result:
|
|
187
188
|
"""
|
188
189
|
return self.result.list_output_files(path_filter=path_filter)
|
189
190
|
|
191
|
+
def list_input_files(
|
192
|
+
self,
|
193
|
+
path_filter: Optional[PathFilter] = None,
|
194
|
+
) -> List[LazyLoadedFile]:
|
195
|
+
"""List input files from the result.
|
196
|
+
|
197
|
+
Args:
|
198
|
+
path_filter (PathFilter, optional): Filter to apply to the input files.
|
199
|
+
Can be a string glob pattern or a callable that takes a path string and returns a boolean.
|
200
|
+
|
201
|
+
Returns:
|
202
|
+
List[LazyLoadedFile]: List of input files.
|
203
|
+
|
204
|
+
Example::
|
205
|
+
>>> result = biolib.get_result("result_id")
|
206
|
+
>>> input_files = result.list_input_files()
|
207
|
+
>>> # Filter files with a glob pattern
|
208
|
+
>>> input_files = result.list_input_files("*.txt")
|
209
|
+
"""
|
210
|
+
presigned_download_url = BiolibJobApi.get_job_storage_download_url(
|
211
|
+
job_uuid=self.id,
|
212
|
+
job_auth_token=self._auth_token,
|
213
|
+
storage_type='input',
|
214
|
+
)
|
215
|
+
response = HttpClient.request(url=presigned_download_url)
|
216
|
+
module_input_serialized: bytes = response.content
|
217
|
+
module_input = ModuleInput(module_input_serialized).deserialize()
|
218
|
+
|
219
|
+
files = []
|
220
|
+
for path, data in module_input['files'].items():
|
221
|
+
buffer = InMemoryIndexableBuffer(data)
|
222
|
+
lazy_file = LazyLoadedFile(path=path, buffer=buffer, start=0, length=len(data))
|
223
|
+
files.append(lazy_file)
|
224
|
+
|
225
|
+
if not path_filter:
|
226
|
+
return files
|
227
|
+
|
228
|
+
return filter_lazy_loaded_files(files, path_filter)
|
229
|
+
|
190
230
|
def get_output_file(self, filename: str) -> LazyLoadedFile:
|
191
231
|
return self.result.get_output_file(filename=filename)
|
192
232
|
|
@@ -256,7 +296,7 @@ class Result:
|
|
256
296
|
self,
|
257
297
|
output_dir: str,
|
258
298
|
path_filter: Optional[PathFilter] = None,
|
259
|
-
skip_file_if_exists:
|
299
|
+
skip_file_if_exists: bool = False,
|
260
300
|
overwrite: bool = False,
|
261
301
|
) -> None:
|
262
302
|
self.result.save_files(
|
@@ -1,16 +1,14 @@
|
|
1
1
|
import time
|
2
|
-
from fnmatch import fnmatch
|
3
2
|
from pathlib import Path
|
4
3
|
|
4
|
+
from biolib._internal.utils import PathFilter, filter_lazy_loaded_files
|
5
5
|
from biolib.biolib_binary_format import ModuleOutputV2
|
6
6
|
from biolib.biolib_binary_format.remote_endpoints import RemoteJobStorageEndpoint
|
7
7
|
from biolib.biolib_binary_format.remote_stream_seeker import StreamSeeker
|
8
8
|
from biolib.biolib_binary_format.utils import LazyLoadedFile, RemoteIndexableBuffer
|
9
9
|
from biolib.biolib_errors import BioLibError
|
10
10
|
from biolib.biolib_logging import logger
|
11
|
-
from biolib.typing_utils import
|
12
|
-
|
13
|
-
PathFilter = Union[str, Callable[[str], bool]]
|
11
|
+
from biolib.typing_utils import List, Optional
|
14
12
|
|
15
13
|
|
16
14
|
class JobResult:
|
@@ -38,12 +36,12 @@ class JobResult:
|
|
38
36
|
self,
|
39
37
|
output_dir: str,
|
40
38
|
path_filter: Optional[PathFilter] = None,
|
41
|
-
skip_file_if_exists:
|
39
|
+
skip_file_if_exists: bool = False,
|
42
40
|
overwrite: bool = False,
|
43
41
|
) -> None:
|
44
42
|
module_output = self._get_module_output()
|
45
43
|
output_files = module_output.get_files()
|
46
|
-
filtered_output_files =
|
44
|
+
filtered_output_files = filter_lazy_loaded_files(output_files, path_filter) if path_filter else output_files
|
47
45
|
|
48
46
|
if len(filtered_output_files) == 0:
|
49
47
|
logger.debug('No output files to save')
|
@@ -100,7 +98,7 @@ class JobResult:
|
|
100
98
|
|
101
99
|
def get_output_file(self, filename) -> LazyLoadedFile:
|
102
100
|
files = self._get_module_output().get_files()
|
103
|
-
filtered_files =
|
101
|
+
filtered_files = filter_lazy_loaded_files(files, path_filter=filename)
|
104
102
|
if not filtered_files:
|
105
103
|
raise BioLibError(f'File {filename} not found in results.')
|
106
104
|
|
@@ -114,26 +112,7 @@ class JobResult:
|
|
114
112
|
if not path_filter:
|
115
113
|
return files
|
116
114
|
|
117
|
-
return
|
118
|
-
|
119
|
-
@staticmethod
|
120
|
-
def _get_filtered_files(files: List[LazyLoadedFile], path_filter: PathFilter) -> List[LazyLoadedFile]:
|
121
|
-
if not (isinstance(path_filter, str) or callable(path_filter)):
|
122
|
-
raise Exception('Expected path_filter to be a string or a function')
|
123
|
-
|
124
|
-
if callable(path_filter):
|
125
|
-
return list(filter(lambda x: path_filter(x.path), files)) # type: ignore
|
126
|
-
|
127
|
-
glob_filter = cast(str, path_filter)
|
128
|
-
|
129
|
-
# since all file paths start with /, make sure filter does too
|
130
|
-
if not glob_filter.startswith('/'):
|
131
|
-
glob_filter = '/' + glob_filter
|
132
|
-
|
133
|
-
def _filter_function(file: LazyLoadedFile) -> bool:
|
134
|
-
return fnmatch(file.path, glob_filter)
|
135
|
-
|
136
|
-
return list(filter(_filter_function, files))
|
115
|
+
return filter_lazy_loaded_files(files, path_filter)
|
137
116
|
|
138
117
|
def _get_module_output(self) -> ModuleOutputV2:
|
139
118
|
if self._module_output is None:
|
@@ -1,18 +0,0 @@
|
|
1
|
-
import time
|
2
|
-
import uuid
|
3
|
-
|
4
|
-
|
5
|
-
def open_browser_window_from_notebook(url_to_open: str) -> None:
|
6
|
-
try:
|
7
|
-
from IPython.display import ( # type:ignore # pylint: disable=import-error, import-outside-toplevel
|
8
|
-
Javascript,
|
9
|
-
display,
|
10
|
-
update_display,
|
11
|
-
)
|
12
|
-
except ImportError as error:
|
13
|
-
raise Exception('Unexpected environment. This function can only be called from a notebook.') from error
|
14
|
-
|
15
|
-
display_id = str(uuid.uuid4())
|
16
|
-
display(Javascript(f'window.open("{url_to_open}");'), display_id=display_id)
|
17
|
-
time.sleep(1)
|
18
|
-
update_display(Javascript(''), display_id=display_id)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/data_record/remote_storage_endpoint.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/fuse_mount/experiment_fuse_mount.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/package.json
RENAMED
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/tsconfig.json
RENAMED
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/gui_template/vite.config.mts
RENAMED
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/.biolib/config.yml
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/_internal/templates/init_template/requirements.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/docker_image_cache.py
RENAMED
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/__init__.py
RENAMED
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/docker_executor.py
RENAMED
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/docker_types.py
RENAMED
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/job_worker/executors/tars/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/compute_node_results_proxy.py
RENAMED
File without changes
|
{pybiolib-1.2.1187 → pybiolib-1.2.1232}/biolib/compute_node/webserver/gunicorn_flask_application.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|