cloudos-cli 2.33.0__tar.gz → 2.35.0__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.
Files changed (34) hide show
  1. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/PKG-INFO +50 -1
  2. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/README.md +49 -0
  3. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/__main__.py +248 -2
  4. cloudos_cli-2.35.0/cloudos_cli/_version.py +1 -0
  5. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/datasets/datasets.py +85 -1
  6. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/PKG-INFO +50 -1
  7. cloudos_cli-2.33.0/cloudos_cli/_version.py +0 -1
  8. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/LICENSE +0 -0
  9. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/__init__.py +0 -0
  10. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/clos.py +0 -0
  11. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/configure/__init__.py +0 -0
  12. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/configure/configure.py +0 -0
  13. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/datasets/__init__.py +0 -0
  14. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/import_wf/__init__.py +0 -0
  15. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/import_wf/import_wf.py +0 -0
  16. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/jobs/__init__.py +0 -0
  17. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/jobs/job.py +0 -0
  18. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/queue/__init__.py +0 -0
  19. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/queue/queue.py +0 -0
  20. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/__init__.py +0 -0
  21. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/cloud.py +0 -0
  22. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/details.py +0 -0
  23. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/errors.py +0 -0
  24. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/requests.py +0 -0
  25. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli/utils/resources.py +0 -0
  26. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/SOURCES.txt +0 -0
  27. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/dependency_links.txt +0 -0
  28. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/entry_points.txt +0 -0
  29. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/requires.txt +0 -0
  30. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/cloudos_cli.egg-info/top_level.txt +0 -0
  31. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/setup.cfg +0 -0
  32. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/setup.py +0 -0
  33. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/tests/__init__.py +0 -0
  34. {cloudos_cli-2.33.0 → cloudos_cli-2.35.0}/tests/functions_for_pytest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudos_cli
3
- Version: 2.33.0
3
+ Version: 2.35.0
4
4
  Summary: Python package for interacting with CloudOS
5
5
  Home-page: https://github.com/lifebit-ai/cloudos-cli
6
6
  Author: David Piñeyro
@@ -1007,6 +1007,55 @@ Please, be aware that renaming can only happen in files and folders that are pre
1007
1007
 
1008
1008
  Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
1009
1009
 
