usecli 0.1.49__tar.gz → 0.1.51__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 (71) hide show
  1. {usecli-0.1.49 → usecli-0.1.51}/PKG-INFO +1 -1
  2. {usecli-0.1.49 → usecli-0.1.51}/pyproject.toml +1 -1
  3. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/base/inspire_command.py +8 -3
  4. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/base/internal/fzf_command.py +5 -3
  5. usecli-0.1.51/src/usecli/cli/core/ui/__init__.py +31 -0
  6. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/ui/list.py +15 -3
  7. usecli-0.1.49/src/usecli/cli/core/ui/__init__.py +0 -16
  8. {usecli-0.1.49 → usecli-0.1.51}/LICENSE +0 -0
  9. {usecli-0.1.49 → usecli-0.1.51}/README.md +0 -0
  10. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/__init__.py +0 -0
  11. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/__init__.py +0 -0
  12. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/README.md +0 -0
  13. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/__init__.py +0 -0
  14. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/custom/README.md +0 -0
  15. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/custom/__init__.py +0 -0
  16. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/__init__.py +0 -0
  17. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/base/__init__.py +0 -0
  18. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/base/about_command.py +0 -0
  19. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/base/help_command.py +0 -0
  20. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/base/internal/__init__.py +0 -0
  21. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/core/__init__.py +0 -0
  22. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/core/utils.py +0 -0
  23. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/make/__init__.py +0 -0
  24. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/make/make_command.py +0 -0
  25. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/defaults/make/make_theme_command.py +0 -0
  26. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/commands/init_command.py +0 -0
  27. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/config/__init__.py +0 -0
  28. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/config/colors.py +0 -0
  29. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/__init__.py +0 -0
  30. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/base_command.py +0 -0
  31. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/error/__init__.py +0 -0
  32. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/error/handler.py +0 -0
  33. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/error/utils.py +0 -0
  34. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/exceptions/__init__.py +0 -0
  35. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/exceptions/base.py +0 -0
  36. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/exceptions/config.py +0 -0
  37. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/exceptions/usage.py +0 -0
  38. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/exceptions/validation.py +0 -0
  39. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/ui/title.py +0 -0
  40. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/ui/title.txt +0 -0
  41. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/validators/__init__.py +0 -0
  42. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/validators/network.py +0 -0
  43. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/validators/numeric.py +0 -0
  44. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/validators/path.py +0 -0
  45. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/core/validators/string.py +0 -0
  46. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/services/__init__.py +0 -0
  47. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/services/command_service.py +0 -0
  48. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/templates/command.py.j2 +0 -0
  49. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/templates/theme.toml.j2 +0 -0
  50. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/templates/usecli.config.toml.j2 +0 -0
  51. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/ayu_dark.toml +0 -0
  52. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/catppuccin_frappe.toml +0 -0
  53. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/catppuccin_latte.toml +0 -0
  54. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/catppuccin_macchiato.toml +0 -0
  55. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/catppuccin_mocha.toml +0 -0
  56. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/default.toml +0 -0
  57. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/dracula.toml +0 -0
  58. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/gruvbox_dark.toml +0 -0
  59. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/nord.toml +0 -0
  60. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/themes/tokyo_night.toml +0 -0
  61. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/utils/__init__.py +0 -0
  62. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/utils/interactive/__init__.py +0 -0
  63. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/cli/utils/interactive/terminal_menu.py +0 -0
  64. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/menu.py +0 -0
  65. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/params.py +0 -0
  66. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/shared/__init__.py +0 -0
  67. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/shared/config/__init__.py +0 -0
  68. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/shared/config/globals.py +0 -0
  69. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/shared/config/manager.py +0 -0
  70. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/ui.py +0 -0
  71. {usecli-0.1.49 → usecli-0.1.51}/src/usecli/usecli.config.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: usecli
3
- Version: 0.1.49
3
+ Version: 0.1.51
4
4
  Summary: A powerful Python CLI framework for building beautiful, developer-friendly command-line tools.
5
5
  Author: Edward Boswell
6
6
  Author-email: Edward Boswell <thememium@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "usecli"
3
- version = "0.1.49"
3
+ version = "0.1.51"
4
4
  description = "A powerful Python CLI framework for building beautiful, developer-friendly command-line tools."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Edward Boswell", email = "thememium@gmail.com" }]
@@ -33,9 +33,14 @@ class InspireCommand(BaseCommand):
33
33
  def handle(self) -> None:
34
34
  """Handle the command execution."""
35
35
  try:
36
- with urllib.request.urlopen(
37
- "https://zenquotes.io/api/random/inspiration"
38
- ) as response:
36
+ req = urllib.request.Request(
37
+ "https://zenquotes.io/api/random/inspiration",
38
+ headers={
39
+ "User-Agent": "Mozilla/5.0 (compatible; usecli/1.0)",
40
+ "Accept": "application/json",
41
+ },
42
+ )
43
+ with urllib.request.urlopen(req, timeout=10) as response:
39
44
  data: list[dict[str, str]] = json.loads(response.read().decode())
40
45
  quote = data[0]["q"]
41
46
  author = data[0]["a"]
@@ -19,6 +19,7 @@ from usecli.cli.config.colors import COLOR
19
19
  from usecli.cli.core.base_command import BaseCommand
20
20
  from usecli.cli.core.error.handler import ErrorHandler
21
21
  from usecli.cli.core.exceptions import UsecliError
22
+ from usecli.cli.core.ui import is_click_group
22
23
  from usecli.cli.utils.interactive.terminal_menu import terminal_menu
23
24
 
24
25
  if TYPE_CHECKING:
@@ -208,9 +209,10 @@ def run_interactive(
208
209
 
209
210
  click_group = typer.main.get_command(app)
210
211
  groups: dict[str, str] = {}
211
- if isinstance(click_group, click.Group):
212
- for cmd_name, cmd_obj in click_group.commands.items():
213
- if isinstance(cmd_obj, click.Group):
212
+ if is_click_group(click_group):
213
+ sub_commands: dict[str, object] = getattr(click_group, "commands", {})
214
+ for cmd_name, cmd_obj in sub_commands.items():
215
+ if is_click_group(cmd_obj):
214
216
  groups[cmd_name] = (
215
217
  getattr(cmd_obj, "help", f"Commands for {cmd_name}")
216
218
  or f"Commands for {cmd_name}"
@@ -0,0 +1,31 @@
1
+ """UI helpers for usecli CLI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import click
6
+
7
+ from usecli.cli.config.colors import COLOR, bold, style
8
+ from usecli.cli.core.ui.list import list_commands
9
+ from usecli.cli.core.ui.title import get_project_name, print_title
10
+
11
+
12
+ def is_click_group(obj: object) -> bool:
13
+ """Check if an object is a Click group (has subcommands).
14
+
15
+ Works with both standard click.Group and Typer's vendored click
16
+ (TyperGroup in typer>=0.26 no longer extends click.Group directly).
17
+ """
18
+ return isinstance(obj, click.Group) or (
19
+ hasattr(obj, "commands") and isinstance(getattr(obj, "commands", None), dict)
20
+ )
21
+
22
+
23
+ __all__ = [
24
+ "COLOR",
25
+ "bold",
26
+ "is_click_group",
27
+ "list_commands",
28
+ "print_title",
29
+ "get_project_name",
30
+ "style",
31
+ ]
@@ -23,6 +23,17 @@ console = Console()
23
23
  SPACER_LENGTH = 6
24
24
 
25
25
 
26
+ def _is_click_group(obj: object) -> bool:
27
+ """Check if an object is a Click group (has subcommands).
28
+
29
+ Works with both standard click.Group and Typer's vendored click
30
+ (TyperGroup in typer>=0.26 no longer extends click.Group directly).
31
+ """
32
+ from usecli.cli.core.ui import is_click_group
33
+
34
+ return is_click_group(obj)
35
+
36
+
26
37
  class CommandEntry(TypedDict):
27
38
  name: str
28
39
  display_name: str
@@ -87,9 +98,10 @@ def list_commands(app: typer.Typer, prefix_filter: str | None = None) -> None:
87
98
  commands.sort(key=lambda x: x["name"])
88
99
 
89
100
  groups: dict[str, str] = {}
90
- if isinstance(click_group, click.Group):
91
- for cmd_name, cmd_obj in click_group.commands.items():
92
- if isinstance(cmd_obj, click.Group):
101
+ if _is_click_group(click_group):
102
+ sub_commands: dict[str, object] = getattr(click_group, "commands", {})
103
+ for cmd_name, cmd_obj in sub_commands.items():
104
+ if _is_click_group(cmd_obj):
93
105
  if (
94
106
  cmd_name in group_alias_to_primary
95
107
  and group_alias_to_primary[cmd_name] != cmd_name
@@ -1,16 +0,0 @@
1
- """UI helpers for usecli CLI."""
2
-
3
- from __future__ import annotations
4
-
5
- from usecli.cli.config.colors import COLOR, bold, style
6
- from usecli.cli.core.ui.list import list_commands
7
- from usecli.cli.core.ui.title import get_project_name, print_title
8
-
9
- __all__ = [
10
- "COLOR",
11
- "bold",
12
- "style",
13
- "print_title",
14
- "get_project_name",
15
- "list_commands",
16
- ]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes