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.

Files changed (45) hide show
  1. qbraid_cli/_version.py +2 -2
  2. qbraid_cli/account/__init__.py +11 -0
  3. qbraid_cli/account/app.py +65 -0
  4. qbraid_cli/admin/__init__.py +11 -0
  5. qbraid_cli/admin/app.py +59 -0
  6. qbraid_cli/admin/headers.py +235 -0
  7. qbraid_cli/admin/validation.py +32 -0
  8. qbraid_cli/chat/__init__.py +11 -0
  9. qbraid_cli/chat/app.py +76 -0
  10. qbraid_cli/configure/__init__.py +6 -1
  11. qbraid_cli/configure/actions.py +111 -0
  12. qbraid_cli/configure/app.py +34 -109
  13. qbraid_cli/devices/__init__.py +6 -1
  14. qbraid_cli/devices/app.py +43 -35
  15. qbraid_cli/devices/validation.py +26 -0
  16. qbraid_cli/envs/__init__.py +6 -1
  17. qbraid_cli/envs/activate.py +8 -5
  18. qbraid_cli/envs/app.py +215 -131
  19. qbraid_cli/envs/create.py +14 -120
  20. qbraid_cli/envs/data_handling.py +46 -0
  21. qbraid_cli/exceptions.py +3 -0
  22. qbraid_cli/files/__init__.py +11 -0
  23. qbraid_cli/files/app.py +118 -0
  24. qbraid_cli/handlers.py +47 -13
  25. qbraid_cli/jobs/__init__.py +6 -1
  26. qbraid_cli/jobs/app.py +84 -97
  27. qbraid_cli/jobs/toggle_braket.py +68 -74
  28. qbraid_cli/jobs/validation.py +94 -0
  29. qbraid_cli/kernels/__init__.py +6 -1
  30. qbraid_cli/kernels/app.py +81 -11
  31. qbraid_cli/main.py +66 -14
  32. qbraid_cli/pip/__init__.py +11 -0
  33. qbraid_cli/pip/app.py +50 -0
  34. qbraid_cli/pip/hooks.py +74 -0
  35. qbraid_cli/py.typed +0 -0
  36. qbraid_cli-0.9.5.dist-info/LICENSE +41 -0
  37. qbraid_cli-0.9.5.dist-info/METADATA +179 -0
  38. qbraid_cli-0.9.5.dist-info/RECORD +42 -0
  39. {qbraid_cli-0.8.0.dev0.dist-info → qbraid_cli-0.9.5.dist-info}/WHEEL +1 -1
  40. qbraid_cli/credits/__init__.py +0 -6
  41. qbraid_cli/credits/app.py +0 -30
  42. qbraid_cli-0.8.0.dev0.dist-info/METADATA +0 -124
  43. qbraid_cli-0.8.0.dev0.dist-info/RECORD +0 -25
  44. {qbraid_cli-0.8.0.dev0.dist-info → qbraid_cli-0.9.5.dist-info}/entry_points.txt +0 -0
  45. {qbraid_cli-0.8.0.dev0.dist-info → qbraid_cli-0.9.5.dist-info}/top_level.txt +0 -0
qbraid_cli/envs/app.py CHANGED
@@ -1,180 +1,256 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
1
4
  """
2
5
  Module defining commands in the 'qbraid envs' namespace.
3
6
 
4
7
  """
5
8
 
6
- import json
7
9
  import shutil
10
+ import subprocess
8
11
  import sys
9
12
  from pathlib import Path
10
- from typing import Dict, List, Optional, Tuple
13
+ from typing import TYPE_CHECKING, Optional
11
14
 
12
15
  import typer
16
+ from qbraid_core.services.environments.schema import EnvironmentConfig
13
17
  from rich.console import Console
14
18
 
15
- from qbraid_cli.handlers import QbraidException, run_progress_task
19
+ from qbraid_cli.envs.create import create_qbraid_env_assets, create_venv
20
+ from qbraid_cli.envs.data_handling import get_envs_data as installed_envs_data
21
+ from qbraid_cli.envs.data_handling import validate_env_name
22
+ from qbraid_cli.handlers import QbraidException, handle_error, run_progress_task
16
23
 