1010
+ ```bash
1011
+ --cloudos-url $CLOUDOS \
1012
+ --apikey $MY_API_KEY \
1013
+ --workspace-id $WORKSPACE_ID \
1014
+ --project-name $PROJEC_NAME
1015
+ ```
1016
+ #### Create a (virtual) folder
1017
+
1018
+ New folders can be created within the `Data` dataset and its subfolders using the following command
1019
+
1020
+ ```
1021
+ cloudos datasets mkdir <new_folder_path>
1022
+ ```
1023
+ where ` new_folder_path` is the path to the folder to be created.
1024
+
1025
+ Please, be aware that the folder creation can only happen in `Data` or its sub-folders.
1026
+
1027
+ Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
1028
+
1029
+ ```bash
1030
+ --cloudos-url $CLOUDOS \
1031
+ --apikey $MY_API_KEY \
1032
+ --workspace-id $WORKSPACE_ID \
1033
+ --project-name $PROJEC_NAME
1034
+ ```
1035
+
1036
+ #### Copying files and folders
1037
+
1038
+ Files and folders can be copied **from** anywhere in the project **to** `Data` or any of its subfolders programmatically (i.e `Data`, `Data/folder/file.txt`).
1039
+
1040
+ 1. The copy can happen **within the same project** running the following command:
1041
+ ```
1042
+ cloudos datasets cp <souce_path> <destination_path> --profile <profile name>
1043
+ ```
1044
+ where the source project as well as the destination one is the one defined in the profile.
1045
+
1046
+ 2. The move can also happen **across different projects** within the same workspace by running the following command
1047
+ ```
1048
+ cloudos datasets cp <source_path> <destiantion_path> --profile <profile_name> --destination-project-name <project_name>
1049
+ ```
1050
+ In this case, only the source project is the one specified in the profile.
1051
+
1052
+ Any of the `source_path` must be a full path; any `destination_path` must be a path starting with `Data` and finishing with the folder where to move the file/folder. An example of such command is:
1053
+
1054
+ ```
1055
+ cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
1056
+ ```
1057
+
1058
+ Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
1010
1059
  ```bash
1011
1060
  --cloudos-url $CLOUDOS \
1012
1061
  --apikey $MY_API_KEY \
@@ -972,6 +972,55 @@ Please, be aware that renaming can only happen in files and folders that are pre
972
972
 
973
973
  Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
974
974
 
975
+ ```bash
976
+ --cloudos-url $CLOUDOS \
977
+ --apikey $MY_API_KEY \
978
+ --workspace-id $WORKSPACE_ID \
979
+ --project-name $PROJEC_NAME
980
+ ```
981
+ #### Create a (virtual) folder
982
+
983
+ New folders can be created within the `Data` dataset and its subfolders using the following command
984
+
985
+ ```
986
+ cloudos datasets mkdir <new_folder_path>
987
+ ```
988
+ where ` new_folder_path` is the path to the folder to be created.
989
+
990
+ Please, be aware that the folder creation can only happen in `Data` or its sub-folders.
991
+
992
+ Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
993
+
994
+ ```bash
995
+ --cloudos-url $CLOUDOS \
996
+ --apikey $MY_API_KEY \
997
+ --workspace-id $WORKSPACE_ID \
998
+ --project-name $PROJEC_NAME
999
+ ```
1000
+
1001
+ #### Copying files and folders
1002
+
1003
+ Files and folders can be copied **from** anywhere in the project **to** `Data` or any of its subfolders programmatically (i.e `Data`, `Data/folder/file.txt`).
1004
+
1005
+ 1. The copy can happen **within the same project** running the following command:
1006
+ ```
1007
+ cloudos datasets cp <souce_path> <destination_path> --profile <profile name>
1008
+ ```
1009
+ where the source project as well as the destination one is the one defined in the profile.
1010
+
1011
+ 2. The move can also happen **across different projects** within the same workspace by running the following command
1012
+ ```
1013
+ cloudos datasets cp <source_path> <destiantion_path> --profile <profile_name> --destination-project-name <project_name>
1014
+ ```
1015
+ In this case, only the source project is the one specified in the profile.
1016
+
1017
+ Any of the `source_path` must be a full path; any `destination_path` must be a path starting with `Data` and finishing with the folder where to move the file/folder. An example of such command is:
1018
+
1019
+ ```
1020
+ cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
1021
+ ```
1022
+
1023
+ Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
975
1024
  ```bash
976
1025
  --cloudos-url $CLOUDOS \
977
1026
  --apikey $MY_API_KEY \
@@ -88,7 +88,9 @@ def run_cloudos_cli(ctx):
88
88
  'datasets': {
89
89
  'ls': shared_config,
90
90
  'mv': shared_config,
91
- 'rename': shared_config
91
+ 'rename': shared_config,
92
+ 'cp': shared_config,
93
+ 'mkdir': shared_config
92
94
  }
93
95
  })
94
96
  else:
@@ -135,7 +137,9 @@ def run_cloudos_cli(ctx):
135
137
  'datasets': {
136
138
  'ls': shared_config,
137
139
  'mv': shared_config,
138
- 'rename': shared_config
140
+ 'rename': shared_config,
141
+ 'cp': shared_config,
142
+ 'mkdir': shared_config
139
143
  }
140
144
  })
141
145
 
