devstuff 1.14.1__tar.gz → 1.14.2__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 (54) hide show
  1. {devstuff-1.14.1 → devstuff-1.14.2}/CHANGELOG.md +6 -0
  2. {devstuff-1.14.1 → devstuff-1.14.2}/PKG-INFO +1 -1
  3. {devstuff-1.14.1 → devstuff-1.14.2}/pyproject.toml +1 -1
  4. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/help_cmd.py +1 -1
  5. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/install_cmd.py +2 -3
  6. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/skills_cmd.py +1 -4
  7. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/update_cmd.py +2 -3
  8. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/ui.py +20 -5
  9. {devstuff-1.14.1 → devstuff-1.14.2}/uv.lock +1 -1
  10. {devstuff-1.14.1 → devstuff-1.14.2}/.claude/skills/run-stuff/SKILL.md +0 -0
  11. {devstuff-1.14.1 → devstuff-1.14.2}/.claude/skills/run-stuff/smoke.sh +0 -0
  12. {devstuff-1.14.1 → devstuff-1.14.2}/.github/workflows/bump.yml +0 -0
  13. {devstuff-1.14.1 → devstuff-1.14.2}/.github/workflows/ci.yml +0 -0
  14. {devstuff-1.14.1 → devstuff-1.14.2}/.github/workflows/publish.yml +0 -0
  15. {devstuff-1.14.1 → devstuff-1.14.2}/.github/workflows/test-installs.yml +0 -0
  16. {devstuff-1.14.1 → devstuff-1.14.2}/.gitignore +0 -0
  17. {devstuff-1.14.1 → devstuff-1.14.2}/CLAUDE.md +0 -0
  18. {devstuff-1.14.1 → devstuff-1.14.2}/README.md +0 -0
  19. {devstuff-1.14.1 → devstuff-1.14.2}/dev/Dockerfile +0 -0
  20. {devstuff-1.14.1 → devstuff-1.14.2}/dev/Dockerfile.ci +0 -0
  21. {devstuff-1.14.1 → devstuff-1.14.2}/dev/Makefile +0 -0
  22. {devstuff-1.14.1 → devstuff-1.14.2}/dev/docker-compose.yml +0 -0
  23. {devstuff-1.14.1 → devstuff-1.14.2}/dev-setup +0 -0
  24. {devstuff-1.14.1 → devstuff-1.14.2}/install.sh +0 -0
  25. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/__init__.py +0 -0
  26. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/__main__.py +0 -0
  27. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/base.py +0 -0
  28. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/catalog.py +0 -0
  29. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/cli.py +0 -0
  30. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/__init__.py +0 -0
  31. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/add_cmd.py +0 -0
  32. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/catalog_cmd.py +0 -0
  33. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/delete_cmd.py +0 -0
  34. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/docs_cmd.py +0 -0
  35. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/functions_cmd.py +0 -0
  36. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/list_cmd.py +0 -0
  37. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/remove_cmd.py +0 -0
  38. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/commands/run_cmd.py +0 -0
  39. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/function_runner.py +0 -0
  40. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/functions.schema.json +0 -0
  41. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/functions.yaml +0 -0
  42. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/functions_catalog.py +0 -0
  43. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/functions_registry.py +0 -0
  44. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/generic.py +0 -0
  45. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/registry.py +0 -0
  46. {devstuff-1.14.1 → devstuff-1.14.2}/src/dev_setup/tools.yaml +0 -0
  47. {devstuff-1.14.1 → devstuff-1.14.2}/tests/__init__.py +0 -0
  48. {devstuff-1.14.1 → devstuff-1.14.2}/tests/integration/__init__.py +0 -0
  49. {devstuff-1.14.1 → devstuff-1.14.2}/tests/integration/conftest.py +0 -0
  50. {devstuff-1.14.1 → devstuff-1.14.2}/tests/integration/test_tools.py +0 -0
  51. {devstuff-1.14.1 → devstuff-1.14.2}/tests/test_catalog.py +0 -0
  52. {devstuff-1.14.1 → devstuff-1.14.2}/tests/test_functions.py +0 -0
  53. {devstuff-1.14.1 → devstuff-1.14.2}/tests/test_generic.py +0 -0
  54. {devstuff-1.14.1 → devstuff-1.14.2}/tests/test_registry.py +0 -0
@@ -1,3 +1,9 @@
1
+ ## v1.14.2 (2026-07-12)
2
+
3
+ ### Fix
4
+
5
+ - make interactive prompts abortable with Ctrl+C/Ctrl+D
6
+
1
7
  ## v1.14.1 (2026-07-12)
2
8
 
3
9
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devstuff
3
- Version: 1.14.1
3
+ Version: 1.14.2
4
4
  Summary: Development environment setup CLI for Linux
5
5
  Project-URL: Repository, https://github.com/thesawdawg/dev-setup-py
6
6
  Author-email: Sawyer <sawyerksu@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "devstuff"
3
- version = "1.14.1"
3
+ version = "1.14.2"
4
4
  description = "Development environment setup CLI for Linux"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -19,7 +19,7 @@ def print_help() -> None:
