qbraid-cli 0.8.0.dev6__py3-none-any.whl → 0.8.1__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.

Potentially problematic release.


This version of qbraid-cli might be problematic. Click here for more details.

qbraid_cli/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.8.0.dev6'
16
- __version_tuple__ = version_tuple = (0, 8, 0, 'dev6')
15
+ __version__ = version = '0.8.1'
16
+ __version_tuple__ = version_tuple = (0, 8, 1)
@@ -7,3 +7,5 @@ Module defining the qbraid admin namespace
7
7
  """
8
8
 
9
9
  from .app import admin_app
10
+
11
+ __all__ = ["admin_app"]
qbraid_cli/admin/app.py CHANGED
@@ -3,21 +3,20 @@
3
3
 
4
4
  """
5
5
  Module defining commands in the 'qbraid admin' namespace.
6
-
7
6
  """
8
7
 
9
8
  from typing import List
10
9
 
11
10
  import typer
12
11
 
12
+ from qbraid_cli.admin.buildlogs import buildlogs_app
13
13
  from qbraid_cli.admin.headers import check_and_fix_headers
14
14
  from qbraid_cli.admin.validation import validate_header_type, validate_paths_exist
15
15
 
16
- # disable pretty_exceptions_show_locals to avoid printing sensative information in the traceback
17
16
  admin_app = typer.Typer(
18
- help="CI/CD commands for qBraid maintainers.",
19
- pretty_exceptions_show_locals=False,
17
+ help="CI/CD commands for qBraid maintainers.", pretty_exceptions_show_locals=False
20
18
  )
19
+ admin_app.add_typer(buildlogs_app, name="buildlogs")
21
20
 
22
21
 
23
22
  @admin_app.command(name="headers")
@@ -0,0 +1,114 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
4
+ """
5
+ Module defining commands in the 'qbraid admin buildlogs' namespace.
6
+
7
+ This module uses the Typer library to create CLI commands for managing Docker builds and logs
8
+ in an administrative context.
9
+ """
10
+
11
+ import json
12
+
13
+ import typer
14
+ from qbraid_core.exceptions import RequestsApiError
15
+ from qbraid_core.services.admin.client import AdminClient
16
+ from rich.console import Console
17
+
18
+ from qbraid_cli.handlers import handle_error
19
+
20
+ buildlogs_app = typer.Typer(
21
+ help="Manage qBraid containerized services logs.", pretty_exceptions_show_locals=False
22
+ )
23
+ console = Console()
24
+
25
+
26
+ @buildlogs_app.command(name="get")
27
+ def get_docker_build_logs(
28
+ build_id: str = typer.Option(None, "--build_id", "-b", help="Name of the build ID")
29
+ ) -> None:
30
+ """
31
+ Fetches and displays Docker build logs for a specified build ID.
32
+
33
+ Args:
34
+ build_id (str, optional): The unique identifier for the Docker build.
35
+
36
+ This function queries the administrative backend to retrieve and display build logs.
37
+ If a build ID is provided, it will retrieve and display logs specific to that build ID.
38
+ If build ID not provided, fetches all logs.
39
+ """
40
+ client = AdminClient()
41
+
42
+ build_log = client.get_docker_build_logs(build_id)
43
+ if build_id and "buildLogs" in build_log and build_log["buildLogs"]:
44
+ log_entry = build_log["buildLogs"][0]
45
+ console.print(log_entry)
46
+ else:
47
+ console.print(build_log)
48
+
49
+
50
+ @buildlogs_app.command(name="post")
51
+ def post_docker_build_log(
52
+ data: str = typer.Option(..., "--data", "-d", help="Data to post to Docker logs")
53
+ ) -> None:
54
+ """
55
+ Posts a new Docker build log entry.
56
+
57
+ Args:
58
+ data (str): JSON string containing the data to be logged.
59
+
60
+ This command converts a JSON string into a dictionary and sends it to the backend service
61
+ to create a new Docker build log.
62
+ """
63
+ client = AdminClient()
64
+
65
+ try:
66
+ data_dict = json.loads(data)
67
+ console.print(client.post_docker_build_logs(data_dict))
68
+ except RequestsApiError:
69
+ handle_error(message="Couldn't post a build_log.")
70
+
71
+
72
+ @buildlogs_app.command(name="put")
73
+ def put_docker_build_log(
74
+ build_id: str = typer.Option(..., "--build_id", "-b", help="Name of the build ID"),
75
+ data: str = typer.Option(..., "--data", "-d", help="Data to post to Docker logs"),
76
+ ) -> None:
77
+ """
78
+ Updates an existing Docker build log entry by a given build ID.
79
+
80
+ Args:
81
+ build_id (str): The unique identifier of the Docker build to update.
82
+ data (str): JSON string containing the updated data for the log.
83
+
84
+ This command updates a Docker build log entry, identified by the provided build ID,
85
+ with the new data provided in JSON format.
86
+ """
87
+ client = AdminClient()
88
+
89
+ try:
90
+ data_dict = json.loads(data)
91
+ console.print(client.put_docker_build_logs(build_id, data_dict))
92
+ except RequestsApiError:
93
+ handle_error(message="Couldn't post a build_log.")
94
+
95
+
96
+ @buildlogs_app.command(name="delete")
97
+ def delete_docker_build_log(
98
+ build_id: str = typer.Option(..., "--build_id", "-b", help="ID of the build log to delete")
99
+ ) -> None:
100
+ """
101
+ Deletes a Docker build log entry by a specified build ID.
102
+
103
+ Args:
104
+ build_id (str): The unique identifier of the Docker build log to delete.
105
+
106
+ This command sends a request to delete a Docker build log identified by the provided build ID.
107
+ """
108
+ client = AdminClient()
109
+
110
+ console.print(client.delete_docker_build_logs(build_id))
111
+
112
+
113
+ if __name__ == "__main__":
114
+ buildlogs_app()
@@ -6,11 +6,13 @@ Script to verify qBraid copyright file headers
6
6
 
7
7
  """
8
8
  import os
9
- import sys
10
9
  from typing import List, Optional
11
10
 
11
+ import typer
12
12
  from rich.console import Console
13
13
 
14
+ from qbraid_cli.handlers import handle_error
15
+
14
16
  # pylint: disable=too-many-branches,too-many-statements
15
17
 
16
18
  DEFAULT_HEADER = """# Copyright (c) 2024, qBraid Development Team
@@ -43,19 +45,17 @@ def check_and_fix_headers(
43
45
  """Script to add or verify qBraid copyright file headers"""
44
46
  try:
45
47
  header = HEADER_TYPES[header_type]
46
- except KeyError as err:
47
- raise ValueError(
48
- f"Invalid header type: {HEADER_TYPES}. Expected one of {list(HEADER_TYPES.keys())}"
49
- ) from err
48
+ except KeyError:
49
+ handle_error(
50
+ error_type="ValueError",
51
+ message=(
52
+ f"Invalid header type: {HEADER_TYPES}. Expected one of {list(HEADER_TYPES.keys())}"
53
+ ),
54
+ )
50
55
 
51
56
  for path in src_paths:
52
57
  if not os.path.exists(path):
53
- sys.stderr.write(
54
- f"Usage: qbraid verify_headers [OPTIONS] SRC ...\n"
55
- f"Try 'qbraid verify_headers --help' for help.\n\n"
56
- f"Error: Invalid value for 'SRC ...': Path '{path}' does not exist.\n"
57
- )
58
- sys.exit(1)
58
+ handle_error(error_type="FileNotFoundError", message=f"Path '{path}' does not exist.")
59
59
 
60
60
  header_2023 = header.replace("2024", "2023")
61
61
 
@@ -139,8 +139,11 @@ def check_and_fix_headers(
139
139
  replace_or_add_header(item, fix)
140
140
  checked += 1
141
141
  else:
142
- failed_headers.append(item)
143
- print(f"File or directory not found: {item}")
142
+ handle_error(error_type="FileNotFoundError", message=f"Path '{item}' does not exist.")
143
+
144
+ if checked == 0:
145
+ console.print("[bold]No Python files present. Nothing to do[/bold] 😴")
146
+ raise typer.Exit(0)
144
147
 
145
148
  if not fix:
146
149
  if failed_headers:
@@ -160,34 +163,31 @@ def check_and_fix_headers(
160
163
 
161
164
  failed_msg = f"[bold][blue]{num_failed}[/blue] file{s1} need{s2} updating{punc}[/bold]"
162
165
  console.print(f"{failed_msg}{passed_msg}")
163
- elif checked == 0:
164
- console.print("[bold]No Python files present. Nothing to do[/bold] 😴")
165
- else:
166
- s_checked = "" if checked == 1 else "s"
167
- console.print("[bold]All done![/bold] 🚀 ")
168
- console.print(f"[blue]{checked}[/blue] file{s_checked} would be left unchanged.")
169
-
166
+ raise typer.Exit(1)
167
+
168
+ s_checked = "" if checked == 1 else "s"
169
+ console.print("[bold]All done![/bold] 🚀 ")
170
+ console.print(f"[blue]{checked}[/blue] file{s_checked} would be left unchanged.")
171
+ raise typer.Exit(0)
172
+
173
+ for file in fixed_headers:
174
+ console.print(f"[bold]fixed {file}[/bold]")
175
+ num_fixed = len(fixed_headers)
176
+ num_ok = checked - num_fixed
177
+ s_fixed = "" if num_fixed == 1 else "s"
178
+ s_ok = "" if num_ok == 1 else "s"
179
+ console.print("\n[bold]All done![/bold] ✨ 🚀 ✨")
180
+ if num_ok > 0:
181
+ punc = ", "
182
+ unchanged_msg = f"[blue]{num_ok}[/blue] file{s_ok} left unchanged."
170
183
  else:
171
- for file in fixed_headers:
172
- console.print(f"[bold]fixed {file}[/bold]")
173
- num_fixed = len(fixed_headers)
174
- num_ok = checked - num_fixed
175
- s_fixed = "" if num_fixed == 1 else "s"
176
- s_ok = "" if num_ok == 1 else "s"
177
- console.print("\n[bold]All done![/bold] ✨ 🚀 ✨")
178
- if num_ok > 0:
179
- punc = ", "
180
- unchanged_msg = f"[blue]{num_ok}[/blue] file{s_ok} left unchanged."
181
- else:
182
- punc = "."
183
- unchanged_msg = ""
184
+ punc = "."
185
+ unchanged_msg = ""
184
186
 
185
- if num_fixed > 0:
186
- fixed_msg = f"[bold][blue]{num_fixed}[/blue] file{s_fixed} fixed{punc}[/bold]"
187
- else:
188
- fixed_msg = ""
187
+ if num_fixed > 0:
188
+ fixed_msg = f"[bold][blue]{num_fixed}[/blue] file{s_fixed} fixed{punc}[/bold]"
189
+ else:
190
+ fixed_msg = ""
189
191
 
190
- if fixed_msg or unchanged_msg:
191
- console.print(f"{fixed_msg}{unchanged_msg}")
192
- else:
193
- console.print("[bold]No Python files present. Nothing to do[/bold] 😴")
192
+ console.print(f"{fixed_msg}{unchanged_msg}")
193
+ raise typer.Exit(0)
@@ -7,3 +7,5 @@ Module defining the qbraid configure namespace
7
7
  """
8
8
 
9
9
  from .app import configure_app
10
+
11
+ __all__ = ["configure_app"]
@@ -7,6 +7,7 @@ Module defining commands in the 'qbraid configure' namespace.
7
7
  """
8
8
 
9
9
  import typer
10
+ from rich.console import Console
10
11
 
11
12
  from qbraid_cli.configure.actions import default_action
12
13
 
@@ -54,15 +55,22 @@ def configure_set(
54
55
 
55
56
  @configure_app.command(name="magic")
56
57
  def configure_magic():
57
- """Configure qBraid IPython magic commands."""
58
+ """Enable qBraid IPython magic commands."""
58
59
  # pylint: disable-next=import-outside-toplevel
59
60
  from qbraid_core.services.environments import add_magic_config
60
61
 
61
62
  add_magic_config()
62
63
 
63
- typer.echo("Successfully configured qBraid IPython magic commands.")
64
- typer.echo("You can now use the qBraid-CLI from inside a Jupyter notebook as follows:")
65
- typer.echo("\n\n\t[ ] %load_ext qbraid_magic\n\n\t[ ] %qbraid")
64
+ console = Console()
65
+
66
+ in_1 = (
67
+ "[green]In [[/green][yellow]1[/yellow][green]]:[/green] [blue]%[/blue]load_ext qbraid_magic"
68
+ )
69
+ in_2 = "[green]In [[/green][yellow]2[/yellow][green]]:[/green] [blue]%[/blue]qbraid"
70
+
71
+ console.print("\nSuccessfully configured qBraid IPython magic commands.\n")
72
+ console.print("You can now use the qBraid-CLI from inside a Jupyter notebook as follows:")
73
+ console.print(f"\n\t{in_1}\n\n\t{in_2}\n")
66
74
 
67
75
 
68
76
  if __name__ == "__main__":
@@ -7,3 +7,5 @@ Module defining the qbraid credits namespace
7
7
  """
8
8
 
9
9
  from .app import credits_app
10
+
11
+ __all__ = ["credits_app"]
qbraid_cli/credits/app.py CHANGED
@@ -24,8 +24,11 @@ def credits_value():
24
24
  return client.user_credits_value()
25
25
 
26
26
  qbraid_credits: float = run_progress_task(get_credits)
27
- credits_text = typer.style(f"{qbraid_credits:.2f}", fg=typer.colors.GREEN, bold=True)
28
- typer.secho(f"\nqBraid credits: {credits_text}")
27
+ typer.secho(
28
+ f"\n{typer.style('qBraid credits remaining:')} "
29
+ f"{typer.style(f'{qbraid_credits:.4f}', fg=typer.colors.MAGENTA, bold=True)}",
30
+ nl=True, # Ensure a newline after output (default is True)
31
+ )
29
32
 
30
33
 
31
34
  if __name__ == "__main__":
@@ -7,3 +7,5 @@ Module defining the qbraid devices namespace
7
7
  """
8
8
 
9
9
  from .app import devices_app
10
+
11
+ __all__ = ["devices_app"]
@@ -7,3 +7,5 @@ Module defining the qbraid envs namespace
7
7
  """
8
8
 
9
9
  from .app import envs_app
10
+
11
+ __all__ = ["envs_app"]
qbraid_cli/envs/app.py CHANGED
@@ -10,14 +10,19 @@ import shutil
10
10
  import subprocess
11
11
  import sys
12
12
  from pathlib import Path
13
- from typing import Any, Dict, Optional, Tuple
13
+ from typing import TYPE_CHECKING, Optional, Tuple
14
14
 
15
15
  import typer
16
16
  from rich.console import Console
17
17
 
18
- from qbraid_cli.envs.data_handling import installed_envs_data, request_delete_env, validate_env_name
18
+ from qbraid_cli.envs.create import create_qbraid_env_assets, create_venv
19
+ from qbraid_cli.envs.data_handling import get_envs_data as installed_envs_data
20
+ from qbraid_cli.envs.data_handling import validate_env_name
19
21
  from qbraid_cli.handlers import QbraidException, run_progress_task
20
22
 
23
+ if TYPE_CHECKING:
24
+ from qbraid_core.services.environments.client import EnvironmentManagerClient as EMC
25
+
21
26
  envs_app = typer.Typer(help="Manage qBraid environments.")
22
27
 
23
28
 
@@ -34,25 +39,14 @@ def envs_create( # pylint: disable=too-many-statements
34
39
  ),
35
40
  ) -> None:
36
41
  """Create a new qBraid environment."""
37
- from .create import create_qbraid_env_assets, create_venv
38
-
39
- def request_new_env(req_body: Dict[str, str]) -> Dict[str, Any]:
40
- """Send request to create new environment and return the slug."""
41
- from qbraid_core import QbraidSession, RequestsApiError
42
-
43
- session = QbraidSession()
44
-
45
- try:
46
- env_data = session.post("/environments/create", json=req_body).json()
47
- except RequestsApiError as err:
48
- raise QbraidException("Create environment request failed") from err
42
+ env_description = description or ""
49
43
 
50
- if env_data is None or len(env_data) == 0 or env_data.get("slug") is None:
51
- raise QbraidException(
52
- "Create environment request responsed with invalid environment data"
53
- )
44
+ def create_environment(*args, **kwargs) -> "Tuple[dict, EMC]":
45
+ """Create a qBraid environment."""
46
+ from qbraid_core.services.environments.client import EnvironmentManagerClient
54
47
 
55
- return env_data
48
+ client = EnvironmentManagerClient()
49
+ return client.create_environment(*args, **kwargs), client
56
50
 
57
51
  def gather_local_data() -> Tuple[Path, str]:
58
52
  """Gather environment data and return the slug."""
@@ -71,20 +65,10 @@ def envs_create( # pylint: disable=too-many-statements
71
65
 
72
66
  return env_path, python_version
73
67
 
74
- req_body = {
75
- "name": name,
76
- "description": description or "",
77
- "tags": "", # comma separated list of tags
78
- "code": "", # newline separated list of packages
79
- "visibility": "private",
80
- "kernelName": "",
81
- "prompt": "",
82
- "origin": "CLI",
83
- }
84
-
85
- environment = run_progress_task(
86
- request_new_env,
87
- req_body,
68
+ environment, emc = run_progress_task(
69
+ create_environment,
70
+ name,
71
+ env_description,
88
72
  description="Validating request...",
89
73
  error_message="Failed to create qBraid environment",
90
74
  )
@@ -94,7 +78,6 @@ def envs_create( # pylint: disable=too-many-statements
94
78
  description="Solving environment...",
95
79
  error_message="Failed to create qBraid environment",
96
80
  )
97
-
98
81
  slug = environment.get("slug")
99
82
  display_name = environment.get("displayName")
100
83
  prompt = environment.get("prompt")
@@ -120,7 +103,7 @@ def envs_create( # pylint: disable=too-many-statements
120
103
  user_confirmation = auto_confirm or typer.confirm("Proceed", default=True)
121
104
  typer.echo("")
122
105
  if not user_confirmation:
123
- request_delete_env(slug)
106
+ emc.delete_environment(slug)
124
107
  typer.echo("qBraidSystemExit: Exiting.")
125
108
  raise typer.Exit()
126
109
 
@@ -165,6 +148,13 @@ def envs_remove(
165
148
  ) -> None:
166
149
  """Delete a qBraid environment."""
167
150
 
151
+ def delete_environment(slug: str) -> None:
152
+ """Delete a qBraid environment."""
153
+ from qbraid_core.services.environments.client import EnvironmentManagerClient
154
+
155
+ emc = EnvironmentManagerClient()
156
+ emc.delete_environment(slug)
157
+
168
158
  def gather_local_data(env_name: str) -> Tuple[Path, str]:
169
159
  """Get environment path and slug from name (alias)."""
170
160
  installed, aliases = installed_envs_data()
@@ -190,7 +180,7 @@ def envs_remove(
190
180
  if auto_confirm or typer.confirm(confirmation_message, abort=True):
191
181
  typer.echo("")
192
182
  run_progress_task(
193
- request_delete_env,
183
+ delete_environment,
194
184
  slug,
195
185
  description="Deleting remote environment data...",
196
186
  error_message="Failed to delete qBraid environment",
qbraid_cli/envs/create.py CHANGED
@@ -5,93 +5,29 @@
5
5
  Module supporting 'qbraid envs create' command.
6
6
 
7
7
  """
8
-
9
8
  import json
10
9
  import os
11
10
  import shutil
12
- import subprocess
13
11
  import sys
14
- from typing import Optional
15
-
16
-
17
- def replace_str(target: str, replacement: str, file_path: str) -> None:
18
- """Replace all instances of string in file"""
19
- with open(file_path, "r", encoding="utf-8") as file:
20
- content = file.read()
21
-
22
- content = content.replace(target, replacement)
23
-
24
- with open(file_path, "w", encoding="utf-8") as file:
25
- file.write(content)
26
-
27
-
28
- def update_state_json(
29
- slug_path: str,
30
- install_complete: int,
31
- install_success: int,
32
- message: Optional[str] = None,
33
- env_name: Optional[str] = None,
34
- ) -> None:
35
- """Update environment's install status values in a JSON file.
36
- Truth table values: 0 = False, 1 = True, -1 = Unknown
37
- """
38
- # Set default message if none provided
39
- message = "" if message is None else message.replace("\n", " ")
40
-
41
- # File path for state.json
42
- state_json_path = os.path.join(slug_path, "state.json")
43
12
 
44
- # Read existing data or use default structure
45
- if os.path.exists(state_json_path):
46
- with open(state_json_path, "r", encoding="utf-8") as f:
47
- data = json.load(f)
48
- else:
49
- data = {"install": {}}
50
-
51
- # Update the data
52
- data["install"]["complete"] = install_complete
53
- data["install"]["success"] = install_success
54
- data["install"]["message"] = message
55
-
56
- if env_name is not None:
57
- data["name"] = env_name
58
-
59
- # Write updated data back to state.json
60
- with open(state_json_path, "w", encoding="utf-8") as f:
61
- json.dump(data, f, indent=4)
62
13
 
14
+ def create_venv(*args, **kwargs) -> None:
15
+ """Create a python virtual environment for the qBraid environment."""
16
+ from qbraid_core.services.environments import create_local_venv
63
17
 
64
- def create_venv(slug_path: str, prompt: str) -> None:
65
- """Create virtual environment and swap PS1 display name."""
66
- venv_path = os.path.join(slug_path, "pyenv")
67
- subprocess.run([sys.executable, "-m", "venv", venv_path], check=True)
18
+ return create_local_venv(*args, **kwargs)
68
19
 
69
- # Determine the correct directory for activation scripts based on the operating system
70
- if sys.platform == "win32":
71
- scripts_path = os.path.join(venv_path, "Scripts")
72
- activate_files = ["activate.bat", "Activate.ps1"]
73
- else:
74
- scripts_path = os.path.join(venv_path, "bin")
75
- activate_files = ["activate", "activate.csh", "activate.fish"]
76
20
 
77
- for file in activate_files:
78
- file_path = os.path.join(scripts_path, file)
79
- if os.path.isfile(file_path):
80
- replace_str("(pyenv)", f"({prompt})", file_path)
21
+ def update_state_json(*ags, **kwargs) -> None:
22
+ """Update the state.json file for the qBraid environment."""
23
+ from qbraid_core.services.environments.state import update_install_status
81
24
 
82
- replace_str(
83
- "include-system-site-packages = false",
84
- "include-system-site-packages = true",
85
- os.path.join(venv_path, "pyvenv.cfg"),
86
- )
87
-
88
- update_state_json(slug_path, 1, 1)
25
+ return update_install_status(*ags, **kwargs)
89
26
 
90
27
 
91
28
  def create_qbraid_env_assets(slug: str, alias: str, kernel_name: str, slug_path: str) -> None:
92
29
  """Create a qBraid environment including python venv, PS1 configs,
93
30
  kernel resource files, and qBraid state.json."""
94
- # pylint: disable-next=import-outside-toplevel
95
31
  from jupyter_client.kernelspec import KernelSpecManager
96
32
 
97
33
  local_resource_dir = os.path.join(slug_path, "kernels", f"python3_{slug}")
@@ -123,6 +59,3 @@ def create_qbraid_env_assets(slug: str, alias: str, kernel_name: str, slug_path:
123
59
  loc_path = os.path.join(local_resource_dir, file)
124
60
  if os.path.isfile(sys_path):
125
61
  shutil.copy(sys_path, loc_path)
126
-
127
- # create python venv
128
- create_venv(slug_path, alias)
@@ -6,85 +6,23 @@ Module for handling data related to qBraid environments.
6
6
 
7
7
  """
8
8
 
9
- import json
10
- import keyword
11
- import re
12
- from pathlib import Path
13
- from typing import Dict, List, Tuple
14
-
15
9
  import typer
16
10
 
17
11
  from qbraid_cli.handlers import QbraidException
18
12
 
19
13
 
20
- def is_valid_env_name(env_name: str) -> bool: # pylint: disable=too-many-return-statements
21
- """
22
- Validates a Python virtual environment name against best practices.
23
-
24
- This function checks if the given environment name is valid based on certain
25
- criteria, including length, use of special characters, reserved names, and
26
- operating system-specific restrictions.
27
-
28
- Args:
29
- env_name (str): The name of the Python virtual environment to validate.
30
-
31
- Returns:
32
- bool: True if the name is valid, False otherwise.
33
-
34
- Raises:
35
- ValueError: If the environment name is not a string or is empty.
36
- """
37
- # Basic checks for empty names or purely whitespace names
38
- if not env_name or env_name.isspace():
39
- return False
40
-
41
- # Check for invalid characters, including shell metacharacters and spaces
42
- if re.search(r'[<>:"/\\|?*\s&;()$[\]#~!{}]', env_name):
43
- return False
44
-
45
- if env_name.startswith("tmp"):
46
- return False
47
-
48
- # Reserved names for Windows (example list, can be expanded)
49
- reserved_names = [
50
- "CON",
51
- "PRN",
52
- "AUX",
53
- "NUL",
54
- "COM1",
55
- "COM2",
56
- "COM3",
57
- "COM4",
58
- "COM5",
59
- "COM6",
60
- "COM7",
61
- "COM8",
62
- "COM9",
63
- "LPT1",
64
- "LPT2",
65
- "LPT3",
66
- "LPT4",
67
- "LPT5",
68
- "LPT6",
69
- "LPT7",
70
- "LPT8",
71
- "LPT9",
72
- ]
73
- if env_name.upper() in reserved_names:
74
- return False
75
-
76
- if len(env_name) > 20:
77
- return False
78
-
79
- # Check against Python reserved words
80
- if keyword.iskeyword(env_name):
81
- return False
82
-
83
- # Check if it starts with a number, which is not a good practice
84
- if env_name[0].isdigit():
85
- return False
86
-
87
- return True
14
+ def get_envs_data(*args, **kwargs) -> dict:
15
+ """Get data for installed environments."""
16
+ from qbraid_core.services.environments.paths import installed_envs_data
17
+
18
+ return installed_envs_data(*args, **kwargs)
19
+
20
+
21
+ def is_valid_env_name(value: str) -> bool:
22
+ """Check if a given string is a valid Python environment name."""
23
+ from qbraid_core.services.environments.validate import is_valid_env_name as is_valid
24
+
25
+ return is_valid(value)
88
26
 
89
27
 
90
28
  def validate_env_name(value: str) -> str:
@@ -96,38 +34,6 @@ def validate_env_name(value: str) -> str:
96
34
  return value
97
35
 
98
36
 
99
- def installed_envs_data() -> Tuple[Dict[str, Path], Dict[str, str]]:
100
- """Gather paths and aliases for all installed qBraid environments."""
101
- from qbraid_core.services.environments.paths import get_default_envs_paths, is_valid_slug
102
-
103
- installed = {}
104
- aliases = {}
105
-
106
- qbraid_env_paths: List[Path] = get_default_envs_paths()
107
-
108
- for env_path in qbraid_env_paths:
109
- for entry in env_path.iterdir():
110
- if entry.is_dir() and is_valid_slug(entry.name):
111
- installed[entry.name] = entry
112
-
113
- if entry.name == "qbraid_000000":
114
- aliases["default"] = entry.name
115
- continue
116
-
117
- state_json_path = entry / "state.json"
118
- if state_json_path.exists():
119
- try:
120
- with open(state_json_path, "r", encoding="utf-8") as f:
121
- data = json.load(f)
122
- aliases[data.get("name", entry.name[:-7])] = entry.name
123
- # pylint: disable-next=broad-exception-caught
124
- except (json.JSONDecodeError, Exception):
125
- aliases[entry.name[:-7]] = entry.name
126
- else:
127
- aliases[entry.name[:-7]] = entry.name
128
- return installed, aliases
129
-
130
-
131
37
  def request_delete_env(slug: str) -> str:
132
38
  """Send request to delete environment given slug."""
133
39
  from qbraid_core import QbraidSession, RequestsApiError
qbraid_cli/handlers.py CHANGED
@@ -7,6 +7,7 @@ and executing operations with progress tracking within the qBraid CLI.
7
7
 
8
8
  """
9
9
 
10
+ import os
10
11
  import traceback
11
12
  from pathlib import Path
12
13
  from typing import Any, Callable, List, Optional, Union
@@ -18,6 +19,11 @@ from rich.progress import Progress, SpinnerColumn, TextColumn
18
19
  from .exceptions import DEFAULT_ERROR_MESSAGE, QbraidException
19
20
 
20
21
 
22
+ def _should_display_progress():
23
+ """Whether to display rich progress UI."""
24
+ return os.getenv("QBRAID_CLI_SHOW_PROGRESS", "true").lower() in ["true", "1", "t", "y", "yes"]
25
+
26
+
21
27
  def handle_error(
22
28
  error_type: Optional[str] = None, message: Optional[str] = None, include_traceback: bool = True
23
29
  ) -> None:
@@ -104,6 +110,13 @@ def run_progress_task(
104
110
  Raises:
105
111
  typer.Exit: If the operation fails, after displaying the error message using typer.secho.
106
112
  """
113
+ if not _should_display_progress():
114
+ try:
115
+ return operation(*args, **kwargs)
116
+ except Exception as err: # pylint: disable=broad-exception-caught
117
+ custom_message = error_message if error_message else str(err)
118
+ return handle_error(message=custom_message)
119
+
107
120
  console = Console()
108
121
  with Progress(
109
122
  "[progress.description]{task.description}",
@@ -117,9 +130,9 @@ def run_progress_task(
117
130
  result = operation(*args, **kwargs)
118
131
  progress.update(task, completed=100, status="Done")
119
132
  return result
120
- except Exception as e: # pylint: disable=broad-exception-caught
133
+ except Exception as err: # pylint: disable=broad-exception-caught
121
134
  progress.update(task, completed=100, status="Failed")
122
- custom_message = error_message if error_message else str(e)
135
+ custom_message = error_message if error_message else str(err)
123
136
  return handle_error(message=custom_message)
124
137
 
125
138
 
@@ -7,3 +7,5 @@ Module defining the qbraid jobs namespace
7
7
  """
8
8
 
9
9
  from .app import jobs_app
10
+
11
+ __all__ = ["jobs_app"]
@@ -7,3 +7,5 @@ Module defining the qbraid kernels namespace
7
7
  """
8
8
 
9
9
  from .app import kernels_app
10
+
11
+ __all__ = ["kernels_app"]
qbraid_cli/kernels/app.py CHANGED
@@ -12,7 +12,6 @@ import typer
12
12
  from jupyter_client.kernelspec import KernelSpecManager
13
13
  from rich.console import Console
14
14
 
15
- from qbraid_cli.envs.data_handling import installed_envs_data
16
15
  from qbraid_cli.handlers import handle_error
17
16
 
18
17
  kernels_app = typer.Typer(help="Manage qBraid kernels.")
@@ -20,6 +19,9 @@ kernels_app = typer.Typer(help="Manage qBraid kernels.")
20
19
 
21
20
  def _get_kernels_path(environment: str) -> Path:
22
21
  """Get the path to the kernels directory for the given environment."""
22
+ # pylint: disable-next=import-outside-toplevel
23
+ from qbraid_core.services.environments.paths import installed_envs_data
24
+
23
25
  slug_to_path, name_to_slug = installed_envs_data()
24
26
 
25
27
  if environment in name_to_slug:
qbraid_cli/main.py CHANGED
@@ -15,6 +15,7 @@ from qbraid_cli.devices.app import devices_app
15
15
  from qbraid_cli.envs.app import envs_app
16
16
  from qbraid_cli.jobs.app import jobs_app
17
17
  from qbraid_cli.kernels.app import kernels_app
18
+ from qbraid_cli.pip.app import pip_app
18
19
 
19
20
  app = typer.Typer(context_settings={"help_option_names": ["-h", "--help"]})
20
21
 
@@ -25,15 +26,17 @@ app.add_typer(devices_app, name="devices")
25
26
  app.add_typer(envs_app, name="envs")
26
27
  app.add_typer(jobs_app, name="jobs")
27
28
  app.add_typer(kernels_app, name="kernels")
29
+ app.add_typer(pip_app, name="pip")
28
30
 
29
31
 
30
32
  def version_callback(value: bool):
31
33
  """Show the version and exit."""
32
34
  if value:
33
- from ._version import __version__
35
+ # pylint: disable-next=import-error
36
+ from ._version import __version__ # type: ignore
34
37
 
35
38
  typer.echo(f"qbraid-cli/{__version__}")
36
- raise typer.Exit()
39
+ raise typer.Exit(0)
37
40
 
38
41
 
39
42
  def show_banner():
@@ -0,0 +1,11 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
4
+ """
5
+ Module defining the qbraid pip namespace
6
+
7
+ """
8
+
9
+ from .app import pip_app
10
+
11
+ __all__ = ["pip_app"]
qbraid_cli/pip/app.py ADDED
@@ -0,0 +1,49 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
4
+ """
5
+ Module defining commands in the 'qbraid pip' namespace.
6
+
7
+ """
8
+ import subprocess
9
+ import sys
10
+
11
+ import typer
12
+ from qbraid_core.system import QbraidSystemError, get_active_python_path
13
+
14
+ from qbraid_cli.handlers import handle_error
15
+ from qbraid_cli.pip.hooks import get_env_cfg_path, safe_set_include_sys_packages
16
+
17
+ # disable pretty_exceptions_show_locals to avoid printing sensative information in the traceback
18
+ pip_app = typer.Typer(help="Run pip command in active qBraid environment.")
19
+
20
+
21
+ @pip_app.command(
22
+ "install", context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
23
+ )
24
+ def pip_install(ctx: typer.Context):
25
+ """
26
+ Perform pip install action with open-ended arguments and options.
27
+
28
+ """
29
+ try:
30
+ python_exe = get_active_python_path()
31
+ cfg_path = get_env_cfg_path(python_exe)
32
+ except QbraidSystemError:
33
+ python_exe = sys.executable
34
+ cfg_path = None
35
+
36
+ safe_set_include_sys_packages(False, cfg_path)
37
+
38
+ command = [str(python_exe), "-m", "pip", "install"] + ctx.args
39
+
40
+ try:
41
+ subprocess.check_call(command)
42
+ except (subprocess.CalledProcessError, FileNotFoundError):
43
+ handle_error(message="Failed carry-out pip command.")
44
+ finally:
45
+ safe_set_include_sys_packages(True, cfg_path)
46
+
47
+
48
+ if __name__ == "__main__":
49
+ pip_app()
@@ -0,0 +1,73 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
4
+ """
5
+ Module defining pre- and post-command hooks for the 'qbraid pip' namespace.
6
+
7
+ """
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Optional, Union
11
+
12
+ from qbraid_core.services.environments import get_default_envs_paths
13
+ from qbraid_core.system.executables import python_paths_equivalent
14
+ from qbraid_core.system.packages import (
15
+ extract_include_sys_site_pkgs_value,
16
+ set_include_sys_site_pkgs_value,
17
+ )
18
+
19
+
20
+ def safe_set_include_sys_packages(value: bool, file_path: Optional[Union[str, Path]]) -> None:
21
+ """Set include-system-site-packages value safely"""
22
+ if not file_path:
23
+ return None
24
+
25
+ try:
26
+ set_include_sys_site_pkgs_value(value, file_path)
27
+ except Exception: # pylint: disable=broad-exception-caught
28
+ pass
29
+
30
+ return None
31
+
32
+
33
+ def find_matching_prefix(python_executable: Path, path_list: list[Path]) -> Optional[Path]:
34
+ """
35
+ Finds and returns the first path in the list that is a prefix of the Python executable path.
36
+
37
+ Args:
38
+ python_executable (Path): The path to the Python executable.
39
+ path_list (List[Path]): A list of paths to check against the Python executable path.
40
+
41
+ Returns:
42
+ Optional[Path]: The first matching path that is a prefix of the Python executable path,
43
+ or None if no match is found.
44
+ """
45
+ python_executable_str = str(python_executable.resolve())
46
+ for path in path_list:
47
+ if python_executable_str.startswith(str(path.resolve())):
48
+ return path
49
+ return None
50
+
51
+
52
+ def get_env_cfg_path(python_exe: Path) -> Optional[Path]:
53
+ """Get the path to the pyvenv.cfg file."""
54
+ is_sys_python = python_paths_equivalent(python_exe, sys.executable)
55
+
56
+ if is_sys_python:
57
+ return None
58
+
59
+ all_envs_paths = get_default_envs_paths()
60
+
61
+ env_path = find_matching_prefix(python_exe, all_envs_paths)
62
+
63
+ if not env_path:
64
+ return None
65
+
66
+ cfg_path = env_path / "pyvenv.cfg"
67
+
68
+ should_flip = extract_include_sys_site_pkgs_value(cfg_path)
69
+
70
+ if should_flip:
71
+ return cfg_path
72
+
73
+ return None
qbraid_cli/py.typed ADDED
File without changes
@@ -0,0 +1,41 @@
1
+ qBraid Closed-Source Software License
2
+
3
+ Copyright (c) 2024, qBraid Development Team
4
+
5
+ All rights reserved.
6
+
7
+ This license agreement ("License") is between the qBraid Development Team ("Author") and you, the Licensee. By using or distributing the qBraid ("Software"), you agree to the following terms:
8
+
9
+ 1. Grant of License.
10
+
11
+ Subject to the terms of this License, the Author grants you a non-exclusive, non-transferable license to use the Software for personal, academic, and educational purposes. Use of the Software for commercial purposes is strictly prohibited unless express permission is granted by the Author.
12
+
13
+ 2. Distribution.
14
+
15
+ You may distribute the Software to others, provided that any such distribution is made under the same terms of this License. Modifications to the Software may not be distributed.
16
+
17
+ 3. Modification.
18
+
19
+ You are permitted to modify the Software for personal use. You may contribute improvements or bug fixes back to the Author or the community, but you may not distribute the modifications.
20
+
21
+ 4. Commercial Use.
22
+
23
+ The Software may not be used for commercial purposes without explicit, prior written permission from the Author. Permissions for commercial use will be considered on a case-by-case basis.
24
+
25
+ 5. Attribution
26
+
27
+ If the Software is used in a non-private setting, including but not limited to academic work, commercial settings, or published literature, attribution must be given to the "qBraid Jupyter Environment Manager authored by the qBraid Development Team."
28
+
29
+ 6. Disclaimer of Warranty.
30
+
31
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
32
+
33
+ 7. Limitation of Liability.
34
+
35
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36
+
37
+ 8. Termination.
38
+
39
+ This License is effective until terminated. Your rights under this License will terminate automatically without notice from the Author if you fail to comply with any term(s) of this License.
40
+
41
+ By using the Software, you agree to be bound by the terms of this License. Redistribution of the Software or use of the Software other than as specifically authorized under this License is prohibited and may result in severe civil and criminal penalties.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qbraid-cli
3
- Version: 0.8.0.dev6
3
+ Version: 0.8.1
4
4
  Summary: Command Line Interface for interacting with all parts of the qBraid platform.
5
5
  Author-email: qBraid Development Team <contact@qbraid.com>
6
6
  License: Proprietary
@@ -26,24 +26,17 @@ Classifier: Programming Language :: Python :: 3.11
26
26
  Classifier: Programming Language :: Python :: 3.12
27
27
  Requires-Python: >=3.9
28
28
  Description-Content-Type: text/markdown
29
+ License-File: LICENSE
29
30
  Requires-Dist: typer >=0.12.1
30
31
  Requires-Dist: rich >=10.11.0
31
32
  Requires-Dist: jupyter-client <9.0.0,>=7.0.0
32
33
  Requires-Dist: ipykernel
33
- Requires-Dist: qbraid-core >=0.1.4
34
+ Requires-Dist: qbraid-core >=0.1.10
34
35
  Provides-Extra: dev
35
- Requires-Dist: black ; extra == 'dev'
36
+ Requires-Dist: ruff ; extra == 'dev'
36
37
  Requires-Dist: isort ; extra == 'dev'
37
- Requires-Dist: pylint ; extra == 'dev'
38
+ Requires-Dist: black ; extra == 'dev'
38
39
  Requires-Dist: pytest ; extra == 'dev'
39
- Provides-Extra: docs
40
- Requires-Dist: sphinx ~=7.2.6 ; extra == 'docs'
41
- Requires-Dist: sphinx-rtd-theme <2.1,>=1.3 ; extra == 'docs'
42
- Requires-Dist: docutils <0.22 ; extra == 'docs'
43
- Requires-Dist: toml ; extra == 'docs'
44
- Requires-Dist: build ; extra == 'docs'
45
- Requires-Dist: m2r ; extra == 'docs'
46
- Requires-Dist: typer ; extra == 'docs'
47
40
  Provides-Extra: jobs
48
41
  Requires-Dist: amazon-braket-sdk >=1.48.1 ; extra == 'jobs'
49
42
 
@@ -54,24 +47,43 @@ Requires-Dist: amazon-braket-sdk >=1.48.1 ; extra == 'jobs'
54
47
  [![Python verions](https://img.shields.io/pypi/pyversions/qbraid-cli.svg?color=blue)](https://pypi.org/project/qbraid-cli/)
55
48
  [![Downloads](https://static.pepy.tech/badge/qbraid-cli)](https://pepy.tech/project/qbraid-cli)
56
49
  [![GitHub](https://img.shields.io/badge/issue_tracking-github-blue?logo=github)](https://github.com/qBraid/qBraid-Lab/issues)
57
- [![Discord](https://img.shields.io/discord/771898982564626445.svg?color=pink)](https://discord.gg/KugF6Cnncm)
58
50
 
59
51
  Command Line Interface for interacting with all parts of the qBraid platform.
60
52
 
61
- The **qBraid CLI** is a specialized command-line interface tool designed *exclusively* for use within the [qBraid Lab](https://docs.qbraid.com/projects/lab/en/latest/lab/overview.html) platform. It is not intended for local installations or use outside the qBraid Lab environment. This tool ensures seamless integration and optimized performance specifically tailored for qBraid Lab's unique cloud-based quantum computing ecosystem.
53
+ The **qBraid CLI** is a versatile command-line interface tool designed for seamless interaction with qBraid cloud services and quantum software management tools. Initially exclusive to the [qBraid Lab](https://docs.qbraid.com/projects/lab/en/latest/lab/overview.html) platform, the CLI now supports local installations as well. This enhancement broadens access to features like [qBraid Quantum Jobs](https://docs.qbraid.com/projects/lab/en/latest/lab/quantum_jobs.html), enabling direct acess to QPU devices from leading providers like IonQ, Oxford Quantum Circuits, QuEra, and Rigetti, as well as on-demand simulators from AWS, all using qBraid credits, with no additional access keys required.
62
54
 
63
55
  ## Getting Started
64
56
 
65
- To use the qBraid CLI, login to qBraid (or create an account), launch Lab, and then open Terminal. You can also access the CLI directly from within [Notebooks](https://docs.qbraid.com/projects/lab/en/latest/lab/notebooks.html) using the ``!`` operator. See [quantum jobs example](https://github.com/qBraid/qbraid-lab-demo/blob/045c7a8fbdcae66a7e64533dd9fe0e981dc02cf4/qbraid_lab/quantum_jobs/aws_quantum_jobs.ipynb).
57
+ The qBraid-CLI comes pre-installed and pre-configured in qBraid Lab:
66
58
 
67
59
  - [Launch qBraid Lab &rarr;](https://lab.qbraid.com/)
68
60
  - [Make an account &rarr;](https://account.qbraid.com/)
69
61
 
70
62
  For help, see qBraid Lab User Guide: [Getting Started](https://docs.qbraid.com/projects/lab/en/latest/lab/getting_started.html).
71
63
 
64
+ You can also install the qBraid-CLI from PyPI with:
65
+
66
+ ```bash
67
+ pip install qbraid-cli
68
+ ```
69
+
70
+ ## Local configuration
71
+
72
+ After installation, you must configure your account credentials to use the CLI locally:
73
+
74
+ 1. Create a qBraid account or log in to your existing account by visiting
75
+ [account.qbraid.com](https://account.qbraid.com/)
76
+ 2. Copy your API Key token from the left side of
77
+ your [account page](https://account.qbraid.com/):
78
+ 3. Save your API key from step 2 in local configuration file `~/.qbraid/qbraidrc` using:
79
+
80
+ ```bash
81
+ $ qbraid configure
82
+ ```
83
+
72
84
  ## Basic Commands
73
85
 
74
- ```shell
86
+ ```bash
75
87
  $ qbraid
76
88
  ----------------------------------
77
89
  * Welcome to the qBraid CLI! *
@@ -94,19 +106,19 @@ Reference Docs: https://docs.qbraid.com/projects/cli/en/stable/guide/overview.ht
94
106
 
95
107
  A qBraid CLI command has the following structure:
96
108
 
97
- ```shell
109
+ ```bash
98
110
  $ qbraid <command> <subcommand> [options and parameters]
99
111
  ```
100
112
 
101
113
  For example, to list installed environments, the command would be:
102
114
 
103
- ```shell
115
+ ```bash
104
116
  $ qbraid envs list
105
117
  ```
106
118
 
107
119
  To view help documentation, use one of the following:
108
120
 
109
- ```shell
121
+ ```bash
110
122
  $ qbraid --help
111
123
  $ qbraid <command> --help
112
124
  $ qbraid <command> <subcommand> --help
@@ -114,7 +126,7 @@ $ qbraid <command> <subcommand> --help
114
126
 
115
127
  For example:
116
128
 
117
- ```shell
129
+ ```bash
118
130
  $ qbraid --help
119
131
 
120
132
  Usage: qbraid [OPTIONS] COMMAND [ARGS]...
@@ -138,6 +150,28 @@ Commands
138
150
 
139
151
  To get the version of the qBraid CLI:
140
152
 
141
- ```shell
153
+ ```bash
142
154
  $ qbraid --version
143
155
  ```
156
+
157
+ ## Magic Commands
158
+
159
+ You can also access the CLI directly from within [Notebooks](https://docs.qbraid.com/projects/lab/en/latest/lab/notebooks.html) using IPython [magic commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). First, configure the qBraid magic commands extension using:
160
+
161
+ ```bash
162
+ $ qbraid configure magic
163
+ ```
164
+
165
+ The above command can also be executed from within a Jupyter notebook using the ``!`` operator. Then, from within a notebook cell, load the qBraid magic IPython extension using:
166
+
167
+ ```python
168
+ In [1]: %load_ext qbraid_magic
169
+ ```
170
+
171
+ Now you can continue to use the qBraid-CLI as normal from within your Jupyter notebook using the magic ``%`` operator, e.g.
172
+
173
+ ```python
174
+ In [2]: %qbraid jobs state
175
+
176
+ In [3]: %qbraid jobs enable braket -y
177
+ ```
@@ -0,0 +1,39 @@
1
+ qbraid_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ qbraid_cli/_version.py,sha256=Z8fNqmfsoA07nbVEewR90wZCgaN6eyDwPwgtgc2KIak,411
3
+ qbraid_cli/exceptions.py,sha256=KjlhYJhSHMVazaNiBjD_Ur06w4sekP8zRsFzBdyIpno,672
4
+ qbraid_cli/handlers.py,sha256=glxTEwxax3zKgYl9qsZ2evZXgrWQrseJS_OGyHTMFeA,7040
5
+ qbraid_cli/main.py,sha256=eRgBEYj9WPxHqTbSQvlV39yaDje-6yvZdrTnw5UQbQY,2638
6
+ qbraid_cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ qbraid_cli/admin/__init__.py,sha256=qcWD5mQEUCtr49mrUpZmk7eGDe0L_Gtc8RwZmzIXSwo,175
8
+ qbraid_cli/admin/app.py,sha256=ZyTBkEvlAR-xK3fbC32yntsE3rywzL4WHjJzRTFTlzs,1454
9
+ qbraid_cli/admin/buildlogs.py,sha256=1i7CRpkIHIcKgGvHesPr9duCkyV7M-MESaHI5Z3ZdD0,3578
10
+ qbraid_cli/admin/headers.py,sha256=E6mE3odZL57VfHHZxYtRUkqMKmrmT4zuUoINzI7eJF8,6435
11
+ qbraid_cli/admin/validation.py,sha256=LkAVXlHtM0MhCa34MIWrfX59wGXMVlZmdVB4-AQ8fBk,1003
12
+ qbraid_cli/configure/__init__.py,sha256=YaJ74Ztz2vl3eYp8_jVBucWkXscxz7EZEIzr70OfuOM,187
13
+ qbraid_cli/configure/actions.py,sha256=3rrWHaCAsogyx0Ll-lcjbSzldD4kPuz1z6VQiWebSWw,3203
14
+ qbraid_cli/configure/app.py,sha256=1uRe2lkUA4TtYb5b4mbD4LH-cKCbsZGT3Wfk7fpNzX0,2414
15
+ qbraid_cli/credits/__init__.py,sha256=MJhgWgpFT1_886sB-_POlRs1y3SRy23HIrKVBkp0X-Y,181
16
+ qbraid_cli/credits/app.py,sha256=AY3qtveO50KeQ2XREiEVqUcTrESgRuoqt9pt2Z8t4Y0,866
17
+ qbraid_cli/devices/__init__.py,sha256=hiScO-px6jCL5cJj5Hbty55EUfNejTO4bmqUZuS3aqc,181
18
+ qbraid_cli/devices/app.py,sha256=zxSxrEQn7irkJoME4S_CBnRqWeB8cqPaBsIMfpdYFk0,2530
19
+ qbraid_cli/devices/validation.py,sha256=YhShyUufgrKnx2XjXOXF-PqFJYklJT9CgeqIwKcNam4,809
20
+ qbraid_cli/envs/__init__.py,sha256=1-cMvrATsddYxcetPJWxq6bEOqJWMktGdhoZ4qm8euA,172
21
+ qbraid_cli/envs/activate.py,sha256=VpvVYSfQDlcmlNWJOgkLIQ2p8YXPPLG8Jbl5t8GHUDw,2140
22
+ qbraid_cli/envs/app.py,sha256=PD7U-zdQeoWPXPRpmKC3nwDVOfa69dk5GCIsE3mpla8,8411
23
+ qbraid_cli/envs/create.py,sha256=HxNciItDoGC5jqiruHm0oUfNSqtuDfzE-ro4ztGUh5Q,2185
24
+ qbraid_cli/envs/data_handling.py,sha256=Ibnp2yJoUDpivb_sNqi0suYgJZNat_LmM6Ya0Ovez5s,1288
25
+ qbraid_cli/jobs/__init__.py,sha256=qVLRHYIzP4XHpx_QWP_vCzd3LsCscCORaEx-Vcbx29U,172
26
+ qbraid_cli/jobs/app.py,sha256=kmg9mYla3Nd7EdjQlFu7IOvm7sejLNfPPA6Qeet-IfE,4898
27
+ qbraid_cli/jobs/toggle_braket.py,sha256=d5C_Di80jWMFlh-77eH8YY9pjMKWXK5abenUDtPlE_I,6662
28
+ qbraid_cli/jobs/validation.py,sha256=xNbjUggMhUs4wzkuRm4PuFPi_wrElYicUgYXLznHz3U,2983
29
+ qbraid_cli/kernels/__init__.py,sha256=jORS9vV17s5laQyq8gSVB18EPBImgEIbMZ1wKC094DA,181
30
+ qbraid_cli/kernels/app.py,sha256=eELxcuYV_d0wNR5t3IYznEcjqGmRM1j7GeHqVgcvDqs,3439
31
+ qbraid_cli/pip/__init__.py,sha256=tJtU0rxn-ODogNh5Y4pp_BgDQXMN-3JY1QGj0OZHwjQ,169
32
+ qbraid_cli/pip/app.py,sha256=yd55KzE1dApxPV5fyBa8PfdxaeDovUZyrPm_UZy_Ie0,1386
33
+ qbraid_cli/pip/hooks.py,sha256=KuDHmntPXVK8tSb4MLk9VANhL-eINswhLd8_g_25WMY,2123
34
+ qbraid_cli-0.8.1.dist-info/LICENSE,sha256=P1gi-ofB8lmkRt_mxDoJpcgQq9Ckq9WhRAS1oYk-G1s,2506
35
+ qbraid_cli-0.8.1.dist-info/METADATA,sha256=Hab46g_Tequpsr6ehVMyS8QoAS051pJTr6lvz57RKXc,6732
36
+ qbraid_cli-0.8.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
37
+ qbraid_cli-0.8.1.dist-info/entry_points.txt,sha256=c5ZJ7NjbxhDqMpou9q5F03_b_KG34HzFDijIDmEIwgQ,47
38
+ qbraid_cli-0.8.1.dist-info/top_level.txt,sha256=LTYJgeYSCHo9Il8vZu0yIPuGdGyNaIw6iRy6BeoZo8o,11
39
+ qbraid_cli-0.8.1.dist-info/RECORD,,
@@ -1,33 +0,0 @@
1
- qbraid_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- qbraid_cli/_version.py,sha256=9V-2xXPHq42ZtrAPqEiMfWvgn4E8aKBKuNNPjD1ffOk,424
3
- qbraid_cli/exceptions.py,sha256=KjlhYJhSHMVazaNiBjD_Ur06w4sekP8zRsFzBdyIpno,672
4
- qbraid_cli/handlers.py,sha256=i3vdRtdy4bZKg3j6fwfVMz1ddhMgzlc2hhmj-vewxpI,6542
5
- qbraid_cli/main.py,sha256=IRKazFqtFpoiq_xOtqb-IXDKAVs4lacFIRCQCoiGNF4,2503
6
- qbraid_cli/admin/__init__.py,sha256=Suo_L1_yBodCvLM_fpw8gRIhD4mVVOXKObtxeoMaBVo,150
7
- qbraid_cli/admin/app.py,sha256=__6lo-iFsbfz-ayD1-AS8X1z_gYhCad1NK17hnrL7HY,1451
8
- qbraid_cli/admin/headers.py,sha256=oE2Ry9221ZV4tgYqFJNHAPilDw72xR3LqG_gBw7BFxM,6667
9
- qbraid_cli/admin/validation.py,sha256=LkAVXlHtM0MhCa34MIWrfX59wGXMVlZmdVB4-AQ8fBk,1003
10
- qbraid_cli/configure/__init__.py,sha256=6GU7vR6JYRGcMsmdrpFbwLO5VSUmnLgwSbtmGWMQND4,158
11
- qbraid_cli/configure/actions.py,sha256=3rrWHaCAsogyx0Ll-lcjbSzldD4kPuz1z6VQiWebSWw,3203
12
- qbraid_cli/configure/app.py,sha256=Y-XQYQ5lwQJkHW1vUNK44RpVmmA86mZR0xf_Q-yT7yE,2160
13
- qbraid_cli/credits/__init__.py,sha256=t-3XAJFAXiu_jI4sgjaIOuNne_AoSYaSEsi-SSRkvPw,154
14
- qbraid_cli/credits/app.py,sha256=iHikmjx8pylMFNzHckuauOg-Nb9pS7xQq_H75ibVJig,774
15
- qbraid_cli/devices/__init__.py,sha256=_PU3eMQRV4DkPw-oCmfCPh8EbVmgG76ieEKuNsY9Xqc,154
16
- qbraid_cli/devices/app.py,sha256=zxSxrEQn7irkJoME4S_CBnRqWeB8cqPaBsIMfpdYFk0,2530
17
- qbraid_cli/devices/validation.py,sha256=YhShyUufgrKnx2XjXOXF-PqFJYklJT9CgeqIwKcNam4,809
18
- qbraid_cli/envs/__init__.py,sha256=YgIoMWxfGqzmwfypO5JHYuCOu6BfFwb9NHgQel1IJM8,148
19
- qbraid_cli/envs/activate.py,sha256=VpvVYSfQDlcmlNWJOgkLIQ2p8YXPPLG8Jbl5t8GHUDw,2140
20
- qbraid_cli/envs/app.py,sha256=t6bRwJGy-M3PAu870ZsttsM8tpSB0OFasgCJiV9nTSA,8620
21
- qbraid_cli/envs/create.py,sha256=uCRex_TcFYw26jUOU06Ta5I8Mq5pRqLVaOE6MxrrExs,4337
22
- qbraid_cli/envs/data_handling.py,sha256=mTVzsj6KleeeYDKGhgD-IesF9KQQMSszKFSEo8Wrv9w,4001
23
- qbraid_cli/jobs/__init__.py,sha256=bj9XmZ4JL8OtMMZbHIu-DPhpOMXGLSB-W1b0wO7wKro,148
24
- qbraid_cli/jobs/app.py,sha256=kmg9mYla3Nd7EdjQlFu7IOvm7sejLNfPPA6Qeet-IfE,4898
25
- qbraid_cli/jobs/toggle_braket.py,sha256=d5C_Di80jWMFlh-77eH8YY9pjMKWXK5abenUDtPlE_I,6662
26
- qbraid_cli/jobs/validation.py,sha256=xNbjUggMhUs4wzkuRm4PuFPi_wrElYicUgYXLznHz3U,2983
27
- qbraid_cli/kernels/__init__.py,sha256=VhpBota_v7OoiGxrPCqJU4XBVcolf81mbCYGSxXzVhc,154
28
- qbraid_cli/kernels/app.py,sha256=ZJWVdKzCDfzGnA1pqp01vDbE7fh8p84jC-y6DDgWlxc,3373
29
- qbraid_cli-0.8.0.dev6.dist-info/METADATA,sha256=2B553-9K_zSo24YJE_PL1t31R9ZQRcvv9TV0CcT-yzA,5919
30
- qbraid_cli-0.8.0.dev6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
31
- qbraid_cli-0.8.0.dev6.dist-info/entry_points.txt,sha256=c5ZJ7NjbxhDqMpou9q5F03_b_KG34HzFDijIDmEIwgQ,47
32
- qbraid_cli-0.8.0.dev6.dist-info/top_level.txt,sha256=LTYJgeYSCHo9Il8vZu0yIPuGdGyNaIw6iRy6BeoZo8o,11
33
- qbraid_cli-0.8.0.dev6.dist-info/RECORD,,