@@ -2960,5 +2964,247 @@ def renaming_item(ctx, source_path, new_name, apikey, cloudos_url,
2960
2964
  sys.exit(1)
2961
2965
 
2962
2966
 
2967
+ @datasets.command(name="cp")
2968
+ @click.argument("source_path", required=True)
2969
+ @click.argument("destination_path", required=True)
2970
+ @click.option('-k', '--apikey', required=True, help='Your CloudOS API key.')
2971
+ @click.option('-c', '--cloudos-url', default=CLOUDOS_URL, required=True, help='The CloudOS URL.')
2972
+ @click.option('--workspace-id', required=True, help='The CloudOS workspace ID.')
2973
+ @click.option('--project-name', required=True, help='The source project name.')
2974
+ @click.option('--destination-project-name', required=False, help='The destination project name. Defaults to the source project.')
2975
+ @click.option('--disable-ssl-verification', is_flag=True, help='Disable SSL certificate verification.')
2976
+ @click.option('--ssl-cert', help='Path to your SSL certificate file.')
2977
+ @click.option('--profile', default=None, help='Profile to use from the config file.')
2978
+ @click.pass_context
2979
+ def copy_item_cli(ctx, source_path, destination_path, apikey, cloudos_url,
2980
+ workspace_id, project_name, destination_project_name,
2981
+ disable_ssl_verification, ssl_cert, profile):
2982
+ """
2983
+ Copy a file or folder (S3 or virtual) from SOURCE_PATH to DESTINATION_PATH.
2984
+
2985
+ SOURCE_PATH [path]: the full path to the file or folder to copy.
2986
+ E.g.: AnalysesResults/my_analysis/results/my_plot.png\n
2987
+ DESTINATION_PATH [path]: the full path to the destination folder. It must be a 'Data' folder path.
2988
+ E.g.: Data/plots
2989
+ """
2990
+ click.echo("Loading configuration profile...")
2991
+ config_manager = ConfigurationProfile()
2992
+ required_dict = {
2993
+ 'apikey': True,
2994
+ 'workspace_id': True,
2995
+ 'workflow_name': False,
2996
+ 'project_name': True
2997
+ }
2998
+ apikey, cloudos_url, workspace_id, workflow_name, _, _, project_name = config_manager.load_profile_and_validate_data(
2999
+ ctx, INIT_PROFILE, CLOUDOS_URL, profile=profile,
3000
+ required_dict=required_dict,
3001
+ apikey=apikey,
3002
+ cloudos_url=cloudos_url,
3003
+ workspace_id=workspace_id,
3004
+ workflow_name=None,
3005
+ repository_platform=None,
3006
+ execution_platform=None,
3007
+ project_name=project_name
3008
+ )
3009
+ destination_project_name = destination_project_name or project_name
3010
+ verify_ssl = ssl_selector(disable_ssl_verification, ssl_cert)
3011
+ # Initialize clients
3012
+ source_client = Datasets(
3013
+ cloudos_url=cloudos_url,
3014
+ apikey=apikey,
3015
+ workspace_id=workspace_id,
3016
+ project_name=project_name,
3017
+ verify=verify_ssl,
3018
+ cromwell_token=None
3019
+ )
3020
+ dest_client = Datasets(
3021
+ cloudos_url=cloudos_url,
3022
+ apikey=apikey,
3023
+ workspace_id=workspace_id,
3024
+ project_name=destination_project_name,
3025
+ verify=verify_ssl,
3026
+ cromwell_token=None
3027
+ )
3028
+ # Validate paths
3029
+ dest_parts = destination_path.strip("/").split("/")
3030
+ if not dest_parts or dest_parts[0] != "Data":
3031
+ click.echo("[ERROR] DESTINATION_PATH must start with 'Data/'.", err=True)
3032
+ sys.exit(1)
3033
+ # Parse source and destination
3034
+ source_parts = source_path.strip("/").split("/")
3035
+ source_parent = "/".join(source_parts[:-1]) if len(source_parts) > 1 else ""
3036
+ source_name = source_parts[-1]
3037
+ dest_folder_name = dest_parts[-1]
3038
+ dest_parent = "/".join(dest_parts[:-1]) if len(dest_parts) > 1 else ""
3039
+ try:
3040
+ source_content = source_client.list_folder_content(source_parent)
3041
+ dest_content = dest_client.list_folder_content(dest_parent)
3042
+ except Exception as e:
3043
+ click.echo(f"[ERROR] Could not access paths: {str(e)}", err=True)
3044
+ sys.exit(1)
3045
+ # Find the source item
3046
+ source_item = None
3047
+ for item in source_content.get('files' or 'folders', {}):
3048
+ if item.get("name") == source_name:
3049
+ source_item = item
3050
+ break
3051
+ if not source_item:
3052
+ click.echo(f"[ERROR] Item '{source_name}' not found in '{source_parent or '[project root]'}'", err=True)
3053
+ sys.exit(1)
3054
+ # Find the destination folder
3055
+ destination_folder = None
3056
+ for folder in dest_content.get("folders", []):
3057
+ if folder.get("name") == dest_folder_name:
3058
+ destination_folder = folder
3059
+ break
3060
+ if not destination_folder:
3061
+ click.echo(f"[ERROR] Destination folder '{destination_path}' not found.", err=True)
3062
+ sys.exit(1)
3063
+ try:
3064
+ # Determine item type
3065
+ if "fileType" in source_item:
3066
+ item_type = "file"
3067
+ elif source_item.get("folderType") == "VirtualFolder":
3068
+ item_type = "virtual_folder"
3069
+ elif "s3BucketName" in source_item and source_item.get("folderType") == "S3Folder":
3070
+ item_type = "s3_folder"
3071
+ else:
3072
+ click.echo("[ERROR] Could not determine item type.", err=True)
3073
+ sys.exit(1)
3074
+ click.echo(f"Copying {item_type.replace('_', ' ')} '{source_name}' to '{destination_path}'...")
3075
+ if destination_folder.get("folderType") is True and destination_folder.get("kind") in ("Data", "Cohorts", "AnalysesResults"):
3076
+ destination_kind = "Dataset"
3077
+ else:
3078
+ destination_kind = "Folder"
3079
+ response = source_client.copy_item(
3080
+ item=source_item,
3081
+ destination_id=destination_folder["_id"],
3082
+ destination_kind=destination_kind
3083
+ )
3084
+ if response.ok:
3085
+ click.secho("[SUCCESS] Item copied successfully.", fg="green", bold=True)
3086
+ else:
3087
+ click.echo(f"[ERROR] Copy failed: {response.status_code} - {response.text}", err=True)
3088
+ sys.exit(1)
3089
+ except Exception as e:
3090
+ click.echo(f"[ERROR] Copy operation failed: {str(e)}", err=True)
3091
+ sys.exit(1)
3092
+
3093
+
3094
+ @datasets.command(name="mkdir")
3095
+ @click.argument("new_folder_path", required=True)
3096
+ @click.option('-k', '--apikey', required=True, help='Your CloudOS API key.')
3097
+ @click.option('-c', '--cloudos-url', default=CLOUDOS_URL, required=True, help='The CloudOS URL.')
3098
+ @click.option('--workspace-id', required=True, help='The CloudOS workspace ID.')
3099
+ @click.option('--project-name', required=True, help='The project name.')
3100
+ @click.option('--disable-ssl-verification', is_flag=True, help='Disable SSL certificate verification.')
3101
+ @click.option('--ssl-cert', help='Path to your SSL certificate file.')
3102
+ @click.option('--profile', default=None, help='Profile to use from the config file.')
3103
+ @click.pass_context
3104
+ def mkdir_item(ctx, new_folder_path, apikey, cloudos_url,
3105
+ workspace_id, project_name,
3106
+ disable_ssl_verification, ssl_cert, profile):
3107
+ """
3108
+ Create a virtual folder in a CloudOS project.
3109
+
3110
+ NEW_FOLDER_PATH [path]: Full path to the new folder including its name. Must start with 'Data'.
3111
+ """
3112
+ new_folder_path = new_folder_path.strip("/")
3113
+ if not new_folder_path.startswith("Data"):
3114
+ click.echo("[ERROR] NEW_FOLDER_PATH must start with 'Data'.", err=True)
3115
+ sys.exit(1)
3116
+
3117
+ path_parts = new_folder_path.split("/")
3118
+ if len(path_parts) < 2:
3119
+ click.echo("[ERROR] NEW_FOLDER_PATH must include at least a parent folder and the new folder name.", err=True)
3120
+ sys.exit(1)
3121
+
3122
+ parent_path = "/".join(path_parts[:-1])
3123
+ folder_name = path_parts[-1]
3124
+
3125
+ click.echo("Loading configuration profile...")
3126
+ config_manager = ConfigurationProfile()
3127
+ required_dict = {
3128
+ 'apikey': True,
3129
+ 'workspace_id': True,
3130
+ 'workflow_name': False,
3131
+ 'project_name': True
3132
+ }
3133
+
3134
+ apikey, cloudos_url, workspace_id, workflow_name, repository_platform, execution_platform, project_name = (
3135
+ config_manager.load_profile_and_validate_data(
3136
+ ctx,
3137
+ INIT_PROFILE,
3138
+ CLOUDOS_URL,
3139
+ profile=profile,
3140
+ required_dict=required_dict,
3141
+ apikey=apikey,
3142
+ cloudos_url=cloudos_url,
3143
+ workspace_id=workspace_id,
3144
+ workflow_name=None,
3145
+ repository_platform=None,
3146
+ execution_platform=None,
3147
+ project_name=project_name
3148
+ )
3149
+ )
3150
+
3151
+ verify_ssl = ssl_selector(disable_ssl_verification, ssl_cert)
3152
+
3153
+ client = Datasets(
3154
+ cloudos_url=cloudos_url,
3155
+ apikey=apikey,
3156
+ workspace_id=workspace_id,
3157
+ project_name=project_name,
3158
+ verify=verify_ssl,
3159
+ cromwell_token=None
3160
+ )
3161
+
3162
+ # Split parent path to get its parent + name
3163
+ parent_parts = parent_path.split("/")
3164
+ parent_name = parent_parts[-1]
3165
+ parent_of_parent_path = "/".join(parent_parts[:-1])
3166
+
3167
+ # List the parent of the parent
3168
+ try:
3169
+ contents = client.list_folder_content(parent_of_parent_path)
3170
+ except Exception as e:
3171
+ click.echo(f"[ERROR] Could not list contents at '{parent_of_parent_path}': {str(e)}", err=True)
3172
+ sys.exit(1)
3173
+
3174
+ # Find the parent folder in the contents
3175
+ folder_info = next(
3176
+ (f for f in contents.get("folders", []) if f.get("name") == parent_name),
3177
+ None
3178
+ )
3179
+
3180
+ if not folder_info:
3181
+ click.echo(f"[ERROR] Could not find folder '{parent_name}' in '{parent_of_parent_path}'.", err=True)
3182
+ sys.exit(1)
3183
+
3184
+ parent_id = folder_info.get("_id")
3185
+ folder_type = folder_info.get("folderType")
3186
+
3187
+ if folder_type is True:
3188
+ parent_kind = "Dataset"
3189
+ elif isinstance(folder_type, str):
3190
+ parent_kind = "Folder"
3191
+ else:
3192
+ click.echo(f"[ERROR] Unrecognized folderType for '{parent_path}'.", err=True)
3193
+ sys.exit(1)
3194
+
3195
+ # Create the folder
3196
+ click.echo(f"Creating folder '{folder_name}' under '{parent_path}' ({parent_kind})...")
3197
+ try:
3198
+ response = client.create_virtual_folder(name=folder_name, parent_id=parent_id, parent_kind=parent_kind)
3199
+ if response.ok:
3200
+ click.secho(f"[SUCCESS] Folder '{folder_name}' created under '{parent_path}'", fg="green", bold=True)
3201
+ else:
3202
+ click.echo(f"[ERROR] Folder creation failed: {response.status_code} - {response.text}", err=True)
3203
+ sys.exit(1)
3204
+ except Exception as e:
3205
+ click.echo(f"[ERROR] Folder creation failed: {str(e)}", err=True)
3206
+ sys.exit(1)
3207
+
3208
+
2963
3209
  if __name__ == "__main__":
2964
3210
  run_cloudos_cli()
@@ -0,0 +1 @@
1
+ __version__ = '2.35.0'
@@ -5,7 +5,7 @@ This is the main class for file explorer (datasets).
5
5
  from dataclasses import dataclass
6
6
  from typing import Union
7
7
  from cloudos_cli.clos import Cloudos
8
- from cloudos_cli.utils.requests import retry_requests_get, retry_requests_put
8
+ from cloudos_cli.utils.requests import retry_requests_get, retry_requests_put, retry_requests_post
9
9
  import json
10
10
 
11
11
  @dataclass
@@ -403,4 +403,88 @@ class Datasets(Cloudos):
403
403
  }