19
19
  ("docs", "<package>", "Open documentation in browser"),
20
20
  ("run", "<function> [args...]", "Run a function/script"),
21
21
  ("functions", "<list|enable|disable|path>", "Manage functions/scripts"),
22
- ("skills", "add", "Append skills from a GitHub repo to claude/codex/pi"),
22
+ ("skills", "add", "Append GitHub skills to claude/codex/pi"),
23
23
  ("version", "", "Show version"),
24
24
  ]
25
25
  for cmd, args, desc in rows:
@@ -102,12 +102,11 @@ def _install_interactive() -> None:
102
102
  disabled=disabled,
103
103
  ))
104
104
 
105
- selected = questionary.checkbox(
105
+ selected = ui.checkbox(
106
106
  "Select packages to install:",
107
107
  choices=choices,
108
108
  instruction="(Space toggle · Enter confirm · installed items are skipped)",
109
- style=ui._STYLE,
110
- ).ask()
109
+ )
111
110
 
112
111
  if not selected:
113
112
  ui.info("No packages selected.")
@@ -112,10 +112,7 @@ def _clone_repo(repo: str, dest: Path) -> str | None:
112
112
  return ssh_url
113
113
 
114
114
  if auth_method == "Personal access token":
115
- token = questionary.password("GitHub personal access token:").ask()
116
- if not token:
117
- ui.warn("No token provided — aborted.")
118
- return None
115
+ token = ui.password("GitHub personal access token:")
119
116
  owner_repo = _owner_repo(repo)
120
117
  token_url = f"https://x-access-token:{token}@github.com/{owner_repo}.git"
121
118
  with ui.spinner("Cloning with token..."):
@@ -124,12 +124,11 @@ def _update_interactive() -> None:
124
124
  ]
125
125
  choices.append(questionary.Choice(title=title, value=t.key, checked=status.available is True))
126
126
 
127
- selected = questionary.checkbox(
127
+ selected = ui.checkbox(
128
128
  "Select packages to update:",
129
129
  choices=choices,
130
130
  instruction="(Space toggle · Enter confirm · pre-checked items have a known update)",
131
- style=ui._STYLE,
132
- ).ask()
131
+ )
133
132
 
134
133
  if not selected:
135
134
  ui.info("No packages selected.")
@@ -75,14 +75,24 @@ def spinner(label: str) -> Generator[None, None, None]:
75
75
  yield
76
76
 
77
77
 
78
+ def _ask(question) -> object:
79
+ """Run a questionary prompt via unsafe_ask() so Ctrl+C/Ctrl+D raise
80
+ KeyboardInterrupt/EOFError instead of being swallowed into a None return
81
+ (questionary's default .ask() catches KeyboardInterrupt and retries
82
+ silently, which makes required prompts impossible to cancel). Click's
83
+ top-level command dispatch already catches both and exits cleanly with
84
+ "Aborted!", so letting them propagate is enough."""
85
+ return question.unsafe_ask()
86
+
87
+
78
88
  def confirm(prompt: str, default: bool = False) -> bool:
79
- result = questionary.confirm(prompt, default=default, style=_STYLE).ask()
89
+ result = _ask(questionary.confirm(prompt, default=default, style=_STYLE))
80
90
  return bool(result)
81
91
 
82
92
 
83
93
  def text_input(prompt: str, default: str = "", required: bool = False) -> str:
84
94
  while True:
85
- result = questionary.text(prompt, default=default, style=_STYLE).ask()
95
+ result = _ask(questionary.text(prompt, default=default, style=_STYLE))
86
96
  val = (result or "").strip()
87
97
  if val or not required:
88
98
  return val
@@ -90,15 +100,20 @@ def text_input(prompt: str, default: str = "", required: bool = False) -> str:
90
100
 
91
101
 
92
102
  def select(prompt: str, choices: list[str]) -> str:
93
- result = questionary.select(prompt, choices=choices, style=_STYLE).ask()
103
+ result = _ask(questionary.select(prompt, choices=choices, style=_STYLE))
94
104
  return result or ""
95
105
 
96
106
 
97
- def checkbox(prompt: str, choices: list) -> list:
98
- result = questionary.checkbox(prompt, choices=choices, style=_STYLE).ask()
107
+ def checkbox(prompt: str, choices: list, **kwargs) -> list:
108
+ result = _ask(questionary.checkbox(prompt, choices=choices, style=_STYLE, **kwargs))
99
109
  return result or []
100
110
 
101
111
 
112
+ def password(prompt: str) -> str:
113
+ result = _ask(questionary.password(prompt, style=_STYLE))
114
+ return result or ""
115
+
116
+
102
117
  def code_block(code: str, language: str = "bash") -> None:
103
118
  """Print a syntax-highlighted code panel."""
104
119
  from rich.syntax import Syntax
@@ -167,7 +167,7 @@ wheels = [
167
167
 
168
168
  [[package]]
169
169
  name = "devstuff"
170
- version = "1.14.1"
170
+ version = "1.14.2"
171
171
  source = { editable = "." }
172
172
  dependencies = [
173
173
  { name = "click" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes