qbraid-cli 0.7.1__py3-none-any.whl → 0.8.0__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 +14 -6
- qbraid_cli/admin/__init__.py +9 -0
- qbraid_cli/admin/app.py +50 -0
- qbraid_cli/admin/headers.py +193 -0
- qbraid_cli/admin/validation.py +33 -0
- qbraid_cli/configure/__init__.py +9 -0
- qbraid_cli/configure/actions.py +111 -0
- qbraid_cli/configure/app.py +77 -0
- qbraid_cli/credits/__init__.py +9 -0
- qbraid_cli/credits/app.py +32 -0
- qbraid_cli/devices/__init__.py +9 -0
- qbraid_cli/devices/app.py +80 -0
- qbraid_cli/devices/validation.py +26 -0
- qbraid_cli/envs/__init__.py +9 -0
- qbraid_cli/envs/activate.py +65 -0
- qbraid_cli/envs/app.py +270 -0
- qbraid_cli/envs/create.py +128 -0
- qbraid_cli/envs/data_handling.py +140 -0
- qbraid_cli/exceptions.py +17 -5
- qbraid_cli/handlers.py +168 -0
- qbraid_cli/jobs/__init__.py +9 -0
- qbraid_cli/jobs/app.py +149 -0
- qbraid_cli/jobs/toggle_braket.py +185 -0
- qbraid_cli/jobs/validation.py +93 -0
- qbraid_cli/kernels/__init__.py +9 -0
- qbraid_cli/kernels/app.py +111 -0
- qbraid_cli/main.py +80 -0
- {qbraid_cli-0.7.1.dist-info → qbraid_cli-0.8.0.dist-info}/METADATA +68 -46
- qbraid_cli-0.8.0.dist-info/RECORD +33 -0
- {qbraid_cli-0.7.1.dist-info → qbraid_cli-0.8.0.dist-info}/WHEEL +1 -1
- qbraid_cli-0.8.0.dist-info/entry_points.txt +2 -0
- qbraid_cli/_display.py +0 -44
- qbraid_cli/bin/qbraid.sh +0 -1346
- qbraid_cli/configure.py +0 -113
- qbraid_cli/envs.py +0 -195
- qbraid_cli/jobs.py +0 -226
- qbraid_cli/wrapper.py +0 -103
- qbraid_cli-0.7.1.data/scripts/qbraid.sh +0 -1346
- qbraid_cli-0.7.1.dist-info/RECORD +0 -15
- qbraid_cli-0.7.1.dist-info/entry_points.txt +0 -2
- {qbraid_cli-0.7.1.dist-info → qbraid_cli-0.8.0.dist-info}/top_level.txt +0 -0
qbraid_cli/configure.py
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Update qbraidrc configuration file
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import configparser
|
|
7
|
-
import re
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
from typing import Optional
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def load_config():
|
|
13
|
-
"""Load the configuration from the file."""
|
|
14
|
-
config_path = Path.home() / ".qbraid" / "qbraidrc"
|
|
15
|
-
config = configparser.ConfigParser()
|
|
16
|
-
config.read(config_path)
|
|
17
|
-
return config
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def save_config(config):
|
|
21
|
-
"""Save the configuration to the file."""
|
|
22
|
-
config_path = Path.home() / ".qbraid"
|
|
23
|
-
|
|
24
|
-
# Create the .qbraid directory if it doesn't exist
|
|
25
|
-
config_path.mkdir(parents=True, exist_ok=True)
|
|
26
|
-
|
|
27
|
-
# Write the configuration to the qbraidrc file
|
|
28
|
-
with (config_path / "qbraidrc").open("w") as configfile:
|
|
29
|
-
config.write(configfile)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def validate_input(key, value):
|
|
33
|
-
"""Validate the user input based on the key."""
|
|
34
|
-
if key == "url":
|
|
35
|
-
if not re.match(r"^https?://\S+$", value):
|
|
36
|
-
raise ValueError("Invalid URL format.")
|
|
37
|
-
elif key == "email":
|
|
38
|
-
if not re.match(r"^\S+@\S+\.\S+$", value):
|
|
39
|
-
raise ValueError("Invalid email format.")
|
|
40
|
-
elif key == "api-key":
|
|
41
|
-
if not re.match(r"^[a-zA-Z0-9]{11}$", value):
|
|
42
|
-
raise ValueError("Invalid API key format.")
|
|
43
|
-
return value
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def prompt_for_config(config, section, key, default_values=None):
|
|
47
|
-
"""Prompt the user for a configuration setting, showing the current value as default."""
|
|
48
|
-
default_values = default_values or {}
|
|
49
|
-
current_value = config.get(section, key, fallback=default_values.get(key, ""))
|
|
50
|
-
display_value = "None" if not current_value else current_value
|
|
51
|
-
|
|
52
|
-
while True:
|
|
53
|
-
try:
|
|
54
|
-
new_value = input(f"Enter {key} [{display_value}]: ").strip()
|
|
55
|
-
new_value = new_value or current_value
|
|
56
|
-
return validate_input(key, new_value)
|
|
57
|
-
except ValueError as e:
|
|
58
|
-
print(f"Error: {e}")
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def configure():
|
|
62
|
-
"""Prompt the user to configure each setting."""
|
|
63
|
-
try:
|
|
64
|
-
config = load_config()
|
|
65
|
-
except Exception as e: # pylint: disable=broad-exception-caught
|
|
66
|
-
print(f"Error loading configuration: {e}")
|
|
67
|
-
return
|
|
68
|
-
|
|
69
|
-
section = "default"
|
|
70
|
-
|
|
71
|
-
if section not in config:
|
|
72
|
-
config[section] = {}
|
|
73
|
-
|
|
74
|
-
default_values = {"url": "https://api.qbraid.com/api"}
|
|
75
|
-
|
|
76
|
-
try:
|
|
77
|
-
config[section]["url"] = prompt_for_config(
|
|
78
|
-
config, section, "url", default_values
|
|
79
|
-
)
|
|
80
|
-
config[section]["email"] = prompt_for_config(
|
|
81
|
-
config, section, "email", default_values
|
|
82
|
-
)
|
|
83
|
-
config[section]["api-key"] = prompt_for_config(
|
|
84
|
-
config, section, "api-key", default_values
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
for key in list(config[section]):
|
|
88
|
-
if not config[section][key]:
|
|
89
|
-
del config[section][key]
|
|
90
|
-
|
|
91
|
-
save_config(config)
|
|
92
|
-
print("Configuration updated successfully.")
|
|
93
|
-
except Exception as e: # pylint: disable=broad-exception-caught
|
|
94
|
-
print(f"Error updating configuration: {e}")
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def configure_set(key: str, value: str, profile: Optional[str] = None):
|
|
98
|
-
"""Set a configuration setting."""
|
|
99
|
-
try:
|
|
100
|
-
config = load_config()
|
|
101
|
-
except Exception as e: # pylint: disable=broad-exception-caught
|
|
102
|
-
print(f"Error loading configuration: {e}")
|
|
103
|
-
return
|
|
104
|
-
|
|
105
|
-
section = profile or "default"
|
|
106
|
-
|
|
107
|
-
if section not in config:
|
|
108
|
-
config[section] = {}
|
|
109
|
-
|
|
110
|
-
config[section][key] = value
|
|
111
|
-
|
|
112
|
-
save_config(config)
|
|
113
|
-
print("Configuration updated successfully.")
|
qbraid_cli/envs.py
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Module for interfacing with qBraid environments.
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import json
|
|
7
|
-
import os
|
|
8
|
-
import shutil
|
|
9
|
-
import subprocess
|
|
10
|
-
import sys
|
|
11
|
-
import threading
|
|
12
|
-
from typing import List, Optional
|
|
13
|
-
|
|
14
|
-
from jupyter_client.kernelspec import KernelSpecManager
|
|
15
|
-
from qbraid.api import QbraidSession
|
|
16
|
-
|
|
17
|
-
from ._display import print_progress_cycle
|
|
18
|
-
|
|
19
|
-
DEFAULT_VISIBILITY = "private"
|
|
20
|
-
|
|
21
|
-
DEFAULT_ENVS_PATH = os.path.join(os.path.expanduser("~"), ".qbraid", "environments")
|
|
22
|
-
QBRAID_ENVS_PATH = os.getenv("QBRAID_USR_ENVS", DEFAULT_ENVS_PATH)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def create_alias(slug: str) -> str:
|
|
26
|
-
"""Create an alias from a slug."""
|
|
27
|
-
return slug[:-7].replace("_", "-").strip("-")
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def replace_str(target: str, replacement: str, file_path: str) -> None:
|
|
31
|
-
"""Replace all instances of string in file"""
|
|
32
|
-
with open(file_path, "r", encoding="utf-8") as file:
|
|
33
|
-
content = file.read()
|
|
34
|
-
|
|
35
|
-
content = content.replace(target, replacement)
|
|
36
|
-
|
|
37
|
-
with open(file_path, "w", encoding="utf-8") as file:
|
|
38
|
-
file.write(content)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def update_install_status(
|
|
42
|
-
slug_path: str, complete: int, success: int, message: Optional[str] = None
|
|
43
|
-
) -> None:
|
|
44
|
-
"""Update environment's install status values in a JSON file.
|
|
45
|
-
Truth table values: 0 = False, 1 = True, -1 = Unknown
|
|
46
|
-
"""
|
|
47
|
-
# Set default message if none provided
|
|
48
|
-
message = "" if message is None else message.replace("\n", " ")
|
|
49
|
-
|
|
50
|
-
# File path for state.json
|
|
51
|
-
state_json_path = os.path.join(slug_path, "state.json")
|
|
52
|
-
|
|
53
|
-
# Read existing data or use default structure
|
|
54
|
-
if os.path.exists(state_json_path):
|
|
55
|
-
with open(state_json_path, "r", encoding="utf-8") as f:
|
|
56
|
-
data = json.load(f)
|
|
57
|
-
else:
|
|
58
|
-
data = {"install": {}}
|
|
59
|
-
|
|
60
|
-
# Update the data
|
|
61
|
-
data["install"]["complete"] = complete
|
|
62
|
-
data["install"]["success"] = success
|
|
63
|
-
data["install"]["message"] = message
|
|
64
|
-
|
|
65
|
-
# Write updated data back to state.json
|
|
66
|
-
with open(state_json_path, "w", encoding="utf-8") as f:
|
|
67
|
-
json.dump(data, f, indent=4)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def create_venv(slug_path: str, prompt: str) -> None:
|
|
71
|
-
"""Create virtual environment and swap PS1 display name."""
|
|
72
|
-
venv_path = os.path.join(slug_path, "pyenv")
|
|
73
|
-
subprocess.run([sys.executable, "-m", "venv", venv_path], check=True)
|
|
74
|
-
|
|
75
|
-
bin_path = os.path.join(venv_path, "bin")
|
|
76
|
-
activate_files = ["activate", "activate.csh", "activate.fish"]
|
|
77
|
-
|
|
78
|
-
for file in activate_files:
|
|
79
|
-
file_path = os.path.join(bin_path, file)
|
|
80
|
-
replace_str("(pyenv)", f"({prompt})", file_path)
|
|
81
|
-
|
|
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_install_status(slug_path, 1, 1)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def create_qbraid_env(slug: str, prompt: str, display_name: str) -> None:
|
|
92
|
-
"""Create a qBraid environment including python venv, PS1 configs,
|
|
93
|
-
kernel resource files, and qBraid state.json."""
|
|
94
|
-
slug_path = os.path.join(QBRAID_ENVS_PATH, slug)
|
|
95
|
-
local_resource_dir = os.path.join(slug_path, "kernels", f"python3_{slug}")
|
|
96
|
-
os.makedirs(local_resource_dir, exist_ok=True)
|
|
97
|
-
|
|
98
|
-
# create state.json
|
|
99
|
-
update_install_status(slug_path, 0, 0)
|
|
100
|
-
|
|
101
|
-
# create kernel.json
|
|
102
|
-
kernel_json_path = os.path.join(local_resource_dir, "kernel.json")
|
|
103
|
-
kernel_spec_manager = KernelSpecManager()
|
|
104
|
-
kernelspec_dict = kernel_spec_manager.get_all_specs()
|
|
105
|
-
kernel_data = kernelspec_dict["python3"]["spec"]
|
|
106
|
-
kernel_data["argv"][0] = os.path.join(slug_path, "pyenv", "bin", "python")
|
|
107
|
-
kernel_data["display_name"] = display_name
|
|
108
|
-
with open(kernel_json_path, "w", encoding="utf-8") as file:
|
|
109
|
-
json.dump(kernel_data, file, indent=4)
|
|
110
|
-
|
|
111
|
-
# copy logo files
|
|
112
|
-
sys_resource_dir = kernelspec_dict["python3"]["resource_dir"]
|
|
113
|
-
logo_files = ["logo-32x32.png", "logo-64x64.png", "logo-svg.svg"]
|
|
114
|
-
|
|
115
|
-
for file in logo_files:
|
|
116
|
-
sys_path = os.path.join(sys_resource_dir, file)
|
|
117
|
-
loc_path = os.path.join(local_resource_dir, file)
|
|
118
|
-
if os.path.isfile(sys_path):
|
|
119
|
-
shutil.copy(sys_path, loc_path)
|
|
120
|
-
|
|
121
|
-
# create python venv
|
|
122
|
-
create_venv(slug_path, prompt)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
# pylint: disable-next=too-many-arguments,too-many-locals
|
|
126
|
-
def create(
|
|
127
|
-
name: str,
|
|
128
|
-
description: Optional[str] = None,
|
|
129
|
-
tags: Optional[List[str]] = None,
|
|
130
|
-
code: Optional[str] = None,
|
|
131
|
-
visibility: Optional[str] = None,
|
|
132
|
-
kernel_name: Optional[str] = None,
|
|
133
|
-
prompt: Optional[str] = None,
|
|
134
|
-
) -> None:
|
|
135
|
-
"""
|
|
136
|
-
Create a new qBraid environment.
|
|
137
|
-
|
|
138
|
-
Args:
|
|
139
|
-
name (str): Name of the environment.
|
|
140
|
-
description (Optional[str]): Description of the environment.
|
|
141
|
-
tags (Optional[List[str]]): List of tags associated with the environment.
|
|
142
|
-
code (Optional[str]): package list in requirements.txt format.
|
|
143
|
-
visibility (Optional[str]): Visibility status (e.g., 'private').
|
|
144
|
-
kernel_name (Optional[str]): Name of the kernel.
|
|
145
|
-
prompt (Optional[str]): Prompt for the environment.
|
|
146
|
-
|
|
147
|
-
Returns:
|
|
148
|
-
None
|
|
149
|
-
"""
|
|
150
|
-
req_body = {
|
|
151
|
-
"name": name,
|
|
152
|
-
"description": description or "",
|
|
153
|
-
"tags": tags or "", # comma separated list of tags
|
|
154
|
-
"code": code or "", # newline separated list of packages
|
|
155
|
-
"visibility": visibility or DEFAULT_VISIBILITY,
|
|
156
|
-
"kernelName": kernel_name or "",
|
|
157
|
-
"prompt": prompt or "",
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
session = QbraidSession()
|
|
161
|
-
|
|
162
|
-
try:
|
|
163
|
-
resp = session.post("/environments/create", json=req_body).json()
|
|
164
|
-
except Exception as e: # pylint: disable=broad-exception-caught
|
|
165
|
-
print(f"Failed to create environment: {e}")
|
|
166
|
-
return
|
|
167
|
-
|
|
168
|
-
slug = resp.get("slug")
|
|
169
|
-
if slug is None:
|
|
170
|
-
print("Failed to create environment: no slug returned")
|
|
171
|
-
return
|
|
172
|
-
|
|
173
|
-
alias = create_alias(slug)
|
|
174
|
-
kernel_name = kernel_name if kernel_name else f"Python 3 [{alias}]"
|
|
175
|
-
prompt = prompt if prompt else alias
|
|
176
|
-
|
|
177
|
-
stop_event = threading.Event()
|
|
178
|
-
message = "Creating qBraid environment"
|
|
179
|
-
interval = 0.5
|
|
180
|
-
|
|
181
|
-
# Start the progress bar in a separate thread
|
|
182
|
-
progress_thread = threading.Thread(
|
|
183
|
-
target=print_progress_cycle,
|
|
184
|
-
args=(
|
|
185
|
-
stop_event,
|
|
186
|
-
message,
|
|
187
|
-
interval,
|
|
188
|
-
),
|
|
189
|
-
)
|
|
190
|
-
progress_thread.start()
|
|
191
|
-
create_qbraid_env(slug, prompt, kernel_name)
|
|
192
|
-
stop_event.set()
|
|
193
|
-
progress_thread.join()
|
|
194
|
-
|
|
195
|
-
print(f"\nSuccessfully created qBraid environment: {slug}\n")
|
qbraid_cli/jobs.py
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Module containing functions to enable/disable quantum jobs.
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import os
|
|
7
|
-
import site
|
|
8
|
-
import subprocess
|
|
9
|
-
import sys
|
|
10
|
-
import threading
|
|
11
|
-
from importlib.metadata import PackageNotFoundError, version
|
|
12
|
-
|
|
13
|
-
import requests
|
|
14
|
-
|
|
15
|
-
from ._display import print_progress_linear
|
|
16
|
-
from .exceptions import QuantumJobsException
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def get_latest_boto3_version() -> str:
|
|
20
|
-
"""Retrieves the latest version of botocore from PyPI."""
|
|
21
|
-
url = "https://pypi.org/pypi/boto3/json"
|
|
22
|
-
try:
|
|
23
|
-
response = requests.get(url, timeout=5)
|
|
24
|
-
response.raise_for_status()
|
|
25
|
-
data = response.json()
|
|
26
|
-
return data["info"]["version"]
|
|
27
|
-
except requests.RequestException as err:
|
|
28
|
-
raise QuantumJobsException("Failed to retrieve latest boto3 version.") from err
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def get_local_boto3_version() -> str:
|
|
32
|
-
"""Retrieves the local version of boto3."""
|
|
33
|
-
try:
|
|
34
|
-
return version("boto3")
|
|
35
|
-
except PackageNotFoundError as err:
|
|
36
|
-
raise QuantumJobsException(
|
|
37
|
-
"boto3 is not installed in the current environment."
|
|
38
|
-
) from err
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def get_target_site_packages_path() -> str:
|
|
42
|
-
"""Retrieves the site-packages path of the current Python environment."""
|
|
43
|
-
|
|
44
|
-
# List of all site-packages directories
|
|
45
|
-
site_packages_paths = site.getsitepackages()
|
|
46
|
-
|
|
47
|
-
if len(site_packages_paths) == 1:
|
|
48
|
-
return site_packages_paths[0]
|
|
49
|
-
|
|
50
|
-
# Path to the currently running Python interpreter
|
|
51
|
-
python_executable_path = sys.executable
|
|
52
|
-
|
|
53
|
-
# Base path of the Python environment
|
|
54
|
-
env_base_path = os.path.dirname(os.path.dirname(python_executable_path))
|
|
55
|
-
|
|
56
|
-
# Find the site-packages path that is within the same environment
|
|
57
|
-
for path in site_packages_paths:
|
|
58
|
-
if env_base_path in path:
|
|
59
|
-
return path
|
|
60
|
-
|
|
61
|
-
raise QuantumJobsException("Failed to find site-packages path.")
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def get_local_boto3_path() -> str:
|
|
65
|
-
"""Retrieves the local path of boto3."""
|
|
66
|
-
try:
|
|
67
|
-
site_packages_path = get_target_site_packages_path()
|
|
68
|
-
return os.path.join(site_packages_path, "boto3")
|
|
69
|
-
except PackageNotFoundError as err:
|
|
70
|
-
raise QuantumJobsException(
|
|
71
|
-
"boto3 is not installed in the current environment."
|
|
72
|
-
) from err
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def verify_boto3_compatible() -> None:
|
|
76
|
-
"""Verifies that the local version of boto3 is compatible with qBraid Quantum Jobs."""
|
|
77
|
-
stop_event = threading.Event()
|
|
78
|
-
message = "Collecting package metadata..."
|
|
79
|
-
interval = 0.1
|
|
80
|
-
|
|
81
|
-
# Start the progress bar in a separate thread
|
|
82
|
-
progress_thread = threading.Thread(
|
|
83
|
-
target=print_progress_linear,
|
|
84
|
-
args=(
|
|
85
|
-
stop_event,
|
|
86
|
-
message,
|
|
87
|
-
interval,
|
|
88
|
-
),
|
|
89
|
-
)
|
|
90
|
-
progress_thread.start()
|
|
91
|
-
|
|
92
|
-
installed_version = get_local_boto3_version()
|
|
93
|
-
latest_version = get_latest_boto3_version()
|
|
94
|
-
|
|
95
|
-
installed_major, intalled_minor, _ = installed_version.split(".")
|
|
96
|
-
latest_major, latest_minor, _ = latest_version.split(".")
|
|
97
|
-
|
|
98
|
-
# Signal the progress thread to stop
|
|
99
|
-
stop_event.set()
|
|
100
|
-
progress_thread.join()
|
|
101
|
-
|
|
102
|
-
if installed_major == latest_major and intalled_minor == latest_minor:
|
|
103
|
-
return None
|
|
104
|
-
|
|
105
|
-
boto3_location = get_local_boto3_path()
|
|
106
|
-
|
|
107
|
-
print("==> WARNING: A newer version of boto3 exists. <==")
|
|
108
|
-
print(f" current version: {installed_version}")
|
|
109
|
-
print(f" latest version: {latest_version}\n\n")
|
|
110
|
-
print(
|
|
111
|
-
"Enabling quantum jobs will automatically update boto3, "
|
|
112
|
-
"which may cause incompatibilities with the amazon-braket-sdk and/or awscli.\n\n"
|
|
113
|
-
)
|
|
114
|
-
print("## Package Plan ##\n")
|
|
115
|
-
print(f" boto3 location: {boto3_location}\n\n")
|
|
116
|
-
user_input = input("Proceed ([y]/n)? ")
|
|
117
|
-
|
|
118
|
-
if user_input.lower() in ["n", "no"]:
|
|
119
|
-
print("\nqBraidSystemExit: Exiting.")
|
|
120
|
-
sys.exit()
|
|
121
|
-
|
|
122
|
-
print("")
|
|
123
|
-
subprocess.check_call(
|
|
124
|
-
[sys.executable, "-m", "pip", "install", "--upgrade", "boto3"]
|
|
125
|
-
)
|
|
126
|
-
print("")
|
|
127
|
-
|
|
128
|
-
return None
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def manage_package(action, package, exception_message) -> None:
|
|
132
|
-
"""Generic function to install or uninstall packages.
|
|
133
|
-
|
|
134
|
-
Args:
|
|
135
|
-
action (str): 'install' or 'uninstall'
|
|
136
|
-
package (str): The package to install or uninstall
|
|
137
|
-
exception_message (str): Error message to raise in case of exception
|
|
138
|
-
|
|
139
|
-
Returns:
|
|
140
|
-
None
|
|
141
|
-
|
|
142
|
-
Raises:
|
|
143
|
-
QuantumJobsException: If the action fails.
|
|
144
|
-
"""
|
|
145
|
-
try:
|
|
146
|
-
if action == "uninstall":
|
|
147
|
-
subprocess.check_call(
|
|
148
|
-
[sys.executable, "-m", "pip", "uninstall", package, "-y", "--quiet"]
|
|
149
|
-
)
|
|
150
|
-
elif action == "install":
|
|
151
|
-
subprocess.check_call(
|
|
152
|
-
[sys.executable, "-m", "pip", "install", package, "--quiet"]
|
|
153
|
-
)
|
|
154
|
-
except subprocess.CalledProcessError as err:
|
|
155
|
-
raise QuantumJobsException(exception_message) from err
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
def enable_quantum_jobs() -> None:
|
|
159
|
-
"""Enables qBraid quantum jobs."""
|
|
160
|
-
try:
|
|
161
|
-
verify_boto3_compatible()
|
|
162
|
-
stop_event = threading.Event()
|
|
163
|
-
message = "Installing qBraid botocore..."
|
|
164
|
-
interval = 1.5
|
|
165
|
-
|
|
166
|
-
# Start the progress bar in a separate thread
|
|
167
|
-
progress_thread = threading.Thread(
|
|
168
|
-
target=print_progress_linear,
|
|
169
|
-
args=(
|
|
170
|
-
stop_event,
|
|
171
|
-
message,
|
|
172
|
-
interval,
|
|
173
|
-
),
|
|
174
|
-
)
|
|
175
|
-
progress_thread.start()
|
|
176
|
-
manage_package(
|
|
177
|
-
"uninstall",
|
|
178
|
-
"botocore",
|
|
179
|
-
"Failed to install qBraid botocore.",
|
|
180
|
-
)
|
|
181
|
-
manage_package(
|
|
182
|
-
"install",
|
|
183
|
-
"git+https://github.com/qBraid/botocore.git",
|
|
184
|
-
"Failed to install qBraid botocore.",
|
|
185
|
-
)
|
|
186
|
-
stop_event.set()
|
|
187
|
-
progress_thread.join()
|
|
188
|
-
except Exception as err:
|
|
189
|
-
stop_event.set()
|
|
190
|
-
progress_thread.join()
|
|
191
|
-
raise QuantumJobsException("Failed to enable qBraid quantum jobs.") from err
|
|
192
|
-
|
|
193
|
-
print("\nSuccessfully enabled qBraid quantum jobs.\n")
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def disable_quantum_jobs() -> None:
|
|
197
|
-
"""Disables qBraid quantum jobs."""
|
|
198
|
-
try:
|
|
199
|
-
stop_event = threading.Event()
|
|
200
|
-
message = "Uninstalling qBraid botocore..."
|
|
201
|
-
interval = 0.5
|
|
202
|
-
|
|
203
|
-
# Start the progress bar in a separate thread
|
|
204
|
-
progress_thread = threading.Thread(
|
|
205
|
-
target=print_progress_linear,
|
|
206
|
-
args=(
|
|
207
|
-
stop_event,
|
|
208
|
-
message,
|
|
209
|
-
interval,
|
|
210
|
-
),
|
|
211
|
-
)
|
|
212
|
-
progress_thread.start()
|
|
213
|
-
manage_package(
|
|
214
|
-
"uninstall",
|
|
215
|
-
"botocore",
|
|
216
|
-
"Failed to uninstall qBraid botocore.",
|
|
217
|
-
)
|
|
218
|
-
manage_package("install", "botocore", "Failed to reinstall original boto3.")
|
|
219
|
-
stop_event.set()
|
|
220
|
-
progress_thread.join()
|
|
221
|
-
except Exception as err:
|
|
222
|
-
stop_event.set()
|
|
223
|
-
progress_thread.join()
|
|
224
|
-
raise QuantumJobsException("Failed to disable qBraid quantum jobs.") from err
|
|
225
|
-
|
|
226
|
-
print("\nSuccessfully disabled qBraid quantum jobs.\n")
|
qbraid_cli/wrapper.py
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Module to run the qbraid command line interface.
|
|
3
|
-
|
|
4
|
-
Lazy loading is used to avoid loading the qbraid package until it is needed.
|
|
5
|
-
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import os
|
|
9
|
-
import subprocess
|
|
10
|
-
import sys
|
|
11
|
-
|
|
12
|
-
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
|
|
13
|
-
|
|
14
|
-
# pylint: disable=import-outside-toplevel
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def flag_help_command():
|
|
18
|
-
"""Check if the help command should be triggered."""
|
|
19
|
-
if len(sys.argv) > 0:
|
|
20
|
-
last_arg = sys.argv[-1]
|
|
21
|
-
if last_arg in ["-h", "--help", "help"]:
|
|
22
|
-
return True
|
|
23
|
-
return False
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def is_help_command(arg_index):
|
|
27
|
-
"""Check if the help command should be triggered for the given argument index"""
|
|
28
|
-
if flag_help_command() and arg_index == len(sys.argv) - 1:
|
|
29
|
-
return True
|
|
30
|
-
return False
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def get_credits():
|
|
34
|
-
"""Get the number of credits available to the user."""
|
|
35
|
-
from qbraid.api import QbraidSession
|
|
36
|
-
|
|
37
|
-
session = QbraidSession()
|
|
38
|
-
res = session.get("/billing/credits/get-user-credits").json()
|
|
39
|
-
qbraid_credits = res["qbraidCredits"]
|
|
40
|
-
print(qbraid_credits)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def main():
|
|
44
|
-
"""The subprocess.run function is used to run the script and pass arguments."""
|
|
45
|
-
if len(sys.argv) == 2 and sys.argv[1] == "configure":
|
|
46
|
-
from .configure import configure
|
|
47
|
-
|
|
48
|
-
configure()
|
|
49
|
-
if len(sys.argv) == 5 and sys.argv[1:3] == ["configure", "set"]:
|
|
50
|
-
from .configure import configure_set
|
|
51
|
-
|
|
52
|
-
configure_set(sys.argv[3], sys.argv[4])
|
|
53
|
-
elif len(sys.argv) == 2 and sys.argv[1] == "credits":
|
|
54
|
-
get_credits()
|
|
55
|
-
elif sys.argv[1:] == ["--version"] or sys.argv[1:] == ["-V"]:
|
|
56
|
-
from ._version import __version__
|
|
57
|
-
|
|
58
|
-
print(f"qbraid-cli/{__version__}")
|
|
59
|
-
elif len(sys.argv) == 3 and sys.argv[1:] == ["jobs", "list"]:
|
|
60
|
-
from qbraid import get_jobs
|
|
61
|
-
|
|
62
|
-
get_jobs()
|
|
63
|
-
elif len(sys.argv) == 3 and sys.argv[1:] == ["devices", "list"]:
|
|
64
|
-
from qbraid import get_devices
|
|
65
|
-
|
|
66
|
-
get_devices()
|
|
67
|
-
elif (
|
|
68
|
-
len(sys.argv) == 5
|
|
69
|
-
and sys.argv[1:3] == ["envs", "create"]
|
|
70
|
-
and sys.argv[3] in ["-n", "--name"]
|
|
71
|
-
):
|
|
72
|
-
from .envs import create
|
|
73
|
-
|
|
74
|
-
create(sys.argv[4])
|
|
75
|
-
else:
|
|
76
|
-
result = subprocess.run(
|
|
77
|
-
[os.path.join(PROJECT_ROOT, "bin", "qbraid.sh")] + sys.argv[1:],
|
|
78
|
-
text=True,
|
|
79
|
-
capture_output=True,
|
|
80
|
-
check=False,
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
if result.stdout:
|
|
84
|
-
if len(sys.argv) == 4 and sys.argv[2] == "activate":
|
|
85
|
-
line_lst = result.stdout.split("\n")
|
|
86
|
-
line_lst = line_lst[:-1] # remove trailing blank line
|
|
87
|
-
bin_path = line_lst.pop() # last line contains bin_path
|
|
88
|
-
std_out = "\n".join(line_lst) # all other lines are regular stdout
|
|
89
|
-
print(std_out)
|
|
90
|
-
# activate python environment using bin_path
|
|
91
|
-
os.system(
|
|
92
|
-
f"cat ~/.bashrc {bin_path}/activate > {bin_path}/activate2 && "
|
|
93
|
-
rf"sed -i 's/echo -e/\# echo -e/' {bin_path}/activate2 && "
|
|
94
|
-
f"/bin/bash --rcfile {bin_path}/activate2"
|
|
95
|
-
)
|
|
96
|
-
else:
|
|
97
|
-
print(result.stdout)
|
|
98
|
-
if result.stderr:
|
|
99
|
-
print(result.stderr)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if __name__ == "__main__":
|
|
103
|
-
main()
|