404
404
 
405
405
  response = retry_requests_put(url, headers=headers, data=json.dumps(payload), verify=self.verify)
406
+ return response
407
+
408
+ def copy_item(self, item, destination_id, destination_kind):
409
+ """Copy a file or folder (S3 or Virtual) to a destination in CloudOS."""
410
+ headers = {
411
+ "accept": "application/json",
412
+ "content-type": "application/json",
413
+ "ApiKey": self.apikey
414
+ }
415
+ parent = {"kind": destination_kind, "id": destination_id}
416
+
417
+ # Virtual folder
418
+ if item.get("folderType") == "VirtualFolder":
419
+ payload = {
420
+ "copyContentsFrom": item["_id"],
421
+ "name": item["name"],
422
+ "parent": parent
423
+ }
424
+ url = f"{self.cloudos_url}/api/v1/folders/virtual?teamId={self.workspace_id}"
425
+ # S3 folder
426
+ elif item.get("folderType") == "S3Folder":
427
+ payload = {
428
+ "s3BucketName": item["s3BucketName"],
429
+ "s3ObjectKey": item.get("s3ObjectKey") or item.get("s3Prefix"),
430
+ "name": item["name"],
431
+ "parent": parent,
432
+ "isManagedByLifebit": item.get("isManagedByLifebit", False)
433
+ }
434
+ url = f"{self.cloudos_url}/api/v1/folders/s3?teamId={self.workspace_id}"
435
+ # S3 file
436
+ elif item.get("fileType") == "S3File":
437
+ payload = {
438
+ "s3BucketName": item["s3BucketName"],
439
+ "s3ObjectKey": item["s3ObjectKey"],
440
+ "name": item["name"],
441
+ "parent": parent,
442
+ "isManagedByLifebit": item.get("isManagedByLifebit", False),
443
+ "sizeInBytes": item.get("sizeInBytes", 0)
444
+ }
445
+ url = f"{self.cloudos_url}/api/v1/files/s3?teamId={self.workspace_id}"
446
+ else:
447
+ raise ValueError(f"Unknown item type for copy: {item.get('name')}")
448
+ response = retry_requests_post(url, headers=headers, json=payload)
449
+
450
+ return response
451
+
452
+ def create_virtual_folder(self, name: str, parent_id: str, parent_kind: str):
453
+ """
454
+ Create a new virtual folder in CloudOS under a given parent.
455
+
456
+ Parameters
457
+ ----------
458
+ name : str
459
+ The name of the new folder.
460
+ parent_id : str
461
+ The ID of the parent (can be a Dataset or a Folder).
462
+ parent_kind : str
463
+ The type of the parent: either "Dataset" or "Folder".
464
+
465
+ Returns
466
+ -------
467
+ response : requests.Response
468
+ The response object from the CloudOS API.
469
+ """
470
+ if parent_kind not in ("Dataset", "Folder"):
471
+ raise ValueError("Invalid parent_kind. Must be 'Dataset' or 'Folder'.")
472
+
473
+ url = f"{self.cloudos_url}/api/v1/folders/virtual?teamId={self.workspace_id}"
474
+
475
+ headers = {
476
+ "accept": "application/json",
477
+ "content-type": "application/json",
478
+ "ApiKey": self.apikey
479
+ }
480
+
481
+ payload = {
482
+ "name": name,
483
+ "parent": {
484
+ "kind": parent_kind,
485
+ "id": parent_id
486
+ }
487
+ }
488
+
489
+ response = retry_requests_post(url, headers=headers, json=payload, verify=self.verify)
406
490
  return response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudos_cli
3
- Version: 2.33.0
3
+ Version: 2.35.0
4
4
  Summary: Python package for interacting with CloudOS
5
5
  Home-page: https://github.com/lifebit-ai/cloudos-cli
6
6
  Author: David Piñeyro
@@ -1007,6 +1007,55 @@ Please, be aware that renaming can only happen in files and folders that are pre
1007
1007
 
1008
1008
  Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
1009
1009
 
1010
+ ```bash
1011
+ --cloudos-url $CLOUDOS \
1012
+ --apikey $MY_API_KEY \
1013
+ --workspace-id $WORKSPACE_ID \
1014
+ --project-name $PROJEC_NAME
1015
+ ```
1016
+ #### Create a (virtual) folder
1017
+
1018
+ New folders can be created within the `Data` dataset and its subfolders using the following command
1019
+
1020
+ ```
1021
+ cloudos datasets mkdir <new_folder_path>
1022
+ ```
1023
+ where ` new_folder_path` is the path to the folder to be created.
1024
+
1025
+ Please, be aware that the folder creation can only happen in `Data` or its sub-folders.
1026
+
1027
+ Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
1028
+
1029
+ ```bash
1030
+ --cloudos-url $CLOUDOS \
1031
+ --apikey $MY_API_KEY \
1032
+ --workspace-id $WORKSPACE_ID \
1033
+ --project-name $PROJEC_NAME
1034
+ ```
1035
+
1036
+ #### Copying files and folders
1037
+
1038
+ Files and folders can be copied **from** anywhere in the project **to** `Data` or any of its subfolders programmatically (i.e `Data`, `Data/folder/file.txt`).
1039
+
1040
+ 1. The copy can happen **within the same project** running the following command:
1041
+ ```
1042
+ cloudos datasets cp <souce_path> <destination_path> --profile <profile name>
1043
+ ```
1044
+ where the source project as well as the destination one is the one defined in the profile.
1045
+
1046
+ 2. The move can also happen **across different projects** within the same workspace by running the following command
1047
+ ```
1048
+ cloudos datasets cp <source_path> <destiantion_path> --profile <profile_name> --destination-project-name <project_name>
1049
+ ```
1050
+ In this case, only the source project is the one specified in the profile.
1051
+
1052
+ Any of the `source_path` must be a full path; any `destination_path` must be a path starting with `Data` and finishing with the folder where to move the file/folder. An example of such command is:
1053
+
1054
+ ```
1055
+ cloudos datasets cp AnalysesResults/my_analysis/results/my_plot.png Data/plots
1056
+ ```
1057
+
1058
+ Please, note that in the above example a preconfigured profile has been used. If no profile is provided and there is no default profile, the user will need to also provide the following flags
1010
1059
  ```bash
1011
1060
  --cloudos-url $CLOUDOS \
1012
1061
  --apikey $MY_API_KEY \
@@ -1 +0,0 @@
1
- __version__ = '2.33.0'
File without changes
File without changes
File without changes