17
- app = typer.Typer(help="Manage qBraid environments.")
24
+ if TYPE_CHECKING:
25
+ from qbraid_core.services.environments.client import EnvironmentManagerClient as EMC
18
26
 
27
+ envs_app = typer.Typer(help="Manage qBraid environments.", no_args_is_help=True)
19
28
 
20
- def installed_envs_data() -> Tuple[Dict[str, Path], Dict[str, str]]:
21
- """Gather paths and aliases for all installed qBraid environments."""
22
- from qbraid.api.system import get_qbraid_envs_paths, is_valid_slug
23
29
 
24
- installed = {}
25
- aliases = {}
30
+ @envs_app.command(name="create")
31
+ def envs_create( # pylint: disable=too-many-statements
32
+ name: str = typer.Option(None, "--name", "-n", help="Name of the environment to create"),
33
+ description: Optional[str] = typer.Option(
34
+ None, "--description", "-d", help="Short description of the environment"
35
+ ),
36
+ file_path: str = typer.Option(
37
+ None, "--file", "-f", help="Path to a .yml file containing the environment details"
38
+ ),
39
+ auto_confirm: bool = typer.Option(
40
+ False, "--yes", "-y", help="Automatically answer 'yes' to all prompts"
41
+ ),
42
+ ) -> None:
43
+ """Create a new qBraid environment."""
44
+ env_description = description or ""
45
+ if name:
46
+ if not validate_env_name(name):
47
+ handle_error(
48
+ error_type="ValueError",
49
+ include_traceback=False,
50
+ message=f"Invalid environment name '{name}'. ",
51
+ )
52
+
53
+ env_details_in_cli = name is not None and env_description != ""
54
+ custom_env_data = None
55
+ if env_details_in_cli and file_path:
56
+ handle_error(
57
+ error_type="ArgumentConflictError",
58
+ include_traceback=False,
59
+ message="Cannot use --file with --name or --description while creating an environment",
60
+ )
61
+ elif not env_details_in_cli and not file_path:
62
+ handle_error(
63
+ error_type="MalformedCommandError",
64
+ include_traceback=False,
65
+ message="Must provide either --name and --description or --file "
66
+ "while creating an environment",
67
+ )
68
+ else:
69
+ try:
70
+ if file_path:
71
+ custom_env_data: EnvironmentConfig = EnvironmentConfig.from_yaml(file_path)
72
+ except ValueError as err:
73
+ handle_error(error_type="YamlValidationError", message=str(err))
26
74
 
27
- qbraid_env_paths: List[Path] = get_qbraid_envs_paths()
75
+ if not name:
76
+ name = custom_env_data.name
28
77
 
29
- for env_path in qbraid_env_paths:
30
- for entry in env_path.iterdir():
31
- if entry.is_dir() and is_valid_slug(entry.name):
32
- installed[entry.name] = entry
78
+ def create_environment(*args, **kwargs) -> "tuple[dict, EMC]":
79
+ """Create a qBraid environment."""
80
+ from qbraid_core.services.environments.client import EnvironmentManagerClient
33
81
 
34
- if entry.name == "qbraid_000000":
35
- aliases["default"] = entry.name
36
- continue
82
+ client = EnvironmentManagerClient()
83
+ return client.create_environment(*args, **kwargs), client
37
84
 
38
- state_json_path = entry / "state.json"
39
- if state_json_path.exists():
40
- try:
41
- with open(state_json_path, "r", encoding="utf-8") as f:
42
- data = json.load(f)
43
- aliases[data.get("name", entry.name[:-7])] = entry.name
44
- # pylint: disable-next=broad-exception-caught
45
- except (json.JSONDecodeError, Exception):
46
- aliases[entry.name[:-7]] = entry.name
47
- else:
48
- aliases[entry.name[:-7]] = entry.name
85
+ def gather_local_data() -> tuple[Path, str]:
86
+ """Gather environment data and return the slug."""
87
+ from qbraid_core.services.environments import get_default_envs_paths
49
88
 
50
- return installed, aliases
89
+ env_path = get_default_envs_paths()[0]
51
90
 
91
+ result = subprocess.run(
92
+ [sys.executable, "--version"],
93
+ capture_output=True,
94
+ text=True,
95
+ check=True,
96
+ )
52
97
 
53
- @app.command(name="create")
54
- def envs_create(
55
- name: str = typer.Option(..., "--name", "-n", help="Name of the environment to create"),
56
- description: Optional[str] = typer.Option(
57
- None, "--description", "-d", help="Short description of the environment"
58
- ),
59
- ) -> None:
60
- """Create a new qBraid environment.
98
+ python_version = result.stdout or result.stderr
61
99
 
62
- NOTE: Requires updated API route from https://github.com/qBraid/api/pull/482,
63
- This command will not work until that PR is merged, and the updates are deployed.
64
- """
65
- from .create import create_qbraid_env
100
+ return env_path, python_version
66
101
 
67
- def request_new_env(req_body: Dict[str, str]) -> str:
68
- """Send request to create new environment and return the slug."""
69
- from qbraid.api import QbraidSession, RequestsApiError
102
+ if not custom_env_data:
103
+ custom_env_data = EnvironmentConfig(
104
+ name=name,
105
+ description=env_description,
106
+ )
70
107
 
71
- session = QbraidSession()
108
+ environment, emc = run_progress_task(
109
+ create_environment,
110
+ custom_env_data,
111
+ description="Validating request...",
112
+ error_message="Failed to create qBraid environment",
113
+ )
72
114
 
