dev-setup 1.2.0__tar.gz → 1.4.0__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.
- dev_setup-1.4.0/.claude/settings.local.json +11 -0
- dev_setup-1.4.0/.github/workflows/publish.yml +44 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/CHANGELOG.md +12 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/PKG-INFO +1 -1
- {dev_setup-1.2.0 → dev_setup-1.4.0}/pyproject.toml +1 -1
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/base.py +1 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/commands/install_cmd.py +17 -9
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/commands/list_cmd.py +3 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/generic.py +12 -0
- dev_setup-1.4.0/src/dev_setup/packages/eza.py +59 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/pi_agent.py +1 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/registry.py +9 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/uv.lock +1 -1
- dev_setup-1.2.0/.claude/settings.local.json +0 -9
- {dev_setup-1.2.0 → dev_setup-1.4.0}/.gitignore +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/README.md +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/app-design-output/recommendations.md +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/dev/Dockerfile +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/dev/Makefile +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/dev/docker-compose.yml +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/dev-setup +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/install.sh +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/__init__.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/__main__.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/cli.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/commands/__init__.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/commands/add_cmd.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/commands/delete_cmd.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/commands/docs_cmd.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/commands/help_cmd.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/commands/remove_cmd.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/__init__.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/aws_cli.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/docker.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/gh.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/go.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/htop.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/java.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/mkcert.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/nvm.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/ollama.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/php.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/ruby.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/saml2aws.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/starship.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/packages/uv_tool.py +0 -0
- {dev_setup-1.2.0 → dev_setup-1.4.0}/src/dev_setup/ui.py +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(uv run *)",
|
|
5
|
+
"Bash(docker build *)",
|
|
6
|
+
"Bash(git -C /home/sawyer/Documents/Projects/ClaudeProjects/dev-setup-py log --format=\"%H %ai %s\")",
|
|
7
|
+
"Bash(git -C /home/sawyer/Documents/Projects/ClaudeProjects/dev-setup-py add src/dev_setup/packages/eza.py)",
|
|
8
|
+
"Bash(git -C /home/sawyer/Documents/Projects/ClaudeProjects/dev-setup-py commit -m ' *)"
|
|
9
|
+
]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: Build distribution
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v5
|
|
17
|
+
|
|
18
|
+
- name: Build wheel and source distribution
|
|
19
|
+
run: uv build
|
|
20
|
+
|
|
21
|
+
- name: Upload dist artifacts
|
|
22
|
+
uses: actions/upload-artifact@v4
|
|
23
|
+
with:
|
|
24
|
+
name: dist
|
|
25
|
+
path: dist/
|
|
26
|
+
|
|
27
|
+
publish:
|
|
28
|
+
name: Publish to PyPI
|
|
29
|
+
needs: build
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
environment:
|
|
32
|
+
name: pypi
|
|
33
|
+
url: https://pypi.org/p/dev-setup
|
|
34
|
+
permissions:
|
|
35
|
+
id-token: write # required for OIDC trusted publishing
|
|
36
|
+
steps:
|
|
37
|
+
- name: Download dist artifacts
|
|
38
|
+
uses: actions/download-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
42
|
+
|
|
43
|
+
- name: Publish to PyPI
|
|
44
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -38,6 +38,11 @@ def _install_one(tool: Tool) -> bool:
|
|
|
38
38
|
if tool.is_installed():
|
|
39
39
|
ui.success(f"{tool.name} is already installed: {tool.get_version()}")
|
|
40
40
|
return True
|
|
41
|
+
missing = registry.missing_requires(tool)
|
|
42
|
+
if missing:
|
|
43
|
+
ui.error(f"Cannot install {tool.name} — missing required tools: {', '.join(missing)}")
|
|
44
|
+
ui.dim(f"Install first: dev-setup install {' '.join(missing)}")
|
|
45
|
+
return False
|
|
41
46
|
try:
|
|
42
47
|
version = tool.install()
|
|
43
48
|
msg = f"{tool.name} installed"
|
|
@@ -54,17 +59,20 @@ def _install_interactive() -> None:
|
|
|
54
59
|
ui.print_banner()
|
|
55
60
|
tools = registry.all_tools()
|
|
56
61
|
|
|
57
|
-
choices = [
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
choices = []
|
|
63
|
+
for t in tools:
|
|
64
|
+
is_inst = t.is_installed()
|
|
65
|
+
missing = registry.missing_requires(t) if not is_inst else []
|
|
66
|
+
label = (
|
|
67
|
+
f"{'[installed] ' if is_inst else ''}"
|
|
68
|
+
f"{t.key:<14} {t.description}"
|
|
69
|
+
)
|
|
70
|
+
choices.append(questionary.Choice(
|
|
71
|
+
title=label,
|
|
63
72
|
value=t.key,
|
|
64
73
|
checked=False,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
]
|
|
74
|
+
disabled=f"requires {', '.join(missing)}" if missing else False,
|
|
75
|
+
))
|
|
68
76
|
|
|
69
77
|
selected = questionary.checkbox(
|
|
70
78
|
"Select packages to install (Space to toggle, Enter to confirm):",
|
|
@@ -48,11 +48,14 @@ def list_cmd(show_filter: str, category: str) -> None:
|
|
|
48
48
|
tbl.add_column("Version", style="dim")
|
|
49
49
|
|
|
50
50
|
for tool, is_inst in entries:
|
|
51
|
+
missing = registry.missing_requires(tool) if not is_inst else []
|
|
51
52
|
icon = "[green bold]✔[/]" if is_inst else "[red bold]✘[/]"
|
|
52
53
|
version = tool.get_version() if is_inst else ""
|
|
53
54
|
tbl.add_row(icon, tool.key, tool.description, tool.install_type, version)
|
|
54
55
|
if tool.help_cmd:
|
|
55
56
|
tbl.add_row("", "", f"[dim cyan] ? {tool.help_cmd}[/]", "", "")
|
|
57
|
+
if missing:
|
|
58
|
+
tbl.add_row("", "", f"[yellow] ⚠ requires: {', '.join(missing)}[/]", "", "")
|
|
56
59
|
|
|
57
60
|
ui.console.print(tbl)
|
|
58
61
|
ui.console.print()
|
|
@@ -48,6 +48,7 @@ class GenericTool(Tool):
|
|
|
48
48
|
remove_script: str = "",
|
|
49
49
|
help_cmd: str = "",
|
|
50
50
|
docs_url: str = "",
|
|
51
|
+
requires: Optional[list] = None,
|
|
51
52
|
) -> None:
|
|
52
53
|
self.key = key
|
|
53
54
|
self.name = name
|
|
@@ -66,6 +67,13 @@ class GenericTool(Tool):
|
|
|
66
67
|
self.remove_script = remove_script
|
|
67
68
|
self.help_cmd = help_cmd
|
|
68
69
|
self.docs_url = docs_url
|
|
70
|
+
# npm packages need nvm/node; explicit requires in JSON takes precedence
|
|
71
|
+
if requires is not None:
|
|
72
|
+
self.requires = requires
|
|
73
|
+
elif install_type == "npm":
|
|
74
|
+
self.requires = ["nvm"]
|
|
75
|
+
else:
|
|
76
|
+
self.requires = []
|
|
69
77
|
|
|
70
78
|
@classmethod
|
|
71
79
|
def from_dict(cls, data: dict, key: str) -> "GenericTool":
|
|
@@ -87,6 +95,7 @@ class GenericTool(Tool):
|
|
|
87
95
|
remove_script=data.get("remove_script", ""),
|
|
88
96
|
help_cmd=data.get("help_cmd", ""),
|
|
89
97
|
docs_url=data.get("docs_url", ""),
|
|
98
|
+
requires=data.get("requires") or None,
|
|
90
99
|
)
|
|
91
100
|
|
|
92
101
|
def to_dict(self) -> dict:
|
|
@@ -112,6 +121,9 @@ class GenericTool(Tool):
|
|
|
112
121
|
]:
|
|
113
122
|
if val:
|
|
114
123
|
d[field] = val
|
|
124
|
+
# Only persist explicit requires — auto-inferred ones are re-derived on load
|
|
125
|
+
if self.requires and not (self.install_type == "npm" and self.requires == ["nvm"]):
|
|
126
|
+
d["requires"] = self.requires
|
|
115
127
|
return d
|
|
116
128
|
|
|
117
129
|
def save(self) -> None:
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from dev_setup.base import WhichTool
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EzaTool(WhichTool):
|
|
10
|
+
key = "eza"
|
|
11
|
+
name = "eza"
|
|
12
|
+
description = "Modern ls replacement with git status, icons, and tree view"
|
|
13
|
+
category = "tools"
|
|
14
|
+
install_type = "script"
|
|
15
|
+
help_cmd = "eza --help"
|
|
16
|
+
docs_url = "https://eza.rocks/"
|
|
17
|
+
|
|
18
|
+
def install(self) -> Optional[str]:
|
|
19
|
+
from dev_setup import ui
|
|
20
|
+
|
|
21
|
+
ui.info("Adding eza apt repository...")
|
|
22
|
+
subprocess.run(
|
|
23
|
+
[
|
|
24
|
+
"bash", "-c",
|
|
25
|
+
"wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc"
|
|
26
|
+
" | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg"
|
|
27
|
+
" && echo 'deb [signed-by=/etc/apt/keyrings/gierens.gpg]"
|
|
28
|
+
" http://deb.gierens.de stable main'"
|
|
29
|
+
" | sudo tee /etc/apt/sources.list.d/gierens.list > /dev/null"
|
|
30
|
+
" && sudo chmod 644 /etc/apt/keyrings/gierens.gpg"
|
|
31
|
+
" /etc/apt/sources.list.d/gierens.list",
|
|
32
|
+
],
|
|
33
|
+
check=True, capture_output=True,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
with ui.spinner("Updating package index..."):
|
|
37
|
+
subprocess.run(["sudo", "apt-get", "update", "-q"], check=True, capture_output=True)
|
|
38
|
+
|
|
39
|
+
ui.info("Installing eza...")
|
|
40
|
+
subprocess.run(["sudo", "apt-get", "install", "-y", "eza"], check=True, capture_output=True)
|
|
41
|
+
|
|
42
|
+
if not self.is_installed():
|
|
43
|
+
raise RuntimeError("eza installation failed — binary not found")
|
|
44
|
+
return self.get_version()
|
|
45
|
+
|
|
46
|
+
def remove(self) -> None:
|
|
47
|
+
from dev_setup import ui
|
|
48
|
+
|
|
49
|
+
with ui.spinner("Removing eza..."):
|
|
50
|
+
subprocess.run(
|
|
51
|
+
["sudo", "apt-get", "remove", "-y", "eza"],
|
|
52
|
+
check=True, capture_output=True,
|
|
53
|
+
)
|
|
54
|
+
subprocess.run(
|
|
55
|
+
["sudo", "rm", "-f",
|
|
56
|
+
"/etc/apt/keyrings/gierens.gpg",
|
|
57
|
+
"/etc/apt/sources.list.d/gierens.list"],
|
|
58
|
+
check=True, capture_output=True,
|
|
59
|
+
)
|
|
@@ -90,3 +90,12 @@ def deregister(key: str) -> None:
|
|
|
90
90
|
_registry.pop(key, None)
|
|
91
91
|
if key in _order:
|
|
92
92
|
_order.remove(key)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def missing_requires(tool: Tool) -> list:
|
|
96
|
+
"""Return keys in tool.requires that are not currently installed."""
|
|
97
|
+
init()
|
|
98
|
+
return [
|
|
99
|
+
key for key in tool.requires
|
|
100
|
+
if key not in _registry or not _registry[key].is_installed()
|
|
101
|
+
]
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|