devit-cli 0.1.4__tar.gz → 0.1.5__tar.gz

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.
Files changed (57) hide show
  1. {devit_cli-0.1.4/devit_cli.egg-info → devit_cli-0.1.5}/PKG-INFO +1 -1
  2. {devit_cli-0.1.4 → devit_cli-0.1.5/devit_cli.egg-info}/PKG-INFO +1 -1
  3. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/__init__.py +1 -1
  4. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/commands/archive.py +35 -27
  5. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/commands/env.py +24 -16
  6. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/commands/find.py +20 -4
  7. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/commands/init.py +20 -4
  8. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/commands/run.py +8 -1
  9. {devit_cli-0.1.4 → devit_cli-0.1.5}/pyproject.toml +1 -1
  10. {devit_cli-0.1.4 → devit_cli-0.1.5}/LICENSE +0 -0
  11. {devit_cli-0.1.4 → devit_cli-0.1.5}/README.md +0 -0
  12. {devit_cli-0.1.4 → devit_cli-0.1.5}/_devkit_entry.py +0 -0
  13. {devit_cli-0.1.4 → devit_cli-0.1.5}/devit_cli.egg-info/SOURCES.txt +0 -0
  14. {devit_cli-0.1.4 → devit_cli-0.1.5}/devit_cli.egg-info/dependency_links.txt +0 -0
  15. {devit_cli-0.1.4 → devit_cli-0.1.5}/devit_cli.egg-info/entry_points.txt +0 -0
  16. {devit_cli-0.1.4 → devit_cli-0.1.5}/devit_cli.egg-info/requires.txt +0 -0
  17. {devit_cli-0.1.4 → devit_cli-0.1.5}/devit_cli.egg-info/top_level.txt +0 -0
  18. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/commands/__init__.py +0 -0
  19. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/commands/clean.py +0 -0
  20. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/commands/info.py +0 -0
  21. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/main.py +0 -0
  22. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/aws/.gitignore +0 -0
  23. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/aws/README.md +0 -0
  24. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/aws/requirements.txt +0 -0
  25. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/aws/scripts/__init__.py +0 -0
  26. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/aws/scripts/ec2.py +0 -0
  27. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/aws/scripts/main.py +0 -0
  28. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/aws/scripts/s3.py +0 -0
  29. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/aws/tests/test_scripts.py +0 -0
  30. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/.gitignore +0 -0
  31. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/README.md +0 -0
  32. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/apps/__init__.py +0 -0
  33. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/apps/core/__init__.py +0 -0
  34. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/apps/core/apps.py +0 -0
  35. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/apps/core/urls.py +0 -0
  36. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/apps/core/views.py +0 -0
  37. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/manage.py +0 -0
  38. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/requirements.txt +0 -0
  39. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/{{module_name}}/__init__.py +0 -0
  40. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/{{module_name}}/settings.py +0 -0
  41. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/{{module_name}}/urls.py +0 -0
  42. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/django/{{module_name}}/wsgi.py +0 -0
  43. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/fastapi/.gitignore +0 -0
  44. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/fastapi/README.md +0 -0
  45. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/fastapi/app/__init__.py +0 -0
  46. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/fastapi/app/routers/__init__.py +0 -0
  47. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/fastapi/app/routers/health.py +0 -0
  48. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/fastapi/main.py +0 -0
  49. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/fastapi/requirements.txt +0 -0
  50. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/fastapi/tests/test_api.py +0 -0
  51. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/package/.gitignore +0 -0
  52. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/package/README.md +0 -0
  53. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/package/pyproject.toml +0 -0
  54. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/package/tests/test_core.py +0 -0
  55. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/package/{{module_name}}/__init__.py +0 -0
  56. {devit_cli-0.1.4 → devit_cli-0.1.5}/devkit_cli/templates/package/{{module_name}}/core.py +0 -0
  57. {devit_cli-0.1.4 → devit_cli-0.1.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devit-cli
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: A full-featured CLI framework for professional Python developers
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/dipenpadhiyar/devit-cli
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devit-cli
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: A full-featured CLI framework for professional Python developers
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/dipenpadhiyar/devit-cli
@@ -1,4 +1,4 @@
1
1
  """devkit-cli — A professional developer toolkit for the terminal."""
2
2
 
3
- __version__ = "0.1.4"
3
+ __version__ = "0.1.5"
4
4
  __author__ = "devkit-cli contributors"
@@ -79,20 +79,24 @@ def zip_cmd(output, sources, level, exclude):
79
79
 
80
80
  compress = zipfile.ZIP_DEFLATED if level > 0 else zipfile.ZIP_STORED
81
81
 
82
- with Progress(
83
- TextColumn("[bold blue]{task.description}"),
84
- BarColumn(),
85
- TaskProgressColumn(),
86
- FileSizeColumn(),
87
- TransferSpeedColumn(),
88
- TimeRemainingColumn(),
89
- console=console,
90
- ) as progress:
91
- task = progress.add_task("Compressing", total=total_size)
92
- with zipfile.ZipFile(out_path, "w", compression=compress, compresslevel=level) as zf:
93
- for fpath, arc_name in all_files:
94
- zf.write(fpath, arc_name)
95
- progress.advance(task, fpath.stat().st_size)
82
+ try:
83
+ with Progress(
84
+ TextColumn("[bold blue]{task.description}"),
85
+ BarColumn(),
86
+ TaskProgressColumn(),
87
+ FileSizeColumn(),
88
+ TransferSpeedColumn(),
89
+ TimeRemainingColumn(),
90
+ console=console,
91
+ ) as progress:
92
+ task = progress.add_task("Compressing", total=total_size)
93
+ with zipfile.ZipFile(out_path, "w", compression=compress, compresslevel=level) as zf:
94
+ for fpath, arc_name in all_files:
95
+ zf.write(fpath, arc_name)
96
+ progress.advance(task, fpath.stat().st_size)
97
+ except OSError as e:
98
+ console.print(f"[red]✗[/red] Failed to create archive: {e}")
99
+ raise click.Abort()
96
100
 
97
101
  final_size = out_path.stat().st_size
98
102
  ratio = (1 - final_size / total_size) * 100 if total_size else 0
@@ -149,18 +153,22 @@ def unzip_cmd(archive, destination, list_only):
149
153
  dest.mkdir(parents=True, exist_ok=True)
150
154
  total_size = sum(m.file_size for m in members if not m.is_dir())
151
155
 
152
- with Progress(
153
- TextColumn("[bold blue]{task.description}"),
154
- BarColumn(),
155
- TaskProgressColumn(),
156
- FileSizeColumn(),
157
- TimeRemainingColumn(),
158
- console=console,
159
- ) as progress:
160
- task = progress.add_task("Extracting", total=total_size)
161
- for member in members:
162
- zf.extract(member, dest)
163
- if not member.is_dir():
164
- progress.advance(task, member.file_size)
156
+ try:
157
+ with Progress(
158
+ TextColumn("[bold blue]{task.description}"),
159
+ BarColumn(),
160
+ TaskProgressColumn(),
161
+ FileSizeColumn(),
162
+ TimeRemainingColumn(),
163
+ console=console,
164
+ ) as progress:
165
+ task = progress.add_task("Extracting", total=total_size)
166
+ for member in members:
167
+ zf.extract(member, dest)
168
+ if not member.is_dir():
169
+ progress.advance(task, member.file_size)
170
+ except OSError as e:
171
+ console.print(f"[red]✗[/red] Extraction failed: {e}")
172
+ raise click.Abort()
165
173
 
166
174
  console.print(f"[green]✔[/green] Extracted [bold]{len(members)}[/bold] items to [cyan]{dest}[/cyan]")
@@ -14,7 +14,11 @@ console = Console()
14
14
  def _load_dotenv(path: Path) -> dict[str, str]:
15
15
  """Parse a .env file into a dict."""
16
16
  result = {}
17
- for line in path.read_text(encoding="utf-8").splitlines():
17
+ try:
18
+ content = path.read_text(encoding="utf-8")
19
+ except OSError as e:
20
+ raise click.ClickException(f"Cannot read {path}: {e}")
21
+ for line in content.splitlines():
18
22
  line = line.strip()
19
23
  if not line or line.startswith("#"):
20
24
  continue
@@ -93,21 +97,25 @@ def env_export(output, filter_str, fmt):
93
97
 
94
98
  out = Path(output)
95
99
 
96
- if fmt == "dotenv":
97
- lines = [f'{k}="{v}"' for k, v in sorted(vars_dict.items())]
98
- out.write_text("\n".join(lines) + "\n", encoding="utf-8")
99
- elif fmt == "json":
100
- out.write_text(json.dumps(vars_dict, indent=2), encoding="utf-8")
101
- elif fmt == "shell":
102
- lines = [f"export {k}={json.dumps(v)}" for k, v in sorted(vars_dict.items())]
103
- out.write_text("\n".join(lines) + "\n", encoding="utf-8")
104
- elif fmt == "powershell":
105
- lines = [f'$env:{k} = {json.dumps(v)}' for k, v in sorted(vars_dict.items())]
106
- out.write_text("\n".join(lines) + "\n", encoding="utf-8")
107
- elif fmt == "cmd":
108
- # Values with special CMD characters are quoted; newlines replaced with space
109
- lines = [f"set {k}={v.replace(chr(10), ' ')}" for k, v in sorted(vars_dict.items())]
110
- out.write_text("\n".join(lines) + "\n", encoding="utf-8")
100
+ try:
101
+ if fmt == "dotenv":
102
+ lines = [f'{k}="{v}"' for k, v in sorted(vars_dict.items())]
103
+ out.write_text("\n".join(lines) + "\n", encoding="utf-8")
104
+ elif fmt == "json":
105
+ out.write_text(json.dumps(vars_dict, indent=2), encoding="utf-8")
106
+ elif fmt == "shell":
107
+ lines = [f"export {k}={json.dumps(v)}" for k, v in sorted(vars_dict.items())]
108
+ out.write_text("\n".join(lines) + "\n", encoding="utf-8")
109
+ elif fmt == "powershell":
110
+ lines = [f'$env:{k} = {json.dumps(v)}' for k, v in sorted(vars_dict.items())]
111
+ out.write_text("\n".join(lines) + "\n", encoding="utf-8")
112
+ elif fmt == "cmd":
113
+ # Values with special CMD characters are quoted; newlines replaced with space
114
+ lines = [f"set {k}={v.replace(chr(10), ' ')}" for k, v in sorted(vars_dict.items())]
115
+ out.write_text("\n".join(lines) + "\n", encoding="utf-8")
116
+ except OSError as e:
117
+ console.print(f"[red]✗[/red] Cannot write to [bold]{out}[/bold]: {e}")
118
+ raise SystemExit(1)
111
119
 
112
120
  console.print(f"[green]✔[/green] Exported [bold]{len(vars_dict)}[/bold] variables to [cyan]{out}[/cyan]")
113
121
 
@@ -60,10 +60,26 @@ def find(pattern, search_dir, ext, min_size, max_size, newer_than, older_than, l
60
60
  devkit find --dirs-only "src"
61
61
  """
62
62
  root = Path(search_dir).resolve()
63
- min_bytes = _parse_size(min_size) if min_size else None
64
- max_bytes = _parse_size(max_size) if max_size else None
65
- newer_cutoff = (datetime.now() - timedelta(days=int(newer_than))).timestamp() if newer_than else None
66
- older_cutoff = (datetime.now() - timedelta(days=int(older_than))).timestamp() if older_than else None
63
+ try:
64
+ min_bytes = _parse_size(min_size) if min_size else None
65
+ except (ValueError, TypeError):
66
+ console.print(f"[red]✗[/red] Invalid --min-size value: [bold]{min_size}[/bold] (example: 10kb, 2mb)")
67
+ raise SystemExit(1)
68
+ try:
69
+ max_bytes = _parse_size(max_size) if max_size else None
70
+ except (ValueError, TypeError):
71
+ console.print(f"[red]✗[/red] Invalid --max-size value: [bold]{max_size}[/bold] (example: 10kb, 2mb)")
72
+ raise SystemExit(1)
73
+ try:
74
+ newer_cutoff = (datetime.now() - timedelta(days=int(newer_than))).timestamp() if newer_than else None
75
+ except (ValueError, TypeError):
76
+ console.print(f"[red]✗[/red] --newer-than must be a whole number of days, got: [bold]{newer_than}[/bold]")
77
+ raise SystemExit(1)
78
+ try:
79
+ older_cutoff = (datetime.now() - timedelta(days=int(older_than))).timestamp() if older_than else None
80
+ except (ValueError, TypeError):
81
+ console.print(f"[red]✗[/red] --older-than must be a whole number of days, got: [bold]{older_than}[/bold]")
82
+ raise SystemExit(1)
67
83
 
68
84
  table = Table(title=f"Search: [cyan]{pattern}[/cyan] in [dim]{root}[/dim]",
69
85
  show_lines=False, expand=False)
@@ -50,7 +50,11 @@ def _create_venv(project_dir: Path, python_version: str) -> None:
50
50
  """Create a native venv inside project_dir."""
51
51
  with Progress(SpinnerColumn(), TextColumn("[bold green]Creating venv..."), transient=True) as p:
52
52
  p.add_task("")
53
- _run([sys.executable, "-m", "venv", ".venv"], cwd=project_dir)
53
+ try:
54
+ _run([sys.executable, "-m", "venv", ".venv"], cwd=project_dir)
55
+ except subprocess.CalledProcessError as e:
56
+ console.print(f"[red]✗[/red] Failed to create virtual environment.\n [dim]{e}[/dim]")
57
+ raise click.Abort()
54
58
  console.print("[green]✔[/green] Virtual environment created at [cyan].venv/[/cyan]")
55
59
 
56
60
 
@@ -62,7 +66,11 @@ def _create_conda_env(project_dir: Path, name: str, python_version: str) -> None
62
66
  return
63
67
  with Progress(SpinnerColumn(), TextColumn(f"[bold green]Creating conda env '{name}'..."), transient=True) as p:
64
68
  p.add_task("")
65
- _run([conda_bin, "create", "-n", name, f"python={python_version}", "-y"])
69
+ try:
70
+ _run([conda_bin, "create", "-n", name, f"python={python_version}", "-y"])
71
+ except subprocess.CalledProcessError as e:
72
+ console.print(f"[red]✗[/red] Failed to create conda environment.\n [dim]{e}[/dim]")
73
+ raise click.Abort()
66
74
  console.print(f"[green]✔[/green] Conda environment [cyan]{name}[/cyan] created.")
67
75
 
68
76
 
@@ -411,7 +419,11 @@ def init(project_name, project_type, env_type, python_version, target_dir, yes):
411
419
  if not overwrite:
412
420
  raise click.Abort()
413
421
  else:
414
- project_dir.mkdir(parents=True)
422
+ try:
423
+ project_dir.mkdir(parents=True)
424
+ except PermissionError:
425
+ console.print(f"[red]✗[/red] Permission denied: cannot create [cyan]{project_dir}[/cyan]")
426
+ raise click.Abort()
415
427
 
416
428
  # --- scaffold ---
417
429
  ctx = {
@@ -429,7 +441,11 @@ def init(project_name, project_type, env_type, python_version, target_dir, yes):
429
441
  py_path = env_decision["python_path"]
430
442
  with Progress(SpinnerColumn(), TextColumn("[bold green]Creating .venv..."), transient=True) as p:
431
443
  p.add_task("")
432
- _run([py_path, "-m", "venv", ".venv"], cwd=project_dir)
444
+ try:
445
+ _run([py_path, "-m", "venv", ".venv"], cwd=project_dir)
446
+ except subprocess.CalledProcessError as e:
447
+ console.print(f"[red]✗[/red] Failed to create virtual environment.\n [dim]{e}[/dim]")
448
+ raise click.Abort()
433
449
  console.print("[green]✔[/green] Virtual environment created at [cyan].venv/[/cyan]")
434
450
  elif kind == "conda_new":
435
451
  _create_conda_env(project_dir, project_name, python_version)
@@ -104,7 +104,14 @@ def _run_cmd(cmd: list[str], cwd: Path) -> None:
104
104
  f" Make sure [cyan]{exe}[/cyan] is installed and on your PATH."
105
105
  )
106
106
  raise SystemExit(1)
107
- result = subprocess.run(cmd, cwd=cwd)
107
+ try:
108
+ result = subprocess.run(cmd, cwd=cwd)
109
+ except FileNotFoundError:
110
+ console.print(
111
+ f"[red]Command not found:[/red] [bold]{cmd[0]}[/bold]\n"
112
+ f" Make sure [cyan]{cmd[0]}[/cyan] is installed and on your PATH."
113
+ )
114
+ raise SystemExit(1)
108
115
  if result.returncode != 0:
109
116
  raise SystemExit(result.returncode)
110
117
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "devit-cli"
7
- version = "0.1.4"
7
+ version = "0.1.5"
8
8
  description = "A full-featured CLI framework for professional Python developers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes
File without changes
File without changes
File without changes
File without changes