73
- try:
74
- resp = session.post("/environments/create", json=req_body).json()
75
- except RequestsApiError as err:
76
- raise QbraidException("Create environment request failed") from err
77
-
78
- slug = resp.get("slug")
79
- if slug is None:
80
- raise QbraidException(f"Create environment request returned invalid slug, {slug}")
81
-
82
- return slug
83
-
84
- req_body = {
85
- "name": name,
86
- "description": description or "",
87
- "tags": "", # comma separated list of tags
88
- "code": "", # newline separated list of packages
89
- "visibility": "private",
90
- "kernelName": "",
91
- "prompt": "",
92
- }
93
- slug = run_progress_task(
94
- request_new_env,
95
- req_body,
96
- description="Validating...",
115
+ env_path, python_version = run_progress_task(
116
+ gather_local_data,
117
+ description="Solving environment...",
97
118
  error_message="Failed to create qBraid environment",
98
119
  )
99
120
 
121
+ slug = environment.get("slug")
122
+ display_name = environment.get("displayName")
123
+ prompt = environment.get("prompt")
124
+ description = environment.get("description")
125
+ tags = environment.get("tags")
126
+ kernel_name = environment.get("kernelName")
127
+
128
+ slug_path = env_path / slug
129
+ description = "None" if description == "" else description
130
+
131
+ typer.echo("## qBraid Metadata ##\n")
132
+ typer.echo(f" name: {display_name}")
133
+ typer.echo(f" description: {description}")
134
+ typer.echo(f" tags: {tags}")
135
+ typer.echo(f" slug: {slug}")
136
+ typer.echo(f" shellPrompt: {prompt}")
137
+ typer.echo(f" kernelName: {kernel_name}")
138
+
139
+ typer.echo("\n\n## Environment Plan ##\n")
140
+ typer.echo(f" location: {slug_path}")
141
+ typer.echo(f" version: {python_version}\n")
142
+
143
+ user_confirmation = auto_confirm or typer.confirm("Proceed", default=True)
144
+ typer.echo("")
145
+ if not user_confirmation:
146
+ emc.delete_environment(slug)
147
+ typer.echo("qBraidSystemExit: Exiting.")
148
+ raise typer.Exit()
149
+
100
150
  run_progress_task(
101
- create_qbraid_env,
151
+ create_qbraid_env_assets,
102
152
  slug,
103
- name,
104
- description="Creating qBraid environment...",
153
+ prompt,
154
+ kernel_name,
155
+ slug_path,
156
+ description="Generating qBraid assets...",
157
+ error_message="Failed to create qBraid environment",
158
+ )
159
+
160
+ run_progress_task(
161
+ create_venv,
162
+ slug_path,
163
+ prompt,
164
+ description="Creating virtual environment...",
105
165
  error_message="Failed to create qBraid environment",
106
166
  )
107
167
 
108
- # TODO: Add the command they can use to activate the environment to end of success message
109
168
  console = Console()
110
169
  console.print(
111
- f"\n[bold green]Successfully created qBraid environment: "
170
+ f"[bold green]Successfully created qBraid environment: "
112
171
  f"[/bold green][bold magenta]{name}[/bold magenta]\n"
113
172
  )
173
+ typer.echo("# To activate this environment, use")
174
+ typer.echo("#")
175
+ typer.echo(f"# $ qbraid envs activate {name}")
176
+ typer.echo("#")
177
+ typer.echo("# To deactivate an active environment, use")
178
+ typer.echo("#")
179
+ typer.echo("# $ deactivate")
180
+
181
+
182
+ @envs_app.command(name="remove")
183
+ def envs_remove(
184
+ name: str = typer.Option(..., "-n", "--name", help="Name of the environment to remove"),
185
+ auto_confirm: bool = typer.Option(
186
+ False, "--yes", "-y", help="Automatically answer 'yes' to all prompts"
187
+ ),
188
+ ) -> None:
189
+ """Delete a qBraid environment."""
114
190
 
191
+ def delete_environment(slug: str) -> None:
192
+ """Delete a qBraid environment."""
193
+ from qbraid_core.services.environments.client import EnvironmentManagerClient
115
194
 
116
- @app.command(name="delete")
117
- def envs_delete(name: str = typer.Argument(..., help="Name of the environment to delete")) -> None:
118
- """Delete a qBraid environment.
119
-
120
- NOTE: Requires updated API route from https://github.com/qBraid/api/pull/482,
121
- This command will not work until that PR is merged, and the updates are deployed.
122
- """
123
-
124
- def request_delete_env(name: str) -> str:
125
- """Send request to create new environment and return the slug."""
126
- from qbraid.api import QbraidSession, RequestsApiError
127
-
128
- session = QbraidSession()
195
+ emc = EnvironmentManagerClient()
196
+ emc.delete_environment(slug)
129
197
 
198
+ def gather_local_data(env_name: str) -> tuple[Path, str]:
199
+ """Get environment path and slug from name (alias)."""
130
200
  installed, aliases = installed_envs_data()
131
- for alias, slug_name in aliases.items():
132
- if alias == name:
133
- slug = slug_name
134
- path = installed[slug_name]
135
-
136
- try:
137
- session.delete(f"/environments/{slug}")
138
- except RequestsApiError as err:
139
- raise QbraidException("Create environment request failed") from err
201
+ for alias, slug in aliases.items():
202
+ if alias == env_name:
203
+ path = installed[slug]
140
204
 
141
- return path
205
+ return path, slug
142
206
 
143
207
  raise QbraidException(f"Environment '{name}' not found.")
144
208
 
145
- path = run_progress_task(
146
- request_delete_env,
147
- name,
148
- description="Deleting remote environment data...",
149
- error_message="Failed to delete qBraid environment",
150
- )
209
+ slug_path, slug = gather_local_data(name)
151
210
 
152
- run_progress_task(
153
- shutil.rmtree,
154
- path,
155
- description="Deleting local environment...",
156
- error_message="Failed to delete qBraid environment",
157
- )
158
-
159
- console = Console()
160
- console.print(
161
- f"\n[bold green]Successfully delete qBraid environment: "
162
- f"[/bold green][bold magenta]{name}[/bold magenta]\n"
211
+ confirmation_message = (
212
+ f"⚠️ Warning: You are about to delete the environment '{name}' "
213
+ f"located at '{slug_path}'.\n"
214
+ "This will remove all local packages and permanently delete all "
215
+ "of its associated qBraid environment metadata.\n"
216
+ "This operation CANNOT be undone.\n\n"
217
+ "Are you sure you want to continue?"
163
218
  )
164
219
 
165
-
166
- @app.command(name="list")
220
+ if auto_confirm or typer.confirm(confirmation_message, abort=True):
221
+ typer.echo("")
222
+ run_progress_task(
223
+ delete_environment,
224
+ slug,
225
+ description="Deleting remote environment data...",
226
+ error_message="Failed to delete qBraid environment",
227
+ )
228
+
229
+ run_progress_task(
230
+ shutil.rmtree,
231
+ slug_path,
232
+ description="Deleting local environment...",
233
+ error_message="Failed to delete qBraid environment",
234
+ )
235
+ typer.echo(f"Environment '{name}' successfully removed.")
236
+
237
+
238
+ @envs_app.command(name="list")
167
239
  def envs_list():
168
240
  """List installed qBraid environments."""
169
241
  installed, aliases = installed_envs_data()
170
242
 
243
+ console = Console()
244
+
171
245
  if len(installed) == 0:
172
- print("No qBraid environments installed.")
173
- print("\nUse 'qbraid envs create' to create a new environment.")
246
+ console.print(
247
+ "No qBraid environments installed.\n\n"
248
+ + "Use 'qbraid envs create' to create a new environment.",
249
+ style="yellow",
250
+ )
174
251
  return
175
252
 
176
253
  alias_path_pairs = [(alias, installed[slug_name]) for alias, slug_name in aliases.items()]
177
-
178
254
  sorted_alias_path_pairs = sorted(
179
255
  alias_path_pairs,
180
256
  key=lambda x: (x[0] != "default", str(x[1]).startswith(str(Path.home())), x[0]),
@@ -183,23 +259,31 @@ def envs_list():
183
259
  current_env_path = Path(sys.executable).parent.parent.parent
184
260
 
185
261
  max_alias_length = (
186
- max(len(alias) for alias, _ in sorted_alias_path_pairs) if sorted_alias_path_pairs else 0
187
- )
188
- max_path_length = (
189
- max(len(str(path)) for _, path in sorted_alias_path_pairs) if sorted_alias_path_pairs else 0
262
+ max(len(str(alias)) for alias, envpath in sorted_alias_path_pairs)
263
+ if sorted_alias_path_pairs
264
+ else 0
190
265
  )
191
266
 
192
- print("# installed environments:")
193
- print("#")
194
- print("")
267
+ output_lines = []
268
+ output_lines.append("# qbraid environments:")
269
+ output_lines.append("#")
270
+ output_lines.append("")
271
+
195
272
  for alias, path in sorted_alias_path_pairs:
196
- mark = "* " if path == current_env_path else " "
197
- print(f"{alias.ljust(max_alias_length + 11)}{mark}{str(path).ljust(max_path_length)}")
273
+ mark = "*" if path == current_env_path else " "
274
+ line = f"{alias.ljust(max_alias_length + 3)}{mark} {path}"
275
+ output_lines.append(line)
276
+
277
+ final_output = "\n".join(output_lines)
198
278
 
279
+ console.print(final_output)
199
280
 
200
- @app.command(name="activate")
281
+
282
+ @envs_app.command(name="activate")
201
283
  def envs_activate(
202
- name: str = typer.Argument(..., help="Name of the environment. Values from 'qbraid envs list'.")
284
+ name: str = typer.Argument(
285
+ ..., help="Name of the environment. Values from 'qbraid envs list'."
286
+ ),
203
287
  ):
204
288
  """Activate qBraid environment.
205
289
 
@@ -219,4 +303,4 @@ def envs_activate(
219
303
 
220
304
 
221
305
  if __name__ == "__main__":
222
- app()
306
+ envs_app()
qbraid_cli/envs/create.py CHANGED
@@ -1,135 +1,29 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
1
4
  """
2
5
  Module supporting 'qbraid envs create' command.
3
6
 
4
7
  """
5
8
 
6
- import json
7
- import os
8
- import shutil
9
- import subprocess
10
- import sys
11
- from typing import Optional
12
-
13
-
14
- def create_alias(slug: str) -> str:
15
- """Create an alias from a slug."""
16
- return slug[:-7].replace("_", "-").strip("-")
17
-
18
-
19
- def replace_str(target: str, replacement: str, file_path: str) -> None:
20
- """Replace all instances of string in file"""
21
- with open(file_path, "r", encoding="utf-8") as file:
22
- content = file.read()
23
-
24
- content = content.replace(target, replacement)
25
-
26
- with open(file_path, "w", encoding="utf-8") as file:
27
- file.write(content)
28
-
29
-
30
- def update_state_json(
31
- slug_path: str,
32
- install_complete: int,
33
- install_success: int,
34
- message: Optional[str] = None,
35
- env_name: Optional[str] = None,
36
- ) -> None:
37
- """Update environment's install status values in a JSON file.
38
- Truth table values: 0 = False, 1 = True, -1 = Unknown
39
- """
40
- # Set default message if none provided
41
- message = "" if message is None else message.replace("\n", " ")
42
-
43
- # File path for state.json
44
- state_json_path = os.path.join(slug_path, "state.json")
45
9
 
46
- # Read existing data or use default structure
47
- if os.path.exists(state_json_path):
48
- with open(state_json_path, "r", encoding="utf-8") as f:
49
- data = json.load(f)
50
- else:
51
- data = {"install": {}}
10
+ def create_venv(*args, **kwargs) -> None:
11
+ """Create a python virtual environment for the qBraid environment."""
12
+ from qbraid_core.services.environments import create_local_venv
52
13
 
53
- # Update the data
54
- data["install"]["complete"] = install_complete
55
- data["install"]["success"] = install_success
56
- data["install"]["message"] = message
14
+ return create_local_venv(*args, **kwargs)
57
15
 
58
- if env_name is not None:
59
- data["name"] = env_name.lower()
60
16
 
61
- # Write updated data back to state.json
62
- with open(state_json_path, "w", encoding="utf-8") as f:
63
- json.dump(data, f, indent=4)
17
+ def update_state_json(*ags, **kwargs) -> None:
18
+ """Update the state.json file for the qBraid environment."""
19
+ from qbraid_core.services.environments.state import update_state_json as update_state
64
20
 
21
+ return update_state(*ags, **kwargs)
65
22
 
66
- def create_venv(slug_path: str, prompt: str) -> None:
67
- """Create virtual environment and swap PS1 display name."""
68
- venv_path = os.path.join(slug_path, "pyenv")
69
- subprocess.run([sys.executable, "-m", "venv", venv_path], check=True)
70
23
 
71
- # Determine the correct directory for activation scripts based on the operating system
72
- if sys.platform == "win32":
73
- scripts_path = os.path.join(venv_path, "Scripts")
74
- activate_files = ["activate.bat", "Activate.ps1"]
75
- else:
76
- scripts_path = os.path.join(venv_path, "bin")
77
- activate_files = ["activate", "activate.csh", "activate.fish"]
78
-
79
- for file in activate_files:
80
- file_path = os.path.join(scripts_path, file)
81
- if os.path.isfile(file_path):
82
- replace_str("(pyenv)", f"({prompt})", file_path)
83
-
84
- replace_str(
85
- "include-system-site-packages = false",
86
- "include-system-site-packages = true",
87
- os.path.join(venv_path, "pyvenv.cfg"),
88
- )
89
-
90
- update_state_json(slug_path, 1, 1)
91
-
92
-
93
- def create_qbraid_env(slug: str, name: str) -> None:
24
+ def create_qbraid_env_assets(slug: str, alias: str, kernel_name: str, slug_path: str) -> None:
94
25
  """Create a qBraid environment including python venv, PS1 configs,
95
26
  kernel resource files, and qBraid state.json."""
96
- # pylint: disable-next=import-outside-toplevel
97
- from jupyter_client.kernelspec import KernelSpecManager
98
- from qbraid.api.system import get_qbraid_envs_paths
99
-
100
- alias = create_alias(slug)
101
- display_name = f"Python 3 [{alias}]"
102
- envs_dir_path = get_qbraid_envs_paths()[0]
103
- slug_path = os.path.join(str(envs_dir_path), slug)
104
- local_resource_dir = os.path.join(slug_path, "kernels", f"python3_{slug}")
105
- os.makedirs(local_resource_dir, exist_ok=True)
106
-
107
- # create state.json
108
- update_state_json(slug_path, 0, 0, env_name=name)
109
-
110
- # create kernel.json
111
- kernel_json_path = os.path.join(local_resource_dir, "kernel.json")
112
- kernel_spec_manager = KernelSpecManager()
113
- kernelspec_dict = kernel_spec_manager.get_all_specs()
114
- kernel_data = kernelspec_dict["python3"]["spec"]
115
- if sys.platform == "win32":
116
- python_exec_path = os.path.join(slug_path, "pyenv", "Scripts", "python.exe")
117
- else:
118
- python_exec_path = os.path.join(slug_path, "pyenv", "bin", "python")
119
- kernel_data["argv"][0] = python_exec_path
120
- kernel_data["display_name"] = display_name
121
- with open(kernel_json_path, "w", encoding="utf-8") as file:
122
- json.dump(kernel_data, file, indent=4)
123
-
124
- # copy logo files
125
- sys_resource_dir = kernelspec_dict["python3"]["resource_dir"]
126
- logo_files = ["logo-32x32.png", "logo-64x64.png", "logo-svg.svg"]
127
-
128
- for file in logo_files:
129
- sys_path = os.path.join(sys_resource_dir, file)
130
- loc_path = os.path.join(local_resource_dir, file)
131
- if os.path.isfile(sys_path):
132
- shutil.copy(sys_path, loc_path)
27
+ from qbraid_core.services.environments.create import create_qbraid_env_assets as create_assets
133
28
 
134
- # create python venv
135
- create_venv(slug_path, alias)
29
+ return create_assets(slug, alias, kernel_name, slug_path)
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
4
+ """
5
+ Module for handling data related to qBraid environments.
6
+
7
+ """
8
+
9
+ import typer
10
+
11
+ from qbraid_cli.handlers import QbraidException
12
+
13
+
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)
26
+
27
+
28
+ def validate_env_name(value: str) -> str:
29
+ """Validate environment name."""
30
+ if not is_valid_env_name(value):
31
+ raise typer.BadParameter(
32
+ f"Invalid environment name '{value}'. " "Please use a valid Python environment name."
33
+ )
34
+ return value
35
+
36
+
37
+ def request_delete_env(slug: str) -> str:
38
+ """Send request to delete environment given slug."""
39
+ from qbraid_core import QbraidSession, RequestsApiError
40
+
41
+ session = QbraidSession()
42
+
43
+ try:
44
+ session.delete(f"/environments/{slug}")
45
+ except RequestsApiError as err:
46
+ raise QbraidException("Delete environment request failed") from err
qbraid_cli/exceptions.py CHANGED
@@ -1,3 +1,6 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
1
4
  """
2
5
  Module defining custom exceptions for the qBraid CLI.
3
6
 
@@ -0,0 +1,11 @@
1
+ # Copyright (c) 2024, qBraid Development Team
2
+ # All rights reserved.
3
+
4
+ """
5
+ Module defining the qbraid files namespace
6
+
7
+ """
8
+
9
+ from .app import files_app
10
+
11
+ __all__ = ["files_app"]