qbraid-cli 0.8.0.dev1__py3-none-any.whl → 0.9.6__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 +93 -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 +116 -197
  19. qbraid_cli/envs/create.py +13 -109
  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 +46 -12
  25. qbraid_cli/jobs/__init__.py +6 -1
  26. qbraid_cli/jobs/app.py +76 -93
  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 +74 -17
  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.6.dist-info/LICENSE +41 -0
  37. qbraid_cli-0.9.6.dist-info/METADATA +179 -0
  38. qbraid_cli-0.9.6.dist-info/RECORD +42 -0
  39. {qbraid_cli-0.8.0.dev1.dist-info → qbraid_cli-0.9.6.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.dev1.dist-info/METADATA +0 -136
  43. qbraid_cli-0.8.0.dev1.dist-info/RECORD +0 -25
  44. {qbraid_cli-0.8.0.dev1.dist-info → qbraid_cli-0.9.6.dist-info}/entry_points.txt +0 -0
  45. {qbraid_cli-0.8.0.dev1.dist-info → qbraid_cli-0.9.6.dist-info}/top_level.txt +0 -0
qbraid_cli/envs/app.py CHANGED
@@ -1,184 +1,92 @@
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
- import keyword
8
- import re
9
9
  import shutil
10
10
  import subprocess
11
11
  import sys
12
12
  from pathlib import Path
13
- from typing import Any, Dict, List, Optional, Tuple
13
+ from typing import TYPE_CHECKING, Optional
14
14
 
15
15
  import typer
16
+ from qbraid_core.services.environments.schema import EnvironmentConfig
16
17
  from rich.console import Console
17
18
 
18
- from qbraid_cli.handlers import QbraidException, run_progress_task
19
-
20
- app = typer.Typer(help="Manage qBraid environments.")
21
-
22
-
23
- def is_valid_env_name(env_name: str) -> bool: # pylint: disable=too-many-return-statements
24
- """
25
- Validates a Python virtual environment name against best practices.
26
-
27
- This function checks if the given environment name is valid based on certain
28
- criteria, including length, use of special characters, reserved names, and
29
- operating system-specific restrictions.
30
-
31
- Args:
32
- env_name (str): The name of the Python virtual environment to validate.
33
-
34
- Returns:
35
- bool: True if the name is valid, False otherwise.
36
-
37
- Raises:
38
- ValueError: If the environment name is not a string or is empty.
39
- """
40
- # Basic checks for empty names or purely whitespace names
41
- if not env_name or env_name.isspace():
42
- return False
43
-
44
- # Check for invalid characters, including shell metacharacters and spaces
45
- if re.search(r'[<>:"/\\|?*\s&;()$[\]#~!{}]', env_name):
46
- return False
47
-
48
- if env_name.startswith("tmp"):
49
- return False
50
-
51
- # Reserved names for Windows (example list, can be expanded)
52
- reserved_names = [
53
- "CON",
54
- "PRN",
55
- "AUX",
56
- "NUL",
57
- "COM1",
58
- "COM2",
59
- "COM3",
60
- "COM4",
61
- "COM5",
62
- "COM6",
63
- "COM7",
64
- "COM8",
65
- "COM9",
66
- "LPT1",
67
- "LPT2",
68
- "LPT3",
69
- "LPT4",
70
- "LPT5",
71
- "LPT6",
72
- "LPT7",
73
- "LPT8",
74
- "LPT9",
75
- ]
76
- if env_name.upper() in reserved_names:
77
- return False
78
-
79
- if len(env_name) > 20:
80
- return False
81
-
82
- # Check against Python reserved words
83
- if keyword.iskeyword(env_name):
84
- return False
85
-
86
- # Check if it starts with a number, which is not a good practice
87
- if env_name[0].isdigit():
88
- return False
89
-
90
- return True
91
-
92
-
93
- def validate_env_name(value: str) -> str:
94
- """Validate environment name."""
95
- if not is_valid_env_name(value):
96
- raise typer.BadParameter(
97
- f"Invalid environment name '{value}'. " "Please use a valid Python environment name."
98
- )
99
- return value
100
-
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
101
23
 
102
- def installed_envs_data() -> Tuple[Dict[str, Path], Dict[str, str]]:
103
- """Gather paths and aliases for all installed qBraid environments."""
104
- from qbraid.api.system import get_qbraid_envs_paths, is_valid_slug
24
+ if TYPE_CHECKING:
25
+ from qbraid_core.services.environments.client import EnvironmentManagerClient as EMC
105
26
 
106
- installed = {}
107
- aliases = {}
27
+ envs_app = typer.Typer(help="Manage qBraid environments.", no_args_is_help=True)
108
28
 
109
- qbraid_env_paths: List[Path] = get_qbraid_envs_paths()
110
29
 
111
- for env_path in qbraid_env_paths:
112
- for entry in env_path.iterdir():
113
- if entry.is_dir() and is_valid_slug(entry.name):
114
- installed[entry.name] = entry
115
-
116
- if entry.name == "qbraid_000000":
117
- aliases["default"] = entry.name
118
- continue
119
-
120
- state_json_path = entry / "state.json"
121
- if state_json_path.exists():
122
- try:
123
- with open(state_json_path, "r", encoding="utf-8") as f:
124
- data = json.load(f)
125
- aliases[data.get("name", entry.name[:-7])] = entry.name
126
- # pylint: disable-next=broad-exception-caught
127
- except (json.JSONDecodeError, Exception):
128
- aliases[entry.name[:-7]] = entry.name
129
- else:
130
- aliases[entry.name[:-7]] = entry.name
131
-
132
- return installed, aliases
133
-
134
-
135
- def request_delete_env(slug: str) -> str:
136
- """Send request to delete environment given slug."""
137
- from qbraid.api import QbraidSession, RequestsApiError
138
-
139
- session = QbraidSession()
140
-
141
- try:
142
- session.delete(f"/environments/{slug}")
143
- except RequestsApiError as err:
144
- raise QbraidException("Delete environment request failed") from err
145
-
146
-
147
- @app.command(name="create")
30
+ @envs_app.command(name="create")
148
31
  def envs_create( # pylint: disable=too-many-statements
149
- name: str = typer.Option(
150
- ..., "--name", "-n", help="Name of the environment to create", callback=validate_env_name
151
- ),
32
+ name: str = typer.Option(None, "--name", "-n", help="Name of the environment to create"),
152
33
  description: Optional[str] = typer.Option(
153
34
  None, "--description", "-d", help="Short description of the environment"
154
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
+ ),
155
42
  ) -> None:
156
43
  """Create a new qBraid environment."""
157
- from .create import create_qbraid_env_assets, create_venv
158
-
159
- def request_new_env(req_body: Dict[str, str]) -> Dict[str, Any]:
160
- """Send request to create new environment and return the slug."""
161
- from qbraid.api import QbraidSession, RequestsApiError
162
-
163
- session = QbraidSession()
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
+ )
164
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:
165
69
  try:
166
- env_data = session.post("/environments/create", json=req_body).json()
167
- except RequestsApiError as err:
168
- raise QbraidException("Create environment request failed") from err
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))
169
74
 
170
- if env_data is None or len(env_data) == 0 or env_data.get("slug") is None:
171
- raise QbraidException(
172
- "Create environment request responsed with invalid environment data"
173
- )
75
+ if not name:
76
+ name = custom_env_data.name
77
+
78
+ def create_environment(*args, **kwargs) -> "tuple[dict, EMC]":
79
+ """Create a qBraid environment."""
80
+ from qbraid_core.services.environments.client import EnvironmentManagerClient
174
81
 
175
- return env_data
82
+ client = EnvironmentManagerClient()
83
+ return client.create_environment(*args, **kwargs), client
176
84
 
177
- def gather_local_data() -> Tuple[Path, str]:
85
+ def gather_local_data() -> tuple[Path, str]:
178
86
  """Gather environment data and return the slug."""
179
- from qbraid.api.system import get_qbraid_envs_paths
87
+ from qbraid_core.services.environments import get_default_envs_paths
180
88
 
181
- env_path = get_qbraid_envs_paths()[0]
89
+ env_path = get_default_envs_paths()[0]
182
90
 
183
91
  result = subprocess.run(
184
92
  [sys.executable, "--version"],
@@ -191,20 +99,15 @@ def envs_create( # pylint: disable=too-many-statements
191
99
 
192
100
  return env_path, python_version
193
101
 
194
- req_body = {
195
- "name": name,
196
- "description": description or "",
197
- "tags": "", # comma separated list of tags
198
- "code": "", # newline separated list of packages
199
- "visibility": "private",
200
- "kernelName": "",
201
- "prompt": "",
202
- "origin": "CLI",
203
- }
204
-
205
- environment = run_progress_task(
206
- request_new_env,
207
- req_body,
102
+ if not custom_env_data:
103
+ custom_env_data = EnvironmentConfig(
104
+ name=name,
105
+ description=env_description,
106
+ )
107
+
108
+ environment, emc = run_progress_task(
109
+ create_environment,
110
+ custom_env_data,
208
111
  description="Validating request...",
209
112
  error_message="Failed to create qBraid environment",
210
113
  )
@@ -225,7 +128,7 @@ def envs_create( # pylint: disable=too-many-statements
225
128
  slug_path = env_path / slug
226
129
  description = "None" if description == "" else description
227
130
 
228
- typer.echo("\n\n## qBraid Metadata ##\n")
131
+ typer.echo("## qBraid Metadata ##\n")
229
132
  typer.echo(f" name: {display_name}")
230
133
  typer.echo(f" description: {description}")
231
134
  typer.echo(f" tags: {tags}")
@@ -237,10 +140,10 @@ def envs_create( # pylint: disable=too-many-statements
237
140
  typer.echo(f" location: {slug_path}")
238
141
  typer.echo(f" version: {python_version}\n")
239
142
 
240
- user_confirmation = typer.confirm("Proceed", default=True)
143
+ user_confirmation = auto_confirm or typer.confirm("Proceed", default=True)
241
144
  typer.echo("")
242
145
  if not user_confirmation:
243
- request_delete_env(slug)
146
+ emc.delete_environment(slug)
244
147
  typer.echo("qBraidSystemExit: Exiting.")
245
148
  raise typer.Exit()
246
149
 
@@ -264,7 +167,7 @@ def envs_create( # pylint: disable=too-many-statements
264
167
 
265
168
  console = Console()
266
169
  console.print(
267
- f"\n[bold green]Successfully created qBraid environment: "
170
+ f"[bold green]Successfully created qBraid environment: "
268
171
  f"[/bold green][bold magenta]{name}[/bold magenta]\n"
269
172
  )
270
173
  typer.echo("# To activate this environment, use")
@@ -276,13 +179,23 @@ def envs_create( # pylint: disable=too-many-statements
276
179
  typer.echo("# $ deactivate")
277
180
 
278
181
 
279
- @app.command(name="remove")
182
+ @envs_app.command(name="remove")
280
183
  def envs_remove(
281
- name: str = typer.Option(..., "-n", "--name", help="Name of the environment to 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
+ ),
282
188
  ) -> None:
283
189
  """Delete a qBraid environment."""
284
190
 
285
- def gather_local_data(env_name: str) -> Tuple[Path, str]:
191
+ def delete_environment(slug: str) -> None:
192
+ """Delete a qBraid environment."""
193
+ from qbraid_core.services.environments.client import EnvironmentManagerClient
194
+
195
+ emc = EnvironmentManagerClient()
196
+ emc.delete_environment(slug)
197
+
198
+ def gather_local_data(env_name: str) -> tuple[Path, str]:
286
199
  """Get environment path and slug from name (alias)."""
287
200
  installed, aliases = installed_envs_data()
288
201
  for alias, slug in aliases.items():
@@ -304,11 +217,10 @@ def envs_remove(
304
217
  "Are you sure you want to continue?"
305
218
  )
306
219
 
307
- # Ask for user confirmation
308
- if typer.confirm(confirmation_message, abort=True):
220
+ if auto_confirm or typer.confirm(confirmation_message, abort=True):
309
221
  typer.echo("")
310
222
  run_progress_task(
311
- request_delete_env,
223
+ delete_environment,
312
224
  slug,
313
225
  description="Deleting remote environment data...",
314
226
  error_message="Failed to delete qBraid environment",
@@ -320,26 +232,25 @@ def envs_remove(
320
232
  description="Deleting local environment...",
321
233
  error_message="Failed to delete qBraid environment",
322
234
  )
323
- typer.echo(f"\nEnvironment '{name}' successfully removed.")
324
- # console = Console()
325
- # console.print(
326
- # f"\n[bold green]Successfully deleted qBraid environment: "
327
- # f"[/bold green][bold magenta]{name}[/bold magenta]\n"
328
- # )
235
+ typer.echo(f"Environment '{name}' successfully removed.")
329
236
 
330
237
 
331
- @app.command(name="list")
238
+ @envs_app.command(name="list")
332
239
  def envs_list():
333
240
  """List installed qBraid environments."""
334
241
  installed, aliases = installed_envs_data()
335
242
 
243
+ console = Console()
244
+
336
245
  if len(installed) == 0:
337
- print("No qBraid environments installed.")
338
- 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
+ )
339
251
  return
340
252
 
341
253
  alias_path_pairs = [(alias, installed[slug_name]) for alias, slug_name in aliases.items()]
342
-
343
254
  sorted_alias_path_pairs = sorted(
344
255
  alias_path_pairs,
345
256
  key=lambda x: (x[0] != "default", str(x[1]).startswith(str(Path.home())), x[0]),
@@ -348,23 +259,31 @@ def envs_list():
348
259
  current_env_path = Path(sys.executable).parent.parent.parent
349
260
 
350
261
  max_alias_length = (
351
- max(len(alias) for alias, _ in sorted_alias_path_pairs) if sorted_alias_path_pairs else 0
352
- )
353
- max_path_length = (
354
- 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
355
265
  )
356
266
 
357
- print("# qbraid environments:")
358
- print("#")
359
- print("")
267
+ output_lines = []
268
+ output_lines.append("# qbraid environments:")
269
+ output_lines.append("#")
270
+ output_lines.append("")
271
+
360
272
  for alias, path in sorted_alias_path_pairs:
361
- mark = "* " if path == current_env_path else " "
362
- print(f"{alias.ljust(max_alias_length + 7)}{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)
363
278
 
279
+ console.print(final_output)
364
280
 
365
- @app.command(name="activate")
281
+
282
+ @envs_app.command(name="activate")
366
283
  def envs_activate(
367
- 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
+ ),
368
287
  ):
369
288
  """Activate qBraid environment.
370
289
 
@@ -384,4 +303,4 @@ def envs_activate(
384
303
 
385
304
 
386
305
  if __name__ == "__main__":
387
- app()
306
+ envs_app()
qbraid_cli/envs/create.py CHANGED
@@ -1,125 +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 replace_str(target: str, replacement: str, file_path: str) -> None:
15
- """Replace all instances of string in file"""
16
- with open(file_path, "r", encoding="utf-8") as file:
17
- content = file.read()
18
-
19
- content = content.replace(target, replacement)
20
-
21
- with open(file_path, "w", encoding="utf-8") as file:
22
- file.write(content)
23
-
24
-
25
- def update_state_json(
26
- slug_path: str,
27
- install_complete: int,
28
- install_success: int,
29
- message: Optional[str] = None,
30
- env_name: Optional[str] = None,
31
- ) -> None:
32
- """Update environment's install status values in a JSON file.
33
- Truth table values: 0 = False, 1 = True, -1 = Unknown
34
- """
35
- # Set default message if none provided
36
- message = "" if message is None else message.replace("\n", " ")
37
-
38
- # File path for state.json
39
- state_json_path = os.path.join(slug_path, "state.json")
40
-
41
- # Read existing data or use default structure
42
- if os.path.exists(state_json_path):
43
- with open(state_json_path, "r", encoding="utf-8") as f:
44
- data = json.load(f)
45
- else:
46
- data = {"install": {}}
47
9
 
48
- # Update the data
49
- data["install"]["complete"] = install_complete
50
- data["install"]["success"] = install_success
51
- data["install"]["message"] = message
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
- if env_name is not None:
54
- data["name"] = env_name
14
+ return create_local_venv(*args, **kwargs)
55
15
 
56
- # Write updated data back to state.json
57
- with open(state_json_path, "w", encoding="utf-8") as f:
58
- json.dump(data, f, indent=4)
59
16
 
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
60
20
 
61
- def create_venv(slug_path: str, prompt: str) -> None:
62
- """Create virtual environment and swap PS1 display name."""
63
- venv_path = os.path.join(slug_path, "pyenv")
64
- subprocess.run([sys.executable, "-m", "venv", venv_path], check=True)
65
-
66
- # Determine the correct directory for activation scripts based on the operating system
67
- if sys.platform == "win32":
68
- scripts_path = os.path.join(venv_path, "Scripts")
69
- activate_files = ["activate.bat", "Activate.ps1"]
70
- else:
71
- scripts_path = os.path.join(venv_path, "bin")
72
- activate_files = ["activate", "activate.csh", "activate.fish"]
73
-
74
- for file in activate_files:
75
- file_path = os.path.join(scripts_path, file)
76
- if os.path.isfile(file_path):
77
- replace_str("(pyenv)", f"({prompt})", file_path)
78
-
79
- replace_str(
80
- "include-system-site-packages = false",
81
- "include-system-site-packages = true",
82
- os.path.join(venv_path, "pyvenv.cfg"),
83
- )
84
-
85
- update_state_json(slug_path, 1, 1)
21
+ return update_state(*ags, **kwargs)
86
22
 
87
23
 
88
24
  def create_qbraid_env_assets(slug: str, alias: str, kernel_name: str, slug_path: str) -> None:
89
25
  """Create a qBraid environment including python venv, PS1 configs,
90
26
  kernel resource files, and qBraid state.json."""
91
- # pylint: disable-next=import-outside-toplevel
92
- from jupyter_client.kernelspec import KernelSpecManager
93
-
94
- local_resource_dir = os.path.join(slug_path, "kernels", f"python3_{slug}")
95
- os.makedirs(local_resource_dir, exist_ok=True)
96
-
97
- # create state.json
98
- update_state_json(slug_path, 0, 0, env_name=alias)
99
-
100
- # create kernel.json
101
- kernel_json_path = os.path.join(local_resource_dir, "kernel.json")
102
- kernel_spec_manager = KernelSpecManager()
103
- kernelspec_dict = kernel_spec_manager.get_all_specs()
104
- kernel_data = kernelspec_dict["python3"]["spec"]
105
- if sys.platform == "win32":
106
- python_exec_path = os.path.join(slug_path, "pyenv", "Scripts", "python.exe")
107
- else:
108
- python_exec_path = os.path.join(slug_path, "pyenv", "bin", "python")
109
- kernel_data["argv"][0] = python_exec_path
110
- kernel_data["display_name"] = kernel_name
111
- with open(kernel_json_path, "w", encoding="utf-8") as file:
112
- json.dump(kernel_data, file, indent=4)
113
-
114
- # copy logo files
115
- sys_resource_dir = kernelspec_dict["python3"]["resource_dir"]
116
- logo_files = ["logo-32x32.png", "logo-64x64.png", "logo-svg.svg"]
117
-
118
- for file in logo_files:
119
- sys_path = os.path.join(sys_resource_dir, file)
120
- loc_path = os.path.join(local_resource_dir, file)
121
- if os.path.isfile(sys_path):
122
- shutil.copy(sys_path, loc_path)
27
+ from qbraid_core.services.environments.create import create_qbraid_env_assets as create_assets
123
28
 
124
- # create python venv
125
- 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"]