accli 2.0.0rc1__tar.gz → 2.0.0rc4__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 (25) hide show
  1. {accli-2.0.0rc1 → accli-2.0.0rc4}/PKG-INFO +4 -4
  2. {accli-2.0.0rc1 → accli-2.0.0rc4}/README.md +2 -2
  3. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/_version.py +1 -1
  4. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/cli.py +249 -98
  5. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/gui.py +10 -3
  6. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/mount_downloader.py +1 -1
  7. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/token.py +15 -1
  8. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli.egg-info/PKG-INFO +4 -4
  9. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli.egg-info/requires.txt +1 -1
  10. {accli-2.0.0rc1 → accli-2.0.0rc4}/pyproject.toml +1 -1
  11. {accli-2.0.0rc1 → accli-2.0.0rc4}/LICENSE +0 -0
  12. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/AcceleratorJobProjectService.py +0 -0
  13. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/AcceleratorTaskDispatcher.py +0 -0
  14. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/AcceleratorTerminalCliProjectService.py +0 -0
  15. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/CsvRegionalTimeseriesValidator.py +0 -0
  16. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/__init__.py +0 -0
  17. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/__main__.py +0 -0
  18. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/cleanup-nfs.ps1 +0 -0
  19. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/common.py +0 -0
  20. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli/setup-nfs.ps1 +0 -0
  21. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli.egg-info/SOURCES.txt +0 -0
  22. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli.egg-info/dependency_links.txt +0 -0
  23. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli.egg-info/entry_points.txt +0 -0
  24. {accli-2.0.0rc1 → accli-2.0.0rc4}/accli.egg-info/top_level.txt +0 -0
  25. {accli-2.0.0rc1 → accli-2.0.0rc4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: accli
3
- Version: 2.0.0rc1
3
+ Version: 2.0.0rc4
4
4
  Summary: IIASA Accelerator Client
5
5
  Author-email: Wrufesh S <wrufesh@gmail.com>
6
6
  License: The MIT License (MIT)
@@ -39,7 +39,7 @@ Requires-Dist: requests>=2.25.1
39
39
  Requires-Dist: jsonschema>=4.5.1
40
40
  Requires-Dist: pydantic>=2.0
41
41
  Requires-Dist: GitPython
42
- Requires-Dist: hf-xet>=1.4.3
42
+ Requires-Dist: hf-xet==1.5.2
43
43
  Dynamic: license-file
44
44
 
45
45
  # Accelerator Terminal Client and Python API
@@ -138,8 +138,8 @@ Usage: accli [OPTIONS] COMMAND [ARGS]...
138
138
 
139
139
  ### Handling self-signed certificates
140
140
 
141
- 1. Copy and paste certificates from `<control_services_backend>/certs/public.crt` as
142
- `./certs/dev-backend.crt` and `<accelerator_service>/minio_certs/public.crt` as
141
+ 1. Copy and paste certificates from `<control_services_backend>/certs/ca.crt` as
142
+ `./certs/dev-backend.crt` and `<accelerator_service>/minio_certs/ca.crt` as
143
143
  `./certs/dev-minio-ca.crt`.
144
144
  2. Run
145
145
  ```
@@ -94,8 +94,8 @@ Usage: accli [OPTIONS] COMMAND [ARGS]...
94
94
 
95
95
  ### Handling self-signed certificates
96
96
 
97
- 1. Copy and paste certificates from `<control_services_backend>/certs/public.crt` as
98
- `./certs/dev-backend.crt` and `<accelerator_service>/minio_certs/public.crt` as
97
+ 1. Copy and paste certificates from `<control_services_backend>/certs/ca.crt` as
98
+ `./certs/dev-backend.crt` and `<accelerator_service>/minio_certs/ca.crt` as
99
99
  `./certs/dev-minio-ca.crt`.
100
100
  2. Run
101
101
  ```
@@ -1,3 +1,3 @@
1
1
  # Please strictly put double quote to use this info for git tag
2
2
  # Read a developer guide for git tag command with regex
3
- VERSION = "v2.0.0-c1"
3
+ VERSION = "v2.0.0-c4"
@@ -300,12 +300,6 @@ def copy(
300
300
  verify_cert=(not ACCLI_DEBUG),
301
301
  )
302
302
 
303
- def make_token_refresher(slug: str):
304
- def refresher() -> tuple[str, int]:
305
- token_str, _, exp_time = exchange_refresh_token(slug)
306
- return token_str, exp_time
307
- return refresher
308
-
309
303
  if is_src_remote:
310
304
  # Download flow: acc://[project_slug]/[remote_prefix] -> local destination
311
305
  source_parsed = source[len("acc://"):]
@@ -336,7 +330,7 @@ def copy(
336
330
  else:
337
331
  dest_path.parent.mkdir(parents=True, exist_ok=True)
338
332
 
339
- download_infos = []
333
+ files_to_download = []
340
334
  for filename in filenames:
341
335
  # Filename returned usually starts with project_slug/
342
336
  if filename.startswith(f"{project_slug}/"):
@@ -378,32 +372,98 @@ def copy(
378
372
 
379
373
  local_dest.parent.mkdir(parents=True, exist_ok=True)
380
374
 
381
- download_infos.append(
382
- hf_xet.PyXetDownloadInfo(
383
- destination_path=str(local_dest.resolve()),
384
- hash=merkle_hash,
385
- file_size=file_size
386
- )
375
+ files_to_download.append(
376
+ (str(local_dest.resolve()), merkle_hash, file_size)
387
377
  )
388
378
 
389
- if not download_infos:
379
+ if not files_to_download:
390
380
  print("[bold red]ERROR: No valid files identified for download.[/bold red]")
391
381
  raise typer.Exit(1)
392
382
 
393
- print(f"[bold cyan]Downloading {len(download_infos)} files using hf-xet...[/bold cyan]")
394
- try:
395
- hf_xet.download_files(
396
- files=download_infos,
397
- endpoint=cas_endpoint,
398
- token_info=(cas_token, expires_at),
399
- token_refresher=make_token_refresher(project_slug),
400
- progress_updater=None,
401
- request_headers=None
402
- )
403
- print("[bold green][OK] Download completed successfully![/bold green]")
404
- except Exception as e:
405
- print(f"[bold red]ERROR: Download failed: {e}[/bold red]")
406
- raise typer.Exit(1)
383
+ MAX_FILES_PER_BATCH = 100
384
+ MAX_BYTES_PER_BATCH = 10 * 1024 * 1024 * 1024 # 10 GB
385
+
386
+ batches = []
387
+ current_batch = []
388
+ current_batch_size = 0
389
+
390
+ for item in files_to_download:
391
+ size = item[2]
392
+ if size >= MAX_BYTES_PER_BATCH and not current_batch:
393
+ batches.append([item])
394
+ continue
395
+
396
+ if len(current_batch) >= MAX_FILES_PER_BATCH or current_batch_size + size > MAX_BYTES_PER_BATCH:
397
+ batches.append(current_batch)
398
+ current_batch = []
399
+ current_batch_size = 0
400
+
401
+ current_batch.append(item)
402
+ current_batch_size += size
403
+
404
+ if current_batch:
405
+ batches.append(current_batch)
406
+
407
+ print(f"[bold cyan]Downloading {len(files_to_download)} files in {len(batches)} batches using hf-xet...[/bold cyan]")
408
+
409
+ refresh_url = f"{server_url.rstrip('/')}/api/v1/oauth/device/cas-token/"
410
+ refresh_headers = {"Authorization": f"Bearer {cas_token}"}
411
+
412
+ with Progress(
413
+ TextColumn("[progress.description]{task.description}"),
414
+ BarColumn(),
415
+ TaskProgressColumn(),
416
+ TimeElapsedColumn(),
417
+ ) as progress:
418
+ total_size = sum(item[2] for item in files_to_download)
419
+ overall_task = progress.add_task("[green]Total Download Progress...", total=total_size)
420
+
421
+ completed_in_previous_batches = 0
422
+
423
+ session = hf_xet.XetSession()
424
+ for batch_index, batch_items in enumerate(batches, 1):
425
+ progress.print(f"[cyan]Processing batch {batch_index}/{len(batches)}...[/cyan]")
426
+
427
+ # capture current completed_in_previous_batches in a local scope to avoid late binding issues
428
+ file_tasks = {}
429
+
430
+ def make_progress_handler(base_completed):
431
+ def on_progress(group_report, item_reports):
432
+ progress.update(overall_task, completed=base_completed + group_report.total_bytes_completed)
433
+ for item_id, item in item_reports.items():
434
+ if item_id not in file_tasks:
435
+ file_tasks[item_id] = progress.add_task(f"[blue]{item.item_name}", total=item.total_bytes)
436
+
437
+ progress.update(file_tasks[item_id], completed=item.bytes_completed)
438
+
439
+ # Hide completed tasks to keep the UI clean when downloading thousands of files
440
+ if item.bytes_completed >= item.total_bytes:
441
+ progress.update(file_tasks[item_id], visible=False)
442
+ return on_progress
443
+
444
+ try:
445
+ with session.new_file_download_group(
446
+ endpoint=cas_endpoint,
447
+ token=cas_token,
448
+ token_expiry_unix_secs=expires_at,
449
+ token_refresh_url=refresh_url,
450
+ token_refresh_headers=refresh_headers,
451
+ progress_callback=make_progress_handler(completed_in_previous_batches),
452
+ progress_interval_ms=500,
453
+ ) as group:
454
+ for dest_path, hash_val, size_val in batch_items:
455
+ info = hf_xet.XetFileInfo(hash_val, size_val)
456
+ group.start_download_file(info, dest_path)
457
+
458
+ batch_size = sum(item[2] for item in batch_items)
459
+ completed_in_previous_batches += batch_size
460
+ progress.update(overall_task, completed=completed_in_previous_batches)
461
+ progress.print(f"[bold green][OK] Batch {batch_index} completed successfully![/bold green]")
462
+ except Exception as e:
463
+ progress.print(f"[bold red]ERROR: Download failed for batch {batch_index}: {e}[/bold red]")
464
+ raise typer.Exit(1)
465
+
466
+ print("[bold green][OK] Download completed successfully![/bold green]")
407
467
 
408
468
  else:
409
469
  # Upload flow: local source -> acc://[project_slug]/[remote_path]
@@ -456,65 +516,137 @@ def copy(
456
516
  print("[bold yellow]No files to upload.[/bold yellow]")
457
517
  raise typer.Exit(0)
458
518
 
459
- print(f"[bold cyan]Uploading {len(local_paths)} files using hf-xet...[/bold cyan]")
460
- try:
461
- upload_results = hf_xet.upload_files(
462
- file_paths=[str(p) for p in local_paths],
463
- endpoint=cas_endpoint,
464
- token_info=(cas_token, expires_at),
465
- token_refresher=make_token_refresher(project_slug),
466
- progress_updater=None,
467
- _repo_type=None,
468
- request_headers=None,
469
- sha256s=None,
470
- skip_sha256=False
471
- )
472
- except Exception as e:
473
- print(f"[bold red]ERROR: Upload failed: {e}[/bold red]")
474
- raise typer.Exit(1)
519
+ MAX_FILES_PER_BATCH = 100
520
+ MAX_BYTES_PER_BATCH = 10 * 1024 * 1024 * 1024 # 10 GB
521
+
522
+ batches = []
523
+ current_batch_paths = []
524
+ current_batch_remote = []
525
+ current_batch_size = 0
526
+
527
+ for local_p, remote_n in zip(local_paths, remote_filenames):
528
+ size = local_p.stat().st_size
529
+ if size >= MAX_BYTES_PER_BATCH and not current_batch_paths:
530
+ batches.append(([local_p], [remote_n]))
531
+ continue
532
+
533
+ if len(current_batch_paths) >= MAX_FILES_PER_BATCH or current_batch_size + size > MAX_BYTES_PER_BATCH:
534
+ batches.append((current_batch_paths, current_batch_remote))
535
+ current_batch_paths = []
536
+ current_batch_remote = []
537
+ current_batch_size = 0
538
+
539
+ current_batch_paths.append(local_p)
540
+ current_batch_remote.append(remote_n)
541
+ current_batch_size += size
542
+
543
+ if current_batch_paths:
544
+ batches.append((current_batch_paths, current_batch_remote))
545
+
546
+ print(f"[bold cyan]Uploading {len(local_paths)} files in {len(batches)} batches using hf-xet...[/bold cyan]")
547
+
548
+ refresh_url = f"{server_url.rstrip('/')}/api/v1/oauth/device/cas-token/"
549
+ refresh_headers = {"Authorization": f"Bearer {cas_token}"}
550
+
551
+ with Progress(
552
+ TextColumn("[progress.description]{task.description}"),
553
+ BarColumn(),
554
+ TaskProgressColumn(),
555
+ TimeElapsedColumn(),
556
+ ) as progress:
557
+ total_size = sum(p.stat().st_size for p in local_paths)
558
+ overall_task = progress.add_task("[green]Total Upload Progress...", total=total_size)
559
+
560
+ completed_in_previous_batches = 0
561
+
562
+ session = hf_xet.XetSession()
563
+ for batch_index, (b_paths, b_remotes) in enumerate(batches, 1):
564
+ progress.print(f"[cyan]Processing batch {batch_index}/{len(batches)}...[/cyan]")
565
+
566
+ file_tasks = {}
567
+
568
+ def make_progress_handler(base_completed):
569
+ def on_progress(group_report, item_reports):
570
+ progress.update(overall_task, completed=base_completed + group_report.total_bytes_completed)
571
+ for item_id, item in item_reports.items():
572
+ if item_id not in file_tasks:
573
+ file_tasks[item_id] = progress.add_task(f"[blue]{item.item_name}", total=item.total_bytes)
574
+
575
+ progress.update(file_tasks[item_id], completed=item.bytes_completed)
576
+
577
+ # Hide completed tasks to keep the UI clean
578
+ if item.bytes_completed >= item.total_bytes:
579
+ progress.update(file_tasks[item_id], visible=False)
580
+ return on_progress
581
+
582
+ try:
583
+ with session.new_upload_commit(
584
+ endpoint=cas_endpoint,
585
+ token=cas_token,
586
+ token_expiry_unix_secs=expires_at,
587
+ token_refresh_url=refresh_url,
588
+ token_refresh_headers=refresh_headers,
589
+ progress_callback=make_progress_handler(completed_in_previous_batches),
590
+ progress_interval_ms=500,
591
+ ) as commit:
592
+ handles = []
593
+ for p in b_paths:
594
+ sha = compute_sha256(str(p))
595
+ h = commit.start_upload_file(str(p), sha256=sha)
596
+ handles.append((p, sha, h))
597
+
598
+ upload_results = [(p, sha, h.result()) for p, sha, h in handles]
599
+ except Exception as e:
600
+ progress.print(f"[bold red]ERROR: Upload failed for batch {batch_index}: {e}[/bold red]")
601
+ raise typer.Exit(1)
475
602
 
476
- # Compute SHA-256 locally and register metadata in database
477
- print("[cyan]Computing SHA-256 hashes and registering metadata...[/cyan]")
478
- registration_items = []
479
- for local_path, remote_filename, upload_info in zip(local_paths, remote_filenames, upload_results):
480
- sha256_hash = compute_sha256(str(local_path))
481
- registration_items.append({
482
- "filename": f"{project_slug}/{remote_filename}",
483
- "merkle_hash": upload_info.hash,
484
- "sha256": sha256_hash,
485
- "file_size": upload_info.file_size,
486
- "content_type": "application/octet-stream"
487
- })
488
-
489
- headers = {
490
- "Content-Type": "application/json",
491
- "X-Project-Slug": project_slug,
492
- "Authorization": f"Bearer {cas_token}"
493
- }
603
+ progress.print("[cyan]Computing SHA-256 hashes and registering metadata for batch...[/cyan]")
604
+ registration_items = []
605
+ for local_path, remote_filename, (p, sha256_hash, upload_info) in zip(b_paths, b_remotes, upload_results):
606
+ registration_items.append({
607
+ "filename": f"{project_slug}/{remote_filename}",
608
+ "merkle_hash": upload_info.xet_info.hash,
609
+ "sha256": sha256_hash,
610
+ "file_size": upload_info.xet_info.file_size,
611
+ "content_type": "application/octet-stream"
612
+ })
613
+
614
+ headers = {
615
+ "Content-Type": "application/json",
616
+ "X-Project-Slug": project_slug,
617
+ "Authorization": f"Bearer {cas_token}"
618
+ }
494
619
 
495
- try:
496
- response = requests.post(
497
- register_url,
498
- json={"items": registration_items},
499
- headers=headers,
500
- verify=(not ACCLI_DEBUG)
501
- )
502
- response.raise_for_status()
503
- print("[bold green][OK] Upload and bulk metadata registration completed successfully![/bold green]")
504
- except requests.exceptions.HTTPError as e:
505
- detail = None
506
- try:
507
- detail = e.response.json().get("detail")
508
- except Exception:
509
- pass
510
- if detail:
511
- print(f"[bold red]ERROR: Bulk metadata registration failed: {detail}[/bold red]")
512
- else:
513
- print(f"[bold red]ERROR: Bulk metadata registration failed: {e}[/bold red]")
514
- raise typer.Exit(1)
515
- except Exception as e:
516
- print(f"[bold red]ERROR: Bulk metadata registration failed: {e}[/bold red]")
517
- raise typer.Exit(1)
620
+ try:
621
+ response = requests.post(
622
+ register_url,
623
+ json={"items": registration_items},
624
+ headers=headers,
625
+ verify=(not ACCLI_DEBUG)
626
+ )
627
+ response.raise_for_status()
628
+
629
+ batch_size = sum(p.stat().st_size for p in b_paths)
630
+ completed_in_previous_batches += batch_size
631
+ progress.update(overall_task, completed=completed_in_previous_batches)
632
+
633
+ progress.print(f"[bold green][OK] Batch {batch_index} registered successfully![/bold green]")
634
+ except requests.exceptions.HTTPError as e:
635
+ detail = None
636
+ try:
637
+ detail = e.response.json().get("detail")
638
+ except Exception:
639
+ pass
640
+ if detail:
641
+ progress.print(f"[bold red]ERROR: Bulk metadata registration failed for batch {batch_index}: {detail}[/bold red]")
642
+ else:
643
+ progress.print(f"[bold red]ERROR: Bulk metadata registration failed for batch {batch_index}: {e}[/bold red]")
644
+ raise typer.Exit(1)
645
+ except Exception as e:
646
+ progress.print(f"[bold red]ERROR: Bulk metadata registration failed for batch {batch_index}: {e}[/bold red]")
647
+ raise typer.Exit(1)
648
+
649
+ print("[bold green][OK] Upload completed successfully![/bold green]")
518
650
 
519
651
 
520
652
  # --- Mount commands group ---
@@ -1314,21 +1446,40 @@ def mount_status(
1314
1446
  args = [str(hf_mount_bin), "status"]
1315
1447
 
1316
1448
  import subprocess
1449
+ active_mounts = []
1450
+
1451
+ # 1. Query hf-mount status directly
1317
1452
  try:
1318
1453
  result = subprocess.run(args, capture_output=True, text=True)
1319
1454
  if result.returncode == 0:
1320
1455
  stdout = result.stdout.strip()
1321
- if not stdout:
1322
- print("[cyan]No running mounts found.[/cyan]")
1323
- else:
1324
- print("[bold cyan]Active Mounts:[/bold cyan]")
1325
- print(stdout)
1326
- else:
1327
- print(f"[bold red][ERROR] Failed to retrieve mount status (exit code {result.returncode}):[/bold red]")
1328
- if result.stderr:
1329
- print(f"[red]{result.stderr}[/red]")
1330
- raise typer.Exit(result.returncode)
1331
- except Exception as e:
1332
- print(f"[bold red]ERROR: Failed to execute status process: {e}[/bold red]")
1333
- raise typer.Exit(1)
1456
+ if stdout:
1457
+ for line in stdout.splitlines():
1458
+ if line.strip():
1459
+ active_mounts.append(line.strip())
1460
+ except Exception:
1461
+ pass
1462
+
1463
+ # 2. Fallback: parse system mount table on Linux to find localhost NFS or FUSE hf-mounts
1464
+ if not active_mounts and platform.system() == "Linux":
1465
+ try:
1466
+ if os.path.exists("/proc/mounts"):
1467
+ with open("/proc/mounts", "r") as f:
1468
+ for line in f:
1469
+ parts = line.strip().split()
1470
+ if len(parts) >= 3:
1471
+ dev, mnt_point, fstype = parts[0], parts[1], parts[2]
1472
+ is_nfs_localhost = (fstype == "nfs" and dev.startswith("127.0.0.1:"))
1473
+ is_fuse_hf = ("hf-mount" in dev or "hf-mount" in fstype)
1474
+ if is_nfs_localhost or is_fuse_hf:
1475
+ active_mounts.append(f"{mnt_point} ({fstype} via {dev})")
1476
+ except Exception:
1477
+ pass
1478
+
1479
+ if not active_mounts:
1480
+ print("[cyan]No running mounts found.[/cyan]")
1481
+ else:
1482
+ print("[bold cyan]Active Mounts:[/bold cyan]")
1483
+ for m in active_mounts:
1484
+ print(m)
1334
1485
 
@@ -113,7 +113,7 @@ class AccliGuiApp(tk.Tk):
113
113
  self.build_auth_tab()
114
114
  self.build_logs_tab()
115
115
 
116
- def run_cli_async(self, args, on_done=None, log_to_viewer=True):
116
+ def run_cli_async(self, args, on_done=None, log_to_viewer=True, elevate=False):
117
117
  """Runs the CLI binary in a background thread to prevent UI freezing."""
118
118
  def worker():
119
119
  # Determine how to invoke accli
@@ -124,6 +124,13 @@ class AccliGuiApp(tk.Tk):
124
124
  # Script mode
125
125
  cmd = [sys.executable, "-m", "accli.cli"] + args
126
126
 
127
+ if elevate and platform.system() != "Windows":
128
+ import shutil
129
+ if shutil.which("pkexec"):
130
+ cmd = ["pkexec"] + cmd
131
+ else:
132
+ cmd = ["sudo"] + cmd
133
+
127
134
  try:
128
135
  if log_to_viewer:
129
136
  self.append_log(f"Executing: {' '.join(cmd)}\n")
@@ -491,7 +498,7 @@ class AccliGuiApp(tk.Tk):
491
498
  self.status_bar_val.set("Mount Failed")
492
499
  messagebox.showerror("Error", f"Failed to mount project '{slug}'. See logs for details.")
493
500
 
494
- self.run_cli_async(args, on_done=on_done)
501
+ self.run_cli_async(args, on_done=on_done, elevate=True)
495
502
 
496
503
  def action_mount_stop(self):
497
504
  selected = self.mounts_list.get(tk.ACTIVE)
@@ -521,7 +528,7 @@ class AccliGuiApp(tk.Tk):
521
528
  self.status_bar_val.set("Stop Failed")
522
529
  messagebox.showerror("Error", f"Failed to stop mount at {mount_point}.")
523
530
 
524
- self.run_cli_async(args, on_done=on_done)
531
+ self.run_cli_async(args, on_done=on_done, elevate=True)
525
532
 
526
533
  # ------------------ COPY TAB ------------------
527
534
  def build_copy_tab(self):
@@ -9,7 +9,7 @@ import typer
9
9
  from rich import print
10
10
  from rich.progress import Progress, TextColumn, BarColumn, TaskProgressColumn, TimeElapsedColumn
11
11
 
12
- DEFAULT_VERSION = "v0.6.5-acc-pr140-p4"
12
+ DEFAULT_VERSION = "v0.6.5-acc-pr140-p5"
13
13
  BINARY_DIR = Path.home() / ".accli" / "bin"
14
14
 
15
15
  # Regex to safely validate version strings to prevent URL manipulation or directory traversal
@@ -4,7 +4,21 @@ from tinydb import TinyDB
4
4
 
5
5
 
6
6
  def get_db_path():
7
- home = os.path.expanduser("~")
7
+ sudo_user = os.environ.get("SUDO_USER")
8
+ pkexec_uid = os.environ.get("PKEXEC_UID")
9
+
10
+ if (sudo_user or pkexec_uid) and os.name != "nt":
11
+ try:
12
+ import pwd
13
+ if pkexec_uid:
14
+ home = pwd.getpwuid(int(pkexec_uid)).pw_dir
15
+ else:
16
+ home = pwd.getpwnam(sudo_user).pw_dir
17
+ except Exception:
18
+ home = os.path.expanduser("~")
19
+ else:
20
+ home = os.path.expanduser("~")
21
+
8
22
  token_directory = f"{home}/.accli"
9
23
 
10
24
  if not os.path.exists(token_directory):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: accli
3
- Version: 2.0.0rc1
3
+ Version: 2.0.0rc4
4
4
  Summary: IIASA Accelerator Client
5
5
  Author-email: Wrufesh S <wrufesh@gmail.com>
6
6
  License: The MIT License (MIT)
@@ -39,7 +39,7 @@ Requires-Dist: requests>=2.25.1
39
39
  Requires-Dist: jsonschema>=4.5.1
40
40
  Requires-Dist: pydantic>=2.0
41
41
  Requires-Dist: GitPython
42
- Requires-Dist: hf-xet>=1.4.3
42
+ Requires-Dist: hf-xet==1.5.2
43
43
  Dynamic: license-file
44
44
 
45
45
  # Accelerator Terminal Client and Python API
@@ -138,8 +138,8 @@ Usage: accli [OPTIONS] COMMAND [ARGS]...
138
138
 
139
139
  ### Handling self-signed certificates
140
140
 
141
- 1. Copy and paste certificates from `<control_services_backend>/certs/public.crt` as
142
- `./certs/dev-backend.crt` and `<accelerator_service>/minio_certs/public.crt` as
141
+ 1. Copy and paste certificates from `<control_services_backend>/certs/ca.crt` as
142
+ `./certs/dev-backend.crt` and `<accelerator_service>/minio_certs/ca.crt` as
143
143
  `./certs/dev-minio-ca.crt`.
144
144
  2. Run
145
145
  ```
@@ -5,4 +5,4 @@ requests>=2.25.1
5
5
  jsonschema>=4.5.1
6
6
  pydantic>=2.0
7
7
  GitPython
8
- hf-xet>=1.4.3
8
+ hf-xet==1.5.2
@@ -20,7 +20,7 @@ dependencies = [
20
20
  "jsonschema>=4.5.1", # 4.5.1+ is safe across libraries
21
21
  "pydantic>=2.0", # Major version 2 required if you're using v2 features
22
22
  "GitPython",
23
- "hf-xet>=1.4.3",
23
+ "hf-xet==1.5.2",
24
24
  ]
25
25
  classifiers = [
26
26
  "Programming Language :: Python :: 3",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes