qbraid-cli 0.8.0.dev0__py3-none-any.whl → 0.9.5__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 +2 -2
- qbraid_cli/account/__init__.py +11 -0
- qbraid_cli/account/app.py +65 -0
- qbraid_cli/admin/__init__.py +11 -0
- qbraid_cli/admin/app.py +59 -0
- qbraid_cli/admin/headers.py +235 -0
- qbraid_cli/admin/validation.py +32 -0
- qbraid_cli/chat/__init__.py +11 -0
- qbraid_cli/chat/app.py +76 -0
- qbraid_cli/configure/__init__.py +6 -1
- qbraid_cli/configure/actions.py +111 -0
- qbraid_cli/configure/app.py +34 -109
- qbraid_cli/devices/__init__.py +6 -1
- qbraid_cli/devices/app.py +43 -35
- qbraid_cli/devices/validation.py +26 -0
- qbraid_cli/envs/__init__.py +6 -1
- qbraid_cli/envs/activate.py +8 -5
- qbraid_cli/envs/app.py +215 -131
- qbraid_cli/envs/create.py +14 -120
- qbraid_cli/envs/data_handling.py +46 -0
- qbraid_cli/exceptions.py +3 -0
- qbraid_cli/files/__init__.py +11 -0
- qbraid_cli/files/app.py +118 -0
- qbraid_cli/handlers.py +47 -13
- qbraid_cli/jobs/__init__.py +6 -1
- qbraid_cli/jobs/app.py +84 -97
- qbraid_cli/jobs/toggle_braket.py +68 -74
- qbraid_cli/jobs/validation.py +94 -0
- qbraid_cli/kernels/__init__.py +6 -1
- qbraid_cli/kernels/app.py +81 -11
- qbraid_cli/main.py +66 -14
- qbraid_cli/pip/__init__.py +11 -0
- qbraid_cli/pip/app.py +50 -0
- qbraid_cli/pip/hooks.py +74 -0
- qbraid_cli/py.typed +0 -0
- qbraid_cli-0.9.5.dist-info/LICENSE +41 -0
- qbraid_cli-0.9.5.dist-info/METADATA +179 -0
- qbraid_cli-0.9.5.dist-info/RECORD +42 -0
- {qbraid_cli-0.8.0.dev0.dist-info → qbraid_cli-0.9.5.dist-info}/WHEEL +1 -1
- qbraid_cli/credits/__init__.py +0 -6
- qbraid_cli/credits/app.py +0 -30
- qbraid_cli-0.8.0.dev0.dist-info/METADATA +0 -124
- qbraid_cli-0.8.0.dev0.dist-info/RECORD +0 -25
- {qbraid_cli-0.8.0.dev0.dist-info → qbraid_cli-0.9.5.dist-info}/entry_points.txt +0 -0
- {qbraid_cli-0.8.0.dev0.dist-info → qbraid_cli-0.9.5.dist-info}/top_level.txt +0 -0
qbraid_cli/configure/app.py
CHANGED
|
@@ -1,121 +1,23 @@
|
|
|
1
|
+
# Copyright (c) 2024, qBraid Development Team
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
1
4
|
"""
|
|
2
5
|
Module defining commands in the 'qbraid configure' namespace.
|
|
3
6
|
|
|
4
7
|
"""
|
|
5
8
|
|
|
6
|
-
import configparser
|
|
7
|
-
import re
|
|
8
|
-
from copy import deepcopy
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
from typing import Dict, Optional
|
|
11
|
-
|
|
12
9
|
import typer
|
|
10
|
+
from rich.console import Console
|
|
13
11
|
|
|
14
|
-
from qbraid_cli.
|
|
15
|
-
from qbraid_cli.handlers import handle_filesystem_operation
|
|
12
|
+
from qbraid_cli.configure.actions import default_action
|
|
16
13
|
|
|
17
14
|
# disable pretty_exceptions_show_locals to avoid printing sensative information in the traceback
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def load_config() -> configparser.ConfigParser:
|
|
22
|
-
"""Load the configuration from the file."""
|
|
23
|
-
config_path = Path.home() / ".qbraid" / "qbraidrc"
|
|
24
|
-
config = configparser.ConfigParser()
|
|
25
|
-
try:
|
|
26
|
-
config.read(config_path)
|
|
27
|
-
if not config.sections():
|
|
28
|
-
raise QbraidException(f"No sections found in configuration file {config_path}")
|
|
29
|
-
return config
|
|
30
|
-
except (FileNotFoundError, PermissionError, configparser.Error) as err:
|
|
31
|
-
raise QbraidException(f"Failed to load configuration from {config_path}.") from err
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def save_config(config: configparser.ConfigParser) -> None:
|
|
35
|
-
"""Save configuration to qbraidrc file."""
|
|
36
|
-
config_path = Path.home() / ".qbraid"
|
|
37
|
-
|
|
38
|
-
def save_operation():
|
|
39
|
-
config_path.mkdir(parents=True, exist_ok=True)
|
|
40
|
-
with (config_path / "qbraidrc").open("w") as configfile:
|
|
41
|
-
config.write(configfile)
|
|
15
|
+
configure_app = typer.Typer(
|
|
16
|
+
help="Configure qBraid CLI options.", pretty_exceptions_show_locals=False
|
|
17
|
+
)
|
|
42
18
|
|
|
43
|
-
handle_filesystem_operation(save_operation, config_path)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def validate_input(key: str, value: str) -> str:
|
|
47
|
-
"""Validate the user input based on the key.
|
|
48
|
-
|
|
49
|
-
Args:
|
|
50
|
-
key (str): The configuration key
|
|
51
|
-
value (str): The user input value
|
|
52
|
-
|
|
53
|
-
Returns:
|
|
54
|
-
str: The validated value
|
|
55
|
-
|
|
56
|
-
Raises:
|
|
57
|
-
typer.BadParameter: If the value is invalid
|
|
58
|
-
"""
|
|
59
|
-
if key == "url":
|
|
60
|
-
if not re.match(r"^https?://\S+$", value):
|
|
61
|
-
raise typer.BadParameter("Invalid URL format.")
|
|
62
|
-
elif key == "email":
|
|
63
|
-
if not re.match(r"^\S+@\S+\.\S+$", value):
|
|
64
|
-
raise typer.BadParameter("Invalid email format.")
|
|
65
|
-
elif key == "api-key":
|
|
66
|
-
if not re.match(r"^[a-zA-Z0-9]{11}$", value):
|
|
67
|
-
raise typer.BadParameter("Invalid API key format.")
|
|
68
|
-
return value
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def prompt_for_config(
|
|
72
|
-
config: configparser.ConfigParser,
|
|
73
|
-
section: str,
|
|
74
|
-
key: str,
|
|
75
|
-
default_values: Optional[Dict[str, str]] = None,
|
|
76
|
-
) -> str:
|
|
77
|
-
"""Prompt the user for a configuration setting, showing the current value as default."""
|
|
78
|
-
default_values = default_values or {}
|
|
79
|
-
current_value = config.get(section, key, fallback=default_values.get(key, ""))
|
|
80
|
-
display_value = "None" if not current_value else current_value
|
|
81
|
-
|
|
82
|
-
if key == "api-key" and current_value:
|
|
83
|
-
display_value = "*" * len(current_value[:-4]) + current_value[-4:]
|
|
84
|
-
|
|
85
|
-
new_value = typer.prompt(f"Enter {key}", default=display_value, show_default=True).strip()
|
|
86
|
-
|
|
87
|
-
if new_value == display_value:
|
|
88
|
-
return current_value
|
|
89
|
-
|
|
90
|
-
return validate_input(key, new_value)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def default_action(section: str = "default"):
|
|
94
|
-
"""Configure qBraid CLI options."""
|
|
95
|
-
config = load_config()
|
|
96
|
-
original_config = deepcopy(config)
|
|
97
19
|
|
|
98
|
-
|
|
99
|
-
config[section] = {}
|
|
100
|
-
|
|
101
|
-
default_values = {"url": "https://api.qbraid.com/api"}
|
|
102
|
-
|
|
103
|
-
config[section]["url"] = prompt_for_config(config, section, "url", default_values)
|
|
104
|
-
config[section]["email"] = prompt_for_config(config, section, "email", default_values)
|
|
105
|
-
config[section]["api-key"] = prompt_for_config(config, section, "api-key", default_values)
|
|
106
|
-
|
|
107
|
-
for key in list(config[section]):
|
|
108
|
-
if not config[section][key]:
|
|
109
|
-
del config[section][key]
|
|
110
|
-
|
|
111
|
-
if config == original_config:
|
|
112
|
-
typer.echo("\nConfiguration saved, unchanged.")
|
|
113
|
-
else:
|
|
114
|
-
save_config(config)
|
|
115
|
-
typer.echo("\nConfiguration updated successfully.")
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
@app.callback(invoke_without_command=True)
|
|
20
|
+
@configure_app.callback(invoke_without_command=True)
|
|
119
21
|
def configure(ctx: typer.Context):
|
|
120
22
|
"""
|
|
121
23
|
Prompts user for configuration values such as your qBraid API Key.
|
|
@@ -130,13 +32,16 @@ def configure(ctx: typer.Context):
|
|
|
130
32
|
default_action()
|
|
131
33
|
|
|
132
34
|
|
|
133
|
-
@
|
|
35
|
+
@configure_app.command(name="set")
|
|
134
36
|
def configure_set(
|
|
135
37
|
name: str = typer.Argument(..., help="Config name"),
|
|
136
38
|
value: str = typer.Argument(..., help="Config value"),
|
|
137
39
|
profile: str = typer.Option("default", help="Profile name"),
|
|
138
40
|
):
|
|
139
41
|
"""Set configuration value in qbraidrc file."""
|
|
42
|
+
# pylint: disable-next=import-outside-toplevel
|
|
43
|
+
from qbraid_core.config import load_config, save_config
|
|
44
|
+
|
|
140
45
|
config = load_config()
|
|
141
46
|
|
|
142
47
|
if profile not in config:
|
|
@@ -148,5 +53,25 @@ def configure_set(
|
|
|
148
53
|
typer.echo("Configuration updated successfully.")
|
|
149
54
|
|
|
150
55
|
|
|
56
|
+
@configure_app.command(name="magic")
|
|
57
|
+
def configure_magic():
|
|
58
|
+
"""Enable qBraid IPython magic commands."""
|
|
59
|
+
# pylint: disable-next=import-outside-toplevel
|
|
60
|
+
from qbraid_core.services.environments import add_magic_config
|
|
61
|
+
|
|
62
|
+
add_magic_config()
|
|
63
|
+
|
|
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")
|
|
74
|
+
|
|
75
|
+
|
|
151
76
|
if __name__ == "__main__":
|
|
152
|
-
|
|
77
|
+
configure_app()
|
qbraid_cli/devices/__init__.py
CHANGED
qbraid_cli/devices/app.py
CHANGED
|
@@ -1,34 +1,24 @@
|
|
|
1
|
+
# Copyright (c) 2024, qBraid Development Team
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
1
4
|
"""
|
|
2
5
|
Module defining commands in the 'qbraid devices' namespace.
|
|
3
6
|
|
|
4
7
|
"""
|
|
5
8
|
|
|
6
|
-
from typing import Callable, Optional
|
|
9
|
+
from typing import Any, Callable, Optional
|
|
7
10
|
|
|
8
11
|
import typer
|
|
12
|
+
from rich.console import Console
|
|
9
13
|
|
|
10
|
-
from qbraid_cli.
|
|
11
|
-
|
|
12
|
-
app = typer.Typer(help="Manage qBraid quantum devices.")
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def validate_status(value: Optional[str]) -> Union[str, None]:
|
|
16
|
-
"""Validate device status query parameter."""
|
|
17
|
-
return validate_item(value, ["ONLINE", "OFFLINE", "RETIRED"], "Status")
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def validate_type(value: Optional[str]) -> Union[str, None]:
|
|
21
|
-
"""Validate device type query parameter."""
|
|
22
|
-
return validate_item(value, ["QPU", "SIMULATOR"], "Type")
|
|
14
|
+
from qbraid_cli.devices.validation import validate_provider, validate_status, validate_type
|
|
15
|
+
from qbraid_cli.handlers import run_progress_task
|
|
23
16
|
|
|
17
|
+
devices_app = typer.Typer(help="Manage qBraid quantum devices.", no_args_is_help=True)
|
|
24
18
|
|
|
25
|
-
def validate_provider(value: Optional[str]) -> Union[str, None]:
|
|
26
|
-
"""Validate device provider query parameter."""
|
|
27
|
-
return validate_item(value, ["AWS", "IBM", "IonQ", "Rigetti", "OQC", "QuEra"], "Provider")
|
|
28
19
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def devices_list(
|
|
20
|
+
@devices_app.command(name="list")
|
|
21
|
+
def devices_list( # pylint: disable=too-many-branches
|
|
32
22
|
status: Optional[str] = typer.Option(
|
|
33
23
|
None, "--status", "-s", help="'ONLINE'|'OFFLINE'|'RETIRED'", callback=validate_status
|
|
34
24
|
),
|
|
@@ -44,16 +34,6 @@ def devices_list(
|
|
|
44
34
|
),
|
|
45
35
|
) -> None:
|
|
46
36
|
"""List qBraid quantum devices."""
|
|
47
|
-
|
|
48
|
-
def import_devices() -> Tuple[Callable, Exception]:
|
|
49
|
-
from qbraid import get_devices
|
|
50
|
-
from qbraid.exceptions import QbraidError
|
|
51
|
-
|
|
52
|
-
return get_devices, QbraidError
|
|
53
|
-
|
|
54
|
-
result: Tuple[Callable, Exception] = run_progress_task(import_devices)
|
|
55
|
-
get_devices, QbraidError = result
|
|
56
|
-
|
|
57
37
|
filters = {}
|
|
58
38
|
if status:
|
|
59
39
|
filters["status"] = status
|
|
@@ -62,11 +42,39 @@ def devices_list(
|
|
|
62
42
|
if provider:
|
|
63
43
|
filters["provider"] = provider
|
|
64
44
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
45
|
+
def import_devices() -> tuple[Any, Callable]:
|
|
46
|
+
from qbraid_core.services.quantum import QuantumClient, process_device_data
|
|
47
|
+
|
|
48
|
+
client = QuantumClient()
|
|
49
|
+
|
|
50
|
+
return client, process_device_data
|
|
51
|
+
|
|
52
|
+
result: tuple[Callable, Callable] = run_progress_task(import_devices)
|
|
53
|
+
client, process_device_data = result
|
|
54
|
+
raw_data = client.search_devices(filters)
|
|
55
|
+
device_data, msg = process_device_data(raw_data)
|
|
56
|
+
|
|
57
|
+
console = Console()
|
|
58
|
+
header_1 = "Provider"
|
|
59
|
+
header_2 = "Device Name"
|
|
60
|
+
header_3 = "ID"
|
|
61
|
+
header_4 = "Status"
|
|
62
|
+
console.print(
|
|
63
|
+
f"[bold]{header_1.ljust(12)}{header_2.ljust(35)}{header_3.ljust(41)}{header_4}[/bold]"
|
|
64
|
+
)
|
|
65
|
+
for device_provider, device_name, device_id, device_status in device_data:
|
|
66
|
+
if device_status == "ONLINE":
|
|
67
|
+
status_color = "green"
|
|
68
|
+
elif device_status == "OFFLINE":
|
|
69
|
+
status_color = "red"
|
|
70
|
+
else:
|
|
71
|
+
status_color = "grey"
|
|
72
|
+
console.print(
|
|
73
|
+
f"{device_provider.ljust(12)}{device_name.ljust(35)}{device_id.ljust(40)}",
|
|
74
|
+
f"[{status_color}]{device_status}[/{status_color}]",
|
|
75
|
+
)
|
|
76
|
+
console.print(f"\n{msg}", style="italic", justify="left")
|
|
69
77
|
|
|
70
78
|
|
|
71
79
|
if __name__ == "__main__":
|
|
72
|
-
|
|
80
|
+
devices_app()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Copyright (c) 2024, qBraid Development Team
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Module for validating command arguments for qBraid devices commands.
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Optional, Union
|
|
10
|
+
|
|
11
|
+
from qbraid_cli.handlers import validate_item
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def validate_status(value: Optional[str]) -> Union[str, None]:
|
|
15
|
+
"""Validate device status query parameter."""
|
|
16
|
+
return validate_item(value, ["ONLINE", "OFFLINE", "RETIRED"], "Status")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def validate_type(value: Optional[str]) -> Union[str, None]:
|
|
20
|
+
"""Validate device type query parameter."""
|
|
21
|
+
return validate_item(value, ["QPU", "SIMULATOR"], "Type")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def validate_provider(value: Optional[str]) -> Union[str, None]:
|
|
25
|
+
"""Validate device provider query parameter."""
|
|
26
|
+
return validate_item(value, ["AWS", "IBM", "IonQ", "Rigetti", "OQC", "QuEra"], "Provider")
|
qbraid_cli/envs/__init__.py
CHANGED
qbraid_cli/envs/activate.py
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# Copyright (c) 2024, qBraid Development Team
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
1
4
|
"""
|
|
2
5
|
Module supporting 'qbraid envs activate' command.
|
|
3
6
|
|
|
@@ -31,13 +34,13 @@ def print_activate_command(venv_path: Path) -> None:
|
|
|
31
34
|
# Windows operating system
|
|
32
35
|
activate_script = venv_path / "Scripts" / "activate"
|
|
33
36
|
activate_script_ps = venv_path / "Scripts" / "Activate.ps1"
|
|
34
|
-
typer.echo("
|
|
37
|
+
typer.echo("\t$ " + str(activate_script))
|
|
35
38
|
typer.echo("\nOr for PowerShell, use:\n")
|
|
36
|
-
typer.echo("
|
|
39
|
+
typer.echo("\t$ " + f"& {activate_script_ps}")
|
|
37
40
|
else:
|
|
38
41
|
# Unix-like operating systems (Linux/macOS)
|
|
39
42
|
activate_script = venv_path / "bin" / "activate"
|
|
40
|
-
typer.echo("
|
|
43
|
+
typer.echo("\t$ " + f"source {activate_script}")
|
|
41
44
|
typer.echo("")
|
|
42
45
|
raise typer.Exit()
|
|
43
46
|
|
|
@@ -48,12 +51,12 @@ def activate_pyvenv(venv_path: Path):
|
|
|
48
51
|
|
|
49
52
|
if shell_path is None:
|
|
50
53
|
print_activate_command(venv_path)
|
|
51
|
-
|
|
54
|
+
return # Return early since we can't proceed without a shell
|
|
52
55
|
try:
|
|
53
56
|
shell_rc = find_shell_rc(shell_path)
|
|
54
57
|
except (FileNotFoundError, ValueError):
|
|
55
58
|
print_activate_command(venv_path)
|
|
56
|
-
|
|
59
|
+
return # Return early since no suitable shell rc file was found
|
|
57
60
|
bin_path = str(venv_path / "bin")
|
|
58
61
|
|
|
59
62
|
os.system(
|