cloudos-cli 2.94.1__tar.gz → 2.95.1__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.
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/PKG-INFO +22 -37
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/README.md +21 -36
- cloudos_cli-2.95.1/cloudos_cli/_version.py +1 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/datasets/cli.py +13 -53
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/interactive_session/link.py +19 -140
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/jobs/cli.py +7 -2
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/jobs/job.py +170 -44
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli.egg-info/PKG-INFO +22 -37
- cloudos_cli-2.94.1/cloudos_cli/_version.py +0 -1
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/LICENSE +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/__main__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/bash/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/bash/cli.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/clos.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/configure/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/configure/cli.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/configure/configure.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/constants.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/cost/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/cost/cost.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/cromwell/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/cromwell/cli.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/datasets/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/datasets/datasets.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/import_wf/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/import_wf/import_wf.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/interactive_session/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/interactive_session/cli.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/interactive_session/interactive_session.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/jobs/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/logging/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/logging/logger.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/procurement/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/procurement/cli.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/procurement/images.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/projects/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/projects/cli.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/queue/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/queue/cli.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/queue/queue.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/related_analyses/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/related_analyses/related_analyses.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/array_job.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/cli_helpers.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/cloud.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/details.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/errors.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/last_wf.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/nextflow_version.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/requests.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/utils/resources.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/workflows/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/workflows/cli.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli.egg-info/SOURCES.txt +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli.egg-info/dependency_links.txt +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli.egg-info/entry_points.txt +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli.egg-info/requires.txt +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli.egg-info/top_level.txt +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/setup.cfg +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/setup.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/functions_for_pytest.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_cli_project_create.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_cost/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_cost/test_job_cost.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_details.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_error_messages.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_create_session.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_link_error_handling.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_link_session.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_list_sessions.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_normalize_path.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_logging/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_logging/test_logger.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_nextflow_version.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_related_analyses/__init__.py +0 -0
- {cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_related_analyses/test_related_analyses.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudos_cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.95.1
|
|
4
4
|
Summary: Python package for interacting with the Lifebit Platform
|
|
5
5
|
Home-page: https://github.com/lifebit-ai/cloudos-cli
|
|
6
6
|
Author: David Piñeyro
|
|
@@ -609,7 +609,7 @@ First, configure your local environment to ease parameter input. We will try to
|
|
|
609
609
|
cloudos job run --profile my_profile --workflow-name rnatoy --job-config cloudos_cli/examples/rnatoy.config --resumable
|
|
610
610
|
```
|
|
611
611
|
|
|
612
|
-
As you can see, a file with the job parameters is used to configure the job. This file
|
|
612
|
+
As you can see, a file with the job parameters is used to configure the job. This file is a list of the parameters to pass to your job, and nothing else. It has the following structure:
|
|
613
613
|
|
|
614
614
|
```
|
|
615
615
|
params {
|
|
@@ -618,6 +618,24 @@ params {
|
|
|
618
618
|
}
|
|
619
619
|
```
|
|
620
620
|
|
|
621
|
+
`--job-config` is shorthand for repeating `--parameter` on the command line: the CLI reads the file line by line, splits each line on the first `=`, and sends each result as one named parameter.
|
|
622
|
+
|
|
623
|
+
Every value is passed through as text, exactly as it would be when launching Nextflow from the command line.
|
|
624
|
+
|
|
625
|
+
> **IMPORTANT: `[ ]` is not expanded into a Nextflow list.** In a real `nextflow.config`, `my_param = ['a', 'b']` gives the pipeline a list of two items. Through `--job-config` it gives the pipeline the *string* `[a,b]`. The line is accepted and the job is submitted, so this fails silently at the point where your pipeline tries to iterate over the value. The CLI prints a warning when it sees a value that looks like a list, showing exactly what the pipeline will receive.
|
|
626
|
+
|
|
627
|
+
To pass a genuine list, define it in the pipeline's own `nextflow.config` in the git repository, or use `--params-file` with a JSON or YAML file (see below), which preserves types.
|
|
628
|
+
|
|
629
|
+
What a `--job-config` file cannot contain, because it is **not** a `nextflow.config` file:
|
|
630
|
+
|
|
631
|
+
- values spanning several lines
|
|
632
|
+
- nested blocks (e.g. `genomes { ... }`)
|
|
633
|
+
- `process`, `profiles`, `docker` or other config sections
|
|
634
|
+
|
|
635
|
+
Comments are supported, both on their own line and after a value, using `//` or `#`.
|
|
636
|
+
|
|
637
|
+
If a parameter needs a genuinely structured value rather than a string, either define it in the pipeline's own `nextflow.config` in the git repository and expose the parts you want to change as individual parameters, or pass it with `--params-file` (see below), which supports JSON and YAML with full type fidelity.
|
|
638
|
+
|
|
621
639
|
In addition, parameters can also be specified using the command-line `-p` or `--parameter`. For instance:
|
|
622
640
|
|
|
623
641
|
```bash
|
|
@@ -2648,7 +2666,7 @@ All configuration parameters are optional. If not specified, the session resumes
|
|
|
2648
2666
|
|
|
2649
2667
|
### Link
|
|
2650
2668
|
|
|
2651
|
-
The `cloudos interactive-session link` command provides a unified interface for linking files and folders to interactive analysis sessions. It consolidates functionality previously available through separate commands (`cloudos job results --link`, `cloudos job workdir --link`, `cloudos job logs --link
|
|
2669
|
+
The `cloudos interactive-session link` command provides a unified interface for linking files and folders to interactive analysis sessions. It consolidates functionality previously available through separate commands (`cloudos job results --link`, `cloudos job workdir --link`, and `cloudos job logs --link`) into a single, intuitive interface.
|
|
2652
2670
|
|
|
2653
2671
|
#### Link Files and Folders to Interactive Analysis
|
|
2654
2672
|
|
|
@@ -2880,41 +2898,8 @@ cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
|
|
|
2880
2898
|
```
|
|
2881
2899
|
|
|
2882
2900
|
|
|
2883
|
-
#### Link Files and Folders to Interactive Analysis
|
|
2884
|
-
|
|
2885
|
-
Connect external S3 buckets, S3 files, or File Explorer files/folders to your interactive analysis sessions. This provides direct access to data without needing to copy files.
|
|
2886
|
-
|
|
2887
|
-
This subcommand uses the `--session-id` option to access the correct interactive session. This option can be added to the CLI or defined in a profile, for convenience.
|
|
2888
|
-
|
|
2889
|
-
```bash
|
|
2890
|
-
cloudos datasets link <PATH> --profile <profile> --session-id <SESSION_ID>
|
|
2891
|
-
```
|
|
2892
|
-
|
|
2893
|
-
Link an S3 folder:
|
|
2894
|
-
```console
|
|
2895
|
-
cloudos datasets link s3://bucket/path/folder --profile test --session-id 1234
|
|
2896
|
-
```
|
|
2897
|
-
|
|
2898
|
-
Link an S3 file:
|
|
2899
|
-
```console
|
|
2900
|
-
cloudos datasets link s3://bucket/path/data.csv --profile test --session-id 1234
|
|
2901
|
-
```
|
|
2902
|
-
|
|
2903
|
-
Link a File Explorer folder (requires `--project-name`):
|
|
2904
|
-
```console
|
|
2905
|
-
cloudos datasets link "Data/HLA" --project-name my-project --session-id 1234
|
|
2906
|
-
```
|
|
2907
|
-
|
|
2908
|
-
Link a File Explorer file (requires `--project-name`):
|
|
2909
|
-
```console
|
|
2910
|
-
cloudos datasets link "Data/observations.csv" --project-name my-project --session-id 1234
|
|
2911
|
-
```
|
|
2912
|
-
|
|
2913
|
-
> [!NOTE]
|
|
2914
|
-
> If running the CLI inside a jupyter session, the pre-configured CLI installation will have the session ID already installed and only the `--apikey` needs to be added.
|
|
2915
|
-
|
|
2916
2901
|
> [!NOTE]
|
|
2917
|
-
>
|
|
2902
|
+
> To link files or folders (S3 or File Explorer) to an interactive analysis session, use `cloudos interactive-session link` or the `--link` option of `cloudos interactive-session create`. Virtual folders in File Explorer cannot be linked.
|
|
2918
2903
|
|
|
2919
2904
|
> [!NOTE]
|
|
2920
2905
|
> A maximum of 100 items can be linked per session. If the new items combined with already-linked items exceed this limit, the entire request is rejected.
|
|
@@ -574,7 +574,7 @@ First, configure your local environment to ease parameter input. We will try to
|
|
|
574
574
|
cloudos job run --profile my_profile --workflow-name rnatoy --job-config cloudos_cli/examples/rnatoy.config --resumable
|
|
575
575
|
```
|
|
576
576
|
|
|
577
|
-
As you can see, a file with the job parameters is used to configure the job. This file
|
|
577
|
+
As you can see, a file with the job parameters is used to configure the job. This file is a list of the parameters to pass to your job, and nothing else. It has the following structure:
|
|
578
578
|
|
|
579
579
|
```
|
|
580
580
|
params {
|
|
@@ -583,6 +583,24 @@ params {
|
|
|
583
583
|
}
|
|
584
584
|
```
|
|
585
585
|
|
|
586
|
+
`--job-config` is shorthand for repeating `--parameter` on the command line: the CLI reads the file line by line, splits each line on the first `=`, and sends each result as one named parameter.
|
|
587
|
+
|
|
588
|
+
Every value is passed through as text, exactly as it would be when launching Nextflow from the command line.
|
|
589
|
+
|
|
590
|
+
> **IMPORTANT: `[ ]` is not expanded into a Nextflow list.** In a real `nextflow.config`, `my_param = ['a', 'b']` gives the pipeline a list of two items. Through `--job-config` it gives the pipeline the *string* `[a,b]`. The line is accepted and the job is submitted, so this fails silently at the point where your pipeline tries to iterate over the value. The CLI prints a warning when it sees a value that looks like a list, showing exactly what the pipeline will receive.
|
|
591
|
+
|
|
592
|
+
To pass a genuine list, define it in the pipeline's own `nextflow.config` in the git repository, or use `--params-file` with a JSON or YAML file (see below), which preserves types.
|
|
593
|
+
|
|
594
|
+
What a `--job-config` file cannot contain, because it is **not** a `nextflow.config` file:
|
|
595
|
+
|
|
596
|
+
- values spanning several lines
|
|
597
|
+
- nested blocks (e.g. `genomes { ... }`)
|
|
598
|
+
- `process`, `profiles`, `docker` or other config sections
|
|
599
|
+
|
|
600
|
+
Comments are supported, both on their own line and after a value, using `//` or `#`.
|
|
601
|
+
|
|
602
|
+
If a parameter needs a genuinely structured value rather than a string, either define it in the pipeline's own `nextflow.config` in the git repository and expose the parts you want to change as individual parameters, or pass it with `--params-file` (see below), which supports JSON and YAML with full type fidelity.
|
|
603
|
+
|
|
586
604
|
In addition, parameters can also be specified using the command-line `-p` or `--parameter`. For instance:
|
|
587
605
|
|
|
588
606
|
```bash
|
|
@@ -2613,7 +2631,7 @@ All configuration parameters are optional. If not specified, the session resumes
|
|
|
2613
2631
|
|
|
2614
2632
|
### Link
|
|
2615
2633
|
|
|
2616
|
-
The `cloudos interactive-session link` command provides a unified interface for linking files and folders to interactive analysis sessions. It consolidates functionality previously available through separate commands (`cloudos job results --link`, `cloudos job workdir --link`, `cloudos job logs --link
|
|
2634
|
+
The `cloudos interactive-session link` command provides a unified interface for linking files and folders to interactive analysis sessions. It consolidates functionality previously available through separate commands (`cloudos job results --link`, `cloudos job workdir --link`, and `cloudos job logs --link`) into a single, intuitive interface.
|
|
2617
2635
|
|
|
2618
2636
|
#### Link Files and Folders to Interactive Analysis
|
|
2619
2637
|
|
|
@@ -2845,41 +2863,8 @@ cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
|
|
|
2845
2863
|
```
|
|
2846
2864
|
|
|
2847
2865
|
|
|
2848
|
-
#### Link Files and Folders to Interactive Analysis
|
|
2849
|
-
|
|
2850
|
-
Connect external S3 buckets, S3 files, or File Explorer files/folders to your interactive analysis sessions. This provides direct access to data without needing to copy files.
|
|
2851
|
-
|
|
2852
|
-
This subcommand uses the `--session-id` option to access the correct interactive session. This option can be added to the CLI or defined in a profile, for convenience.
|
|
2853
|
-
|
|
2854
|
-
```bash
|
|
2855
|
-
cloudos datasets link <PATH> --profile <profile> --session-id <SESSION_ID>
|
|
2856
|
-
```
|
|
2857
|
-
|
|
2858
|
-
Link an S3 folder:
|
|
2859
|
-
```console
|
|
2860
|
-
cloudos datasets link s3://bucket/path/folder --profile test --session-id 1234
|
|
2861
|
-
```
|
|
2862
|
-
|
|
2863
|
-
Link an S3 file:
|
|
2864
|
-
```console
|
|
2865
|
-
cloudos datasets link s3://bucket/path/data.csv --profile test --session-id 1234
|
|
2866
|
-
```
|
|
2867
|
-
|
|
2868
|
-
Link a File Explorer folder (requires `--project-name`):
|
|
2869
|
-
```console
|
|
2870
|
-
cloudos datasets link "Data/HLA" --project-name my-project --session-id 1234
|
|
2871
|
-
```
|
|
2872
|
-
|
|
2873
|
-
Link a File Explorer file (requires `--project-name`):
|
|
2874
|
-
```console
|
|
2875
|
-
cloudos datasets link "Data/observations.csv" --project-name my-project --session-id 1234
|
|
2876
|
-
```
|
|
2877
|
-
|
|
2878
|
-
> [!NOTE]
|
|
2879
|
-
> If running the CLI inside a jupyter session, the pre-configured CLI installation will have the session ID already installed and only the `--apikey` needs to be added.
|
|
2880
|
-
|
|
2881
2866
|
> [!NOTE]
|
|
2882
|
-
>
|
|
2867
|
+
> To link files or folders (S3 or File Explorer) to an interactive analysis session, use `cloudos interactive-session link` or the `--link` option of `cloudos interactive-session create`. Virtual folders in File Explorer cannot be linked.
|
|
2883
2868
|
|
|
2884
2869
|
> [!NOTE]
|
|
2885
2870
|
> A maximum of 100 items can be linked per session. If the new items combined with already-linked items exceed this limit, the entire request is rejected.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.95.1'
|
|
@@ -4,7 +4,6 @@ import rich_click as click
|
|
|
4
4
|
import csv
|
|
5
5
|
import sys
|
|
6
6
|
from cloudos_cli.datasets import Datasets
|
|
7
|
-
from cloudos_cli.interactive_session.link import Link
|
|
8
7
|
from cloudos_cli.utils.resources import ssl_selector, format_bytes
|
|
9
8
|
from cloudos_cli.configure.configure import with_profile_config, CLOUDOS_URL
|
|
10
9
|
from cloudos_cli.logging.logger import update_command_context_from_click
|
|
@@ -727,57 +726,18 @@ def rm_item(ctx,
|
|
|
727
726
|
raise ValueError(f"Remove operation failed. {str(e)}")
|
|
728
727
|
|
|
729
728
|
|
|
730
|
-
@datasets.command(
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
@click.option('--project-name',
|
|
737
|
-
help='The name of a Lifebit Platform project.',
|
|
738
|
-
required=False)
|
|
739
|
-
@click.option('--workspace-id', help='The specific Lifebit Platform workspace id.', required=True)
|
|
740
|
-
@click.option('--session-id', help='The specific Lifebit Platform interactive session id.', required=True)
|
|
741
|
-
@click.option('--disable-ssl-verification', is_flag=True, help='Disable SSL certificate verification.')
|
|
742
|
-
@click.option('--ssl-cert', help='Path to your SSL certificate file.')
|
|
743
|
-
@click.option('--profile', help='Profile to use from the config file', default='default')
|
|
729
|
+
@datasets.command(
|
|
730
|
+
name="link",
|
|
731
|
+
hidden=True,
|
|
732
|
+
add_help_option=False,
|
|
733
|
+
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
|
|
734
|
+
)
|
|
744
735
|
@click.pass_context
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
session_id,
|
|
753
|
-
disable_ssl_verification,
|
|
754
|
-
ssl_cert,
|
|
755
|
-
profile):
|
|
756
|
-
"""
|
|
757
|
-
Link a file or folder (S3 or File Explorer) to an active interactive analysis.
|
|
758
|
-
|
|
759
|
-
PATH [path]: the full path to the S3 file/folder or relative path in File Explorer
|
|
760
|
-
(relative to the project specified by --project-name).
|
|
761
|
-
E.g.: 's3://bucket-name/folder/subfolder', 's3://bucket/data/file.csv',
|
|
762
|
-
'Data/Downloads', 'Data', or 'Data/file.csv'.
|
|
763
|
-
"""
|
|
764
|
-
if not path.startswith("s3://") and project_name is None:
|
|
765
|
-
raise click.UsageError("When using File Explorer paths '--project-name' needs to be defined")
|
|
766
|
-
|
|
767
|
-
verify_ssl = ssl_selector(disable_ssl_verification, ssl_cert)
|
|
768
|
-
|
|
769
|
-
link_p = Link(
|
|
770
|
-
cloudos_url=cloudos_url,
|
|
771
|
-
apikey=apikey,
|
|
772
|
-
workspace_id=workspace_id,
|
|
773
|
-
cromwell_token=None,
|
|
774
|
-
project_name=project_name,
|
|
775
|
-
verify=verify_ssl
|
|
736
|
+
def link_deprecated(ctx):
|
|
737
|
+
raise click.ClickException(
|
|
738
|
+
"'cloudos datasets link' has been removed.\n\n"
|
|
739
|
+
"Use one of the supported alternatives:\n"
|
|
740
|
+
" cloudos interactive-session link <PATH> --session-id <SESSION_ID>\n"
|
|
741
|
+
" cloudos interactive-session create --link <PATH> [...]\n\n"
|
|
742
|
+
"Add --profile <my_profile> to either command to use a saved profile."
|
|
776
743
|
)
|
|
777
|
-
|
|
778
|
-
try:
|
|
779
|
-
success = link_p.link_folder(path, session_id)
|
|
780
|
-
except Exception as e:
|
|
781
|
-
raise ValueError(f"Could not link item. {e}")
|
|
782
|
-
if not success:
|
|
783
|
-
raise click.ClickException("Linking failed: mount verification did not reach 'mounted' status.")
|
|
@@ -78,8 +78,7 @@ class Link(Cloudos):
|
|
|
78
78
|
committed_count: int = 0) -> bool:
|
|
79
79
|
"""Link multiple folders/files (S3 or File Explorer) to an interactive session in one request.
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
with automatic fallback to v1 (individual requests) if v2 is not available.
|
|
81
|
+
Uses API v2 which supports multiple items per request.
|
|
83
82
|
|
|
84
83
|
Parameters
|
|
85
84
|
----------
|
|
@@ -112,17 +111,13 @@ class Link(Cloudos):
|
|
|
112
111
|
# Parse and validate all items
|
|
113
112
|
data_items, folder_info = self._parse_items_to_data_items(folders, existing_mount_names)
|
|
114
113
|
|
|
115
|
-
#
|
|
114
|
+
# Mount via v2 API (supports batch)
|
|
116
115
|
status_code = self._try_mount_v2(data_items, session_id)
|
|
117
116
|
|
|
118
|
-
if status_code is None:
|
|
119
|
-
# v2 failed or not available, fall back to v1
|
|
120
|
-
status_code = self._fallback_mount_v1(folder_info, session_id)
|
|
121
|
-
|
|
122
117
|
# Verify mount completion for all items (any 2xx response means success)
|
|
123
|
-
if
|
|
118
|
+
if 200 <= status_code < 300:
|
|
124
119
|
return self._verify_all_mounts(folder_info, session_id)
|
|
125
|
-
return
|
|
120
|
+
return False
|
|
126
121
|
|
|
127
122
|
def _parse_items_to_data_items(self, folders: list, existing_mount_names: set = None) -> tuple:
|
|
128
123
|
"""Parse and validate folders/files, extracting data items for API payload.
|
|
@@ -206,7 +201,7 @@ class Link(Cloudos):
|
|
|
206
201
|
)
|
|
207
202
|
|
|
208
203
|
def _try_mount_v2(self, data_items: list, session_id: str) -> int:
|
|
209
|
-
"""
|
|
204
|
+
"""Mount items using API v2.
|
|
210
205
|
|
|
211
206
|
Parameters
|
|
212
207
|
----------
|
|
@@ -217,151 +212,35 @@ class Link(Cloudos):
|
|
|
217
212
|
|
|
218
213
|
Returns
|
|
219
214
|
-------
|
|
220
|
-
int
|
|
221
|
-
|
|
215
|
+
int
|
|
216
|
+
HTTP status code on success.
|
|
222
217
|
|
|
223
218
|
Raises
|
|
224
219
|
------
|
|
225
220
|
ValueError
|
|
226
|
-
If
|
|
221
|
+
If the mount request fails.
|
|
227
222
|
"""
|
|
228
223
|
v2_payload = {"dataItems": data_items}
|
|
229
224
|
|
|
230
225
|
try:
|
|
231
|
-
|
|
226
|
+
return self.mount_fuse_filesystem_v2(
|
|
232
227
|
session_id=session_id,
|
|
233
228
|
team_id=self.workspace_id,
|
|
234
229
|
payload=v2_payload,
|
|
235
230
|
verify=self.verify
|
|
236
231
|
)
|
|
237
|
-
return status_code
|
|
238
232
|
except Exception as v2_error:
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# Session-not-found errors should propagate immediately
|
|
243
|
-
if "Session not found" in error_str:
|
|
244
|
-
raise # Re-raise session-not-found errors immediately
|
|
245
|
-
|
|
246
|
-
should_fallback = (
|
|
247
|
-
"404" in error_str or "Not Found" in error_str or "not found" in error_str.lower()
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
if should_fallback:
|
|
251
|
-
return None # Trigger v1 fallback
|
|
252
|
-
else:
|
|
253
|
-
# v2 failed for reasons other than not available
|
|
254
|
-
self._handle_mount_error(v2_error, "folder")
|
|
255
|
-
|
|
256
|
-
def _fallback_mount_v1(self, folder_info: list, session_id: str) -> int:
|
|
257
|
-
"""Fall back to v1 API, mounting folders one at a time.
|
|
258
|
-
|
|
259
|
-
Parameters
|
|
260
|
-
----------
|
|
261
|
-
folder_info : list
|
|
262
|
-
List of folder metadata dictionaries.
|
|
263
|
-
session_id : str
|
|
264
|
-
The interactive session ID.
|
|
265
|
-
|
|
266
|
-
Returns
|
|
267
|
-
-------
|
|
268
|
-
int
|
|
269
|
-
Status code from the last successful mount (typically 204).
|
|
270
|
-
|
|
271
|
-
Raises
|
|
272
|
-
------
|
|
273
|
-
ValueError
|
|
274
|
-
If any item is a file (v1 only supports folders), or if any folder
|
|
275
|
-
fails to mount. Note: Earlier folders may have successfully mounted
|
|
276
|
-
before the failure.
|
|
277
|
-
"""
|
|
278
|
-
for f in folder_info:
|
|
279
|
-
item_type = f['data'].get('type', '')
|
|
280
|
-
item_kind = f['data'].get('kind', '')
|
|
281
|
-
if item_type == 'S3File' or item_kind == 'File':
|
|
233
|
+
if isinstance(v2_error, ValueError):
|
|
234
|
+
raise
|
|
235
|
+
if isinstance(v2_error, BadRequestException) and v2_error.rv.status_code == 404:
|
|
282
236
|
raise ValueError(
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
for folder_data in folder_info:
|
|
291
|
-
try:
|
|
292
|
-
status_code = self._mount_single_folder_v1(folder_data, session_id)
|
|
293
|
-
mounted_folders.append(folder_data['path'])
|
|
294
|
-
except ValueError as e:
|
|
295
|
-
# If we've already mounted some folders, inform the user
|
|
296
|
-
if mounted_folders:
|
|
297
|
-
error_msg = f"{str(e)}\n\nNote: The following folders were successfully mounted before this error: {', '.join(mounted_folders)}"
|
|
298
|
-
raise ValueError(error_msg)
|
|
299
|
-
else:
|
|
300
|
-
raise
|
|
301
|
-
return status_code
|
|
302
|
-
|
|
303
|
-
def _mount_single_folder_v1(self, folder_data: dict, session_id: str) -> int:
|
|
304
|
-
"""Mount a single folder using API v1.
|
|
305
|
-
|
|
306
|
-
Parameters
|
|
307
|
-
----------
|
|
308
|
-
folder_data : dict
|
|
309
|
-
Folder metadata including type, path, and data.
|
|
310
|
-
session_id : str
|
|
311
|
-
The interactive session ID.
|
|
312
|
-
|
|
313
|
-
Returns
|
|
314
|
-
-------
|
|
315
|
-
int
|
|
316
|
-
Status code (typically 204 on success).
|
|
317
|
-
|
|
318
|
-
Raises
|
|
319
|
-
------
|
|
320
|
-
ValueError
|
|
321
|
-
If the mount request fails.
|
|
322
|
-
"""
|
|
323
|
-
v1_payload = {"dataItem": folder_data["data"]}
|
|
324
|
-
|
|
325
|
-
url = (
|
|
326
|
-
f"{self.cloudos_url}/api/v1/"
|
|
327
|
-
f"interactive-sessions/{session_id}/fuse-filesystem/mount"
|
|
328
|
-
f"?teamId={self.workspace_id}"
|
|
329
|
-
)
|
|
330
|
-
headers = {
|
|
331
|
-
"Content-type": "application/json",
|
|
332
|
-
"apikey": self.apikey
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
try:
|
|
336
|
-
r = retry_requests_post(url, headers=headers, json=v1_payload, verify=self.verify)
|
|
337
|
-
|
|
338
|
-
if r.status_code >= 400:
|
|
339
|
-
# Handle v1 errors using consolidated error handling
|
|
340
|
-
if r.status_code == 403:
|
|
341
|
-
raise ValueError(f"Provided {folder_data['type']} item already exists with 'mounted' status")
|
|
342
|
-
elif r.status_code == 401:
|
|
343
|
-
raise ValueError("Unauthorized. Invalid API key or insufficient permissions.")
|
|
344
|
-
elif r.status_code == 400:
|
|
345
|
-
try:
|
|
346
|
-
r_content = json.loads(r.content)
|
|
347
|
-
if r_content.get("message") == "Invalid Supported DataItem folderType. Supported values are S3Folder":
|
|
348
|
-
raise ValueError(f"Invalid Supported DataItem '{folder_data['type']}' folderType. Virtual folders cannot be linked.")
|
|
349
|
-
elif r_content.get("message") == "Request failed with status code 403":
|
|
350
|
-
raise ValueError(f"Interactive Analysis session is not active")
|
|
351
|
-
else:
|
|
352
|
-
raise ValueError(f"Cannot link item")
|
|
353
|
-
except json.JSONDecodeError:
|
|
354
|
-
raise ValueError(f"Bad request (400): Unable to parse error response")
|
|
355
|
-
else:
|
|
356
|
-
raise ValueError(f"Failed to mount item: HTTP {r.status_code}")
|
|
357
|
-
|
|
358
|
-
return r.status_code
|
|
359
|
-
|
|
360
|
-
except ValueError:
|
|
361
|
-
# Re-raise ValueError as-is
|
|
362
|
-
raise
|
|
363
|
-
except Exception as v1_error:
|
|
364
|
-
raise ValueError(f"Failed to mount {folder_data['type']} item: {str(v1_error)}")
|
|
237
|
+
"The linking API (v2) is not available on this platform. "
|
|
238
|
+
"Contact your platform administrator."
|
|
239
|
+
) from v2_error
|
|
240
|
+
all_s3 = all(item.get("type", "").startswith("S3") for item in data_items)
|
|
241
|
+
all_fe = all(not item.get("type", "").startswith("S3") for item in data_items)
|
|
242
|
+
label = "S3" if all_s3 else "File Explorer" if all_fe else "item"
|
|
243
|
+
self._handle_mount_error(v2_error, label)
|
|
365
244
|
|
|
366
245
|
def _verify_all_mounts(self, folder_info: list, session_id: str):
|
|
367
246
|
"""Verify mount completion status for all items (files and folders).
|
|
@@ -62,8 +62,13 @@ def job():
|
|
|
62
62
|
help=('When the workflows are duplicated, use the latest imported workflow (by date).'),
|
|
63
63
|
is_flag=True)
|
|
64
64
|
@click.option('--job-config',
|
|
65
|
-
help=('A
|
|
66
|
-
'
|
|
65
|
+
help=('A file listing the parameters to use with your job, as ' +
|
|
66
|
+
'\'name = value\' pairs inside a \'params\' block. It is ' +
|
|
67
|
+
'equivalent to repeating --parameter, so only flat ' +
|
|
68
|
+
'parameters are supported: it is not a nextflow.config ' +
|
|
69
|
+
'and cannot contain multi-line parameters, nested blocks or sections ' +
|
|
70
|
+
'such as \'process\' and \'profiles\'. Use --params-file ' +
|
|
71
|
+
'for parameters that need a structured value.'))
|
|
67
72
|
@click.option('--params-file',
|
|
68
73
|
help=('A file containing the parameters to pass to the job call. ' +
|
|
69
74
|
'It should be a .json or .yaml file with a dictionary structure ' +
|
|
@@ -176,6 +176,167 @@ class Job(Cloudos):
|
|
|
176
176
|
else:
|
|
177
177
|
raise ValueError(f'No {name} element in {resource} was found')
|
|
178
178
|
|
|
179
|
+
@staticmethod
|
|
180
|
+
def strip_inline_comment(line):
|
|
181
|
+
"""Remove a trailing '//' or '#' comment from a job config line.
|
|
182
|
+
|
|
183
|
+
Only comments preceded by whitespace are removed, so that values
|
|
184
|
+
containing these characters, such as 's3://bucket/key', are preserved.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
line : string
|
|
189
|
+
A single raw line from a job config file.
|
|
190
|
+
|
|
191
|
+
Returns
|
|
192
|
+
-------
|
|
193
|
+
string
|
|
194
|
+
The line with any trailing comment removed.
|
|
195
|
+
"""
|
|
196
|
+
return re.sub(r'\s+(?://|#).*$', '', line)
|
|
197
|
+
|
|
198
|
+
@staticmethod
|
|
199
|
+
def list_literal_warning(p_name, p_value):
|
|
200
|
+
"""Build a warning for a value that looks like a list but is sent as text.
|
|
201
|
+
|
|
202
|
+
A '[a, b]' literal in a job config file is not expanded into a Nextflow
|
|
203
|
+
list: every job config value is sent as text. Users coming from real
|
|
204
|
+
nextflow.config files expect the expansion, so warn and show the value
|
|
205
|
+
the pipeline actually receives.
|
|
206
|
+
|
|
207
|
+
Parameters
|
|
208
|
+
----------
|
|
209
|
+
p_name : string
|
|
210
|
+
The parameter name.
|
|
211
|
+
p_value : string
|
|
212
|
+
The parameter value, as it will be sent.
|
|
213
|
+
|
|
214
|
+
Returns
|
|
215
|
+
-------
|
|
216
|
+
string or None
|
|
217
|
+
The warning message, or None if the value is not a list literal.
|
|
218
|
+
"""
|
|
219
|
+
if not (p_value.startswith('[') and p_value.endswith(']')):
|
|
220
|
+
return None
|
|
221
|
+
elements = [e for e in p_value[1:-1].split(',') if len(e) > 0]
|
|
222
|
+
element_noun = 'element' if len(elements) == 1 else 'elements'
|
|
223
|
+
listed = ', '.join(f"'{e}'" for e in elements) if elements else 'nothing'
|
|
224
|
+
return (f"Warning: parameter '{p_name}' looks like a list of "
|
|
225
|
+
f"{len(elements)} {element_noun} ({listed}), but every "
|
|
226
|
+
'--job-config value is sent as text.\n'
|
|
227
|
+
f"\tThe pipeline will receive the string --{p_name} '{p_value}', "
|
|
228
|
+
'not a Nextflow list of '
|
|
229
|
+
f'{len(elements)} {element_noun}.\n'
|
|
230
|
+
"\tTo pass a real list, define it in the pipeline's own "
|
|
231
|
+
'nextflow.config, or use --params-file with a JSON or YAML file.')
|
|
232
|
+
|
|
233
|
+
@staticmethod
|
|
234
|
+
def parse_job_config_params(job_config, workflow_type='nextflow'):
|
|
235
|
+
"""Parse a job config file into a list of (name, value) parameter pairs.
|
|
236
|
+
|
|
237
|
+
The job config file is a list of parameters, equivalent to repeating
|
|
238
|
+
'--parameter name=value' on the command line. Every value is sent as
|
|
239
|
+
text, exactly as when launching Nextflow from the command line, so a
|
|
240
|
+
literal such as "['a', 'b']" is passed through as a string. Values
|
|
241
|
+
spanning several lines and nested blocks cannot be represented.
|
|
242
|
+
|
|
243
|
+
Parameters
|
|
244
|
+
----------
|
|
245
|
+
job_config : string
|
|
246
|
+
Path to the job config file.
|
|
247
|
+
workflow_type : string
|
|
248
|
+
The type of workflow to run. Quotes are kept for 'wdl' workflows.
|
|
249
|
+
|
|
250
|
+
Returns
|
|
251
|
+
-------
|
|
252
|
+
list
|
|
253
|
+
A list of (name, value) tuples, in file order.
|
|
254
|
+
|
|
255
|
+
Raises
|
|
256
|
+
------
|
|
257
|
+
ValueError
|
|
258
|
+
If the file has no 'params' block, if the block is opened and closed
|
|
259
|
+
on the same line, or if a line inside the block is not a
|
|
260
|
+
'name = value' pair, has a value spanning several lines, or has no
|
|
261
|
+
value at all. Every message reports the offending line, and all but
|
|
262
|
+
the missing block report its line number.
|
|
263
|
+
|
|
264
|
+
Notes
|
|
265
|
+
-----
|
|
266
|
+
A value that looks like a list is parsed and returned, but prints a
|
|
267
|
+
warning first, since it is sent as text rather than as a Nextflow list.
|
|
268
|
+
The warning is skipped for 'wdl' workflows.
|
|
269
|
+
"""
|
|
270
|
+
parsed = []
|
|
271
|
+
with open(job_config, 'r') as p:
|
|
272
|
+
reading = False
|
|
273
|
+
found_params_block = False
|
|
274
|
+
for line_no, p_l in enumerate(p, start=1):
|
|
275
|
+
if re.match(r'^\s*params\s*\{', p_l, re.IGNORECASE):
|
|
276
|
+
found_params_block = True
|
|
277
|
+
reading = True
|
|
278
|
+
remainder = Job.strip_inline_comment(p_l).split('{', 1)[1].strip()
|
|
279
|
+
if len(remainder) > 0 and remainder[0] not in ('/', '#'):
|
|
280
|
+
raise ValueError(
|
|
281
|
+
f'Could not parse line {line_no} of {job_config}: ' +
|
|
282
|
+
f'"{p_l.strip()}". The \'params\' block must span ' +
|
|
283
|
+
'several lines, with one \'name = value\' pair per ' +
|
|
284
|
+
'line.')
|
|
285
|
+
continue
|
|
286
|
+
if not reading:
|
|
287
|
+
continue
|
|
288
|
+
p_l_no_comment = Job.strip_inline_comment(p_l)
|
|
289
|
+
if workflow_type == 'wdl':
|
|
290
|
+
p_l_strip = p_l_no_comment.strip().replace(' ', '')
|
|
291
|
+
else:
|
|
292
|
+
p_l_strip = p_l_no_comment.strip().replace(
|
|
293
|
+
' ', '').replace('\"', '').replace('\'', '')
|
|
294
|
+
if len(p_l_strip) == 0:
|
|
295
|
+
continue
|
|
296
|
+
elif p_l_strip[0] in ('/', '#', '*'):
|
|
297
|
+
continue
|
|
298
|
+
elif p_l_strip == '}':
|
|
299
|
+
reading = False
|
|
300
|
+
continue
|
|
301
|
+
p_list = p_l_strip.split('=')
|
|
302
|
+
if len(p_list) < 2:
|
|
303
|
+
raise ValueError(
|
|
304
|
+
f'Could not parse line {line_no} of {job_config}: ' +
|
|
305
|
+
f'"{p_l.strip()}". Expected a \'name = value\' pair. ' +
|
|
306
|
+
'The job config file is a list of parameters, not a ' +
|
|
307
|
+
'Nextflow config: it cannot contain values spanning ' +
|
|
308
|
+
'several lines, nested blocks, or sections such as ' +
|
|
309
|
+
'\'process\' and \'profiles\'.')
|
|
310
|
+
p_name = p_list[0]
|
|
311
|
+
p_value = '='.join(p_list[1:])
|
|
312
|
+
if p_value.count('[') > p_value.count(']'):
|
|
313
|
+
raise ValueError(
|
|
314
|
+
f'Could not parse line {line_no} of {job_config}: ' +
|
|
315
|
+
f'"{p_l.strip()}". Values spanning several lines are ' +
|
|
316
|
+
'not supported. Keep the value on a single line, ' +
|
|
317
|
+
'define it in the pipeline\'s own nextflow.config, ' +
|
|
318
|
+
'or pass it with --params-file using a JSON or YAML ' +
|
|
319
|
+
'file.')
|
|
320
|
+
if len(p_value) == 0:
|
|
321
|
+
raise ValueError(
|
|
322
|
+
f'Could not parse line {line_no} of {job_config}: ' +
|
|
323
|
+
f'"{p_l.strip()}". Parameter \'{p_name}\' has no ' +
|
|
324
|
+
'value. Give it a value, or remove the line. A value ' +
|
|
325
|
+
'that starts with \'//\' or \'#\' must be quoted, ' +
|
|
326
|
+
'otherwise it is read as a comment.')
|
|
327
|
+
if workflow_type != 'wdl':
|
|
328
|
+
warning = Job.list_literal_warning(p_name, p_value)
|
|
329
|
+
if warning is not None:
|
|
330
|
+
click.secho(warning, fg='yellow', bold=True)
|
|
331
|
+
parsed.append((p_name, p_value))
|
|
332
|
+
if not found_params_block:
|
|
333
|
+
raise ValueError(
|
|
334
|
+
f'No \'params\' block was found in {job_config}. ' +
|
|
335
|
+
'The parameters must be listed inside a \'params { ... }\' ' +
|
|
336
|
+
'block, one \'name = value\' pair per line. The ' +
|
|
337
|
+
'\'params.name = value\' form is not supported.')
|
|
338
|
+
return parsed
|
|
339
|
+
|
|
179
340
|
def build_parameters_file_payload(self, params_file):
|
|
180
341
|
"""Build the parametersFile payload for a params file path."""
|
|
181
342
|
if params_file is None:
|
|
@@ -323,12 +484,12 @@ class Job(Cloudos):
|
|
|
323
484
|
command,
|
|
324
485
|
cpus,
|
|
325
486
|
memory):
|
|
326
|
-
"""Converts a
|
|
487
|
+
"""Converts a job config file into a json formatted dict.
|
|
327
488
|
|
|
328
489
|
Parameters
|
|
329
490
|
----------
|
|
330
491
|
job_config : string
|
|
331
|
-
Path to a
|
|
492
|
+
Path to a file with parameters scope.
|
|
332
493
|
params_file : string
|
|
333
494
|
S3 or File Explorer path to a JSON/YAML file with Nextflow parameters.
|
|
334
495
|
parameter : tuple
|
|
@@ -422,47 +583,12 @@ class Job(Cloudos):
|
|
|
422
583
|
raise ValueError('No --job-config or --parameter were provided. At least one of ' +
|
|
423
584
|
'these are required for WDL workflows.')
|
|
424
585
|
if job_config is not None:
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if reading:
|
|
432
|
-
if workflow_type == 'wdl':
|
|
433
|
-
p_l_strip = p_l.strip().replace(
|
|
434
|
-
' ', '')
|
|
435
|
-
else:
|
|
436
|
-
p_l_strip = p_l.strip().replace(
|
|
437
|
-
' ', '').replace('\"', '').replace('\'', '')
|
|
438
|
-
if len(p_l_strip) == 0:
|
|
439
|
-
continue
|
|
440
|
-
elif p_l_strip[0] == '/' or p_l_strip[0] == '#':
|
|
441
|
-
continue
|
|
442
|
-
elif p_l_strip == '}':
|
|
443
|
-
reading = False
|
|
444
|
-
else:
|
|
445
|
-
p_list = p_l_strip.split('=')
|
|
446
|
-
p_name = p_list[0]
|
|
447
|
-
p_value = '='.join(p_list[1:])
|
|
448
|
-
if len(p_list) < 2:
|
|
449
|
-
raise ValueError('Please, specify your ' +
|
|
450
|
-
'parameters in ' +
|
|
451
|
-
f'{job_config} using ' +
|
|
452
|
-
'the \'=\' as spacer. ' +
|
|
453
|
-
'E.g: name = my_name')
|
|
454
|
-
elif workflow_type == 'wdl':
|
|
455
|
-
param = {"prefix": "",
|
|
456
|
-
"name": p_name,
|
|
457
|
-
"parameterKind": "textValue",
|
|
458
|
-
"textValue": p_value}
|
|
459
|
-
workflow_params.append(param)
|
|
460
|
-
else:
|
|
461
|
-
param = {"prefix": "--",
|
|
462
|
-
"name": p_name,
|
|
463
|
-
"parameterKind": "textValue",
|
|
464
|
-
"textValue": p_value}
|
|
465
|
-
workflow_params.append(param)
|
|
586
|
+
p_prefix = "" if workflow_type == 'wdl' else "--"
|
|
587
|
+
for p_name, p_value in Job.parse_job_config_params(job_config, workflow_type):
|
|
588
|
+
workflow_params.append({"prefix": p_prefix,
|
|
589
|
+
"name": p_name,
|
|
590
|
+
"parameterKind": "textValue",
|
|
591
|
+
"textValue": p_value})
|
|
466
592
|
if len(workflow_params) == 0:
|
|
467
593
|
raise ValueError(f'The {job_config} file did not contain any ' +
|
|
468
594
|
'valid parameter')
|
|
@@ -611,7 +737,7 @@ class Job(Cloudos):
|
|
|
611
737
|
Parameters
|
|
612
738
|
----------
|
|
613
739
|
job_config : string
|
|
614
|
-
Path to a
|
|
740
|
+
Path to a file with parameters scope.
|
|
615
741
|
params_file : string
|
|
616
742
|
S3 or File Explorer path to a JSON/YAML file with Nextflow parameters.
|
|
617
743
|
parameter : tuple
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudos_cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.95.1
|
|
4
4
|
Summary: Python package for interacting with the Lifebit Platform
|
|
5
5
|
Home-page: https://github.com/lifebit-ai/cloudos-cli
|
|
6
6
|
Author: David Piñeyro
|
|
@@ -609,7 +609,7 @@ First, configure your local environment to ease parameter input. We will try to
|
|
|
609
609
|
cloudos job run --profile my_profile --workflow-name rnatoy --job-config cloudos_cli/examples/rnatoy.config --resumable
|
|
610
610
|
```
|
|
611
611
|
|
|
612
|
-
As you can see, a file with the job parameters is used to configure the job. This file
|
|
612
|
+
As you can see, a file with the job parameters is used to configure the job. This file is a list of the parameters to pass to your job, and nothing else. It has the following structure:
|
|
613
613
|
|
|
614
614
|
```
|
|
615
615
|
params {
|
|
@@ -618,6 +618,24 @@ params {
|
|
|
618
618
|
}
|
|
619
619
|
```
|
|
620
620
|
|
|
621
|
+
`--job-config` is shorthand for repeating `--parameter` on the command line: the CLI reads the file line by line, splits each line on the first `=`, and sends each result as one named parameter.
|
|
622
|
+
|
|
623
|
+
Every value is passed through as text, exactly as it would be when launching Nextflow from the command line.
|
|
624
|
+
|
|
625
|
+
> **IMPORTANT: `[ ]` is not expanded into a Nextflow list.** In a real `nextflow.config`, `my_param = ['a', 'b']` gives the pipeline a list of two items. Through `--job-config` it gives the pipeline the *string* `[a,b]`. The line is accepted and the job is submitted, so this fails silently at the point where your pipeline tries to iterate over the value. The CLI prints a warning when it sees a value that looks like a list, showing exactly what the pipeline will receive.
|
|
626
|
+
|
|
627
|
+
To pass a genuine list, define it in the pipeline's own `nextflow.config` in the git repository, or use `--params-file` with a JSON or YAML file (see below), which preserves types.
|
|
628
|
+
|
|
629
|
+
What a `--job-config` file cannot contain, because it is **not** a `nextflow.config` file:
|
|
630
|
+
|
|
631
|
+
- values spanning several lines
|
|
632
|
+
- nested blocks (e.g. `genomes { ... }`)
|
|
633
|
+
- `process`, `profiles`, `docker` or other config sections
|
|
634
|
+
|
|
635
|
+
Comments are supported, both on their own line and after a value, using `//` or `#`.
|
|
636
|
+
|
|
637
|
+
If a parameter needs a genuinely structured value rather than a string, either define it in the pipeline's own `nextflow.config` in the git repository and expose the parts you want to change as individual parameters, or pass it with `--params-file` (see below), which supports JSON and YAML with full type fidelity.
|
|
638
|
+
|
|
621
639
|
In addition, parameters can also be specified using the command-line `-p` or `--parameter`. For instance:
|
|
622
640
|
|
|
623
641
|
```bash
|
|
@@ -2648,7 +2666,7 @@ All configuration parameters are optional. If not specified, the session resumes
|
|
|
2648
2666
|
|
|
2649
2667
|
### Link
|
|
2650
2668
|
|
|
2651
|
-
The `cloudos interactive-session link` command provides a unified interface for linking files and folders to interactive analysis sessions. It consolidates functionality previously available through separate commands (`cloudos job results --link`, `cloudos job workdir --link`, `cloudos job logs --link
|
|
2669
|
+
The `cloudos interactive-session link` command provides a unified interface for linking files and folders to interactive analysis sessions. It consolidates functionality previously available through separate commands (`cloudos job results --link`, `cloudos job workdir --link`, and `cloudos job logs --link`) into a single, intuitive interface.
|
|
2652
2670
|
|
|
2653
2671
|
#### Link Files and Folders to Interactive Analysis
|
|
2654
2672
|
|
|
@@ -2880,41 +2898,8 @@ cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
|
|
|
2880
2898
|
```
|
|
2881
2899
|
|
|
2882
2900
|
|
|
2883
|
-
#### Link Files and Folders to Interactive Analysis
|
|
2884
|
-
|
|
2885
|
-
Connect external S3 buckets, S3 files, or File Explorer files/folders to your interactive analysis sessions. This provides direct access to data without needing to copy files.
|
|
2886
|
-
|
|
2887
|
-
This subcommand uses the `--session-id` option to access the correct interactive session. This option can be added to the CLI or defined in a profile, for convenience.
|
|
2888
|
-
|
|
2889
|
-
```bash
|
|
2890
|
-
cloudos datasets link <PATH> --profile <profile> --session-id <SESSION_ID>
|
|
2891
|
-
```
|
|
2892
|
-
|
|
2893
|
-
Link an S3 folder:
|
|
2894
|
-
```console
|
|
2895
|
-
cloudos datasets link s3://bucket/path/folder --profile test --session-id 1234
|
|
2896
|
-
```
|
|
2897
|
-
|
|
2898
|
-
Link an S3 file:
|
|
2899
|
-
```console
|
|
2900
|
-
cloudos datasets link s3://bucket/path/data.csv --profile test --session-id 1234
|
|
2901
|
-
```
|
|
2902
|
-
|
|
2903
|
-
Link a File Explorer folder (requires `--project-name`):
|
|
2904
|
-
```console
|
|
2905
|
-
cloudos datasets link "Data/HLA" --project-name my-project --session-id 1234
|
|
2906
|
-
```
|
|
2907
|
-
|
|
2908
|
-
Link a File Explorer file (requires `--project-name`):
|
|
2909
|
-
```console
|
|
2910
|
-
cloudos datasets link "Data/observations.csv" --project-name my-project --session-id 1234
|
|
2911
|
-
```
|
|
2912
|
-
|
|
2913
|
-
> [!NOTE]
|
|
2914
|
-
> If running the CLI inside a jupyter session, the pre-configured CLI installation will have the session ID already installed and only the `--apikey` needs to be added.
|
|
2915
|
-
|
|
2916
2901
|
> [!NOTE]
|
|
2917
|
-
>
|
|
2902
|
+
> To link files or folders (S3 or File Explorer) to an interactive analysis session, use `cloudos interactive-session link` or the `--link` option of `cloudos interactive-session create`. Virtual folders in File Explorer cannot be linked.
|
|
2918
2903
|
|
|
2919
2904
|
> [!NOTE]
|
|
2920
2905
|
> A maximum of 100 items can be linked per session. If the new items combined with already-linked items exceed this limit, the entire request is rejected.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.94.1'
|
|
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
|
{cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/cloudos_cli/interactive_session/interactive_session.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
|
|
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
|
{cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_create_session.py
RENAMED
|
File without changes
|
{cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_link_error_handling.py
RENAMED
|
File without changes
|
{cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_link_session.py
RENAMED
|
File without changes
|
{cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_list_sessions.py
RENAMED
|
File without changes
|
{cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_interactive_session/test_normalize_path.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudos_cli-2.94.1 → cloudos_cli-2.95.1}/tests/test_related_analyses/test_related_analyses.py
RENAMED
|
File without changes
|