scientiflow-cli 0.4.7__py3-none-any.whl → 0.4.8__py3-none-any.whl

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.
scientiflow_cli/main.py CHANGED
@@ -7,10 +7,11 @@ from importlib.metadata import PackageNotFoundError
7
7
  from scientiflow_cli.cli.login import login_user
8
8
  from scientiflow_cli.cli.logout import logout_user
9
9
  from scientiflow_cli.pipeline.get_jobs import get_jobs
10
- from scientiflow_cli.services.executor import execute_jobs, execute_jobs_sync, execute_job_id
10
+ from scientiflow_cli.services.executor import execute_jobs
11
11
  from scientiflow_cli.services.base_directory import set_base_directory, get_base_directory
12
12
  from scientiflow_cli.utils.singularity import install_singularity_main as install_singularity
13
13
  from scientiflow_cli.pipeline.container_manager import manage_containers
14
+ from scientiflow_cli.services.modes import set_mode
14
15
  from scientiflow_cli.services.rich_printer import RichPrinter
15
16
  from art import text2art
16
17
 
@@ -82,6 +83,8 @@ def main():
82
83
  parser.add_argument('--execute-jobs', nargs='*', type=int, help="Execute jobs. Specify job IDs as arguments \n(e.g., --execute-jobs jobID1 jobID2 ...) or leave empty to execute all jobs.\nUse -p or --parallel flag to execute jobs in parallel.")
83
84
  parser.add_argument('--hostname', type=str, help=argparse.SUPPRESS) # Hide --hostname from --help
84
85
  parser.add_argument('--token', type=str, help=argparse.SUPPRESS) # Hide --token from --help
86
+ parser.add_argument('--set-mode', type=str, choices=["dev", "prod"], help=argparse.SUPPRESS) # Hide --set-mode from --help
87
+ parser.add_argument('--cloud-job', action='store_true', help=argparse.SUPPRESS) # Hide --cloud-job from --help
85
88
 
86
89
  # Parse arguments
87
90
  args, unknown_args = parser.parse_known_args()
@@ -120,7 +123,7 @@ def main():
120
123
  elif args.execute_jobs is not None:
121
124
  # Use the parsed `parallel` flag
122
125
  job_ids = args.execute_jobs if args.execute_jobs else None
123
- execute_jobs(job_ids=job_ids, parallel=args.parallel)
126
+ execute_jobs(job_ids=job_ids, parallel=args.parallel, is_cloud=args.cloud_job)
124
127
  elif args.install_singularity:
125
128
  install_singularity(enable_gpu=args.enable_gpu)
126
129
  elif args.manage_containers:
@@ -128,6 +131,10 @@ def main():
128
131
  if not base_dir:
129
132
  sys.exit(2)
130
133
  manage_containers(base_dir=base_dir)
134
+ elif args.set_mode:
135
+ logout_user()
136
+ set_mode(args.set_mode)
137
+ sys.exit(0)
131
138
  else:
132
139
  display_title()
133
140
  printer.print_message("No arguments specified. Use --help to see available options", style="bold red")
@@ -21,7 +21,7 @@ def get_all_pending_jobs() -> list[dict]:
21
21
  return []
22
22
 
23
23
 
24
- def execute_jobs(job_ids: list[int] = None, parallel: bool = False) -> None:
24
+ def execute_jobs(job_ids: list[int] = None, parallel: bool = False, is_cloud: bool = False) -> None:
25
25
  """
26
26
  Execute jobs based on the provided job IDs. If no job IDs are provided, execute all pending jobs.
27
27
  If `parallel` is True, execute jobs asynchronously.
@@ -50,32 +50,8 @@ def execute_jobs(job_ids: list[int] = None, parallel: bool = False) -> None:
50
50
  else:
51
51
  # Execute jobs synchronously
52
52
  for job in jobs_to_execute:
53
- execute_single_job(job)
53
+ execute_single_job(job, is_cloud)
54
54
 
55
- # Wait for all background jobs from all executed jobs to complete
56
- global_bg_tracker.wait_for_all_jobs()
57
-
58
-
59
- def execute_jobs_sync(job_ids: list[int] = None) -> None:
60
- """
61
- Execute all jobs synchronously and in order
62
- """
63
-
64
- all_pending_jobs: list[dict] = []
65
- all_pending_jobs = get_all_pending_jobs()
66
- all_pending_jobs = sort_jobs_by_id(all_pending_jobs)
67
-
68
- job_dict: dict[int, dict] = store_jobs_in_dict(all_pending_jobs)
69
-
70
- for job_id in job_ids:
71
- if job_id not in job_dict:
72
- printer.print_error(f"No job found with ID: {job_id}")
73
- continue
74
- execute_single_job(job_dict[job_id])
75
-
76
- # Wait for all background jobs from all executed jobs to complete
77
- global_bg_tracker.wait_for_all_jobs()
78
-
79
55
 
80
56
  def sort_jobs_by_id(all_pending_jobs: list[dict]) -> list[dict]:
81
57
  """
@@ -103,31 +79,6 @@ def store_jobs_in_dict(all_pending_jobs: list[dict]) -> dict:
103
79
 
104
80
  return job_dict
105
81
 
106
-
107
- def execute_job_id(job_id: int) -> None:
108
- """
109
- Execute job with the given job_id
110
- """
111
-
112
- # Retrieve all jobs using 'get_jobs'
113
- all_pending_jobs: list[dict] = []
114
-
115
- all_pending_jobs = get_all_pending_jobs()
116
-
117
- # Store jobs in order of their job_id
118
- job_dict: dict[int, dict] = store_jobs_in_dict(all_pending_jobs)
119
-
120
- if job_id not in job_dict:
121
- printer.print_error(f"No job found with ID: {job_id}")
122
- return
123
-
124
- execute_single_job(job_dict[job_id])
125
-
126
- # Wait for all background jobs to complete
127
- global_bg_tracker.wait_for_all_jobs()
128
-
129
-
130
-
131
82
  async def execute_async(jobs: list[dict]) -> None:
132
83
  """Execute jobs asynchronously."""
133
84
  running_jobs = []
@@ -164,7 +115,7 @@ async def execute_async(jobs: list[dict]) -> None:
164
115
  global_bg_tracker.wait_for_all_jobs()
165
116
 
166
117
 
167
- def execute_single_job(job: dict) -> None:
118
+ def execute_single_job(job: dict, is_cloud: bool = False) -> None:
168
119
  """Function to decode and execute a job."""
169
120
  try:
170
121
  # Validate the job dictionary
@@ -201,7 +152,7 @@ def execute_single_job(job: dict) -> None:
201
152
  if job_status != "running":
202
153
  if job["new_job"] == 1:
203
154
  # Initialize folders for the project / project_job
204
- create_job_dirs(job)
155
+ create_job_dirs(job, is_cloud)
205
156
 
206
157
  # Fetch the files and folder from the backend
207
158
  get_job_files(job)
@@ -0,0 +1,45 @@
1
+ from pathlib import Path
2
+ from scientiflow_cli.services.rich_printer import RichPrinter
3
+ import os
4
+
5
+ printer = RichPrinter()
6
+
7
+ # Use ~/.scientiflow/mode for mode configuration (plain text file)
8
+ MODE_FILE = os.path.expanduser("~/.scientiflow/mode")
9
+ MODE_DIR = os.path.dirname(MODE_FILE)
10
+
11
+ def set_mode(mode: str):
12
+ mode = mode.lower()
13
+ if mode not in {"dev", "prod"}:
14
+ raise ValueError("Mode must be either 'dev' or 'prod'")
15
+
16
+ # Ensure directory exists
17
+ os.makedirs(MODE_DIR, exist_ok=True)
18
+
19
+ # Write mode to plain text file
20
+ with open(MODE_FILE, "w") as file:
21
+ file.write(mode)
22
+
23
+ printer.print_message(
24
+ f"ScientiFlow mode set to '{mode}'",
25
+ style="bold green"
26
+ )
27
+
28
+
29
+ def get_mode() -> str:
30
+ # Create mode file with default "prod" if it doesn't exist
31
+ if not os.path.exists(MODE_FILE):
32
+ os.makedirs(MODE_DIR, exist_ok=True)
33
+ with open(MODE_FILE, "w") as file:
34
+ file.write("prod")
35
+ return "prod"
36
+
37
+ # Read mode from file
38
+ try:
39
+ with open(MODE_FILE, "r") as file:
40
+ mode = file.read().strip().lower()
41
+ if mode in {"dev", "prod"}:
42
+ return mode
43
+ return "prod"
44
+ except Exception:
45
+ return "prod"
@@ -1,31 +1,44 @@
1
1
  import requests
2
- from scientiflow_cli.config import Config
2
+ from scientiflow_cli.utils.config import get_app_base_url
3
3
  from scientiflow_cli.cli.auth_utils import getAuthToken
4
4
 
5
- app_base_url = Config.APP_BASE_URL
6
-
7
5
 
8
6
  def handle_response(response, error_message):
9
7
  return response
10
8
 
11
- def make_auth_request(endpoint,method,data=None,params=None,error_message=None):
9
+ def make_auth_request(endpoint, method, data=None, params=None, error_message=None):
12
10
  headers = {'Authorization': f'Bearer {getAuthToken()}'}
11
+ base_url = get_app_base_url()
12
+
13
13
  try:
14
14
  if method == 'GET':
15
- response = requests.get(app_base_url+endpoint,headers=headers,params=params)
15
+ response = requests.get(base_url + endpoint, headers=headers, params=params)
16
16
  elif method == 'POST':
17
- response = requests.post(app_base_url+endpoint, json=data,headers=headers)
17
+ response = requests.post(base_url + endpoint, json=data, headers=headers)
18
+ else:
19
+ raise ValueError("Unsupported HTTP method")
20
+
18
21
  return handle_response(response, error_message)
22
+
19
23
  except requests.RequestException as e:
20
- return "Unsupported HTTP method"
21
-
22
- def make_no_auth_request(endpoint,method,data=None,error_message=None):
24
+ print(e)
25
+ return "Request failed"
26
+
27
+
28
+ def make_no_auth_request(endpoint, method, data=None, error_message=None):
29
+ base_url = get_app_base_url()
30
+
23
31
  try:
24
32
  if method == 'GET':
25
- response = requests.get(app_base_url+endpoint)
33
+ response = requests.get(base_url + endpoint)
26
34
  elif method == 'POST':
27
- response = requests.post(app_base_url+endpoint, json=data)
35
+ response = requests.post(base_url + endpoint, json=data)
36
+ print(response)
37
+ else:
38
+ raise ValueError("Unsupported HTTP method")
39
+
28
40
  return handle_response(response, error_message)
41
+
29
42
  except requests.RequestException as e:
30
- return "Unsupported HTTP method"
31
-
43
+ print(e)
44
+ return "Request failed"
@@ -0,0 +1,9 @@
1
+ from scientiflow_cli.services.modes import get_mode
2
+
3
+
4
+ def get_app_base_url() -> str:
5
+ mode = get_mode()
6
+ if mode == "dev":
7
+ return "https://www.scientiflow-backend-dev.scientiflow.com/api"
8
+
9
+ return "https://www.backend.scientiflow.com/api"
@@ -37,9 +37,12 @@ def get_job_files(job: dict) -> None:
37
37
 
38
38
  printer.print_success(f"[+] Files extracted to {str(project_dir_name).strip()}")
39
39
 
40
- def create_job_dirs(job: dict) -> None:
40
+ def create_job_dirs(job: dict, is_cloud: bool = False) -> None:
41
41
  base_dir = Path(job['server']['base_directory'])
42
- project_dir = base_dir / job['project']['project_title']
42
+ if is_cloud:
43
+ project_dir = base_dir / (job['project']['id']+"_"+job['project']['project_title'])
44
+ else:
45
+ project_dir = base_dir / job['project']['project_title']
43
46
  job_dir = project_dir / job['project_job']['job_directory']
44
47
  job_dir.mkdir(parents=True, exist_ok=True)
45
48
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scientiflow-cli
3
- Version: 0.4.7
3
+ Version: 0.4.8
4
4
  Summary: CLI tool for scientiflow. This application runs on the client side, decodes pipelines, and executes them in the configured order!
5
5
  License: Proprietary
6
6
  Author: ScientiFlow
@@ -4,8 +4,7 @@ scientiflow_cli/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
4
4
  scientiflow_cli/cli/auth_utils.py,sha256=XeGLqBhbaV5q-I7br-WvLxpL1O_XMB1hhZPEunc1DQc,1793
5
5
  scientiflow_cli/cli/login.py,sha256=RLoVpbAH9MpySCsGSe29MUpz4kdTDdBhxs1L41Xg8qw,846
6
6
  scientiflow_cli/cli/logout.py,sha256=EzpFPA1ENoXqLvduo6rxaVF09GqgO5GCRvnGMDr5BEw,420
7
- scientiflow_cli/config.py,sha256=wVSXwo-ibbspMHEYpnipNgH0hy7Upi6gmgY6Vf4N_S8,284
8
- scientiflow_cli/main.py,sha256=PbZRL4GatzXVK95GGPWJnpBCKPqyn1dVmiwNHDyjXkU,6584
7
+ scientiflow_cli/main.py,sha256=AliEFU3bebJV2tbvxQYbiMY1bqVGqq3-a6dzkVUXong,6982
9
8
  scientiflow_cli/pipeline/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
9
  scientiflow_cli/pipeline/container_manager.py,sha256=KAnE5AvsSg4cewLc_v4gWCqhKGoc7ycHOtl_HYxUK7E,8444
11
10
  scientiflow_cli/pipeline/decode_and_execute.py,sha256=M_0RPiJhenPc9HShGIB7CLzb-Jc0MPsHClGhNQYh-Xk,18926
@@ -13,18 +12,20 @@ scientiflow_cli/pipeline/get_jobs.py,sha256=69jOIVwXd8j2lAYy28r2QcsjFT4yRpXNOqsf
13
12
  scientiflow_cli/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
13
  scientiflow_cli/services/auth_service.py,sha256=lknARfVTjRCH-4yWVPKiS330NIVHxFw3HlQdN2Lw3Og,3343
15
14
  scientiflow_cli/services/base_directory.py,sha256=2dUvGYk4enLe3Cagcs_bfv2kNuHg1ws-dtMDEW_tccI,2726
16
- scientiflow_cli/services/executor.py,sha256=jdGIOqukVwZxh6MQwgzysveY5yRtHIMinI1Uw3SDCMM,12778
17
- scientiflow_cli/services/request_handler.py,sha256=tJF00TQLbgDKBiyJtyYZXGCv6lvd13BjLB2gQAKzQEw,1172
15
+ scientiflow_cli/services/executor.py,sha256=Qj_DfU8umsmc9_rzTsy47EeaOehc6E24x_t4lFmWKcY,11480
16
+ scientiflow_cli/services/modes.py,sha256=-Bk1CJO0vgc8v_rXktfKAyHSF6cr5bGbufSGa_DtvY4,1241
17
+ scientiflow_cli/services/request_handler.py,sha256=5Y1B84kpHP-EDAI9d6fjaPtQE1-dMKCtoCaqvixifSU,1397
18
18
  scientiflow_cli/services/rich_printer.py,sha256=5ORAaZOa_84m6vP-novpPOI70UPxt0pEvmRq9999Ifg,2129
19
19
  scientiflow_cli/services/status_updater.py,sha256=VjC2V6lWzjwBN7ZhCQzW_h_sMG25Poeh35MNTeVdt5E,2910
20
20
  scientiflow_cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ scientiflow_cli/utils/config.py,sha256=iq9aEVwlJA-KLPWX6Vtx6SaEgH3UAuKjNIODw2mGYxY,256
21
22
  scientiflow_cli/utils/encryption.py,sha256=iQ-b40i75JvoB1cGANDqzZXLztD54toO_6loX1m5W9Q,1107
22
- scientiflow_cli/utils/file_manager.py,sha256=J6FBaZ0xz6OH4vcArOGj5KqKSZ2AD78HNeiQPFEfmlY,1916
23
+ scientiflow_cli/utils/file_manager.py,sha256=JRCXPENFHdPOc0NBwGorRh4EpeZ-UtMtwHGVJjSVihc,2070
23
24
  scientiflow_cli/utils/logger.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
25
  scientiflow_cli/utils/mock.py,sha256=UZ9cN2Qx3EAXcxnLQY5z4DQWy4jflnWFnfNTsuvnFH8,11237
25
26
  scientiflow_cli/utils/singularity.py,sha256=jy8ep7Xa1Eg4fptNjyXLPuVN2KA8l4dFil-w-KaVNkw,4956
26
- scientiflow_cli-0.4.7.dist-info/LICENSE.md,sha256=nb6GGGYuS_KXe33mSNwcEW-QzvwM475NQ4cNE7KBb34,425
27
- scientiflow_cli-0.4.7.dist-info/METADATA,sha256=XKOZAyb60hSC0Y2bSmzLuuh1TEt7ET563x6vfzCnGbs,2491
28
- scientiflow_cli-0.4.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
29
- scientiflow_cli-0.4.7.dist-info/entry_points.txt,sha256=0lq2mjcG5hGfODrQodeMSAy9RfE2EX1MZSHRpfSncxc,61
30
- scientiflow_cli-0.4.7.dist-info/RECORD,,
27
+ scientiflow_cli-0.4.8.dist-info/LICENSE.md,sha256=nb6GGGYuS_KXe33mSNwcEW-QzvwM475NQ4cNE7KBb34,425
28
+ scientiflow_cli-0.4.8.dist-info/METADATA,sha256=NqrIebvitUWmK3PNgD06jx-Tghwz3Cak-jQ2XfU8S9U,2491
29
+ scientiflow_cli-0.4.8.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
30
+ scientiflow_cli-0.4.8.dist-info/entry_points.txt,sha256=0lq2mjcG5hGfODrQodeMSAy9RfE2EX1MZSHRpfSncxc,61
31
+ scientiflow_cli-0.4.8.dist-info/RECORD,,
scientiflow_cli/config.py DELETED
@@ -1,8 +0,0 @@
1
- import os
2
-
3
- class Config:
4
- mode="prod"
5
- if mode=="prod":
6
- APP_BASE_URL = os.getenv("APP_BASE_URL", "https://www.backend.scientiflow.com/api")
7
- elif mode=="dev":
8
- APP_BASE_URL = os.getenv("APP_BASE_URL", "https://www.scientiflow-backend-dev.scientiflow.com/api")